[
  {
    "path": ".clang-format",
    "content": "---\n# TODO BreakBeforeLambdaBody\n# TODO IncludeBlocks\nLanguage: Cpp\nAccessModifierOffset: -2\nAlignAfterOpenBracket: Align\nAlignConsecutiveAssignments: true\nAlignConsecutiveDeclarations: true\nAlignEscapedNewlines: Right\nAlignOperands: true\nAlignTrailingComments: true\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowShortBlocksOnASingleLine: false\nAllowShortCaseLabelsOnASingleLine: false\nAllowShortFunctionsOnASingleLine: All\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakAfterDefinitionReturnType: None\nAlwaysBreakAfterReturnType: None\nAlwaysBreakBeforeMultilineStrings: false\nAlwaysBreakTemplateDeclarations: true\nBinPackArguments: false\nBinPackParameters: false\nBreakBeforeBraces: Custom\nBraceWrapping: \n  AfterClass: true\n  AfterControlStatement: false\n  AfterEnum: true\n  AfterFunction: true\n  AfterNamespace: false\n  AfterObjCDeclaration: false\n  AfterStruct: true\n  AfterUnion: true\n  #AfterExternBlock: true\n  BeforeCatch: false\n  BeforeElse: false\n  IndentBraces: false\n  SplitEmptyFunction: true\n  SplitEmptyRecord: true\n  SplitEmptyNamespace: true\nBreakBeforeBinaryOperators: None\nBreakBeforeInheritanceComma: true\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: true\nBreakConstructorInitializers: BeforeColon\nBreakAfterJavaFieldAnnotations: false\nBreakStringLiterals: true\nColumnLimit: 120\nCommentPragmas: '^ IWYU pragma:'\nCompactNamespaces: true\nConstructorInitializerAllOnOneLineOrOnePerLine: false\nConstructorInitializerIndentWidth: 4\nContinuationIndentWidth: 4\nCpp11BracedListStyle: true\nDerivePointerAlignment: false\nDisableFormat: false\nExperimentalAutoDetectBinPacking: false\nFixNamespaceComments: true\nForEachMacros: \n  - foreach\n  - Q_FOREACH\n  - BOOST_FOREACH\nIncludeCategories: \n  - Regex: '^\"(llvm|llvm-c|clang|clang-c)/'\n    Priority: 2\n  - Regex: '^(<|\"(gtest|gmock|isl|json)/)'\n    Priority: 3\n  - Regex: '.*'\n    Priority: 1\nIncludeIsMainRegex: '(Test)?$'\nIndentCaseLabels: true\n#IndentPPDirectives: None\nIndentWidth: 4\nIndentWrappedFunctionNames: false\nKeepEmptyLinesAtTheStartOfBlocks: false\nMacroBlockBegin: ''\nMacroBlockEnd: ''\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nPenaltyBreakAssignment: 2\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 300\nPenaltyBreakFirstLessLess: 120\nPenaltyBreakString: 1000\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 60\nPointerAlignment: Left\n#RawStringFormats: \n#  - Delimiter: pb\n#    Language: TextProto\n#    BasedOnStyle: google\nReflowComments: true\nSortIncludes: true\nSortUsingDeclarations: true\nSpaceAfterCStyleCast: false\nSpaceAfterTemplateKeyword: true\nSpaceBeforeAssignmentOperators: true\nSpaceBeforeParens: ControlStatements\nSpaceInEmptyParentheses: false\nSpacesBeforeTrailingComments: 1\nSpacesInAngles: false\nSpacesInContainerLiterals: true\nSpacesInCStyleCastParentheses: false\nSpacesInParentheses: false\nSpacesInSquareBrackets: false\nStandard: Cpp11\nUseTab: Never\n...\n\n"
  },
  {
    "path": ".dockerignore",
    "content": "src/packages\nsrc/cmake-build-*\nbuild-scripts\nbuild\nresources\n.git\n.vscode\nCMakeFiles\ncasparcg_server\n\ndist\nbuild\nsrc/cmake-build-*\n"
  },
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\nend_of_line = lf\ninsert_final_newline = true\ntrim_trailing_whitespace = true\n\n[*.diff]\ntrim_trailing_whitespace = false\n\n[*.patch]\ntrim_trailing_whitespace = false\n\n[debian/rules]\nindent_style = tab\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.yaml",
    "content": "name: Bug report 🐛\ndescription: Use this if you've found a bug\ntitle: \"Bug: [Short description of the bug]\"\nlabels:\n  - type/bug\n\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Before you post, make sure to check for existing bug reports of the issue:\n        https://github.com/CasparCG/server/issues?q=+is%3Aissue+label%3Atype%2Fbug\n\n  - type: textarea\n    attributes:\n      label: Observed Behavior\n      description: What happened?\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Expected behaviour\n      description: What did you expect to happen?\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Steps to reproduce\n      description: How can we reproduce the issue?\n      value: |\n        1.\n        2.\n        3. ...\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Environment\n      description: What version of CasparCG and OS are you using?\n      value: |\n        * Commit: [e.g. ab1234c]\n        * Server version: [e.g. v2.2]\n        * Operating system: [e.g. Windows 10]\n    validations:\n      required: true\n      "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: Question or need help?\n    url: https://casparcgforum.org/\n    about: Ask the community here."
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.yaml",
    "content": "name: Feature request\ndescription: Suggest an idea for this project\nlabels:\n  - type/enhancement\n\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        Before you post, make sure to check for existing matching feature requests:\n        https://github.com/CasparCG/server/issues?q=+is%3Aissue+label%3Atype%2Fbug\n\n  - type: textarea\n    attributes:\n      label: Description\n      description: How should the feature/enhancement work?\n    validations:\n      required: true\n\n  - type: textarea\n    attributes:\n      label: Solution suggestion\n      description: If you have any suggestions on how the solution should work, add that here.\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n    - package-ecosystem: \"github-actions\"\n      directory: \"/\"\n      schedule:\n          interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/linux-system.yml",
    "content": "name: Build Linux with system dependencies\n\non:\n    push:\n        # branches: [ \"master\" ]\n    pull_request:\n        branches: [\"master\"]\n\njobs:\n    build:\n        name: ${{ matrix.container || matrix.os }} ${{ matrix.arch }} (${{matrix.family}}:${{ matrix.distribution }})\n        strategy:\n            fail-fast: false\n            matrix:\n                include:\n                    - os: ubuntu-24.04\n                      family: ubuntu\n                      distribution: noble\n                      arch: amd64\n                      container: \"\"\n                      apt_prefix: sudo\n                      upload_artifacts: true\n                    - os: ubuntu-latest\n                      family: ubuntu\n                      distribution: resolute\n                      arch: amd64\n                      container: ubuntu:26.04\n                      apt_prefix: \"\"\n                      upload_artifacts: false\n                    - os: ubuntu-24.04-arm\n                      family: ubuntu\n                      distribution: resolute\n                      arch: arm64\n                      container: ubuntu:26.04\n                      apt_prefix: \"\"\n                      upload_artifacts: false\n                    - os: ubuntu-latest\n                      family: debian\n                      distribution: trixie\n                      arch: amd64\n                      container: debian:trixie # Debian 13\n                      apt_prefix: \"\"\n                      upload_artifacts: false # Because of CEF, this is not built correctly\n                    - os: ubuntu-latest\n                      family: debian\n                      distribution: sid\n                      arch: amd64\n                      container: debian:sid # Debian Testing\n                      apt_prefix: \"\"\n                      upload_artifacts: false # Because of CEF, this is not built correctly\n                    - os: ubuntu-latest\n                      family: debian\n                      distribution: trixie\n                      arch: amd64\n                      container: debian:trixie\n                      apt_prefix: \"\"\n                      upload_artifacts: false # Because of CEF, this is not built correctly\n                    - os: ubuntu-latest\n                      family: archlinux\n                      distribution: latest\n                      arch: amd64\n                      container: archlinux:latest\n                      apt_prefix: \"\"\n                      upload_artifacts: false # Not supported\n\n        runs-on: ${{ matrix.os }}\n        container: ${{ matrix.container }}\n        defaults:\n            run:\n                shell: bash\n\n        steps:\n            - name: Install git (archlinux)\n              if: ${{ matrix.family == 'archlinux' }}\n              run: pacman -Sy --noconfirm git\n\n            - uses: actions/checkout@v6\n\n            - name: Setup environment\n              id: setup-env\n              if: ${{ matrix.family == 'ubuntu' || matrix.family == 'debian' }}\n              run: |\n                  ln -s tools/linux/deb/${{ matrix.family }}-${{ matrix.distribution }}/debian ./\n\n                  # Build a version number for this build\n                  GH_REF=\"${GITHUB_REF##*/}\"\n                  GH_REF=$(echo \"$GH_REF\" | sed 's/[\\/]/_/g' | sed 's/ /_/g')\n\n                  VERSION_MAJOR=$(grep -oPi 'set\\(CONFIG_VERSION_MAJOR \\K\\d+' src/CMakeLists.txt)\n                  VERSION_MINOR=$(grep -oPi 'set\\(CONFIG_VERSION_MINOR \\K\\d+' src/CMakeLists.txt)\n                  VERSION_PATCH=$(grep -oPi 'set\\(CONFIG_VERSION_BUG \\K\\d+' src/CMakeLists.txt)\n\n                  BUILD_VERSION=\"${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}~${GH_REF}-${{ matrix.distribution }}+${GITHUB_SHA:0:7}\"\n                  echo \"BUILD_VERSION=$BUILD_VERSION\" >> $GITHUB_OUTPUT\n                  echo \"Building as $BUILD_VERSION\"\n\n                  BUILD_FILENAME=\"casparcg-server-${BUILD_VERSION}\"\n                  echo \"BUILD_FILENAME=$BUILD_FILENAME\" >> $GITHUB_OUTPUT\n\n                  # install some needed tooling\n                  $APT_PREFIX apt-get update\n                  $APT_PREFIX apt-get -y install build-essential dpkg-dev debhelper devscripts\n\n                  if [[ \"${{ matrix.family }}\" == \"ubuntu\" ]]; then\n                    $APT_PREFIX apt-get -y install software-properties-common\n                    $APT_PREFIX add-apt-repository ppa:casparcg/ppa\n                  fi\n\n                  # Put something in the changelog\n                  export DEBEMAIL=\"builds@casparcg.com\"\n                  export DEBFULLNAME=\"CasparCG Builds\"\n                  dch -v \"$BUILD_VERSION\" --create -D ${{ matrix.distribution }} --package casparcg-server-beta \"Build\"\n\n                  # Install build dependencies\n                  $APT_PREFIX apt-get -y build-dep .\n\n                  if [[ \"${{ matrix.family }}\" == \"ubuntu\" ]]; then\n                    # update the control file to reference the current cef version\n                    CASPARCG_CEF_VER=$(dpkg-query -W -f='${Version}' casparcg-cef-142)\n                    sed -i \"s/@CASPARCG_CEF_VER@/${CASPARCG_CEF_VER}/\" debian/control\n\n                    # Download required packages\n                    cd ..\n                    apt-get download casparcg-cef-142=$CASPARCG_CEF_VER\n                    apt-get download casparcg-scanner\n                  fi\n              env:\n                  CI: 1\n                  DEBIAN_FRONTEND: noninteractive\n                  APT_PREFIX: ${{ matrix.apt_prefix }}\n\n            - name: Run build\n              if: ${{ matrix.family == 'ubuntu' || matrix.family == 'debian' }}\n              run: |\n                  # Perform build\n                  debuild -b -uc -us\n              env:\n                  CI: 1\n\n            - name: Collect artifacts\n              id: artifacts\n              if: ${{ (matrix.family == 'ubuntu' || matrix.family == 'debian') && matrix.upload_artifacts }}\n              run: |\n                  mkdir -p dist\n                  mv ../*.deb dist/\n\n                  # collect some docs for the zip\n                  cp README.md dist/\n                  cp tools/linux/deb/INSTALLING dist/\n\n                  # check if a release branch, or master, or a tag\n                  if [[ \"${{ github.ref_name }}\" == \"master\" || \"${{ github.ref_name }}\" == \"2.3.x-lts\" ]]\n                  then\n                    # Only proceed if we have an sftp password\n                    if [ -n \"${{ secrets.SFTP_PASSWORD }}\" ]\n                    then\n                      zip -r \"${{ steps.setup-env.outputs.BUILD_FILENAME }}.zip\" dist\n\n                      set -x\n                      eval $(ssh-agent -s)\n                      mkdir -v -m 700 $HOME/.ssh\n                      ssh-keyscan -H ${{ secrets.SFTP_HOST }} > $HOME/.ssh/known_hosts\n                      sshpass -p '${{ secrets.SFTP_PASSWORD }}' rsync -avvz --mkpath \"${{ steps.setup-env.outputs.BUILD_FILENAME }}.zip\" \"${{ secrets.SFTP_USERNAME }}@${{ secrets.SFTP_HOST }}:${{ secrets.SFTP_ROOT }}/${{ github.ref_name }}/${{ steps.setup-env.outputs.BUILD_FILENAME }}.zip\"\n                    fi\n                  fi\n\n              env:\n                  CI: 1\n\n            - uses: actions/upload-artifact@v7\n              if: ${{ (matrix.family == 'ubuntu' || matrix.family == 'debian') && matrix.upload_artifacts }}\n              with:\n                  name: ${{ steps.setup-env.outputs.BUILD_FILENAME }}\n                  path: dist\n\n            - name: Setup environment (archlinux)\n              if: ${{ matrix.family == 'archlinux' }}\n              run: |\n                  pacman -Syu --noconfirm\n                  pacman -S --noconfirm --needed \\\n                    base-devel cmake ninja pkg-config \\\n                    boost boost-libs ffmpeg glew libglvnd \\\n                    onetbb openal sfml \\\n                    libxrandr simde\n              env:\n                  CI: 1\n\n            - name: Run build (archlinux)\n              if: ${{ matrix.family == 'archlinux' }}\n              run: |\n                  cmake -B build -S src \\\n                    -DCMAKE_BUILD_TYPE=Release \\\n                    -DDIAG_FONT_PATH=\"/usr/share/fonts/liberation/LiberationMono-Regular.ttf\" \\\n                    -DENABLE_HTML=OFF \\\n                    -G Ninja\n\n                  cmake --build build\n              env:\n                  CI: 1\n"
  },
  {
    "path": ".github/workflows/linux.yml",
    "content": "name: Build Linux\n\non:\n    push:\n        # branches: [ \"master\" ]\n    pull_request:\n        branches: [\"master\"]\n\njobs:\n    build:\n        runs-on: ubuntu-latest\n\n        permissions:\n            packages: write\n\n        steps:\n            - uses: actions/checkout@v6\n\n            - name: Run build\n              run: |\n                  ./tools/linux/build-in-docker\n              env:\n                  CI: 1\n"
  },
  {
    "path": ".github/workflows/windows.yml",
    "content": "name: Build Windows\n\non:\n    push:\n        # branches: [ \"master\" ]\n    pull_request:\n        branches: [\"master\"]\n\njobs:\n    build:\n        runs-on: windows-2022\n\n        steps:\n            - uses: actions/checkout@v6\n\n            - name: Download media-scanner\n              uses: robinraju/release-downloader@v1.12\n              with:\n                  repository: \"casparcg/media-scanner\"\n                  latest: true\n                  fileName: \"*-win32-x64.zip\"\n                  tarBall: false\n                  zipBall: false\n                  out-file-path: \"media-scanner\"\n                  extract: true\n\n            - name: Tidy media-scanner download\n              shell: bash\n              run: |\n                  rm media-scanner/*.zip\n\n            - name: Run build\n              run: |\n                  ./tools/windows/build.bat\n              env:\n                  CI: 1\n                  MEDIA_SCANNER_FOLDER: \"..\\\\media-scanner\"\n\n            - name: Rename build\n              id: \"rename-build\"\n              shell: bash\n              run: |\n                  TARGET=casparcg-server-${{ github.sha }}-windows.zip\n                  mv dist/casparcg_server.zip \"$TARGET\"\n\n                  echo \"artifactname=$TARGET\" >> $GITHUB_OUTPUT\n\n                  # check if a release branch, or master, or a tag\n                  if [[ \"${{ github.ref_name }}\" == \"master\" || \"${{ github.ref_name }}\" == \"2.3.x-lts\" ]]\n                  then\n                    # Only report if we have an sftp password\n                    if [ -n \"${{ secrets.SFTP_PASSWORD }}\" ]\n                    then\n                        echo \"uploadname=$TARGET\" >> $GITHUB_OUTPUT\n                    fi\n                  fi\n\n            - uses: actions/upload-artifact@v7\n              with:\n                  path: ${{ steps.rename-build.outputs.artifactname }}\n                  archive: false\n\n            - name: Copy single file to remote\n              uses: garygrossgarten/github-action-scp@0.10.0\n              if: ${{ steps.rename-build.outputs.uploadname }}\n              timeout-minutes: 5\n              with:\n                  local: \"${{ steps.rename-build.outputs.uploadname }}\"\n                  remote: \"${{ secrets.SFTP_ROOT }}/${{ github.ref_name }}/${{ steps.rename-build.outputs.uploadname }}\"\n                  host: ${{ secrets.SFTP_HOST }}\n                  username: ${{ secrets.SFTP_USERNAME }}\n                  password: ${{ secrets.SFTP_PASSWORD }}\n"
  },
  {
    "path": ".gitignore",
    "content": "*.dir\n*.vcxproj\n*.vcxproj.filters\n*.tlog\n*.sln\n.settings\n.vscode\n.idea\n.vs\nbuild\ndist\nCMakeFiles\ncasparcg_server\n*.spv\n\nsrc/cmake-build-*\nsrc/.idea\n\n# debian build artifacts\n/debian\n/obj-*"
  },
  {
    "path": "BUILDING.md",
    "content": "# Building the CasparCG Server\n\nThe CasparCG Server source code uses the CMake build system in order to easily\ngenerate build systems for multiple platforms. CMake is basically a build\nsystem for generating build systems.\n\nOn Windows we can use CMake to generate a .sln file and .vcproj files. On\nLinux CMake can generate make files or ninja files. Qt Creator has support for\nloading CMakeLists.txt files directly.\n\n# Dependency caching\n\nCMake will automatically download some dependencies as part of the build process.\nThese are taken from https://github.com/CasparCG/dependencies/releases (make sure to expand the 'Assets' group under each release to see the files), most of which are direct copies of distributions from upstream.\n\nDuring the build, you can specify the CMake option `CASPARCG_DOWNLOAD_MIRROR` to download from an alternate HTTP server (such as an internally hosted mirror), or `CASPARCG_DOWNLOAD_CACHE` to use a specific path on disk for the local cache of these files, by default a folder called `external` will be created inside the build directory to cache these files.\n\nIf you want to be able to build CasparCG offline, you may need to manually seed this cache. You can do so by placing the correct tar.gz or zip into a folder and using `CASPARCG_DOWNLOAD_CACHE` to tell CMake where to find it.\nYou can figure out which files you need by looking at each of the `ExternalProject_Add` function calls inside of [Bootstrap_Linux.cmake](./src/CMakeModules/Bootstrap_Linux.cmake) or [Bootstrap_Windows.cmake](./src/CMakeModules/Bootstrap_Windows.cmake). Some of the ones listed are optional, depending on other CMake flags.\n\n# Windows\n\n## Building distributable\n\n1. Install Visual Studio 2022.\n\n2. Install 7-zip (https://www.7-zip.org/).\n\n3. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master`\n\n4. `cd casparcg-server-master`\n\n5. `.\\tools\\windows\\build.bat`\n\n6. Copy the `dist\\casparcg_server.zip` file for distribution\n\n## Development using Visual Studio\n\n1. Install Visual Studio 2022.\n\n2. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master`\n\n3. Open the cloned folder in Visual Studio.\n\n4. Build All and ensure it builds successfully\n\n# Linux\n\n## Building on your system\n\nWe only officially support Ubuntu LTS releases, other distros may work but often run into build issues. We are happy to accept PRs to resolve these issues, but are unlikely to write fixes ourselves.\n\nWe currently document two approaches to building CasparCG. The recommended way is to use the `deb` packaging we have in the repository, but we only provide that for Ubuntu LTS releases.\nOther deb based distros can work with some tweaks to one of those, other distros will need something else which is not documented here.\n\nWe also provide a script to produce a build in docker, but this is not recommended unless absolutely necessary. The resulting builds are often rather brittle depending on where they are used.\n\nTo perform a custom build, follow the Development steps below, and you may need to do some extra packaging steps, or install steps on the target systems.\n\n### Building inside Docker\n\n1. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master`\n2. `cd casparcg-server-master`\n3. `./tools/linux/build-in-docker`\n\nIf all goes to plan, a docker image `casparcg/server` has been created containing CasparCG Server.\n\n### Extracting CasparCG Server from Docker\n\n1. `./tools/linux/extract-from-docker`\n\nYou will then find a folder called `casparcg_server` which should contain everything you need to run CasparCG Server.\n\n_Note: if you ran docker with sudo, CasparCG server will not be able to run without sudo out of the box. For security reasons we do not recommend to run CasparCG with sudo. Instead you can use chown to change the ownership of the CasparCG Server folder._\n\n## Development\n\nBefore beginning, check the build options section below, to decide if you want to use any to simplify or customise your build.\n\n1. `git clone --single-branch --branch master https://github.com/CasparCG/server casparcg-server-master`\n2. `cd casparcg-server-master`\n3. Install dependencies, this can be done with `sudo ./tools/linux/install-dependencies`\n4. If using system CEF (default & recommended), `sudo add-apt-repository ppa:casparcg/ppa` and `sudo apt-get install casparcg-cef-142-dev`\n5. `mkdir build && cd build`\n6. `cmake ../src` You can add any of the build options from below to this command\n7. `cmake --build . --parallel`\n8. `cmake --install . --prefix staging`\n\nIf all goes to plan, a folder called 'staging' has been created with everything you need to run CasparCG server.\n\n## Build options\n\n-DENABLE_HTML=OFF - useful if you lack CEF, and would like to build without that module.\n\n-DUSE_STATIC_BOOST=ON - (Linux only, default OFF) statically link against Boost.\n\n-DUSE_SYSTEM_CEF=OFF - (Linux only, default ON) use the version of CEF from your OS. This expects to be using builds from https://launchpad.net/~casparcg/+archive/ubuntu/ppa\n\n-DENABLE_AVX2=ON (Linux only, default OFF) Enable the AVX and AVX2 instruction sets (requires a CPU that supports it)\n\n-DDIAG_FONT_PATH - Specify an alternate path/font to use for the DIAG window. On linux, this will often want to be set to an absolute path of a font\n\n-DCASPARCG_BINARY_NAME=casparcg-server - (Linux only) generate the executable with the specified name. This also reconfigures the install target to be a bit more friendly with system package managers.\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "CasparCG 2.5.0 Stable\n==========================================\n\n### Core\n##### Improvements\n* Initial support for HDR. This is limited to a subset of producers and consumers at this stage.\n* Build for Windows with VS2022\n* Rework linux builds to produce ubuntu deb files\n* Update ffmpeg to 7.0\n* Reimplement mixer transforms, to handle routes correctly\n* Support more pixel formats from ffmpeg, to preserve colour accuracy better\n* Support running on headless linux\n* Transitions: Additional behaviours\n##### Fixes\n* Build with boost 1.85/1.86/1.87/1.88\n* Build with ffmpeg 7.1\n* Only produce mixed frames on channels which have consumers\n* Routed channels not compositing correctly when channel used a MIXER KEY\n* Handle audio for fractional framerates properly\n* Gracefully exit on SIGINT and SIGTERM\n\n### Producers\n##### Improvements\n* FFmpeg: Support loading with a scaling-mode, to configure how clips get fit into the channel\n* FFmpeg: Support more pixel formats without cpu conversion\n* FFmpeg: Enable alpha for webm videos\n* Image: Support loading with a scaling-mode, to configure how images get fit into the channel\n* Image: Replace freeimage with ffmpeg\n* HTML: Update CEF to 142\n* HTML: Support audio\n##### Fixes\n* Route: Use full field rate when performing i->p channel route\n* HTML: Gracefully handle page load errors\n* HTML: Always set cache path\n\n### Consumers\n##### Improvements\n* Screen: Set size and position from AMCP\n* Screen: Improve performance\n* Image: Propagate AMCP parameters from PRINT command\n* FFmpeg: Remove unnecessary forced conversion to YUVA422\n* Decklink: Support explicit yuv output (requires AVX2)\n* Decklink: Allow selecting device by hardware persistent id\n\n##### Fixes\n* FFmpeg: Correctly handle PTS on frame drop\n\n\nCasparCG 2.4.3 Stable\n==========================================\n\n### Core\n##### Fixes\n* Improve error handling for invalid config files #1571\n* Flush logs before exit #1571\n* Check audio cadence values look sane before accepting format #1588\n* Cross-channel routes from progressive to interlaced showing lots of black #1576\n* Transition: ignoring some transforms of input frames #1602\n\n### Producers\n##### Fixes\n* FFmpeg: fix crash on invalid frame header\n* Decklink: Crash with ffmpeg 7 #1582\n* HTML: Fix crash during uninit on exit\n* Image: update state during init #1601\n\n### Consumers\n##### Fixes\n* FFmpeg: set frame_rate for rtmp streams #1462\n\n\nCasparCG 2.4.2 Stable\n==========================================\n\n### Consumers\n##### Fixes\n* Decklink: fix support for driver 14.3 and later\n\n\nCasparCG 2.4.1 Stable\n==========================================\n\n### Core\n##### Fixes\n* Fix bad config file examples\n* Fix `casparcg_auto_restart.bat` not starting scanner\n* Revert removal of tbbmalloc, due to notable performance loss on windows\n* Suppress some cmake build warnings\n* Build failure when doxygen installed on system\n* Build failures with ffmpeg 7.0\n* Revert RPATH linking changes\n\n### Producers\n##### Fixes\n* FFmpeg: Ignore ndi:// urls\n* FFmpeg: Using both in and seek could result in incorrect duration\n* Route: Race condition during destruction\n* Image: Update freeimage on windows with some CVE fixes and failures with certain pngs\n* Image: Respect EXIF rotate flag\n* NDI: list local sources\n\n### Consumers\n##### Fixes\n* Decklink: subregion copy not respecting frame height\n* Decklink: subregion vertical offset\n* Decklink: subregion height limited with some formats\n\n\nCasparCG 2.4.0 Stable\n==========================================\n\n### Core\n##### Improvements\n* Custom resolutions can be specified in casparcg.config\n* Interlaced mixer pipeline to ensure field accuracy\n* Preserve unicode characters in console input/output\n* Producers to be run at startup can be defined in casparcg.config\n* Support 8K frames\n* Support 4K DCI frames\n* Remove undocumented CII and CLK protocol implementations\n* Config parameter can be an absolute system path, not just relative to the working directory\n* AMCP: Add CLEAR ALL command\n* AMCP: Command batching syntax\n* AMCP: LOAD/LOADBG/PLAY commands accept a CLEAR_ON_404 parameter, to instruct the layer to be cleared when the requested file was not found\n* AMCP: Add commands to subscribe and unsubscribe to OSC on any port number\n* AMCP: Add CALLBG command to perform CALL on background producer\n* Build: Require C++17 for building\n* Build: Support newer versions of Boost\n* Build: Support newer versions of TBB\n* Build: Disable precompiled headers for linux\n* Build: Support VS2022\n* Build: Replace nuget and locally committed dependencies with direct http downloads\n* Build: Allow configuring diag font path at build time\n* Linux: Support setting thread priorities\n* Linux: Initial ARM64 compatibility\n* Linux: Rework build to always use system boost\n* Linux: Rework build process to better support being build as a system package\n* Logging: add config option to disable logging to file and to disable column alignment\n* Transitions: Support additional audio fade properties for STING transition\n##### Fixes\n* Crash upon exiting if HTML producer was running\n* AMCP: Ensure all consumers and producers are reported in `INFO` commands\n* AMCP: Deferred mixer operations were not being cleared after being applied\n* AMCP: `LOAD` command would show a frame or two of black while new producer was loading\n* OpenGL: Fix support for recent Linux drivers\n* Linux: Fix endless looping on stdin\n* Route: Fix error when clearing layer\n* Transitions: Fix wipe duration\n\n### Producers\n##### Improvements\n* Decklink: Require driver 11.0 or later\n* Decklink: Scale received frames on GPU\n* FFmpeg: Update to v5.1\n* FFmpeg: Improve performance\n* FFmpeg: Allow specifying both SEEK and IN for PLAY commands\n* HTML: Update to CEF 117\n* HTML: `CALL 1-10 RELOAD` to reload a renderer\n* HTML: Expose `cache-path` setting\n* NDI: Upgrade to NDI5\n* System Audio: Allow specifying output device to use\n##### Fixes\n* Decklink: Log spamming when using some input formats\n* FFmpeg: Prevent loading unreadable files\n* FFmpeg: Unable to play files with unicode filenames\n* FFmpeg: Don't lowercase filter parameters\n* FFmpeg: Support parameters with name containing a dash\n* HTML: media-stream permission denied\n* HTML: Expose angle backend config field, the best backend varies depending on the templates and machine\n* HTML: Crash when multiple iframes were loaded within a renderer\n* Image: Improve file loading algorithm to match the case insensitive and absolute path support already used by ffmpeg\n\n### Consumers\n##### Improvements\n* Artnet: New artnet consumer\n* Decklink: Configure device duplex modes in casparcg.config\n* Decklink: Output a subregion of the channel\n* Decklink: Add secondary outputs in a consumer, to ensure sync when used within a single card\n* iVGA: Remove consumer\n* NDI: Upgrade to NDI5\n##### Fixes\n* Decklink: Fix stutter when loading clips\n* FFmpeg: Fix RTMP streaming missing headers\n* NDI: dejitter\n\n\nCasparCG 2.3.3 LTS Stable\n==========================================\n\n### Producers\n##### Improvements\n* Image Scroll Producer: Ported from 2.1\n\n\nCasparCG 2.3.2 LTS Stable\n==========================================\n\n### Producers\n##### Fixes\n* Packages: Update TBB library to v2021.1.1 - fixes CPU and memory growth when deleting threads\n* FFmpeg: Fix possible deadlock leading to producer not being cleaned up correctly\n\n\nCasparCG 2.3.2 Beta\n==========================================\n\n### Producers\n##### Fixes\n* Packages: Update TBB library to v2021.1.1 - fixes CPU and memory growth when deleting threads\n* FFmpeg: Fix possible deadlock leading to producer not being cleaned up correctly\n\n\nCasparCG 2.3.1 Stable\n==========================================\n\n### Producers\n##### Fixes\n* Flash: Use proper file urls when loading templates, to allow it to work after Flash Player EOL\n* FFmpeg: Various HTTP playback improvements\n\n\nCasparCG 2.3.0 Stable\n==========================================\n\n### Producers\n##### Features\n* FFmpeg: Add more common file extensions to the supported list\n* NDI: Require minimum of NDI v4.0\n##### Fixes\n* HTML: Minimise performance impact on other producers\n\n\nCasparCG 2.3.0 RC\n==========================================\n\n### Producers\n##### Features\n* Flash: Disable by default, requires enabling in the config file\n* FFmpeg: Remove fixed thread limit to better auto select a number\n##### Fixes\n* Decklink: Downgrade severity of video-format not supported\n* FFmpeg: Correctly handle error codes. Ignore exit errors during initialisation\n* Route: Detect circular routes and break the loop\n\n### Consumers\n##### Features\n* Bluefish: Various improvmements including support for Kronos K8\n\n### General\n##### Fixes\n* Diag not reflecting channel videoformat changes\n\n\nCasparCG 2.3.0 Beta 1\n==========================================\n\n### Producers\n##### Features\n* Decklink: Detect and update input format when no format is specified in AMCP\n* Decklink: Improve performance (gpu colour conversion & less heavy deinterlacing when possible)\n* Decklink: `LOAD DECKLINK` will display live frames instead of black\n* FFmpeg: Update to 4.2.2\n* HTML: Better performance for gpu-enabled mode\n* HTML: `window.remove()` has been partially reimplemented\n* NDI: Native NDI producer\n* Route: Allow routing first frame of background producer\n* Route: zero delay routes when within a channel, with 1 frame when cross-channel\n* Transition: Add sting transitions\n* Add frames_left field to osc/info for progress towards autonext\n##### Fixes\n* Colour: parsing too much of amcp string as list of colours\n* FFmpeg: Always resample clips to 48khz\n* FFmpeg: Ensure frame time reaches the end of the clip\n* FFmpeg: RTMP stream playback\n* FFmpeg: SEEK and LENGTH parameters causing issues with AUTONEXT\n* FFmpeg: Ensure packets/frames after the decided end of the clip are not displayed\n* FFmpeg: Incorrect seek for audio when not 48khz\n* FFmpeg: Some cases where it would not be destroyed if playing a bad stream\n* HTML: unlikely but possible exception when handling frames\n* HTML: set autoplay-policy\n* HTML: animations being ticked too much\n* Route: Sending empty frame into a route would cause the destination to reuse the last frame\n\n### Consumers\n##### Features\n* Audio: Fix audio crackling\n* Audio: Fix memory leak\n* Bluefish: Various improvmements including supporting more channels and UHD.\n* NDI: Native NDI consumer\n* Screen: Add side by side key output\n* Screen: Add support for Datavideo TC-100/TC-200\n##### Fixes\n* Decklink: Tick channel at roughly consistent rate when running interlaced output\n* Possible crash when adding/removing consumers\n\n### General\n##### Features\n* Add mixer colour invert property\n* Restore `INFO CONFIG` and `INFO PATHS` commands\n* Linux: Update docker images to support running in docker (not recommended for production use)\n##### Fixes\n* NTSC audio cadence\n* Ignore empty lines in console input\n* Fix building with clang on linux\n* Fix building with vs2019\n* Better error when startup fails due to AMCP port being in use\n* Backslash is a valid trailing slash for windows\n\nCasparCG 2.2.0\n==========================================\n\nGeneral\n-------\n\n * C++14\n * Major refactoring, cleanup, optimization\n   and stability improvements.\n * Removed unmaintained documentation API.\n * Removed unmaintained program options API.\n * Removed unused frame age API.\n * Removed misc unused and/or unmaintained APIs.\n * Removed TCP logger.\n * Fixed memory leak in transition producer.\n * Removed PSD Producer (moved to 3.0.0).\n * Removed Text Producer (moved to 3.0.0).\n * Removed SyncTo consumer.\n * Removed channel layout in favor of 8 channel passthrough\n    and FFMPEG audio filters.\n * Major stability and performance improvements of GPU code.\n * Requires OpenGL 4.5.\n * Repo cleanup (>2GB => <100MB when cloning).\n * Misc cleanup and fixes.\n\nBuild\n-----\n * Linux build re done with Docker.\n * Windows build re done with Nuget.\n\nHTML\n----\n * Updated to Chromium 63 (Julusian).\n * Allow running templates from arbitrary urls (Julusian).\n\nDECKLINK\n--------\n * Fixed broken Linux.\n * Misc cleanup and fixes.\n * Complex FFMPEG filters (VF, AF).\n\nMIXER\n-----\n * Performance improvements.\n * Removed straight output (moved to 3.0.0).\n * Proper OpenGL pipelining.\n * Blend modes are always enabled.\n * Misc cleanup and fixes.\n * Removed CPU mixer.\n * Mixer always runs in progressive mode. Consumers are expected to convert to interlaced if required.\n\nIMAGE\n-----\n * Correctly apply alpha to base64 encoded pngs from AMCP (Julusian).\n * Unmultiply frame before writing to png (Julusian).\n * Removed scroll producer (moved to 3.0.0)\n\n ROUTE\n -----\n\n * Reimplemented, simplified.\n * Cross channel routing will render full stage instead of simply copying channel output.\n * Reduced overhead and latency.\n\nFFMPEG\n------\n * Rewritten from scratch for better accuracy, stability and\n    performance.\n * Update freezed frame during seeking.\n * FFMPEG 3.4.1.\n * Reduce blocking during initialization.\n * Fixed timestamp handling.\n * Fixed V/A sync.\n * Fixed interlacing.\n * Fixed framerate handling.\n * Fixed looping.\n * Fixed seeking.\n * Fixed duration.\n * Audio resampling to match timestamps.\n * Fixed invalid interlaced YUV (411, 420) handling.\n * Added YUV(A)444.\n * Added IO timeout.\n * Added HTTP reconnect.\n * FFMPEG video filter support.\n * FFMPEG audio filter support.\n * Complex FFMPEG filters (VF, AF).\n * CALL SEEK return actually sought value.\n * All AMCP options are based on channel format.\n * Misc improvements, cleanup and fixes.\n\nBluefish\n--------\n * Misc cleanup and fixes.\n\nOAL\n------------\n * Added audio sample compensation to avoid audio distortions\n    during time drift.\n * Misc cleanup and fixes.\n\nScreen\n---------------\n * Proper OpenGL pipelining.\n * Misc cleanup and fixes.\n\nAMCP\n----\n * Added PING command (Julusian).\n * Removed INFO commands in favor of OSC.\n * Moved CLS, CINF, TLS, FLS, TLS, THUMBNAIL implementations into\n    a separate NodeJS service which is proxied through\n    an HTTP API.\n * Misc cleanup and fixes.\n\nCasparCG 2.1.0 Next (w.r.t 2.1.0 Beta 2)\n==========================================\n\nGeneral\n-------\n\n * Removed asmlib dependency in favor of using standard library std::memcpy and\n    std::memset, because of better performance.\n\nCasparCG 2.1.0 Beta 2 (w.r.t 2.1.0 Beta 1)\n==========================================\n\nGeneral\n-------\n\n * Fail early with clear error message if configured paths are not\n    creatable/writable.\n * Added backwards compatibility (with deprecation warning) for using\n    thumbnails-path instead of thumbnail-path in casparcg.config.\n * Suppress the logging of full path names in stack traces so that only the\n    relative path within the source tree is visible.\n * General stability improvements.\n * Native thread id is now logged in Linux as well. Finally they are mappable\n    against INFO THREADS, ps and top.\n * Created automatically generated build number, so that it is easier to see\n    whether a build is newer or older than an other.\n * Changed configuration element mipmapping_default_on to mipmapping-default-on\n    for consistency with the rest of the configuration (Jesper Stærkær).\n * Handle stdin EOF as EXIT.\n * Added support for RESTART in Linux startup script run.sh.\n * Copy casparcg_auto_restart.bat into Windows releases.\n * Fixed bug with thumbnail generation when there are .-files in the media\n    folder.\n * Removed CMake platform specification in Linux build script\n    (Krzysztof Pyrkosz).\n * Build script for building FFmpeg for Linux now part of the repository.\n    Contributions during development (not w.r.t 2.1.0 Beta 1):\n   * Fix ffmpeg build dependencies on clean Ubuntu desktop amd64 14.04.3 or\n      higher (Walter Sonius).\n * Added support for video modes 2160p5000, 2160p5994 and 2160p6000\n    (Antonio Ruano Cuesta).\n * Fixed serious buffer overrun in FFmpeg logging code.\n\nConsumers\n---------\n\n * FFmpeg consumer:\n   * Fixed long overdue bug where HD material was always recorded using the\n      BT.601 color matrix instead of the BT.709 color matrix. RGB codecs like\n      qtrle was never affected but all the YCbCr based codecs were.\n   * Fixed bug in parsing of paths containing -.\n   * Fixed bugs where previously effective arguments like -pix_fmt were\n      ignored.\n   * Fixed bug where interlaced channels where not recorded correctly for\n      some codecs.\n * DeckLink consumer:\n   * Rewrote the frame hand-off between send() and ScheduledFrameCompleted() in\n      a way that hopefully resolves all dead-lock scenarios previously possible.\n * Bluefish consumer:\n   * Largely rewritten against newest SDK Driver 5.11.0.47 (Satchit Nambiar and\n      James Wise sponsored by Bluefish444):\n     * Added support for Epoch Neutron and Supernova CG. All current Epoch\n        cards are now supported.\n     * Added support for for multiple SDI channels per card. 1 to 4 channels\n        per Bluefish444 card depending on model and firmware.\n     * Added support for single SDI output, complementing existing external key\n        output support.\n     * Added support for internal key using the Bluefish444 hardware keyer.\n * Screen consumer:\n   * Fixed full screen mode.\n\nProducers\n---------\n\n * FFmpeg producer:\n   * Increased the max number of frames that audio/video can be badly\n      interleaved with (Dimitry Ishenko).\n   * Fixed bug where decoders sometimes requires more than one video packet to\n      decode the first frame.\n   * Added support for IN and OUT parameters (Dimitry Ishenko).\n   * Added DV/HDV video device support under Linux (Walter Sonius).\n   * Remove unused flags variable in queued_seek (Dimitry Ishenko).\n   * Now recognizes .ts files without probing contents (Ovidijus Striaukas).\n   * Fixed uninitialized value causing initial log printout to usually say that\n      clips are interlaced when they are not.\n * Destroy producer proxy:\n   * Created workaround for bug in FFmpeg where every new thread used to\n      cleanup caused handles to leak (not sure why). Reduced the effect by using\n      only one thread for all producer destructions.\n * Framerate producer:\n   * Fixed bug when INFO was used on a not yet playing framerate producer.\n * HTML producer:\n   * Fixed bug where only URL:s with . in them where recognized.\n * Image producer:\n   * Added LENGTH parameter to allow for queueing with LOADBG AUTO.\n   * Fixed inconsistency in what file extensions are supported vs listed in\n      CLS/CINF.\n * Layer producer:\n   * Fixed serious bug where a circular reference of layer producers caused a\n      stack overflow and server crash.\n   * Can now route from layer on a channel with an incompatible framerate.\n * Channel producer:\n   * Can now route from channel with an incompatible framerate.\n   * Deinterlaces interlaced content from source channel.\n   * Added optional NO_AUTO_DEINTERLACE parameter to opt out of the mentioned\n      deinterlacing.\n * Scene producer:\n   * Added abs(), floor(), to_lower(), to_upper() and length() functions to the\n      expression language.\n   * Created XML Schema for the *.scene XML format. Allows for IDE-like auto-\n      completion, API documentation and validation.\n   * Added possibility to specify the width and height of a layer instead of\n      letting the producer on the layer decide.\n   * Added global variables scene_width, scene_height and fps.\n   * Made it possible to use expressions in keyframe values.\n   * Fixed serious bug where uninitialized values were used.\n   * Created more example scenes.\n   * Can now forward CALL, CG PLAY, CG STOP, CG NEXT and CG INVOKE to the\n      producer on a layer.\n * CG proxy wrapper producer:\n   * New in 2.1.0.\n   * Allows all CG producers to be used as an ordinary producer inside a layer\n      in a scene.\n   * Allows the Scene producer to know what variables are available in a\n      template.\n * Color producer:\n   * Now has support for gradients.\n * PSD producer:\n   * Added support for centered and right justified text.\n * Text producer:\n   * Fixed bug where tracking contributed to the overall text width on the\n      last character.\n\nMixer\n-----\n\n * Fixed bug in the contrast/saturation/brightness code where the wrong luma\n    coefficients was used.\n * Rewrote the chroma key code to support variable hue, instead of fixed green\n    or blue. Threshold setting was removed in favour of separate hue width,\n    minimum saturation and minimum brightness constraints. Also a much more\n    effective spill suppression method was implemented.\n * Fixed bug where glReadPixels() was done from the last drawn to texture\n    instead of always from the target texture. This means that for example a\n    MIXER KEYER layer without a layer above to key, as well as a separate alpha\n    file with MIXER OPACITY 0 now works as expected.\n * Fixed bug where already drawn GL_QUADS were not composited against, causing\n    for example italic texts to be rendered incorrectly in the text_producer.\n\nAMCP\n----\n\n * INFO PATHS now adds all the path elements even if they are using the default\n    values.\n * MIXER CHROMA syntax deprecated (still supported) in favour of the more\n    advanced syntax required by the rewritten chroma key code.\n * Added special command REQ that can be prepended before any command to\n    identify the response with a client specified request id, allowing a client\n    to know exactly what asynchronous response matched a specific request.\n * Added support for listing contents of a specific directory for CLS, TLS,\n    DATA LIST and THUMBNAIL LIST.\n * Fixed bug where CINF only returned the first match.\n * Fixed bug where a client closing the connection after BYE instead of\n    letting the server close the connection caused an exception to be logged.\n\n\n\nCasparCG 2.1.0 Beta 1 (w.r.t 2.0.7 Stable)\n==========================================\n\nGeneral\n-------\n\n * 64 bit!\n * Linux support!\n   * Moved to CMake build system for better platform independence.\n     * Contributions before build system switch (not w.r.t 2.0.7 Stable):\n       * gitrev.bat adaptions for 2.1 (Thomas Kaltz III).\n   * Thanks to our already heavy use of the pimpl idiom, abstracting platform\n      specifics was easily done by having different versions of the .cpp files\n      included in the build depending on target platform. No #ifdef necessary,\n      except for in header only platform specific code.\n   * Flash, Bluefish and NewTek modules are not ported to the Linux build.\n   * Contributions during development (not w.r.t 2.0.7 Stable):\n     * Fixed compilation problems in Linux build (Dimitry Ishenko).\n     * Fixed compilation problem in GCC 5 (Krzysztof Pyrkosz).\n     * Fixed thumbnail image saving on Linux (Krzysztof Pyrkosz).\n     * Fixed compilation problem in PSD module (Krzysztof Pyrkosz).\n * Major code refactoring:\n   * Mixer abstraction so different implementations can be created. Currently\n      CPU mixer and GPU mixer (previously the usage of the GPU was mandatory)\n      exists.\n   * Flattened folder structure for easier inclusion of header files.\n   * Many classes renamed to better describe the abstractions they provide.\n   * Sink parameters usually taken by value and moved into place instead of\n      taken by const reference as previously done.\n   * Old Windows specific AsyncEventServer class has been replaced by platform\n      independent implementation based on Boost.Asio.\n   * Pimpl classes are now stack allocated with internal shared_ptr to\n      implementation, instead of both handle and body being dynamically\n      allocated. This means that objects are now often passed by value instead\n      of via safe_ptr/shared_ptr, because they are internally reference counted.\n   * Protocol strategies are now easier to implement correctly, because of\n      separation of state between different client connections.\n   * Complete AMCP command refactoring.\n   * On-line help system that forces the developer to document AMCP commands,\n      producer syntaxes and consumer syntaxes making the documentation coupled\n      to the code, which is great.\n     * Added missing help for VERSION command (Jesper Stærkær).\n   * Upgraded Windows build to target Visual Studio 2015 making it possible to\n      use the C++11 features also supported by GCC 4.8 which is targeted on\n      Linux.\n     * Fixed compilation problems in Visual Studio 2015 Update 1\n        (Roman Tarasov)\n   * Created abstraction of the different forms of templates (flash, html, psd\n      and scene). Each module registers itself as a CG producer provides. All CG\n      commands transparently works with all of them.\n   * Audio mixer now uses double samples instead of float samples to fully\n      accommodate all int32 samples.\n   * Reduced coupling between core and modules (and modules and modules):\n     * Modules can register system info providers to contribute to INFO SYSTEM.\n     * XML configuration factories for adding support for new consumer elements\n        in casparcg.config.\n     * Server startup hooks can be registered (used by HTML producer to fork\n        its sub process).\n     * Version providers can contribute content to the VERSION command.\n * Refactored multichannel audio support to use FFmpeg's PAN filter and\n    simplified the configuration a lot.\n * Upgraded most third party libraries we depend on.\n * Some unit tests have been created.\n * Renamed README.txt to README, CHANGES.txt to CHANGELOG and LICENSE.txt to\n    LICENSE\n * Created README.md for github front page in addition to README which is\n    distributed with builds.\n * README file updates (Jonas Hummelstrand).\n * Created BUILDING file describing how to build the server on Windows and\n    Linux.\n * Diagnostics:\n   * Now also sent over OSC.\n   * Diag window is now scrollable and without squeezing of graphs.\n   * Contextual information such as video channel and video layer now included\n      in graphs.\n * Logging:\n   * Implemented a TCP server, simply sending every log line to each connected\n      client. Default port is 3250.\n   * Changed default log level to info and moved debug statements that are\n      interesting in a production system to info.\n   * Try to not log full stack traces when user error is the cause. Stacktraces\n      should ideally only be logged when a system error or a programming error\n      has occurred.\n   * More contextual information about an error added to exceptions. An example\n      of this is that XML configuration errors now cause the XPath of the error\n      is logged.\n   * Improved the readability of the log format.\n   * Added optional calltrace.log for logging method calls. Allows for trace\n      logging to be enabled while calltracing is disabled etc.\n\nOSC\n---\n\n * Improved message formatting performance.\n * Added possibility to disable sending OSC to connected AMCP clients.\n * Fixed inconsistent element name predefined_client to predefined-client in\n    casparcg.config (Krzysztof Pyrkosz).\n\nConsumers\n---------\n\n * System audio consumer:\n   * Pushes data to openal instead of being callbacked by SFML when data is\n      needed.\n   * Added possibility to specify the expected delay in the sound card. Might\n      help get better consumer synchronization.\n * Screen consumer:\n   * Added mouse interaction support, usable by the producers running on the\n      video channel.\n * FFmpeg consumer:\n   * Replaced by Streaming Consumer after it was adapted to support everything\n      that FFmpeg Consumer did.\n   * Added support for recording all audio channels into separate mono audio\n      streams.\n   * Now sends recording progress via OSC.\n * SyncTo consumer:\n   * New in 2.1.0.\n   * Allows the pace of a channel to follow another channel. This is useful for\n      virtual \"precomp\" channels without a DeckLink consumer to pace it.\n * DeckLink consumer:\n   * Added workaround for timescale bug found in Decklink SDK 10.7.\n   * Now ScheduledFrameCompleted is no longer only used for video scheduling\n      but for audio as well, simplifying the code a lot.\n * iVGA consumer:\n   * No longer provides sync to the video channel.\n   * Supports NewTek NDI out of the box just by upgrading the\n      Processing.AirSend library.\n\nProducers\n---------\n\n * Scene producer:\n   * New in 2.1.0.\n   * Utilizes CasparCG concepts such as producers, mixer transforms and uses\n      them in a nested way to form infinite number of sub layers. Think movie\n      clip in Flash.\n   * A scene consists of variables, layers, timelines and marks (intro and\n      outro for example).\n   * Mostly for use by other producers but comes with a XML based producer that\n      is a registered CG producer and shows up in TLS.\n   * Enables frame accurate compositions and animations.\n   * Has a powerful variable binding system (think expressions in After Effects\n      or JavaFX Bindings).\n * PSD producer:\n   * New in 2.1.0.\n   * Parses PSD files and sets up a scene for the Scene producer to display.\n   * Text layers based on CG parameters.\n   * Supports Photoshop timeline.\n   * Uses Photoshop comment key-frames to describe where intro and outro (CG\n      PLAY and CG STOP) should be in the timeline.\n   * Shows up as regular templates in TLS.\n * Text producer:\n   * New in 2.1.0.\n   * Renders text using FreeType library.\n   * Is used by the PSD producer for dynamic text layers.\n * Image scroll producer:\n   * Speed can be changed while running using a CALL. The speed change can be\n      tweened.\n   * Added support for an absolute end time so that the duration is calculated\n      based on when PLAY is called for shows when an exact end time is\n      important.\n * Image producer:\n   * Fixed bug where too large (OpenGL limit) images were accepted, causing\n      problems during thumbnail generation.\n * Framerate producer:\n   * New in 2.1.0.\n   * Wraps a producer with one framerate and converts it to another. It is not\n      usable on its own but is utilized in the FFmpeg producer and the DeckLink\n      consumer.\n   * Supports different interpolation algorithms. Currently a no-op\n      drop-and-repeat mode and a two different frame blending modes.\n   * It also supports changing the speed on demand with tweening support.\n * FFmpeg producer:\n   * Supports decoding all audio streams from a clip. Useful with .mxf files\n      which usually have separate mono streams for every audio channel.\n   * No longer do framerate conversion (half or double), but delegates that\n      task to the Framerate producer.\n   * Added support for v4l2 devices.\n   * Added relative and \"from end\" seeking (Dimitry Ishenko).\n   * Contributions during development (not w.r.t 2.0.7 Stable):\n     * Fixed 100% CPU problem on clip EOF (Peter Keuter, Robert Nagy).\n     * Constrained SEEK within the length of a clip (Dimitry Ishenko).\n     * Fixed a regular expression (Dimitry Ishenko).\n * DeckLink producer:\n   * No longer do framerate conversion (half or double), but delegates that\n      task to the Framerate producer.\n * Route producer:\n   * Added possibility to delay frames routed from a layer or a channel.\n * HTML Producer:\n   * Disabled web security in HTML Producer (Robert Nagy).\n   * Reimplemented requestAnimationFrame handling in Javascript instead of C++.\n   * Implemented cancelAnimationFrame.\n   * Increased animation smoothness in HTML Producer with interlaced video\n      modes.\n   * Added remote debugging support.\n   * Added mouse interaction support by utilizing the Screen consumer's new\n      interaction support.\n * Flash Producer:\n   * Contributions during development (not w.r.t 2.0.7 Stable):\n     * Workaround for flickering with high CPU usage and CPU accelerator\n        (Robert Nagy)\n\nAMCP\n----\n\n * TLS has a new column for \"template type\" for clients that want to\n    differentiate between html and flash for example.\n * SET CHANNEL_LAYOUT added to be able to change the audio channel layout of a\n    video channel at runtime.\n * HELP command added for accessing the new on-line help system.\n * FLS added to list the fonts usable by the Text producer.\n * LOCK command added for controlling/gaining exclusive access to a video\n    channel.\n * LOG CATEGORY command added to enable/disable the new log categories.\n * SWAP command now optionally supports swapping the transforms as well as the\n    layers.\n * VERSION command can now provide CEF version.\n\n\n\nCasparCG Server 2.0.7 Stable (as compared to CasparCG Server 2.0.7 Beta 2)\n==========================================================================\n\nGeneral\n-------\n\n * Added support for using a different configuration file at startup than the\n    default casparcg.config by simply adding the name of the file to use as the\n    first command line argument to casparcg.exe.\n * Upgraded FFmpeg to latest stable.\n * Created build script.\n * Fixed bug where both layer_producer and channel_producer display:s and\n    empty/late first frame when the producer is called before the consumer in\n    the other end has received the first frame.\n * Added rudimentary support for audio for layer_producer and channel_producer.\n * Upgraded DeckLink SDK to 10.1.4, bringing new 2K and 4K DCI video modes. New\n    template hosts also available for those modes.\n * General bug fixes (mostly memory and resource leaks, some serious).\n * Updated Boost to version 1.57\n * Frontend no longer maintained and therefore not included in the release.\n\nMixer\n-----\n\n * Added support for rotation.\n * Added support for changing the anchor point around which fill_translation,\n    fill_scale and rotation will be done from.\n * Added support for perspective correct corner pinning.\n * Added support for mipmapped textures with anisotropic filtering for\n    increased downscaling quality. Whether to enable by default can be\n    configured in casparcg.config.\n * Added support for cropping a layer. Not the same as clipping.\n\nAMCP\n----\n\n * Added RESUME command to complement PAUSE. (Peter Keuter)\n * To support the new mixer features the following commands has been added:\n\n   * MIXER ANCHOR -- will return or modify the anchor point for a layer\n      (default is 0 0 for backwards compatibility). Example:\n      MIXER 1-10 ANCHOR 0.5 0.5\n      ...for changing the anchor to the middle of the layer\n      (a MIXER 1-10 FILL 0.5 0.5 1 1 will be necessary to place the layer at the\n      same place on screen as it was before).\n\n   * MIXER ROTATION -- will return or modify the angle of which a layer is\n      rotated by (clockwise degrees) around the point specified by ANCHOR.\n\n   * MIXER PERSPECTIVE -- will return or modify the corners of the perspective\n      transformation of a layer. One X Y pair for each corner (order upper left,\n      upper right, lower right and lower left). Example:\n      MIXER 1-10 PERSPECTIVE 0.4 0.4 0.6 0.4 1 1 0 1\n\n   * MIXER MIPMAP -- will return or modify whether to enable mipmapping of\n      textures produced on a layer. Only frames produced after a change will be\n      affected. So for example image_producer will not be affected while the\n      image is displayed.\n\n   * MIXER CROP -- will return or modify how textures on a layer will be\n      cropped. One X Y pair each for the upper left corner and for the lower\n      right corner.\n\n * Added INFO QUEUES command for debugging AMCP command queues. Useful for\n    debugging command queue overflows, where a command is deadlocked. Hopefully\n    always accessible via console, even though the TCP command queue may be\n    full.\n * Added GL command:\n    - GL INFO prints information about device buffers and host buffers.\n    - GL GC garbage collects pooled but unused GL resources.\n * Added INFO THREADS command listing the known threads and their descriptive\n    names. Can be matched against the thread id column of log entries.\n\nConsumers\n---------\n\n * Removed blocking_decklink_consumer. It was more like an experiment at best\n    and its usefulness was questionable.\n * Added a 10 second time-out for consumer sends, to detect/recover from\n    blocked consumers.\n * Some consumers which are usually added and removed during playout (for\n    example ffmpeg_consumer, streaming_consumer and channel_consumer) no longer\n    affect the presentation time on other consumers. Previously a lag on the SDI\n    output could be seen when adding such consumers.\n\nHTML producer\n-------------\n\n * No longer tries to play all files with a . in their name.\n    (Georgi Chorbadzhiyski)\n * Reimplemented using CEF3 instead of Berkelium, which enables use of WebGL\n    and more. CEF3 is actively maintained, which Berkelium is not. (Robert Nagy)\n * Implements a custom version of window.requestAnimationFrame which will\n    follow the pace of the channel, for perfectly smooth animations.\n * No longer manually interlaces frames, to allow for mixer fill transforms\n    without artifacts.\n * Now uses CEF3 event loop to avoid 100% CPU core usage.\n\n\n\nCasparCG Server 2.0.7 Beta 2 (as compared to CasparCG Server 2.0.7 Beta 1)\n==========================================================================\n\nGeneral\n-------\n\n * Added sending of OSC messages for channel_grid channel in addition to\n    regular channels.\n\nProducers\n---------\n\n * FFmpeg: Reports correct nb_frames() when using SEEK (Thomas Kaltz III)\n * Flash: Fixed bug where CG PLAY, CG INVOKE did not work.\n\nConsumers\n---------\n\n * channel_consumer: Added support for more than one channel_consumer per\n    channel.\n * decklink_consumer: Added support for a single instance of the consumer to\n    manage a separate key output for use with DeckLink Duo/Quad cards:\n\n    <decklink>\n      <device>1</device>\n      <key-device>2</key-device>\n      <keyer>external_separate_device</keyer>\n    </decklink>\n\n    ...in the configuration will enable the feature. The value of <key-device />\n    defaults to the value of <device /> + 1.\n * synchronizing_consumer: Removed in favour of a single decklink_consumer\n    managing both fill and key device.\n * streaming_consumer: A new implementation of ffmpeg_consumer with added\n    support for streaming and other PTS dependent protocols. Examples:\n\n    <stream>\n      <path>udp://localhost:5004</path>\n      <args>-vcodec libx264 -tune zerolatency -preset ultrafast -crf 25 -format mpegts -vf scale=240:180</args>\n    </stream>\n\n    ...in configuration or:\n\n    ADD 1 STREAM udp://localhost:5004 -vcodec libx264 -tune zerolatency -preset ultrafast -crf 25 -format mpegts -vf scale=240:180\n\n    ...via AMCP. (Robert Nagy sponsored by Ericsson Broadcasting Services)\n * newtek_ivga_consumer: Added support for iVGA consumer to not provide channel\n    sync even though connected. Useful for iVGA clients that downloads as fast\n    as possible instead of in frame-rate pace, like Wirecast. To enable:\n\n    <newtek-ivga>\n      <provide-sync>false</provide-sync>\n    </newtek-ivga>\n\n    ...in config to not provide channel sync when connected. The default is\n    true.\n\nAMCP\n----\n\n * Added support in ADD and REMOVE for a placeholder <CLIENT_IP_ADDRESS> which\n    will resolve to the connected AMCP client's IPV4 address.\n * Fixed bug where AMCP commands split into multiple TCP packets where not\n    correctly parsed (http://casparcg.com/forum/viewtopic.php?f=3&t=2480)\n\n\n\nCasparCG Server 2.0.7 Beta 1 (as compared to 2.0.6 Stable)\n==========================================================\n\nGeneral\n-------\n * FFmpeg: Upgraded to master and adapted CasparCG to FFmpeg API changes\n    (Robert Nagy sponsored by SVT)\n * FFmpeg: Fixed problem with frame count calculation (Thomas Kaltz III)\n * Fixed broken CG UPDATE.\n\nProducers\n---------\n\n * New HTML producer has been created (Robert Nagy sponsored by Flemish Radio\n    and Television Broadcasting Organization, VRT)\n\n\n\nCasparCG Server 2.0.6 Stable (as compared to 2.0.4 Stable)\n==========================================================\n\nGeneral\n-------\n * iVGA: Allow for the server to work without Processing.AirSend.x86.dll to\n    prevent a possible GPL violation. It is available as a separate optional\n    download.\n * iVGA: Only provide sync to channel while connected, to prevent channel\n    ticking too fast.\n * FFmpeg: Fixed bug during deinterlace-bob-reinterlace where output fields\n    were offset by one field in relation to input fields.\n * FFmpeg: Fixed bug in ffmpeg_consumer where an access violation occurred\n    during destruction.\n * FFmpeg: Improved seeking. (Robert Nagy and Thomas Kaltz III)\n * Frontend: Only writes elements to casparcg.config which overrides a default\n    value to keep the file as compact as possible.\n * System audio: Patched sfml-audio to work better with oal-consumer and\n    therefore removed PortAudio as the system audio implementation and went back\n    to oal.\n * Flash: Changed so that the initial buffer fill of frames is rendered at a\n    frame-duration pace instead of as fast as possible. Otherwise time based\n    animations render incorrectly. During buffer recovery, a higher paced\n    rendering takes place, but still not as fast as possible, which can cause\n    animations to be somewhat incorrectly rendered. This is the only way though\n    if we want the buffer to be able to recover after depletion.\n * Fixed race condition during server shutdown.\n * OSC: outgoing audio levels from the audio mixer for each audio channel is\n    now transmitted (pFS and dBFS). (Thomas Kaltz III)\n * Stage: Fixed bug where tweened transforms were only ticked when a\n    corresponding layer existed.\n * Screen consumer: Added borderless option and correct handling of name\n    option. (Thomas Kaltz III)\n * AMCP: CLS now reports duration and framerate for MOVIE files were\n    information is possible to extract. (Robert Nagy)\n * Version bump to keep up with CasparCG Client version.\n\n\n\nCasparCG Server 2.0.4 Stable (as compared to 2.0.4 Beta 1)\n==========================================================\n\nGeneral\n-------\n * Can now open media with file names that only consist of digits.\n    (Cambell Prince)\n * Miscellaneous stability and performance improvements.\n\nVideo mixer\n-----------\n * Conditional compilation of chroma key support and straight alpha output\n    support in shader (just like with blend-modes) because of performance impact\n    even when not in use on a layer or on a channel. New <mixer /> element added\n    to configuration for turning on mixer features that not everybody would want\n    to pay for (performance-wise.) blend-modes also moved into this element.\n * Fixed bug where MIXER LEVELS interpreted arguments in the wrong order, so\n    that gamma was interpreted as max_input and vice versa.\n\nConsumers\n---------\n * Added support for NewTek iVGA, which enables the use of CasparCG Server\n    fill+key output(s) as input source(s) to a NewTek TriCaster without\n    requiring video card(s) in the CasparCG Server machine, or taking up inputs\n    in the TriCaster. <newtek-ivga /> element in config enables iVGA on a\n    channel. (Robert Nagy sponsored by NewTek)\n * DeckLink: Created custom decklink allocator to reduce the memory footprint.\n * Replaced usage of SFML for <system-audio /> with PortAudio, because of\n    problems with SFML since change to static linkage. Also PortAudio seems to\n    give lower latency.\n\nProducers\n---------\n * FFmpeg: Added support for arbitrary FFmpeg options/parameters\n    in ffmpeg_producer. (Cambell Prince)\n * Flash: Flash Player 11.8 now tested and fully supported.\n * Flash: No longer starts a Flash Player to service CG commands that mean\n    nothing without an already running Flash Player.\n * Flash: globally serialize initialization and destruction of Flash Players,\n    to avoid race conditions in Flash.\n * Flash: changed so that the Flash buffer is filled with Flash Player\n    generated content at initialization instead of empty frames.\n\nOSC\n---\n * Performance improvements. (Robert Nagy sponsored by Boffins Technologies)\n * Never sends old values to OSC receivers. Collects the latest value of each\n    path logged since last UDP send, and sends the new UDP packet (to each\n    subscribing OSC receiver) with the values collected. (Robert Nagy sponsored\n    by Boffins Technologies)\n * Batches as many OSC messages as possible in an OSC bundle to reduce the\n    number of UDP packets sent. Breakup into separate packages if necessary to\n    avoid fragmentation. (Robert Nagy sponsored by Boffins Technologies)\n * Removed usage of Microsoft Agents library (Server ran out of memory after a\n    while) in favour of direct synchronous invocations.\n\n\n\nCasparCG Server 2.0.4 Beta 1 (as compared to 2.0.3 Stable)\n==========================================================\n\nGeneral\n-------\n * Front-end GUI for simplified configuration and easy access to common tasks.\n    (Thomas Kaltz III and Jeff Lafforgue)\n * Added support for video and images file thumbnail generation. By default the\n    media directory is scanned every 5 seconds for new/modified/removed files\n    and thumbnails are generated/regenerated/removed accordingly.\n * Support for new video modes: 1556p2398, 1556p2400, 1556p2500, 2160p2398,\n    2160p2400, 2160p2500, 2160p2997 and 2160p3000.\n * Experimental ATI graphics card support by using static linking against SFML\n    instead of dynamic. Should improve ATI GPU support, but needs testing.\n * Added support for playback and pass-through of up to 16 audio channels. See\n    http://casparcg.com/forum/viewtopic.php?f=3&t=1453 for more information.\n * Optimizations in AMCP protocol implementations for large incoming messages,\n    for example base64 encoded PNG images.\n * Logging output now includes milliseconds and has modified format:\n    YYYY-MM-DD hh:mm:ss.zzz\n * Improved audio playback with 720p5994 and 720p6000 channels.\n * An attempt to improve output synchronization of consumers has been made. Use\n    for example:\n\n    <consumers>\n      <synchronizing>\n        <decklink>\n          <device>1</device>\n          <embedded-audio>true</embedded-audio>\n        </decklink>\n        <decklink>\n          <device>2</device>\n          <key-only>true</key-only>\n        </decklink>\n      </synchronizing>\n    </consumers>\n\n    ...to instruct the server to keep both DeckLink consumers in sync with each\n    other. Consider this experimental, so don't wrap everything in\n    <synchronizing /> unless synchronization of consumer outputs is needed. For\n    synchronization to be effective all synchronized cards must have genlock\n    reference signal connected.\n * Transfer of source code and issue tracker to github. (Thomas Kaltz III)\n\nLayer\n-----\n * Fixed a problem where the first frame was not always shown on LOAD.\n    (Robert Nagy)\n\nStage\n-----\n\n * Support for layer consumers for listening to frames coming out of producers.\n    (Cambell Prince)\n\nAudio mixer\n-----------\n * Added support for a master volume mixer setting for each channel.\n\nVideo mixer\n-----------\n * Added support for chroma keying. (Cambell Prince)\n * Fixed bug where MIXER CONTRAST set to < 1 can cause transparency issues.\n * Experimental support for straight alpha output.\n\nConsumers\n---------\n * Avoid that the FFmpeg consumer blocks the channel output when it can't keep\n    up with the frame rate (drops frames instead).\n * Added support for to create a separate key and fill file when recording with\n    the FFmpeg consumer. Add the SEPARATE_KEY parameter to the FFmpeg consumer\n    parameter list. The key file will get the _A file name suffix to be picked\n    up by the separated_producer when doing playback.\n * The Image consumer now writes to the media folder instead of the data\n    folder.\n * Fixed bug in DeckLink consumer where we submit too few audio samples to the\n    driver when the video format has a frame rate > 50.\n * Added another experimental DeckLink consumer implementation where scheduled\n    playback is not used, but a similar approach as in the bluefish consumer\n    where we wait for a frame to be displayed and then display the next frame.\n    It is configured via a <blocking-decklink> consumer element. The benefits of\n    this consumer is lower latency and more deterministic synchronization\n    between multiple instances (should not need to be wrapped in a\n    <synchronizing> element when separated key/fill is used).\n\nProducers\n---------\n * Added support for playing .swf files using the Flash producer. (Robert Nagy)\n * Image producer premultiplies PNG images with their alpha.\n * Image producer can load a PNG image encoded as base64 via:\n    PLAY 1-0 [PNG_BASE64] <base64 string>\n * FFmpeg producer can now use a directshow input filters:\n    PLAY 1-10 \"dshow://video=Some Camera\"\n    (Cambell Prince, Julian Waller and Robert Nagy)\n * New layer producer which directs the output of a layer to another layer via\n    a layer consumer. (Cambell Prince)\n\nAMCP\n----\n * The master volume feature is controlled via the MASTERVOLUME MIXER\n    parameter. Example: MIXER 1 MASTERVOLUME 0.5\n * THUMBNAIL LIST/RETRIEVE/GENERATE/GENERATE_ALL command was added to support\n    the thumbnail feature.\n * ADD 1 FILE output.mov SEPARATE_KEY activates the separate key feature of the\n    FFmpeg consumer creating an additional output_a.mov containing only the key.\n * Added KILL command for shutting down the server without console access.\n * Added RESTART command for shutting down the server in the same way as KILL\n    except that the return code from CasparCG Server is 5 instead of 0, which\n    can be used by parent process to take other actions. The\n    'casparcg_auto_restart.bat' script restarts the server if the return code is\n    5.\n * DATA RETRIEVE now returns linefeeds encoded as an actual linefeed (the\n    single character 0x0a) instead of the previous two characters:\n    \\ followed by n.\n * MIXER CHROMA command added to control the chroma keying. Example:\n    MIXER 1-1 CHROMA GREEN|BLUE 0.10 0.04\n    (Cambell Prince)\n * Fixed bug where MIXER FILL overrides any previous MIXER CLIP on the same\n    layer. The bug-fix also has the side effect of supporting negative scale on\n    MIXER FILL, causing the image to be flipped.\n * MIXER <ch> STRAIGHT_ALPHA_OUTPUT added to control whether to output straight\n    alpha or not.\n * Added INFO <ch> DELAY and INFO <ch>-<layer> DELAY commands for showing some\n    delay measurements.\n * PLAY 1-1 2-10 creates a layer producer on 1-1 redirecting the output of\n    2-10. (Cambell Prince)\n\nOSC\n---\n * Support for sending OSC messages over UDP to either a predefined set of\n    clients (servers in the OSC sense) or dynamically to the ip addresses of the\n    currently connected AMCP clients.\n    (Robert Nagy sponsored by Boffins Technologies)\n * /channel/[1-9]/stage/layer/[0-9]\n   * always             /paused           [paused or not]\n   * color producer     /color            [color string]\n   * ffmpeg producer    /profiler/time    [render time]     [frame duration]\n   * ffmpeg producer    /file/time        [elapsed seconds] [total seconds]\n   * ffmpeg producer    /file/frame       [frame]           [total frames]\n   * ffmpeg producer    /file/fps         [fps]\n   * ffmpeg producer    /file/path        [file path]\n   * ffmpeg producer    /loop             [looping or not]\n   * during transitions /transition/frame [current frame]   [total frames]\n   * during transitions /transition/type  [transition type]\n   * flash producer     /host/path        [filename]\n   * flash producer     /host/width       [width]\n   * flash producer     /host/height      [height]\n   * flash producer     /host/fps         [fps]\n   * flash producer     /buffer           [buffered]        [buffer size]\n   * image producer     /file/path        [file path]\n\n\n\nCasparCG Server 2.0.3 Stable (as compared to 2.0.3 Alpha)\n=========================================================\n\nStage\n-----\n\n * Fixed dead-lock that can occur with multiple mixer tweens. (Robert Nagy)\n\nAMCP\n----\n\n * DATA STORE now supports creating folders of path specified if they does not\n    exist. (Jeff Lafforgue)\n * DATA REMOVE command was added. (Jeff Lafforgue)\n\n\n\nCasparCG Server 2.0.3 Alpha (as compared to 2.0 Stable)\n=======================================================\n\nGeneral\n-------\n\n * Data files are now stored in UTF-8 with BOM. Latin1 files are still\n    supported for backwards compatibility.\n * Commands written in UTF-8 to log file but only ASCII characters to console.\n * Added supported video formats:\n   * 720p2398 (not supported by DeckLink)\n   * 720p2400 (not supported by DeckLink)\n   * 1080p5994\n   * 1080p6000\n   * 720p30 (not supported by DeckLink)\n   * 720p29.976 (not supported by DeckLink)\n\nCLK\n---\n\n * CLK protocol implementation can now serve more than one connection at a time\n    safely.\n * Added timeline support to the CLK protocol.\n * Refactored parts of the CLK parser implementation.\n\nConsumers\n---------\n\n * Consumers on same channel now invoked asynchronously to allow for proper\n    sync of multiple consumers.\n * System audio consumer:\n   * no longer provides sync to the video channel.\n * Screen consumer:\n   * Support for multiple screen consumers on the same channel\n   * No longer spin-waits for vsync.\n   * Now deinterlaces to two separate frames so for example 50i will no longer\n      be converted to 25p but instead to 50p for smooth playback of interlaced\n      content.\n * DeckLink consumer now logs whether a reference signal is detected or not.\n\nProducers\n---------\n\n * Image scroll producer:\n   * Field-rate motion instead of frame-rate motion with interlaced video\n      formats. This can be overridden by giving the PROGRESSIVE parameter.\n   * SPEED parameter now defines pixels per frame/field instead of half pixels\n      per frame. The scrolling direction is also reversed so SPEED 0.5 is the\n      previous equivalent of SPEED -1. Movements are done with sub-pixel\n      accuracy.\n   * Fixed incorrect starting position of image.\n   * Rounding error fixes to allow for more exact scrolling.\n   * Added support for motion blur via a new BLUR parameter\n   * Added PREMULTIPLY parameter to support images stored with straight alpha.\n\n\n\nCasparCG Server 2.0 Stable (as compared to Beta 3)\n==================================================\n\nGeneral\n-------\n\n * Misc stability and performance fixes.\n\nConsumers\n---------\n\n * File Consumer\n   * Changed semantics to more closely follow FFmpeg (see forums).\n   * Added options, -r, -acodec, -s, -pix_fmt, -f and more.\n * Screen Consumer\n   * Added vsync support.\n\n\n\nCasparCG Server 2.0 Beta 3 (as compared to Beta 1)\n==================================================\n\nFormats\n-------\n\n * ProRes Support\n   * Both encoding and decoding.\n * NTSC Support\n   * Updated audio-pipeline for native NTSC support. Previous implementation\n      did not fully support NTSC audio and could cause incorrect behaviour or\n      even crashes.\n\nConsumers\n---------\n\n * File Consumer added\n   * See updated wiki or ask in forum for more information.\n   * Should support anything FFmpeg supports. However, we will work mainly with\n      DNxHD, PRORES and H264.\n    - Key-only is not supported.\n * Bluefish Consumer\n   * 24 bit audio support.\n    - Embedded-audio does not work with Epoch cards.\n * DeckLink Consumer\n   * Low latency enabled by default.\n   * Added graphs for driver buffers.\n * Screen Consumer\n   * Changed screen consumer square PAL to the more common wide-square PAL.\n   * Can now be closed.\n   * Fixed interpolation artifacts when running non-square video-modes.\n   * Automatically deinterlace interlaced input.\n\nProducers\n---------\n\n * DeckLink Producer\n   * Improved color quality be avoiding unnecessary conversion to BGRA.\n * FFMPEG Producer\n   * Fixed missing alpha for (RGB)A formats when deinterlacing.\n   * Updated buffering to work better with files with long audio/video\n      interleaving.\n   * Seekable while running and after reaching EOF. CALL 1-1 SEEK 200.\n   * Enable/disable/query looping while running. CALL 1-1 LOOP 1.\n   * Fixed bug with duration calculation.\n   * Fixed bug with fps calculation.\n   * Improved auto-transcode accuracy.\n   * Improved seeking accuracy.\n   * Fixed bug with looping and LENGTH.\n   * Updated to newer FFmpeg version.\n   * Fixed incorrect scaling of NTSC DV files.\n   * Optimized color conversion when using YADIF filters.\n * Flash Producer\n   * Release Flash Player when empty.\n   * Use native resolution TemplateHost.\n   * TemplateHosts are now chosen automatically if not configured. The\n      TemplateHost with the corresponding video-mode name is now chosen.\n   * Use square pixel dimensions.\n\nAMCP\n----\n\n * When possible, commands will no longer wait for rendering pipeline. This\n    reduces command execution latencies, especially when sending a lot of\n    commands in a short timespan.\n * Fixed CINF command.\n * ADD/REMOVE no longer require subindex,\n    e.g. \"ADD 1 SCREEN\" / \"REMOVE 1 SCREEN\" instead of \"ADD 1-1 SCREEN\" / ...\n * PARAM is renamed to CALL.\n * STATUS command is replaced by INFO.\n * INFO command has been extended:\n   * INFO (lists channels).\n   * INFO 1 (channel info).\n   * INFO 1-1 (layer info).\n   * INFO 1-1 F (foreground producer info).\n   * INFO 1-1 B (background producer info).\n   * INFO TEMPLATE mytemplate (template meta-data info, e.g. field names).\n * CG INFO command has been extended.\n   * CG INFO 1 (template-host information, e.g. what layers are occupied).\n\nMixer\n-----\n\n * Fixed alpha with blend modes.\n * Automatically deinterlace for MIXER FILL commands.\n\nChannel\n-------\n\n * SET MODE now reverts back to old video-mode on failure.\n\nDiagnostics\n-----------\n\n * Improved graphs and added more status information.\n * Print configuration into log at startup.\n * Use the same log file for the entire day, instead of one per startup as\n    previously.\n * Diagnostics window is now closable.\n\n\n\nCasparCG Server 2.0 Beta 1 (as compared to Alpha)\n=================================================\n\n * Blending Modes (needs to be explicitly enabled)\n   * overlay\n   * screen\n   * multiply\n   * and many more.\n * Added additive keyer in addition to linear keyer.\n * Image adjustments\n   * saturation\n   * brightness\n   * contrast\n   * min input-level\n   * max input-level\n   * min output-level\n   * max output-level\n   * gamma\n * Support for FFmpeg-filters such as (ee http://ffmpeg.org/libavfilter.html)\n   * yadif deinterlacer (optimized in CasparCG for full multi-core support)\n   * de-noising\n   * dithering\n   * box blur\n   * and many more\n * 32-bit SSE optimized audio pipeline.\n * DeckLink-Consumer uses external-key by default.\n * DeckLink-Consumer has 24 bit embedded-audio support.\n * DeckLink-Producer has 24 bit embedded-audio support.\n * LOADBG with AUTO feature which automatically plays queued clip when\n    foreground clip has ended.\n * STATUS command for layers.\n * LOG LEVEL command for log filtering.\n * MIX transition works with transparent clips.\n * Freeze on last frame.\n * Producer buffering is now configurable.\n * Consumer buffering is now configurable.\n * Now possible to configure template-hosts for different video-modes.\n * Added auto transcoder for FFmpeg producer which automatically transcodes\n    input video into compatible video format for the channel.\n   * interlacing (50p -> 50i)\n   * deinterlacing (50i -> 25p)\n   * bob-deinterlacing (50i -> 50p)\n   * bob-deinterlacing and reinterlacing (w1xh150i -> w2xh250i)\n   * doubling (25p -> 50p)\n   * halfing (50p -> 25p)\n   * field-order swap (upper <-> lower)\n * Screen consumer now automatically deinterlaces when receiving interlaced\n    content.\n * Optimized renderer.\n * Renderer can now be run asynchronously with producer by using a\n    producer-buffer size greater than 0.\n * Improved error and crash recovery.\n * Improved logging.\n * Added Image-Scroll-Producer.\n * Key-only has now near zero performance overhead.\n * Reduced memory requirements.\n * Removed \"warm up lag\" which occurred when playing the first media clip after\n    the server has started.\n * Added read-back fence for OpenGL device for improved multi-channel\n    performance.\n * Memory support increased from standard 2 GB to 4 GB on 64 bit Win 7 OS.\n * Added support for 2* DeckLink cards in Full HD.\n * Misc bugs fixes and performance improvements.\n * Color producer now support some color codes in addition to color codes, e.g.\n    EMPTY, BLACK, RED etc...\n * Alpha value in color codes is now optional.\n * More than 2 DeckLink cards might be possible but have not yet been tested.\n\n\n\nCasparCG Server 2.0 Alpha (as compared to 1.8)\n==============================================\n\nGeneral\n-------\n\n * Mayor refactoring for improved readability and maintainability.\n * Some work towards platform-independence. Currently the greatest challenge\n    for full platform-independence is flash-producer.\n * Misc improved scalability.\n * XML-configuration.\n * DeckLink\n   * Support for multiple DeckLink cards.\n\nCore\n----\n\n * Multiple producers per video_channel.\n * Multiple consumers per video_channel.\n * Swap producers between layers and channels during run-time.\n * Support for upper-field and lower-field interlacing.\n * Add and remove consumers during run-time.\n * Preliminary support for NTSC.\n\nAMCP\n----\n\n * Query flash and template-host version.\n * Recursive media-folder listing.\n * Misc changes.\n\nMixer\n-----\n\n * Animated tween transforms.\n * Image-Mixer\n   * Fully GPU accelerated (all features listed below are done on the GPU),\n   * Layer composition.\n   * Color spaces (rgba, bgra, argb, yuv, yuva, yuv-hd, yuva-hd).\n   * Interlacing.\n   * Per-layer image transforms:\n     * Opacity\n     * Gain\n     * Scaling\n     * Clipping\n     * Translation\n * Audio Mixer\n   * Per-layer and per-sample audio transforms:\n       * Gain\n   * Fully internal audio mixing. Single output video_channel.\n\nConsumers\n---------\n\n * DeckLink Consumer\n   * Embedded audio.\n   * HD support.\n   * Hardware clock.\n * Bluefish Consumer\n   * Drivers are loaded on-demand (server now runs on computers without\n      installed Bluefish drivers).\n   * Embedded audio.\n   * Allocated frames are no longer leaked.\n\nProducers\n---------\n\n * Decklink Producer\n   * Embedded audio.\n   * HD support.\n * Color Producer\n   * GPU accelerated.\n * FFMPEG Producer\n   * Asynchronous file IO.\n   * Parallel decoding of audio and video.\n   * Color space transform are moved to GPU.\n * Transition Producer\n   * Fully interlaced transition (previously only progressive, even when\n      running in interlaced mode).\n   * Per-sample mixing between source and destination clips.\n   * Tween transitions.\n * Flash Producer\n   * DirectDraw access (slightly improved performance).\n   * Improved time-sync. Smoother animations and proper interlacing.\n * Image Producer\n   * Support for various image formats through FreeImage library.\n\nDiagnostics\n-----------\n\n * Graphs for monitoring performance and events.\n * Misc logging improvements.\n * Separate log file for every run of the server.\n * Error logging provides full exception details, instead of only printing that\n    an error has occurred.\n * Console with real-time logging output.\n * Console with AMCP input.\n\nRemoved\n-------\n\n * Registry configuration (replaced by XML Configuration).\n * TGA Producer (replaced by Image Producer).\n * TGA Scroll Producer\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# CasparCG Code of Conduct\n\n> CasparCG is all about showing respect and professionalism one to another.\n\n## Community\n\nWe want a positive and inspiring community that welcomes and embraces new ideas with respect and professionalism. CasparCG community has arisen through hard work and tremendous enthusiasm of hundreds of people around the world.\n\nThis Code of Conduct is about how we behave, act and cooperate in this positive and inspiring community. Contributors and users who engage in the CasparCG project in one way or another share this Code of Conduct.\n\n## We strive to:\n\n### Be considerate\nCasparCG is used by other people and in various environments such as production. Your actions will affect other community members and therefore we expect you to take those consequences into account when making decisions.\n\n### Be respectful\nIn a community there will always be some form of disagreement, but that is no excuse for poor behavior and poor manners. Treat one another with respect and professionalism to make community members feel comfortable. We work together, as a union, to resolve conflicts and to maintain the positive and inspiring atmosphere in our community.\n\nWe do not tolerate personal attacks, racism, sexism or any other form of discrimination or abuses. Maintainers of the project have right to suspend the person who persistently breaks to our Code of Conduct.\n\n### Be collaborative\nCollaboration helps to reduce redundancy while improving the quality of the project and the software produced. To avoid misunderstanding, try to be clear when requesting for help, giving help or asking for feedback. If something is unclear ask for clarification.\n\n### Be supportive\nCasparCG community is made up by mutual respect, collaboration and professional behavior. If you witness others being discriminated or abused, think about how you can be supportive. If the identified situation is beyond your ability, ask the victim privately if some form of official intervention is needed to solve the uncomfortable situation.\n\n### Ask for help\nBy asking questions early we can avoid many problems that can arise later on. We encourage you to ask questions. Those who are asked should be helpful and answer with professionalism in mind.\n"
  },
  {
    "path": "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": "README.md",
    "content": "CasparCG Server\n===============\n\nThank you for your interest in CasparCG Server, a professional software used to\nplay out and record professional graphics, audio and video to multiple outputs.\nCasparCG Server has been in 24/7 broadcast production since 2006.\n\nThe CasparCG Server works on Windows and Linux.\n\nSystem Requirements\n-------------------\n\n- A graphics card (GPU) capable of OpenGL 4.5 is required.\n- An Nvidia GPU is recommended, but other GPU's will likely work fine.\n- Intel and AMD CPU's have been tested and are known to work\n- PCIE bandwidth is important between your GPU and CPU, as well as Decklink and CPU. Avoid chipset lanes when possible.\n\n### Windows\n\n - Windows 11 is recommended\n - Windows 10 is supported as best effort\n\n### Linux\n\n - Ubuntu 24.04 is recommended\n - Other distributions and releases will work but you will need to compile it yourself and have not been tested\n\nGetting Started\n---------------\n\n1. Download a release from (http://casparcg.com/downloads).\n   Alternatively, newer testing versions can be downloaded from (http://builds.casparcg.com) or [built from source](BUILDING.md)\n\n2. Install any optional non-GPL modules\n    - Flash template support (Windows only):\n\n    1. Uninstall any previous version of the Adobe Flash Player using this file:\n        (http://download.macromedia.com/get/flashplayer/current/support/uninstall_flash_player.exe)\n\n    2. Download and unpack\n        (http://download.macromedia.com/pub/flashplayer/installers/archive/fp_11.8.800.94_archive.zip)\n\n    3. Install Adobe Flash Player 11.8.800.94 from the unpacked archive:\n        fp_11.8.800.94_archive\\11_8_r800_94\\flashplayer11_8r800_94_winax.exe\n\n3. Configure the server by editing the self-documented \"casparcg.config\" file in\n   a text editor.\n\n4.\n   1. Windows: start `casparcg_auto_restart.bat`, or `casparcg.exe` and `scanner.exe` separately.\n   1. Linux: start the `run.sh` program or use tools/linux/start_docker.sh to run within docker (documentation is at the top of the file).\n\n5. Connect to the Server from a client software, such as the \"CasparCG Client\"\n   which is available as a separate download.\n\nDocumentation\n-------------\n\nThe most up-to-date documentation is always available at\nhttps://github.com/CasparCG/help/wiki\n\nAsk questions in the forum: https://casparcgforum.org/\n\nDevelopment\n-----------\n\nSee [BUILDING](BUILDING.md) for instructions on how to build the CasparCG Server from source manually.\n\nLicense\n---------\n\nCasparCG Server is distributed under the GNU General Public License GPLv3 or\nhigher, see [LICENSE](LICENSE) for details.\n\nCasparCG Server uses the following third party libraries:\n- FFmpeg (http://ffmpeg.org/) under the GPLv2 Licence.\n  FFmpeg is a trademark of Fabrice Bellard, originator of the FFmpeg project.\n- Threading Building Blocks (http://www.threadingbuildingblocks.org/) library under the GPLv2 Licence.\n- SFML (http://www.sfml-dev.org/) under the zlib/libpng License.\n- GLEW (http://glew.sourceforge.net) under the modified BSD License.\n- boost (http://www.boost.org/) under the Boost Software License, version 1.0.\n"
  },
  {
    "path": "_typos.toml",
    "content": "[default]\n# Ignore lines following the commment `// typos: ignore-next\nextend-ignore-re = [\".*// typos: ignore-next\\\\n[^\\\\n]*\\\\n\"]\n\n[default.extend-words]\n# NDI is a common acronym in the context of video and audio over IP\nndi = \"ndi\"\n# it was seeoing NDIfoo as ND-Ifoo and turning it into ANDIfoo\nnd = \"nd\"\n# ANC is short for \"ancillary\" and is used in the bluefish drivers\nanc = \"anc\"\n\n"
  },
  {
    "path": "src/CMakeLists.txt",
    "content": "cmake_minimum_required(VERSION 3.16)\n\n# Project settings\nproject(\"CasparCG Server\")\nset(CONFIG_VERSION_MAJOR 2)\nset(CONFIG_VERSION_MINOR 6)\nset(CONFIG_VERSION_BUG 0)\nset(CONFIG_VERSION_TAG \"Dev\")\n\n# support for language servers (eg, clangd or ccls)\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\nset(CASPARCG_DOWNLOAD_MIRROR https://github.com/CasparCG/dependencies/releases/download/ CACHE STRING \"Source/mirror to use for external dependencies\")\nset(CASPARCG_DOWNLOAD_CACHE ${CMAKE_CURRENT_BINARY_DIR}/external CACHE STRING \"Download cache directory for cmake ExternalProjects\")\n\noption(ENABLE_HTML \"Enable HTML module, require CEF\" ON)\n\nset(DIAG_FONT_PATH \"LiberationMono-Regular.ttf\" CACHE STRING\n    \"Path to font that will be used to load diag font at runtime. By default\n    this loads the font distributed with the application from the working\n    directory. It can be set to an absolute path to instead load a font from\n    the system.\"\n)\nadd_compile_definitions(\"DIAG_FONT_PATH=\\\"${DIAG_FONT_PATH}\\\"\")\n\n# Add custom cmake modules path\nset(CASPARCG_PATCH_DIR ${CMAKE_SOURCE_DIR}/CMakeModules/patches)\nlist(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/CMakeModules)\n\n# Determine the git hash\nfind_package(Git)\nset(CONFIG_VERSION_GIT_HASH \"N/A\")\nif(DEFINED ENV{GIT_HASH} AND NOT $ENV{GIT_HASH} STREQUAL \"\")\n    set(CONFIG_VERSION_GIT_HASH \"$ENV{GIT_HASH}\")\nelseif(GIT_FOUND AND EXISTS \"${PROJECT_SOURCE_DIR}/../.git\")\n    execute_process(\n            COMMAND \"${GIT_EXECUTABLE}\" rev-parse --verify --short HEAD\n            WORKING_DIRECTORY \"${PROJECT_SOURCE_DIR}/../\"\n            OUTPUT_VARIABLE CONFIG_VERSION_GIT_HASH\n            OUTPUT_STRIP_TRAILING_WHITESPACE\n    )\nendif()\n\ncmake_host_system_information(RESULT CONFIG_CPU_COUNT QUERY NUMBER_OF_PHYSICAL_CORES)\n\ninclude(CasparCG_Util)\nconfigure_file(\"${PROJECT_SOURCE_DIR}/version.tmpl\" \"${CMAKE_BINARY_DIR}/generated/version.h\")\n\nif(MSVC)\n    include(Bootstrap_Windows)\nelse ()\n    include(Bootstrap_Linux)\n\n    # Output build settings\n    message(STATUS \"Target architecture: ${CMAKE_SYSTEM_PROCESSOR}\")\n    message(STATUS \"CPU Count: ${CONFIG_CPU_COUNT}\")\n    message(STATUS \"Target build type: ${CMAKE_BUILD_TYPE}\")\n    message(STATUS \"Build Version: ${CONFIG_VERSION_MAJOR}.${CONFIG_VERSION_MINOR}.${CONFIG_VERSION_BUG} ${CONFIG_VERSION_TAG} (Revision: ${CONFIG_VERSION_GIT_HASH})\")\nendif ()\n\nIF(ENABLE_VULKAN)\n    add_definitions(-DENABLE_VULKAN)\nENDIF()\n\ninclude_directories(\"${CMAKE_BINARY_DIR}/generated\")\n\nadd_subdirectory(tools)\nadd_subdirectory(accelerator)\nadd_subdirectory(common)\nadd_subdirectory(core)\nadd_subdirectory(modules)\nadd_subdirectory(protocol)\nadd_subdirectory(shell)\n"
  },
  {
    "path": "src/CMakeModules/Bootstrap_Linux.cmake",
    "content": "cmake_minimum_required (VERSION 3.28)\n\ninclude(ExternalProject)\ninclude(FetchContent)\n\nif(POLICY CMP0135)\n    cmake_policy(SET CMP0135 NEW)\nendif()\n# Prefer the new boost helper\nif(POLICY CMP0167)\n    cmake_policy(SET CMP0167 NEW)\nendif()\n\nset(ENABLE_HTML ON CACHE BOOL \"Enable CEF and HTML producer\")\nset(USE_STATIC_BOOST OFF CACHE BOOL \"Use shared library version of Boost\")\nset(USE_SYSTEM_CEF ON CACHE BOOL \"Use the version of cef from your OS (only tested with Ubuntu)\")\nset(CASPARCG_BINARY_NAME \"casparcg\" CACHE STRING \"Custom name of the binary to build (this disables some install files)\")\nset(ENABLE_AVX2 OFF CACHE BOOL \"Enable the AVX2 instruction set (requires a CPU that supports it)\")\nset(ENABLE_VULKAN OFF CACHE BOOL \"Enable Vulkan support\")\n\n# Determine build (target) platform\nSET (PLATFORM_FOLDER_NAME \"linux\")\n\nIF (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)\n\tMESSAGE (STATUS \"Setting build type to 'Release' as none was specified.\")\n\tSET (CMAKE_BUILD_TYPE \"Release\" CACHE STRING \"Choose the type of build.\" FORCE)\n\tSET_PROPERTY (CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS \"Debug\" \"Release\" \"MinSizeRel\" \"RelWithDebInfo\")\nENDIF ()\nMARK_AS_ADVANCED (CMAKE_INSTALL_PREFIX)\n\nif (USE_STATIC_BOOST)\n\tSET (Boost_USE_STATIC_LIBS ON)\nendif()\nfind_package(Boost 1.83.0 COMPONENTS thread filesystem log_setup log locale regex date_time coroutine REQUIRED)\nfind_package(FFmpeg REQUIRED)\nfind_package(OpenGL REQUIRED COMPONENTS OpenGL GLX EGL)\nfind_package(GLEW REQUIRED)\nfind_package(TBB REQUIRED)\nfind_package(OpenAL REQUIRED)\nfind_package(SFML 3 COMPONENTS Graphics System Window QUIET)\nif(NOT SFML_FOUND)\n    find_package(SFML 2 COMPONENTS graphics system window REQUIRED)\nendif()\n\nIF (ENABLE_VULKAN)\n    find_package(Vulkan REQUIRED)\n\n    FetchContent_Declare(vk_bootstrap\n            URL ${CASPARCG_DOWNLOAD_MIRROR}/vk-bootstrap/vk-bootstrap-1.4.328.tar.gz\n            URL_HASH SHA256=3be0220de218dc3e692aeac552b2953860a0e0a48257f4a61c3f1c1472674744\n            DOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n            )\n    FetchContent_MakeAvailable(vk_bootstrap)\n\n    FetchContent_Declare(vma\n            URL ${CASPARCG_DOWNLOAD_MIRROR}/VulkanMemoryAllocator/VulkanMemoryAllocator-3.3.0.tar.gz\n            URL_HASH SHA256=c4f6bbe6b5a45c2eb610ca9d231158e313086d5b1a40c9922cb42b597419b14e\n            DOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n    )\n    FetchContent_MakeAvailable(vma)\nendif()\n\n\nfind_package(X11 REQUIRED)\n\nif (ENABLE_HTML)\n    if (USE_SYSTEM_CEF)\n        set(CEF_LIB_PATH \"/usr/lib/casparcg-cef-142\")\n\n        add_library(CEF::CEF INTERFACE IMPORTED)\n        target_include_directories(CEF::CEF INTERFACE\n            \"/usr/include/casparcg-cef-142\"\n        )\n        target_link_libraries(CEF::CEF INTERFACE\n            \"-Wl,-rpath,${CEF_LIB_PATH} ${CEF_LIB_PATH}/libcef.so\"\n            \"${CEF_LIB_PATH}/libcef_dll_wrapper.a\"\n        )\n    else()\n        casparcg_add_external_project(cef)\n        ExternalProject_Add(cef\n            URL ${CASPARCG_DOWNLOAD_MIRROR}/cef/cef_binary_142.0.17+g60aac24+chromium-142.0.7444.176_linux64_minimal.tar.bz2\n            URL_HASH SHA256=1d89e19b2f446105f9a1fe6fdc96bced86249b5884241dcc4013b7c94dabf424\n            DOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n            CMAKE_ARGS -DUSE_SANDBOX=Off\n            INSTALL_COMMAND \"\"\n            BUILD_BYPRODUCTS\n                \"<SOURCE_DIR>/Release/libcef.so\"\n                \"<BINARY_DIR>/libcef_dll_wrapper/libcef_dll_wrapper.a\"\n        )\n        ExternalProject_Get_Property(cef SOURCE_DIR)\n        ExternalProject_Get_Property(cef BINARY_DIR)\n\n        add_library(CEF::CEF INTERFACE IMPORTED)\n        target_include_directories(CEF::CEF INTERFACE\n            \"${SOURCE_DIR}\"\n        )\n        target_link_libraries(CEF::CEF INTERFACE\n            # Note: All of these must be referenced in the BUILD_BYPRODUCTS above, to satisfy ninja\n            \"${SOURCE_DIR}/Release/libcef.so\"\n            \"${BINARY_DIR}/libcef_dll_wrapper/libcef_dll_wrapper.a\"\n        )\n\n        install(DIRECTORY ${SOURCE_DIR}/Resources/locales TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Resources/chrome_100_percent.pak TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Resources/chrome_200_percent.pak TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Resources/icudtl.dat TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Resources/resources.pak TYPE LIB)\n\n        install(FILES ${SOURCE_DIR}/Release/chrome-sandbox TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/libcef.so TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/libEGL.so TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/libGLESv2.so TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/libvk_swiftshader.so TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/libvulkan.so.1 TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/v8_context_snapshot.bin TYPE LIB)\n        install(FILES ${SOURCE_DIR}/Release/vk_swiftshader_icd.json TYPE LIB)\n    endif()\nendif ()\n\nSET (BOOST_INCLUDE_PATH \"${Boost_INCLUDE_DIRS}\")\nSET (FFMPEG_INCLUDE_PATH \"${FFMPEG_INCLUDE_DIRS}\")\n\nLINK_DIRECTORIES(\"${FFMPEG_LIBRARY_DIRS}\")\n\nSET_PROPERTY (GLOBAL PROPERTY USE_FOLDERS ON)\n\nADD_DEFINITIONS (-DSFML_STATIC)\nADD_DEFINITIONS (-DUNICODE)\nADD_DEFINITIONS (-D_UNICODE)\nADD_DEFINITIONS (-DGLEW_NO_GLU)\nADD_DEFINITIONS (-DGLEW_EGL)\nADD_DEFINITIONS (-D__NO_INLINE__) # Needed for precompiled headers to work\nADD_DEFINITIONS (-DBOOST_NO_SWPRINTF) # swprintf on Linux seems to always use , as decimal point regardless of C-locale or C++-locale\nADD_DEFINITIONS (-DTBB_USE_CAPTURED_EXCEPTION=1)\nADD_DEFINITIONS (-DNDEBUG) # Needed for precompiled headers to work\nADD_DEFINITIONS (-DBOOST_LOCALE_HIDE_AUTO_PTR) # Needed for C++17 in boost 1.67+\n\n\nif (NOT USE_STATIC_BOOST)\n\tADD_DEFINITIONS (-DBOOST_ALL_DYN_LINK)\nendif()\n\nIF (NOT CMAKE_BUILD_TYPE STREQUAL \"Debug\")\n\tADD_COMPILE_OPTIONS (-O3) # Needed for precompiled headers to work\nendif()\nIF (CMAKE_SYSTEM_PROCESSOR MATCHES \"(i[3-6]86|x64|x86_64|amd64|e2k)\")\n    ADD_COMPILE_OPTIONS (-msse3)\n    ADD_COMPILE_OPTIONS (-mssse3)\n    ADD_COMPILE_OPTIONS (-msse4.1)\n    IF (ENABLE_AVX2)\n        ADD_COMPILE_OPTIONS (-mfma)\n        ADD_COMPILE_OPTIONS (-mavx)\n        ADD_COMPILE_OPTIONS (-mavx2)\n    ENDIF ()\nELSE ()\n    ADD_COMPILE_DEFINITIONS (USE_SIMDE) # Enable OpenMP support in simde\n    ADD_COMPILE_DEFINITIONS (SIMDE_ENABLE_OPENMP) # Enable OpenMP support in simde\n    ADD_COMPILE_OPTIONS (-fopenmp-simd) # Enable OpenMP SIMD support\nENDIF ()\n\nADD_COMPILE_OPTIONS (-fnon-call-exceptions) # Allow signal handler to throw exception\n\nADD_COMPILE_OPTIONS (-Wno-deprecated-declarations -Wno-write-strings -Wno-multichar -Wno-cpp -Werror)\n\nIF (ENABLE_VULKAN)\n    ADD_COMPILE_OPTIONS (-Wno-nonnull -Wno-nullability-completeness)\nENDIF()\n\nIF (CMAKE_CXX_COMPILER_ID MATCHES \"GNU\")\n    ADD_COMPILE_OPTIONS (-Wno-terminate)\nELSEIF (CMAKE_CXX_COMPILER_ID MATCHES \"Clang\")\n    # Help TBB figure out what compiler support for c++11 features\n    # https://github.com/01org/tbb/issues/22\n    string(REPLACE \".\" \"0\" TBB_USE_GLIBCXX_VERSION ${CMAKE_CXX_COMPILER_VERSION})\n    message(STATUS \"ADDING: -DTBB_USE_GLIBCXX_VERSION=${TBB_USE_GLIBCXX_VERSION}\")\n    add_definitions(-DTBB_USE_GLIBCXX_VERSION=${TBB_USE_GLIBCXX_VERSION})\nENDIF ()\n\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG} -D_DEBUG\")\n"
  },
  {
    "path": "src/CMakeModules/Bootstrap_Windows.cmake",
    "content": "cmake_minimum_required (VERSION 3.28)\n\ninclude(ExternalProject)\ninclude(FetchContent)\n\nif(POLICY CMP0135)\n\tcmake_policy(SET CMP0135 NEW)\nendif()\n# Prefer the new boost helper\nif(POLICY CMP0167)\n\tcmake_policy(SET CMP0167 NEW)\nendif()\n\nset(BOOST_USE_PRECOMPILED ON CACHE BOOL \"Use precompiled boost\")\nset(ENABLE_VULKAN OFF CACHE BOOL \"Enable Vulkan support\")\n\nset(CASPARCG_RUNTIME_DEPENDENCIES_RELEASE \"\" CACHE INTERNAL \"\")\nset(CASPARCG_RUNTIME_DEPENDENCIES_DEBUG \"\" CACHE INTERNAL \"\")\nset(CASPARCG_RUNTIME_DEPENDENCIES_RELEASE_DIRS \"\" CACHE INTERNAL \"\")\nset(CASPARCG_RUNTIME_DEPENDENCIES_DEBUG_DIRS \"\" CACHE INTERNAL \"\")\n\nfunction(casparcg_add_runtime_dependency FILE_TO_COPY)\n\tif (\"${ARGV1}\" STREQUAL \"Release\" OR NOT ARGV1)\n\t\tset(CASPARCG_RUNTIME_DEPENDENCIES_RELEASE \"${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE}\" \"${FILE_TO_COPY}\" CACHE INTERNAL \"\")\n\tendif()\n\tif (\"${ARGV1}\" STREQUAL \"Debug\" OR NOT ARGV1)\n\t\tset(CASPARCG_RUNTIME_DEPENDENCIES_DEBUG \"${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG}\" \"${FILE_TO_COPY}\" CACHE INTERNAL \"\")\n\tendif()\nendfunction()\nfunction(casparcg_add_runtime_dependency_dir FILE_TO_COPY)\n\tif (\"${ARGV1}\" STREQUAL \"Release\" OR NOT ARGV1)\n\t\tset(CASPARCG_RUNTIME_DEPENDENCIES_RELEASE_DIRS \"${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE_DIRS}\" \"${FILE_TO_COPY}\" CACHE INTERNAL \"\")\n\tendif()\n\tif (\"${ARGV1}\" STREQUAL \"Debug\" OR NOT ARGV1)\n\t\tset(CASPARCG_RUNTIME_DEPENDENCIES_DEBUG_DIRS \"${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG_DIRS}\" \"${FILE_TO_COPY}\" CACHE INTERNAL \"\")\n\tendif()\nendfunction()\nfunction(casparcg_add_runtime_dependency_from_target TARGET)\n\tget_target_property(_runtime_lib_name ${TARGET} IMPORTED_LOCATION_RELEASE)\n\tif (NOT \"${_runtime_lib_name}\" STREQUAL \"\")\n\t\tset(CASPARCG_RUNTIME_DEPENDENCIES_RELEASE \"${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE}\" \"${_runtime_lib_name}\" CACHE INTERNAL \"\")\n\tendif()\n\n\tget_target_property(_runtime_lib_name ${TARGET} IMPORTED_LOCATION_DEBUG)\n\tif (NOT \"${_runtime_lib_name}\" STREQUAL \"\")\n\t\tset(CASPARCG_RUNTIME_DEPENDENCIES_DEBUG \"${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG}\" \"${_runtime_lib_name}\" CACHE INTERNAL \"\")\n\tendif()\nendfunction()\n\ncasparcg_add_runtime_dependency(\"${PROJECT_SOURCE_DIR}/shell/casparcg.config\")\n\n# BOOST\ncasparcg_add_external_project(boost)\nif (BOOST_USE_PRECOMPILED)\n\tExternalProject_Add(boost\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/boost/boost_1_83_0-win32-x64-debug-release.zip\n\tURL_HASH MD5=0b9990a24259867c8c04ae30c423f86b\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\tCONFIGURE_COMMAND \"\"\n\tBUILD_COMMAND \"\"\n\tINSTALL_COMMAND \"\"\n\t)\n\tExternalProject_Get_Property(boost SOURCE_DIR)\n\tset(BOOST_INCLUDE_PATH \"${SOURCE_DIR}/include/boost-1_83\")\n\tlink_directories(\"${SOURCE_DIR}/lib\")\nelse ()\n\tset(BOOST_INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/boost-install)\n\tExternalProject_Add(boost\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/boost/boost_1_83_0.zip\n\tURL_HASH MD5=03d5aea72401ffed848cb5daf8cd2b9b\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\tBUILD_IN_SOURCE 1\n\tCONFIGURE_COMMAND ./bootstrap.bat\n\t\t--with-libraries=filesystem\n\t\t--with-libraries=locale\n\t\t--with-libraries=log\n\t\t--with-libraries=log_setup\n\t\t--with-libraries=regex\n\t\t--with-libraries=system\n\t\t--with-libraries=thread\n\tBUILD_COMMAND ./b2 install debug release --prefix=${BOOST_INSTALL_DIR} link=static threading=multi runtime-link=shared -j ${CONFIG_CPU_COUNT}\n\tINSTALL_COMMAND \"\"\n\t)\n\tset(BOOST_INCLUDE_PATH \"${BOOST_INSTALL_DIR}/include/boost-1_83\")\n\tlink_directories(\"${BOOST_INSTALL_DIR}/lib\")\nendif ()\nadd_definitions( -DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE )\nadd_definitions( -DBOOST_COROUTINES_NO_DEPRECATION_WARNING )\nadd_definitions( -DBOOST_LOCALE_HIDE_AUTO_PTR )\n\n# FFMPEG\ncasparcg_add_external_project(ffmpeg-lib)\nExternalProject_Add(ffmpeg-lib\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/ffmpeg/ffmpeg-7.0.2-full_build-shared.7z\n\tURL_HASH MD5=c5127aeed36a9a86dd3b84346be182f8\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\tCONFIGURE_COMMAND \"\"\n\tBUILD_COMMAND \"\"\n\tINSTALL_COMMAND \"\"\n)\nExternalProject_Get_Property(ffmpeg-lib SOURCE_DIR)\nset(FFMPEG_INCLUDE_PATH \"${SOURCE_DIR}/include\")\nset(FFMPEG_BIN_PATH \"${SOURCE_DIR}/bin\")\nlink_directories(\"${SOURCE_DIR}/lib\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/avcodec-61.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/avdevice-61.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/avfilter-10.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/avformat-61.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/avutil-59.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/postproc-58.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/swresample-5.dll\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/swscale-8.dll\")\n# for scanner:\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/ffmpeg.exe\")\ncasparcg_add_runtime_dependency(\"${FFMPEG_BIN_PATH}/ffprobe.exe\")\n\nget_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)\n\nset(EXTERNAL_CMAKE_ARGS \"\")\nif (is_multi_config)\n\tset(EXTERNAL_CMAKE_ARGS \"-DCMAKE_BUILD_TYPE:STRING=$<CONFIG>\")\nelse()\n\tset(EXTERNAL_CMAKE_ARGS \"-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}\")\nendif ()\n\n# TBB\nFetchContent_Declare(tbb\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/tbb/oneapi-tbb-2022.3.0-win.zip\n\tURL_HASH SHA256=e1b2373f25558bf47d16b4c89cf0a31e6689aaf7221400d209e8527afc7c9eee\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n)\nFetchContent_MakeAvailable(tbb)\n\nlist(APPEND CMAKE_PREFIX_PATH ${tbb_SOURCE_DIR}/lib/cmake/tbb)\nfind_package(tbb REQUIRED)\n\ncasparcg_add_runtime_dependency_from_target(TBB::tbb)\ncasparcg_add_runtime_dependency_from_target(TBB::tbbmalloc)\ncasparcg_add_runtime_dependency_from_target(TBB::tbbmalloc_proxy)\n\n# GLEW\nFetchContent_Declare(glew\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/glew/glew-2.2.0-win32.zip\n\tURL_HASH MD5=1feddfe8696c192fa46a0df8eac7d4bf\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n)\nFetchContent_MakeAvailable(glew)\n\nadd_library(GLEW::glew INTERFACE IMPORTED)\ntarget_include_directories(GLEW::glew INTERFACE ${glew_SOURCE_DIR}/include)\ntarget_link_directories(GLEW::glew INTERFACE ${glew_SOURCE_DIR}/lib/Release/x64)\ntarget_link_libraries(GLEW::glew INTERFACE glew32)\ncasparcg_add_runtime_dependency(\"${glew_SOURCE_DIR}/bin/Release/x64/glew32.dll\")\n\nIF(ENABLE_VULKAN)\n\tfind_package(Vulkan REQUIRED)\n\n\tFetchContent_Declare(vk_bootstrap\n\t\t\tURL ${CASPARCG_DOWNLOAD_MIRROR}/vk-bootstrap/vk-bootstrap-1.4.328.zip\n\t\t\tURL_HASH SHA256=10f257c30a0a49d30b28a72cf3a7942d93a61f977adaa04bee29304c6506dc12\n\t\t\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\t\t\t)\n\tFetchContent_MakeAvailable(vk_bootstrap)\n\n\tFetchContent_Declare(vma\n\t\t\tURL ${CASPARCG_DOWNLOAD_MIRROR}/VulkanMemoryAllocator/VulkanMemoryAllocator-3.3.0.zip\n\t\t\tURL_HASH SHA256=81755d8fcb411b97292c6682e828501315db319374c7c34ba6e1226452c6c392\n\t\t\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\t)\n\tFetchContent_MakeAvailable(vma)\nENDIF()\n\n# SFML\nFetchContent_Declare(sfml\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/sfml/SFML-2.6.2-windows-vc17-64-bit.zip\n\tURL_HASH MD5=dee0602d6f94d1843eef4d7568d2c23d\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n)\nFetchContent_MakeAvailable(sfml)\n\nlist(APPEND CMAKE_PREFIX_PATH ${sfml_SOURCE_DIR}/lib/cmake/SFML)\n# set(SFML_STATIC_LIBRARIES TRUE)\nfind_package(SFML 2 COMPONENTS graphics system window REQUIRED)\n\ncasparcg_add_runtime_dependency_from_target(sfml-graphics)\ncasparcg_add_runtime_dependency_from_target(sfml-system)\ncasparcg_add_runtime_dependency_from_target(sfml-window)\n\n#ZLIB\ncasparcg_add_external_project(zlib)\nExternalProject_Add(zlib\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/zlib/zlib-1.3.tar.gz\n\tURL_HASH MD5=60373b133d630f74f4a1f94c1185a53f\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\tCMAKE_ARGS ${EXTERNAL_CMAKE_ARGS}\n\tINSTALL_COMMAND \"\"\n)\nExternalProject_Get_Property(zlib SOURCE_DIR)\nExternalProject_Get_Property(zlib BINARY_DIR)\nset(ZLIB_INCLUDE_PATH \"${SOURCE_DIR};${BINARY_DIR}\")\nlink_directories(${BINARY_DIR})\n\n# OpenAL\nFetchContent_Declare(openal\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/openal/openal-soft-1.19.1-bin.zip\n\tURL_HASH MD5=b78ef1ba26f7108e763f92df6bbc3fa5\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n)\nFetchContent_MakeAvailable(openal)\nfile(COPY_FILE ${openal_SOURCE_DIR}/bin/Win64/soft_oal.dll ${openal_SOURCE_DIR}/bin/Win64/OpenAL32.dll)\n\nadd_library(OpenAL::OpenAL INTERFACE IMPORTED)\ntarget_include_directories(OpenAL::OpenAL INTERFACE ${openal_SOURCE_DIR}/include)\ntarget_link_directories(OpenAL::OpenAL INTERFACE ${openal_SOURCE_DIR}/libs/Win64)\ntarget_link_libraries(OpenAL::OpenAL INTERFACE OpenAL32)\ncasparcg_add_runtime_dependency(\"${openal_SOURCE_DIR}/bin/Win64/OpenAL32.dll\")\n\n# flash template host\ncasparcg_add_external_project(flashtemplatehost)\nExternalProject_Add(flashtemplatehost\n\tURL ${CASPARCG_DOWNLOAD_MIRROR}/flash-template-host/flash-template-host-files.zip\n\tURL_HASH MD5=360184ce21e34d585d1d898fdd7a6bd8\n\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\tBUILD_IN_SOURCE 1\n\tCONFIGURE_COMMAND \"\"\n\tBUILD_COMMAND \"\"\n\tINSTALL_COMMAND \"\"\n)\nExternalProject_Get_Property(flashtemplatehost SOURCE_DIR)\nset(TEMPLATE_HOST_PATH \"${SOURCE_DIR}\")\n# casparcg_add_runtime_dependency_dir(\"${TEMPLATE_HOST_PATH}\")\n\n# LIBERATION_FONTS\nset(LIBERATION_FONTS_BIN_PATH \"${PROJECT_SOURCE_DIR}/shell/liberation-fonts\")\ncasparcg_add_runtime_dependency(\"${LIBERATION_FONTS_BIN_PATH}/LiberationMono-Regular.ttf\")\n\n# CEF\nif (ENABLE_HTML)\n\tcasparcg_add_external_project(cef)\n\tExternalProject_Add(cef\n\t\tURL ${CASPARCG_DOWNLOAD_MIRROR}/cef/cef_binary_142.0.17+g60aac24+chromium-142.0.7444.176_windows64_minimal.tar.bz2\n\t\tURL_HASH SHA256=16c072a44484fe521037c74d03a339a77573b1fc0146cf44cc71e79fd0cc0198\n\t\tDOWNLOAD_DIR ${CASPARCG_DOWNLOAD_CACHE}\n\t\tCMAKE_ARGS -DUSE_SANDBOX=Off -DCEF_RUNTIME_LIBRARY_FLAG=/MD ${EXTERNAL_CMAKE_ARGS}\n\t\tINSTALL_COMMAND \"\"\n\t)\n\tExternalProject_Get_Property(cef SOURCE_DIR)\n\tExternalProject_Get_Property(cef BINARY_DIR)\n\n    add_library(CEF::CEF INTERFACE IMPORTED)\n\tadd_dependencies(CEF::CEF cef)\n    target_include_directories(CEF::CEF INTERFACE\n        \"${SOURCE_DIR}\"\n    )\n\n\tset(CEF_RESOURCE_PATH ${SOURCE_DIR}/Resources)\n\tset(CEF_BIN_PATH ${SOURCE_DIR}/Release)\n\n\tif (is_multi_config)\n\t    target_link_libraries(CEF::CEF INTERFACE\n\t\t\t${SOURCE_DIR}/Release/libcef.lib\n\t\t\toptimized ${BINARY_DIR}/libcef_dll_wrapper/Release/libcef_dll_wrapper.lib\n\t\t\tdebug ${BINARY_DIR}/libcef_dll_wrapper/Debug/libcef_dll_wrapper.lib)\n\telse()\n\t\tlink_directories(${SOURCE_DIR}/Release ${BINARY_DIR}/libcef_dll_wrapper)\n\t\ttarget_link_libraries(CEF::CEF INTERFACE\n\t\t\tlibcef.lib\n\t\t\tlibcef_dll_wrapper.lib)\n\tendif()\n\n\tcasparcg_add_runtime_dependency_dir(\"${CEF_RESOURCE_PATH}/locales\")\n\tcasparcg_add_runtime_dependency(\"${CEF_RESOURCE_PATH}/chrome_100_percent.pak\")\n\tcasparcg_add_runtime_dependency(\"${CEF_RESOURCE_PATH}/chrome_200_percent.pak\")\n\tcasparcg_add_runtime_dependency(\"${CEF_RESOURCE_PATH}/resources.pak\")\n\tcasparcg_add_runtime_dependency(\"${CEF_RESOURCE_PATH}/icudtl.dat\")\n\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/v8_context_snapshot.bin\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/libcef.dll\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/chrome_elf.dll\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/d3dcompiler_47.dll\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/libEGL.dll\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/libGLESv2.dll\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/vk_swiftshader.dll\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/vk_swiftshader_icd.json\")\n\tcasparcg_add_runtime_dependency(\"${CEF_BIN_PATH}/vulkan-1.dll\")\nendif ()\n\nset_property(GLOBAL PROPERTY USE_FOLDERS ON)\nset_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT casparcg)\n\nadd_definitions(-DUNICODE)\nadd_definitions(-D_UNICODE)\nadd_definitions(-DCASPAR_SOURCE_PREFIX=\"${CMAKE_CURRENT_SOURCE_DIR}\")\nadd_definitions(-D_WIN32_WINNT=0x601)\n\n# ignore boost deprecated headers, as these are often reported inside boost\nadd_definitions(\"-DBOOST_ALLOW_DEPRECATED_HEADERS\")\n\n# Ensure /EHsc is not defined as it clashes with EHa below\nstring(REPLACE \"/EHsc\" \"\" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})\n\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} /EHa /Zi /W4 /WX /MP /fp:fast /Zm192 /FIcommon/compiler/vs/disable_silly_warnings.h\")\nset(CMAKE_CXX_FLAGS_DEBUG \"${CMAKE_CXX_FLAGS_DEBUG}\t/D TBB_USE_ASSERT=1 /D TBB_USE_DEBUG /bigobj\")\nset(CMAKE_CXX_FLAGS_RELEASE \"${CMAKE_CXX_FLAGS_RELEASE}\t/Oi /arch:AVX /Ot /Gy /bigobj\")\n"
  },
  {
    "path": "src/CMakeModules/CasparCG_Util.cmake",
    "content": "# Collect all ExternalProjects that have been defined\nset(CASPARCG_EXTERNAL_PROJECTS \"\" CACHE INTERNAL \"\")\nFUNCTION (casparcg_add_external_project NAME)\n\tSET (CASPARCG_EXTERNAL_PROJECTS \"${CASPARCG_EXTERNAL_PROJECTS}\" \"${NAME}\" CACHE INTERNAL \"\")\nENDFUNCTION()\n\n# Mark a project as depending on all of the ExternalProjects, to ensure build order\nFUNCTION(casparcg_add_build_dependencies TARGET)\n\tif (CASPARCG_EXTERNAL_PROJECTS)\n\t\tADD_DEPENDENCIES (${TARGET} ${CASPARCG_EXTERNAL_PROJECTS})\n\tendif()\nENDFUNCTION()\n\nSET (CASPARCG_MODULE_INCLUDE_STATEMENTS \"\" CACHE INTERNAL \"\")\nSET (CASPARCG_MODULE_INIT_STATEMENTS \"\" CACHE INTERNAL \"\")\nSET (CASPARCG_MODULE_UNINIT_STATEMENTS \"\" CACHE INTERNAL \"\")\nSET (CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS \"\" CACHE INTERNAL \"\")\nSET (CASPARCG_MODULE_TARGETS \"\" CACHE INTERNAL \"\")\n\n# CasparCG version of CMake `add_library`\nFUNCTION (casparcg_add_library TARGET)\n\tcmake_parse_arguments(\n        PARSED_ARGS # prefix of output variables\n        \"\" # list of names of the boolean arguments (only defined ones will be true)\n        \"\" # list of names of mono-valued arguments\n        \"SOURCES\" # list of names of multi-valued arguments (output variables are lists)\n        ${ARGN} # arguments of the function to parse, here we take the all original ones\n    )\n\n\tif(NOT TARGET)\n        message(FATAL_ERROR \"You must provide a target name\")\n\tendif()\n\n\t# Setup the library and some default config\n\tADD_LIBRARY (${TARGET} ${PARSED_ARGS_SOURCES})\n\ttarget_compile_features (${TARGET} PRIVATE cxx_std_20)\n\ttarget_include_directories(${TARGET} SYSTEM PRIVATE\n\t\t${BOOST_INCLUDE_PATH}\n\t)\n\ttarget_link_libraries(${TARGET} PRIVATE TBB::tbb)\n\n\tif (CASPARCG_EXTERNAL_PROJECTS)\n\t\t# Setup dependency on ExternalProject\n\t\tADD_DEPENDENCIES (${TARGET} ${CASPARCG_EXTERNAL_PROJECTS})\n\tendif()\n\nENDFUNCTION ()\n\n# CasparCG version of CMake `add_library` specifically for modules\nSET (CASPARCG_MODULE_TARGETS \"\" CACHE INTERNAL \"\")\nFUNCTION (casparcg_add_module_project TARGET)\n\tcmake_parse_arguments(\n        PARSED_ARGS # prefix of output variables\n        \"\" # list of names of the boolean arguments (only defined ones will be true)\n        \"NAME;HEADER_FILE;INIT_FUNCTION;UNINIT_FUNCTION;CLI_INTERCEPTOR\" # list of names of mono-valued arguments\n        \"SOURCES\" # list of names of multi-valued arguments (output variables are lists)\n        ${ARGN} # arguments of the function to parse, here we take the all original ones\n    )\n\n\t# Use target if name is missing\n\tif (NOT PARSED_ARGS_NAME)\n\t\tset (PARSED_ARGS_NAME ${TARGET})\n\tendif()\n\t# Use default path if header not defined\n\tif (NOT PARSED_ARGS_HEADER_FILE)\n\t\tset (PARSED_ARGS_HEADER_FILE \"modules/${TARGET}/${TARGET}.h\")\n\tendif()\n\t# Use default init name if not d\n\tif (NOT PARSED_ARGS_INIT_FUNCTION)\n        message(FATAL_ERROR \"You must provide an INIT_FUNCTION\")\n\tendif()\n\n\t# Setup the library and some default config\n\tcasparcg_add_library (${TARGET} SOURCES ${PARSED_ARGS_SOURCES})\n\ttarget_link_libraries(${TARGET} PRIVATE common core)\n\ttarget_include_directories(${TARGET} PRIVATE\n\t\t\t# TODO: This should be replaced by the linked libraries eventually\n\t\t\t../..\n\t)\n\n\t# Setup linker and code loading\n\tSET (CASPARCG_MODULE_TARGETS \"${CASPARCG_MODULE_TARGETS}\" \"${TARGET}\" CACHE INTERNAL \"\")\n\tSET (CASPARCG_MODULE_INCLUDE_STATEMENTS \"${CASPARCG_MODULE_INCLUDE_STATEMENTS}\"\n\t\t\"#include <${PARSED_ARGS_HEADER_FILE}>\"\n\t\tCACHE INTERNAL \"\"\n\t)\n\tSET (CASPARCG_MODULE_INIT_STATEMENTS \"${CASPARCG_MODULE_INIT_STATEMENTS}\"\n\t\t\"\t${PARSED_ARGS_INIT_FUNCTION}(dependencies)\\;\"\n\t\t\"\tCASPAR_LOG(info) << L\\\"Initialized ${PARSED_ARGS_NAME} module.\\\"\\;\"\n\t\t\"\"\n\t\tCACHE INTERNAL \"\"\n\t)\n\n\tIF (PARSED_ARGS_UNINIT_FUNCTION)\n\t\tSET (CASPARCG_MODULE_UNINIT_STATEMENTS\n\t\t\t\"\t${PARSED_ARGS_UNINIT_FUNCTION}()\\;\"\n\t\t\t\"${CASPARCG_MODULE_UNINIT_STATEMENTS}\"\n\t\t\tCACHE INTERNAL \"\"\n\t\t)\n\tENDIF ()\n\n\tIF (PARSED_ARGS_CLI_INTERCEPTOR)\n\t\tSET (CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS \"${CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS}\"\n\t\t\t\"\tif (${PARSED_ARGS_CLI_INTERCEPTOR}(argc, argv))\"\n\t\t\t\"\t\treturn true\\;\"\n\t\t\t\"\"\n\t\t\tCACHE INTERNAL \"\"\n\t\t)\n\tENDIF ()\n\nENDFUNCTION ()\n\n# http://stackoverflow.com/questions/7172670/best-shortest-way-to-join-a-list-in-cmake\nFUNCTION (join_list VALUES GLUE OUTPUT)\n\tSTRING (REGEX REPLACE \"([^\\\\]|^);\" \"\\\\1${GLUE}\" _TMP_STR \"${VALUES}\")\n\tSTRING (REGEX REPLACE \"[\\\\](.)\" \"\\\\1\" _TMP_STR \"${_TMP_STR}\") #fixes escaping\n\tSET (${OUTPUT} \"${_TMP_STR}\" PARENT_SCOPE)\nENDFUNCTION ()\n"
  },
  {
    "path": "src/CMakeModules/FindFFmpeg.cmake",
    "content": "# vim: ts=2 sw=2\n# - Try to find the required ffmpeg components(default: AVFORMAT, AVUTIL, AVCODEC)\n#\n# Once done this will define\n#  FFMPEG_FOUND         - System has the all required components.\n#  FFMPEG_INCLUDE_DIRS  - Include directory necessary for using the required components headers.\n#  FFMPEG_LIBRARIES     - Link these to use the required ffmpeg components.\n#  FFMPEG_DEFINITIONS   - Compiler switches required for using the required ffmpeg components.\n#\n# For each of the components it will additionally set.\n#   - AVCODEC\n#   - AVDEVICE\n#   - AVFORMAT\n#   - AVFILTER\n#   - AVUTIL\n#   - SWSCALE\n# the following variables will be defined\n#  <component>_FOUND        - System has <component>\n#  <component>_INCLUDE_DIRS - Include directory necessary for using the <component> headers\n#  <component>_LIBRARIES    - Link these to use <component>\n#  <component>_DEFINITIONS  - Compiler switches required for using <component>\n#  <component>_VERSION      - The components version\n#\n# Copyright (c) 2006, Matthias Kretz, <kretz@kde.org>\n# Copyright (c) 2008, Alexander Neundorf, <neundorf@kde.org>\n# Copyright (c) 2011, Michael Jansen, <kde@michael-jansen.biz>\n#\n# Redistribution and use is allowed according to the terms of the BSD license.\n# For details see the accompanying COPYING-CMAKE-SCRIPTS file.\n\ninclude(FindPackageHandleStandardArgs)\n\n# The default components were taken from a survey over other FindFFMPEG.cmake files\nif (NOT FFmpeg_FIND_COMPONENTS)\n  set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL AVDEVICE AVFILTER SWSCALE SWRESAMPLE)\nendif ()\n\n#\n### Macro: set_component_found\n#\n# Marks the given component as found if both *_LIBRARIES AND *_INCLUDE_DIRS is present.\n#\nmacro(set_component_found _component )\n  if (${_component}_LIBRARIES AND ${_component}_INCLUDE_DIRS)\n    # message(STATUS \"  - ${_component} found.\")\n    set(${_component}_FOUND TRUE)\n  else ()\n    # message(STATUS \"  - ${_component} not found.\")\n  endif ()\nendmacro()\n\n#\n### Macro: find_component\n#\n# Checks for the given component by invoking pkgconfig and then looking up the libraries and\n# include directories.\n#\nmacro(find_component _component _pkgconfig _library _header)\n\n  if (NOT WIN32)\n     # use pkg-config to get the directories and then use these values\n     # in the FIND_PATH() and FIND_LIBRARY() calls\n     find_package(PkgConfig)\n     if (PKG_CONFIG_FOUND)\n       pkg_check_modules(${_component} ${_pkgconfig})\n     endif ()\n  endif (NOT WIN32)\n\n  find_path(${_component}_INCLUDE_DIRS ${_header}\n    HINTS\n      ${PC_LIB${_component}_INCLUDEDIR}\n      ${PC_LIB${_component}_INCLUDE_DIRS}\n    PATH_SUFFIXES\n      ffmpeg\n  )\n\n  find_library(${_component}_LIBRARIES NAMES ${_library}\n      HINTS\n      ${PC_LIB${_component}_LIBDIR}\n      ${PC_LIB${_component}_LIBRARY_DIRS}\n  )\n\n  set(${_component}_DEFINITIONS  ${PC_${_component}_CFLAGS_OTHER} CACHE STRING \"The ${_component} CFLAGS.\")\n  set(${_component}_VERSION      ${PC_${_component}_VERSION}      CACHE STRING \"The ${_component} version number.\")\n\n  set_component_found(${_component})\n\n  mark_as_advanced(\n    ${_component}_LIBRARY_DIRS\n    ${_component}_INCLUDE_DIRS\n    ${_component}_LIBRARIES\n    ${_component}_DEFINITIONS\n    ${_component}_VERSION\n  )\n\nendmacro()\n\n\n# Check for cached results. If there are skip the costly part.\nif (NOT FFMPEG_LIBRARIES)\n\n  # Check for all possible component.\n  find_component(AVCODEC    libavcodec    avcodec  libavcodec/avcodec.h)\n  find_component(AVFORMAT   libavformat   avformat libavformat/avformat.h)\n  find_component(AVDEVICE   libavdevice   avdevice libavdevice/avdevice.h)\n  find_component(AVUTIL     libavutil     avutil   libavutil/avutil.h)\n  find_component(AVFILTER   libavfilter   avfilter libavfilter/avfilter.h)\n  find_component(SWSCALE    libswscale    swscale  libswscale/swscale.h)\n  find_component(SWRESAMPLE libswresample swresample libswresample/swresample.h)\n\n  # Check if the required components were found and add their stuff to the FFMPEG_* vars.\n  foreach (_component ${FFmpeg_FIND_COMPONENTS})\n    if (${_component}_FOUND)\n      # message(STATUS \"Required component ${_component} present.\")\n      set(FFMPEG_LIBRARIES   ${FFMPEG_LIBRARIES}   ${${_component}_LIBRARIES})\n      set(FFMPEG_DEFINITIONS ${FFMPEG_DEFINITIONS} ${${_component}_DEFINITIONS})\n      list(APPEND FFMPEG_LIBRARY_DIRS ${${_component}_LIBRARY_DIRS})\n      list(APPEND FFMPEG_INCLUDE_DIRS ${${_component}_INCLUDE_DIRS})\n    else ()\n      # message(STATUS \"Required component ${_component} missing.\")\n    endif ()\n  endforeach ()\n\n  # Build the include path with duplicates removed.\n  if (FFMPEG_INCLUDE_DIRS)\n    list(REMOVE_DUPLICATES FFMPEG_INCLUDE_DIRS)\n  endif ()\n\n  # Build the lib path with duplicates removed.\n  if (FFMPEG_LIBRARY_DIRS)\n    list(REMOVE_DUPLICATES FFMPEG_LIBRARY_DIRS)\n  endif ()\n\n  # cache the vars.\n  set(FFMPEG_INCLUDE_DIRS ${FFMPEG_INCLUDE_DIRS} CACHE STRING \"The FFmpeg include directories.\" FORCE)\n  set(FFMPEG_LIBRARY_DIRS ${FFMPEG_LIBRARY_DIRS} CACHE STRING \"The FFmpeg lib directories.\" FORCE)\n  set(FFMPEG_LIBRARIES    ${FFMPEG_LIBRARIES}    CACHE STRING \"The FFmpeg libraries.\" FORCE)\n  set(FFMPEG_DEFINITIONS  ${FFMPEG_DEFINITIONS}  CACHE STRING \"The FFmpeg cflags.\" FORCE)\n\n  mark_as_advanced(\n    FFMPEG_INCLUDE_DIRS\n    FFMPEG_LIBRARY_DIRS\n    FFMPEG_LIBRARIES\n    FFMPEG_DEFINITIONS\n  )\n\nendif ()\n\n# Now set the noncached _FOUND vars for the components.\nforeach (_component AVCODEC AVDEVICE AVFORMAT AVUTIL SWSCALE)\n  set_component_found(${_component})\nendforeach ()\n\n# Compile the list of required vars\nif (FFMPEG_INCLUDE_DIRS)\n  set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES FFMPEG_INCLUDE_DIRS)\nelse ()\n  set(_FFmpeg_REQUIRED_VARS FFMPEG_LIBRARIES)\nendif ()\nforeach (_component ${FFmpeg_FIND_COMPONENTS})\n  if (${_component}_INCLUDE_DIRS)\n    list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES ${_component}_INCLUDE_DIRS)\n  else ()\n    list(APPEND _FFmpeg_REQUIRED_VARS ${_component}_LIBRARIES)\n  endif ()\nendforeach ()\n\n# Give a nice error message if some of the required vars are missing.\nfind_package_handle_standard_args(FFmpeg DEFAULT_MSG ${_FFmpeg_REQUIRED_VARS})\n"
  },
  {
    "path": "src/CMakeSettings.json",
    "content": "﻿{\n    \"configurations\": [\n        {\n            \"name\": \"x64-Debug\",\n            \"generator\": \"Ninja\",\n            \"configurationType\": \"Debug\",\n            \"inheritEnvironments\": [ \"msvc_x64_x64\" ],\n            \"buildRoot\": \"${projectDir}\\\\out\\\\build\\\\${name}\",\n            \"installRoot\": \"${projectDir}\\\\out\\\\install\\\\${name}\",\n            \"cmakeCommandArgs\": \"\",\n            \"buildCommandArgs\": \"\",\n            \"ctestCommandArgs\": \"\"\n        },\n        {\n            \"name\": \"x64-Release\",\n            \"generator\": \"Ninja\",\n            \"configurationType\": \"Release\",\n            \"buildRoot\": \"${projectDir}\\\\out\\\\build\\\\${name}\",\n            \"installRoot\": \"${projectDir}\\\\out\\\\install\\\\${name}\",\n            \"cmakeCommandArgs\": \"\",\n            \"buildCommandArgs\": \"\",\n            \"ctestCommandArgs\": \"\",\n            \"inheritEnvironments\": [ \"msvc_x64_x64\" ]\n        },\n        {\n            \"name\": \"x64-RelWithDebInfo\",\n            \"generator\": \"Ninja\",\n            \"configurationType\": \"RelWithDebInfo\",\n            \"buildRoot\": \"${projectDir}\\\\out\\\\build\\\\${name}\",\n            \"installRoot\": \"${projectDir}\\\\out\\\\install\\\\${name}\",\n            \"cmakeCommandArgs\": \"\",\n            \"buildCommandArgs\": \"\",\n            \"ctestCommandArgs\": \"\",\n            \"inheritEnvironments\": [ \"msvc_x64_x64\" ],\n            \"variables\": []\n        }\n    ]\n}"
  },
  {
    "path": "src/accelerator/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (accelerator)\n\nset(SOURCES\n\togl/image/image_kernel.cpp\n\togl/image/image_mixer.cpp\n\togl/image/image_shader.cpp\n\n\togl/util/buffer.cpp\n\togl/util/context.cpp\n\togl/util/device.cpp\n\togl/util/shader.cpp\n\togl/util/texture.cpp\n\togl/util/matrix.cpp\n\togl/util/transforms.cpp\n\n\taccelerator.cpp\n)\n\nset(HEADERS\n\togl/image/image_kernel.h\n\togl/image/image_mixer.h\n\togl/image/image_shader.h\n\n\togl/util/buffer.h\n\togl/util/context.h\n\togl/util/device.h\n\togl/util/shader.h\n\togl/util/texture.h\n\togl/util/matrix.h\n\togl/util/transforms.h\n\n\togl_image_vertex.h\n\togl_image_fragment.h\n\n\taccelerator.h\n\tStdAfx.h\n)\n\nIF(ENABLE_VULKAN)\n\tlist(APPEND SOURCES\n\t\tvulkan/image/image_kernel.cpp\n\t\tvulkan/image/image_mixer.cpp\n\n\t\tvulkan/util/buffer.cpp\n\t\tvulkan/util/device.cpp\n\t\tvulkan/util/pipeline.cpp\n\t\tvulkan/util/renderpass.cpp\n\t\tvulkan/util/texture.cpp\n\t\tvulkan/util/matrix.cpp\n\t\tvulkan/util/transforms.cpp\n\t)\n\n\tlist(APPEND HEADERS\n\t\tvulkan/image/image_kernel.h\n\t\tvulkan/image/image_mixer.h\n\n\t\tvulkan/util/buffer.h\n\t\tvulkan/util/device.h\n\t\tvulkan/util/draw_params.h\n\t\tvulkan/util/pipeline.h\n\t\tvulkan/util/texture.h\n\t\tvulkan/util/matrix.h\n\t\tvulkan/util/transforms.h\n\t\tvulkan/util/uniform_block.h\n\n\t\tvulkan_image_vertex.h\n\t\tvulkan_image_fragment.h\n\t)\nENDIF()\n\nif (MSVC)\n\tlist(APPEND SOURCES\n        d3d/d3d_device.cpp\n\t\td3d/d3d_device_context.cpp\n\t\td3d/d3d_texture2d.cpp\n\t)\n\tlist(APPEND HEADERS\n        d3d/d3d_device.h\n\t\td3d/d3d_device_context.h\n\t\td3d/d3d_texture2d.h\n\t)\nendif ()\n\nIF (ENABLE_VULKAN)\n\tfind_program(glslc_executable NAMES glslc HINTS Vulkan::glslc)\n\tset(SHADER_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/image)\n\tset(SHADER_BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vulkan/image)\n\n\tfile(GLOB SHADERS\n\t\t${SHADER_SOURCE_DIR}/vertex_shader.vert\n\t\t${SHADER_SOURCE_DIR}/fragment_shader.frag)\n\n\tforeach(source IN LISTS SHADERS)\n\t\tget_filename_component(FILENAME ${source} NAME_WLE)\n\t\tadd_custom_command(\n\t\t\tCOMMAND\n\t\t\t\t${glslc_executable}\n\t\t\t\t#      -MD -MF ${SHADER_BINARY_DIR}/${FILENAME}.d\n\t\t\t\t-o ${SHADER_BINARY_DIR}/${FILENAME}.spv\n\t\t\t\t${source}\n\t\t\tOUTPUT ${SHADER_BINARY_DIR}/${FILENAME}.spv\n\t\t\tDEPENDS ${source} ${SHADER_BINARY_DIR}\n\t\t\tCOMMENT \"Compiling ${FILENAME}\"\n\t\t)\n\t\tlist(APPEND SPV_SHADERS ${SHADER_BINARY_DIR}/${FILENAME}.spv)\n\tendforeach()\n\n\tadd_custom_target(shaders ALL DEPENDS ${SPV_SHADERS})\n\n\tbin2c(\"vulkan/image/vertex_shader.spv\" \"vulkan_image_vertex.h\" \"caspar::accelerator::vulkan\" \"vertex_shader\")\n\tbin2c(\"vulkan/image/fragment_shader.spv\" \"vulkan_image_fragment.h\" \"caspar::accelerator::vulkan\" \"fragment_shader\")\nENDIF()\n\nbin2c(\"ogl/image/shader.vert\" \"ogl_image_vertex.h\" \"caspar::accelerator::ogl\" \"vertex_shader\")\nbin2c(\"ogl/image/shader.frag\" \"ogl_image_fragment.h\" \"caspar::accelerator::ogl\" \"fragment_shader\")\n\ncasparcg_add_library(accelerator SOURCES ${SOURCES} ${HEADERS})\ntarget_include_directories(accelerator PRIVATE .. ${CMAKE_CURRENT_BINARY_DIR})\ntarget_precompile_headers(accelerator PRIVATE StdAfx.h)\ntarget_link_libraries(accelerator PRIVATE common core GLEW::glew sfml-window)\n\nIF(ENABLE_VULKAN)\n\ttarget_link_libraries(accelerator PRIVATE vk-bootstrap::vk-bootstrap GPUOpen::VulkanMemoryAllocator Vulkan::Headers)\n\ttarget_compile_definitions(accelerator PUBLIC VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1)\nENDIF()\n\nsource_group(sources ./.*)\nsource_group(sources\\\\cpu\\\\image cpu/image/.*)\nsource_group(sources\\\\cpu\\\\util cpu/util/.*)\nsource_group(sources\\\\ogl\\\\image ogl/image/.*)\nsource_group(sources\\\\ogl\\\\util ogl/util/.*)\n\nIF(ENABLE_VULKAN)\n\tsource_group(sources\\\\vulkan\\\\image vulkan/image/.*)\n\tsource_group(sources\\\\vulkan\\\\util vulkan/util/.*)\nENDIF()"
  },
  {
    "path": "src/accelerator/StdAfx.h",
    "content": "#include <GL/glew.h>\n#include <algorithm>\n#include <array>\n#include <boost/algorithm/cxx11/all_of.hpp>\n#include <boost/asio/deadline_timer.hpp>\n#include <boost/asio/dispatch.hpp>\n#include <boost/asio/io_context.hpp>\n#include <boost/asio/post.hpp>\n#include <boost/asio/spawn.hpp>\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n#include <boost/range/algorithm_ext/erase.hpp>\n#include <cmath>\n#include <common/array.h>\n#include <common/assert.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/future.h>\n#include <common/gl/gl_check.h>\n#include <common/memory.h>\n#include <common/scope_exit.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/frame_visitor.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <core/fwd.h>\n#include <core/mixer/image/blend_modes.h>\n#include <core/mixer/image/image_mixer.h>\n#include <core/video_format.h>\n#include <cstddef>\n#include <cstdint>\n#include <future>\n#include <memory>\n#include <mutex>\n#include <set>\n#include <string>\n#include <tbb/concurrent_queue.h>\n#include <tbb/concurrent_unordered_map.h>\n#include <thread>\n#include <type_traits>\n#include <unordered_map>\n#include <vector>\n"
  },
  {
    "path": "src/accelerator/accelerator.cpp",
    "content": "#include \"accelerator.h\"\n\n#include \"ogl/image/image_mixer.h\"\n#include \"ogl/util/device.h\"\n\n#ifdef ENABLE_VULKAN\n#include \"vulkan/image/image_mixer.h\"\n#include \"vulkan/util/device.h\"\n#endif\n\n#include <boost/property_tree/ptree.hpp>\n\n#include <common/bit_depth.h>\n#include <common/except.h>\n\n#include <core/mixer/image/image_mixer.h>\n\n#include <memory>\n#include <mutex>\n#include <utility>\n\nnamespace caspar { namespace accelerator {\n\nstruct accelerator::impl\n{\n    std::shared_ptr<accelerator_device> device_;\n    const core::video_format_repository format_repository_;\n    accelerator_backend                 backend_;\n\n    impl(const core::video_format_repository format_repository)\n        : format_repository_(format_repository)\n        , backend_(accelerator_backend::invalid)\n    {\n    }\n\n    void set_backend(accelerator_backend backend)\n    {\n        if (backend_ != accelerator_backend::invalid) {\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Accelerator backend already set\"));\n        }\n\n        backend_ = backend;\n    }\n\n    std::unique_ptr<core::image_mixer> create_image_mixer(int channel_id, common::bit_depth depth)\n    {\n#ifdef ENABLE_VULKAN\n        if (backend_ == accelerator_backend::vulkan) {\n            return std::make_unique<vulkan::image_mixer>(\n                spl::make_shared_ptr(std::dynamic_pointer_cast<vulkan::device>(get_device())),\n                channel_id,\n                format_repository_.get_max_video_format_size(),\n                depth);\n        }\n#endif\n        return std::make_unique<ogl::image_mixer>(\n            spl::make_shared_ptr(std::dynamic_pointer_cast<ogl::device>(get_device())),\n            channel_id,\n            format_repository_.get_max_video_format_size(),\n            depth);\n    }\n\n    std::shared_ptr<accelerator_device> get_device()\n    {\n        if (backend_ == accelerator_backend::invalid) {\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Accelerator backend not set\"));\n        }\n#ifdef ENABLE_VULKAN\n        if (backend_ == accelerator_backend::vulkan) {\n            if (!device_) {\n                device_ = std::dynamic_pointer_cast<accelerator_device>(std::make_shared<vulkan::device>());\n            }\n\n            return device_;\n        }\n#endif\n\n        if (!device_) {\n            device_ = std::dynamic_pointer_cast<accelerator_device>(std::make_shared<ogl::device>());\n        }\n        return device_;\n    }\n};\n\naccelerator::accelerator(const core::video_format_repository format_repository)\n    : impl_(std::make_unique<impl>(format_repository))\n{\n}\n\naccelerator::~accelerator() {}\n\nvoid accelerator::set_backend(accelerator_backend backend) { impl_->set_backend(backend); }\n\nstd::unique_ptr<core::image_mixer> accelerator::create_image_mixer(const int channel_id, common::bit_depth depth)\n{\n    return impl_->create_image_mixer(channel_id, depth);\n}\n\nstd::shared_ptr<accelerator_device> accelerator::get_device() const { return impl_->get_device(); }\n\n}} // namespace caspar::accelerator\n"
  },
  {
    "path": "src/accelerator/accelerator.h",
    "content": "#pragma once\n\n#include <common/bit_depth.h>\n\n#include <core/frame/pixel_format.h>\n#include <core/mixer/mixer.h>\n#include <core/video_format.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <future>\n#include <memory>\n#include <string>\n\nnamespace caspar { namespace accelerator {\n\nclass accelerator_device\n{\n  public:\n    virtual boost::property_tree::wptree info() const = 0;\n    virtual std::future<void>            gc()         = 0;\n};\n\nenum class accelerator_backend\n{\n    invalid = 0,\n    opengl,\n#ifdef ENABLE_VULKAN\n    vulkan,\n#endif\n};\n\nclass accelerator\n{\n  public:\n    explicit accelerator(const core::video_format_repository format_repository);\n    accelerator(accelerator&) = delete;\n    ~accelerator();\n\n    accelerator& operator=(accelerator&) = delete;\n\n    void set_backend(accelerator_backend backend);\n\n    std::unique_ptr<caspar::core::image_mixer> create_image_mixer(int channel_id, common::bit_depth depth);\n\n    std::shared_ptr<accelerator_device> get_device() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}} // namespace caspar::accelerator\n"
  },
  {
    "path": "src/accelerator/d3d/d3d_device.cpp",
    "content": "#include \"d3d_device.h\"\n\n#include \"d3d_device_context.h\"\n#include \"d3d_texture2d.h\"\n\n#include <common/assert.h>\n#include <common/except.h>\n#include <common/log.h>\n#include <common/utf.h>\n\n#include <tbb/concurrent_queue.h>\n#include <tbb/concurrent_unordered_map.h>\n\n#include <d3d11_1.h>\n\n#include <GL/glew.h>\n#include <GL/wglew.h>\n\n#include <atlcomcli.h>\n#include <mutex>\n\nnamespace caspar { namespace accelerator { namespace d3d {\nstruct d3d_device::impl : public std::enable_shared_from_this<impl>\n{\n    using texture_queue_t = tbb::concurrent_bounded_queue<std::shared_ptr<d3d_texture2d>>;\n\n    mutable std::mutex                                     device_pools_mutex_;\n    tbb::concurrent_unordered_map<size_t, texture_queue_t> device_pools_;\n\n    std::wstring                        adaptor_name_ = L\"N/A\";\n    std::shared_ptr<ID3D11Device>       device_;\n    std::shared_ptr<d3d_device_context> ctx_;\n\n    impl()\n    {\n        HRESULT hr;\n\n        UINT flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;\n\n        D3D_FEATURE_LEVEL feature_levels[] = {\n            D3D_FEATURE_LEVEL_11_1,\n            D3D_FEATURE_LEVEL_11_0,\n            D3D_FEATURE_LEVEL_10_1,\n            D3D_FEATURE_LEVEL_10_0,\n        };\n        UINT num_feature_levels = sizeof(feature_levels) / sizeof(feature_levels[0]);\n\n        D3D_FEATURE_LEVEL selected_level = D3D_FEATURE_LEVEL_9_3;\n\n        ID3D11Device*        pdev = nullptr;\n        ID3D11DeviceContext* pctx = nullptr;\n\n        hr = D3D11CreateDevice(nullptr,\n                               D3D_DRIVER_TYPE_HARDWARE,\n                               nullptr,\n                               flags,\n                               feature_levels,\n                               num_feature_levels,\n                               D3D11_SDK_VERSION,\n                               &pdev,\n                               &selected_level,\n                               &pctx);\n\n        if (hr == E_INVALIDARG) {\n            // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1\n            // so we need to retry without it\n            hr = D3D11CreateDevice(nullptr,\n                                   D3D_DRIVER_TYPE_HARDWARE,\n                                   nullptr,\n                                   flags,\n                                   &feature_levels[1],\n                                   num_feature_levels - 1,\n                                   D3D11_SDK_VERSION,\n                                   &pdev,\n                                   &selected_level,\n                                   &pctx);\n        }\n\n        if (SUCCEEDED(hr)) {\n            device_ = std::shared_ptr<ID3D11Device>(pdev, [](ID3D11Device* p) {\n                if (p)\n                    p->Release();\n            });\n            ctx_    = std::make_shared<d3d_device_context>(pctx);\n\n            CComQIPtr<ID3D11Device1> d3d11_1(device_.get());\n            if (!d3d11_1) {\n                return;\n            }\n\n            /* needs to support extended resource sharing */\n            D3D11_FEATURE_DATA_D3D11_OPTIONS opts = {};\n            hr = d3d11_1->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &opts, sizeof(opts));\n            if (FAILED(hr) || !opts.ExtendedResourceSharing) {\n                CASPAR_THROW_EXCEPTION(bad_alloc() << msg_info(L\"Device does not support ExtendedResourceSharing\"));\n            }\n\n            {\n                CComQIPtr<IDXGIDevice> dxgi_dev = device_.get();\n                if (dxgi_dev) {\n                    IDXGIAdapter* dxgi_adapt = nullptr;\n                    hr                       = dxgi_dev->GetAdapter(&dxgi_adapt);\n                    if (SUCCEEDED(hr)) {\n                        DXGI_ADAPTER_DESC desc;\n                        hr = dxgi_adapt->GetDesc(&desc);\n                        dxgi_adapt->Release();\n                        if (SUCCEEDED(hr)) {\n                            adaptor_name_ = u16(desc.Description);\n                        }\n                    }\n                }\n            }\n\n            CASPAR_LOG(info) << L\"D3D11: Selected adapter: \" << adaptor_name_;\n\n            CASPAR_LOG(info) << L\"D3D11: Selected feature level: \" << selected_level;\n        } else\n            CASPAR_THROW_EXCEPTION(bad_alloc() << msg_info(L\"Failed to create d3d11 device\"));\n    }\n\n    std::shared_ptr<d3d_texture2d> open_shared_texture(void* handle)\n    {\n        ID3D11Texture2D* tex = nullptr;\n\n        CComQIPtr<ID3D11Device1> dev = device_.get();\n        if (dev) {\n            auto hr = dev->OpenSharedResource1((HANDLE)(uintptr_t)handle, __uuidof(ID3D11Texture2D), (void**)(&tex));\n            if (SUCCEEDED(hr))\n                return std::make_shared<d3d_texture2d>(tex);\n        }\n\n        return nullptr;\n    }\n};\n\nd3d_device::d3d_device()\n    : impl_(new impl())\n{\n}\n\nd3d_device::~d3d_device() {}\n\nstd::wstring d3d_device::adapter_name() const { return impl_->adaptor_name_; }\n\nvoid* d3d_device::device() const { return impl_->device_.get(); }\n\nstd::shared_ptr<d3d_device_context> d3d_device::immedidate_context() { return impl_->ctx_; }\n\nstd::shared_ptr<d3d_texture2d> d3d_device::open_shared_texture(void* handle)\n{\n    return impl_->open_shared_texture(handle);\n}\n\nconst std::shared_ptr<d3d_device>& d3d_device::get_device()\n{\n    static std::shared_ptr<d3d_device> device = []() -> std::shared_ptr<d3d_device> {\n        if (!WGLEW_NV_DX_interop2) {\n            // Device doesn't support the extension, so skip\n            return nullptr;\n        }\n\n        try {\n            return std::make_shared<d3d_device>();\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n\n        return nullptr;\n    }();\n\n    return device;\n}\n}}} // namespace caspar::accelerator::d3d"
  },
  {
    "path": "src/accelerator/d3d/d3d_device.h",
    "content": "#pragma once\n\n#include <memory>\n#include <string>\n\nnamespace caspar { namespace accelerator { namespace d3d {\nclass d3d_device\n{\n  public:\n    d3d_device();\n    ~d3d_device();\n\n    d3d_device(const d3d_device&)            = delete;\n    d3d_device& operator=(const d3d_device&) = delete;\n\n    std::wstring adapter_name() const;\n\n    void* device() const;\n\n    std::shared_ptr<class d3d_device_context> immedidate_context();\n\n    std::shared_ptr<class d3d_texture2d> open_shared_texture(void* handle);\n\n    static const std::shared_ptr<d3d_device>& get_device();\n\n  private:\n    struct impl;\n    std::shared_ptr<impl> impl_;\n};\n}}} // namespace caspar::accelerator::d3d"
  },
  {
    "path": "src/accelerator/d3d/d3d_device_context.cpp",
    "content": "#include \"d3d_device_context.h\"\n\nnamespace caspar { namespace accelerator { namespace d3d {\nd3d_device_context::d3d_device_context(ID3D11DeviceContext* ctx)\n    : ctx_(std::shared_ptr<ID3D11DeviceContext>(ctx, [](ID3D11DeviceContext* p) {\n        if (p)\n            p->Release();\n    }))\n{\n}\n}}} // namespace caspar::accelerator::d3d"
  },
  {
    "path": "src/accelerator/d3d/d3d_device_context.h",
    "content": "#pragma once\n\n#undef NOMINMAX\n#define NOMINMAX\n\n#include <d3d11_1.h>\n\n#include <memory>\n\nnamespace caspar { namespace accelerator { namespace d3d {\nclass d3d_device_context\n{\n  public:\n    d3d_device_context(ID3D11DeviceContext* ctx);\n\n    d3d_device_context(const d3d_device_context&)            = delete;\n    d3d_device_context& operator=(const d3d_device_context&) = delete;\n\n    ID3D11DeviceContext* context() const { return ctx_.get(); }\n\n  private:\n    std::shared_ptr<ID3D11DeviceContext> const ctx_;\n};\n}}} // namespace caspar::accelerator::d3d"
  },
  {
    "path": "src/accelerator/d3d/d3d_texture2d.cpp",
    "content": "#include \"d3d_texture2d.h\"\n\n#include <common/gl/gl_check.h>\n\n#include <GL/glew.h>\n#include <GL/wglew.h>\n#include <atlcomcli.h>\n\n#include \"../ogl/util/device.h\"\n\nnamespace caspar { namespace accelerator { namespace d3d {\n\nd3d_texture2d::d3d_texture2d(ID3D11Texture2D* tex)\n    : texture_(tex)\n{\n    share_handle_ = nullptr;\n\n    D3D11_TEXTURE2D_DESC desc;\n    texture_->GetDesc(&desc);\n    width_  = desc.Width;\n    height_ = desc.Height;\n    format_ = desc.Format;\n\n    if ((desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE) == 0) {\n        CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"D3D texture is not sharable.\"));\n    }\n\n    {\n        CComQIPtr<IDXGIResource1> res = texture_;\n        if (res) {\n            res->CreateSharedHandle(nullptr, DXGI_SHARED_RESOURCE_READ, nullptr, &share_handle_);\n        }\n    }\n\n    if (share_handle_ == nullptr || !wglDXSetResourceShareHandleNV(texture_, share_handle_)) {\n        CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to setup shared d3d texture.\"));\n    }\n}\n\nd3d_texture2d::~d3d_texture2d()\n{\n    const std::shared_ptr<ogl::device> ogl = ogl_.lock();\n    if (ogl != nullptr) {\n        // The cleanup must happen be done on the opengl thread\n        ogl->dispatch_sync([&] {\n            const std::shared_ptr<void> interop = ogl->d3d_interop();\n            if (texture_handle_ != nullptr && interop != nullptr) {\n                wglDXUnlockObjectsNV(interop.get(), 1, &texture_handle_);\n                wglDXUnregisterObjectNV(interop.get(), texture_handle_);\n                texture_handle_ = nullptr;\n            }\n\n            if (gl_texture_id_ != 0) {\n                GL(glDeleteTextures(1, &gl_texture_id_));\n                gl_texture_id_ = 0;\n            }\n\n            // TODO: This appears to be leaking something opengl, but it is not clear what that is.\n\n            if (share_handle_ != nullptr) {\n                CloseHandle(share_handle_);\n                share_handle_ = nullptr;\n            }\n        });\n    }\n\n    if (texture_ != nullptr) {\n        texture_->Release();\n        texture_ = nullptr;\n    }\n}\n\nvoid d3d_texture2d::gen_gl_texture(std::shared_ptr<ogl::device> ogl)\n{\n    if (gl_texture_id_ != 0 || texture_ == nullptr)\n        return;\n\n    ogl_ = ogl;\n\n    const std::shared_ptr<void> interop = ogl->d3d_interop();\n    if (!interop) {\n        CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"d3d interop not setup to bind shared d3d texture.\"));\n    }\n\n    ogl->dispatch_sync([&] {\n        GL(glGenTextures(1, &gl_texture_id_));\n\n        texture_handle_ =\n            wglDXRegisterObjectNV(interop.get(), texture_, gl_texture_id_, GL_TEXTURE_2D, WGL_ACCESS_READ_ONLY_NV);\n        if (!texture_handle_) {\n            GL(glDeleteTextures(1, &gl_texture_id_));\n            gl_texture_id_ = 0;\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to bind shared d3d texture.\"));\n        }\n\n        if (!wglDXLockObjectsNV(interop.get(), 1, &texture_handle_)) {\n            wglDXUnregisterObjectNV(interop.get(), texture_handle_);\n            texture_handle_ = nullptr;\n            GL(glDeleteTextures(1, &gl_texture_id_));\n            gl_texture_id_ = 0;\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to lock shared d3d texture.\"));\n        }\n    });\n}\n\n}}} // namespace caspar::accelerator::d3d"
  },
  {
    "path": "src/accelerator/d3d/d3d_texture2d.h",
    "content": "#pragma once\n\n#undef NOMINMAX\n#define NOMINMAX\n\n#include <d3d11_1.h>\n\n#include <memory>\n\nnamespace caspar { namespace accelerator { namespace d3d {\n\nclass d3d_texture2d\n{\n  public:\n    d3d_texture2d(ID3D11Texture2D* tex);\n\n    ~d3d_texture2d();\n\n    d3d_texture2d(const d3d_texture2d&)            = delete;\n    d3d_texture2d& operator=(const d3d_texture2d&) = delete;\n\n    uint32_t width() const { return width_; }\n\n    uint32_t height() const { return height_; }\n\n    DXGI_FORMAT format() const { return format_; }\n\n    void* share_handle() const { return share_handle_; }\n\n    ID3D11Texture2D* texture() const { return texture_; }\n\n    uint32_t gl_texture_id() const { return gl_texture_id_; }\n\n    void gen_gl_texture(std::shared_ptr<ogl::device>);\n\n  private:\n    HANDLE share_handle_;\n\n    ID3D11Texture2D* texture_;\n    uint32_t         width_  = 0;\n    uint32_t         height_ = 0;\n    DXGI_FORMAT      format_ = DXGI_FORMAT::DXGI_FORMAT_UNKNOWN;\n\n    std::weak_ptr<ogl::device> ogl_;\n    HANDLE                     texture_handle_ = nullptr;\n    uint32_t                   gl_texture_id_  = 0;\n};\n}}} // namespace caspar::accelerator::d3d"
  },
  {
    "path": "src/accelerator/ogl/image/image_kernel.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"image_kernel.h\"\n\n#include \"image_shader.h\"\n\n#include \"../util/device.h\"\n#include \"../util/shader.h\"\n#include \"../util/texture.h\"\n\n#include <common/assert.h>\n#include <common/gl/gl_check.h>\n\n#include <core/frame/frame_transform.h>\n#include <core/frame/pixel_format.h>\n\n#include <boost/algorithm/cxx11/all_of.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n\n#include <GL/glew.h>\n\n#include <array>\n#include <cmath>\n\nnamespace caspar::accelerator::ogl {\n\ndouble get_precision_factor(common::bit_depth depth)\n{\n    switch (depth) {\n        case common::bit_depth::bit8:\n            return 1.0;\n        case common::bit_depth::bit10:\n            return 64.0;\n        case common::bit_depth::bit12:\n            return 16.0;\n        case common::bit_depth::bit16:\n            return 1.0;\n        default:\n            return 1.0;\n    }\n}\n\nbool is_above_screen(double y) { return y < 0.0; }\n\nbool is_below_screen(double y) { return y > 1.0; }\n\nbool is_left_of_screen(double x) { return x < 0.0; }\n\nbool is_right_of_screen(double x) { return x > 1.0; }\n\nbool is_outside_screen(const std::vector<core::frame_geometry::coord>& coords)\n{\n    auto x_coords =\n        coords | boost::adaptors::transformed([](const core::frame_geometry::coord& c) { return c.vertex_x; });\n    auto y_coords =\n        coords | boost::adaptors::transformed([](const core::frame_geometry::coord& c) { return c.vertex_y; });\n\n    return boost::algorithm::all_of(x_coords, &is_left_of_screen) ||\n           boost::algorithm::all_of(x_coords, &is_right_of_screen) ||\n           boost::algorithm::all_of(y_coords, &is_above_screen) || boost::algorithm::all_of(y_coords, &is_below_screen);\n}\n\nstatic const double epsilon = 0.001;\n\nstruct image_kernel::impl\n{\n    spl::shared_ptr<device> ogl_;\n    spl::shared_ptr<shader> shader_;\n    GLuint                  vao_;\n    GLuint                  vbo_;\n\n    explicit impl(const spl::shared_ptr<device>& ogl)\n        : ogl_(ogl)\n        , shader_(ogl_->dispatch_sync([&] { return get_image_shader(ogl); }))\n    {\n        ogl_->dispatch_sync([&] {\n            GL(glGenVertexArrays(1, &vao_));\n            GL(glGenBuffers(1, &vbo_));\n        });\n    }\n\n    ~impl()\n    {\n        ogl_->dispatch_sync([&] {\n            GL(glDeleteVertexArrays(1, &vao_));\n            GL(glDeleteBuffers(1, &vbo_));\n        });\n    }\n\n    void draw(draw_params params)\n    {\n        CASPAR_ASSERT(params.pix_desc.planes.size() == params.textures.size());\n\n        if (params.textures.empty() || !params.background) {\n            return;\n        }\n\n        if (params.transforms.image_transform.opacity < epsilon) {\n            return;\n        }\n\n        auto coords = params.geometry.data();\n        if (coords.empty()) {\n            return;\n        }\n\n        auto transforms = params.transforms;\n\n        auto const first_plane = params.pix_desc.planes.at(0);\n        if (params.geometry.mode() != core::frame_geometry::scale_mode::stretch && first_plane.width > 0 &&\n            first_plane.height > 0) {\n            auto width_scale  = static_cast<double>(params.target_width) / static_cast<double>(first_plane.width);\n            auto height_scale = static_cast<double>(params.target_height) / static_cast<double>(first_plane.height);\n\n            core::image_transform transform;\n            double                target_scale;\n            switch (params.geometry.mode()) {\n                case core::frame_geometry::scale_mode::fit:\n                    target_scale = std::min(width_scale, height_scale);\n\n                    transform.fill_scale[0] *= target_scale / width_scale;\n                    transform.fill_scale[1] *= target_scale / height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::fill:\n                    target_scale = std::max(width_scale, height_scale);\n                    transform.fill_scale[0] *= target_scale / width_scale;\n                    transform.fill_scale[1] *= target_scale / height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::original:\n                    transform.fill_scale[0] /= width_scale;\n                    transform.fill_scale[1] /= height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::hfill:\n                    transform.fill_scale[1] *= width_scale / height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::vfill:\n                    transform.fill_scale[0] *= height_scale / width_scale;\n                    break;\n\n                default:;\n            }\n\n            transforms = transforms.combine_transform(transform, params.aspect_ratio);\n        }\n\n        coords = transforms.transform_coords(coords);\n\n        // Skip drawing if all the coordinates will be outside the screen.\n        if (coords.size() < 3 || is_outside_screen(coords)) {\n            return;\n        }\n\n        double precision_factor[4] = {1, 1, 1, 1};\n\n        // Bind textures\n\n        for (int n = 0; n < params.textures.size(); ++n) {\n            params.textures[n]->bind(n);\n            precision_factor[n] = get_precision_factor(params.textures[n]->depth());\n        }\n\n        if (params.local_key) {\n            params.local_key->bind(static_cast<int>(texture_id::local_key));\n        }\n\n        if (params.layer_key) {\n            params.layer_key->bind(static_cast<int>(texture_id::layer_key));\n        }\n\n        const auto is_hd       = params.pix_desc.planes.at(0).height > 700;\n        const auto color_space = is_hd ? params.pix_desc.color_space : core::color_space::bt601;\n\n        const float color_matrices[3][9] = {\n            {1.0, 0.0, 1.402, 1.0, -0.344, -0.509, 1.0, 1.772, 0.0},                          // bt.601\n            {1.0, 0.0, 1.5748, 1.0, -0.1873, -0.4681, 1.0, 1.8556, 0.0},                      // bt.709\n            {1.0, 0.0, 1.4746, 1.0, -0.16455312684366, -0.57135312684366, 1.0, 1.8814, 0.0}}; // bt.2020\n        const auto color_matrix = color_matrices[static_cast<int>(color_space)];\n\n        const float luma_coefficients[3][3] = {{0.299, 0.587, 0.114},     // bt.601\n                                               {0.2126, 0.7152, 0.0722},  // bt.709\n                                               {0.2627, 0.6780, 0.0593}}; // bt.2020\n        const auto  luma_coeff              = luma_coefficients[static_cast<int>(color_space)];\n\n        // Setup shader\n        shader_->use();\n\n        shader_->set(\"is_straight_alpha\", params.pix_desc.is_straight_alpha);\n        shader_->set(\"plane[0]\", texture_id::plane0);\n        shader_->set(\"plane[1]\", texture_id::plane1);\n        shader_->set(\"plane[2]\", texture_id::plane2);\n        shader_->set(\"plane[3]\", texture_id::plane3);\n        shader_->set(\"precision_factor[0]\", precision_factor[0]);\n        shader_->set(\"precision_factor[1]\", precision_factor[1]);\n        shader_->set(\"precision_factor[2]\", precision_factor[2]);\n        shader_->set(\"precision_factor[3]\", precision_factor[3]);\n        shader_->set(\"local_key\", texture_id::local_key);\n        shader_->set(\"layer_key\", texture_id::layer_key);\n        shader_->set_matrix3(\"color_matrix\", color_matrix);\n        shader_->set(\"luma_coeff\", luma_coeff[0], luma_coeff[1], luma_coeff[2]);\n        shader_->set(\"has_local_key\", static_cast<bool>(params.local_key));\n        shader_->set(\"has_layer_key\", static_cast<bool>(params.layer_key));\n        shader_->set(\"pixel_format\", params.pix_desc.format);\n        shader_->set(\"opacity\", transforms.image_transform.is_key ? 1.0 : transforms.image_transform.opacity);\n\n        if (transforms.image_transform.chroma.enable) {\n            shader_->set(\"chroma\", true);\n            shader_->set(\"chroma_show_mask\", transforms.image_transform.chroma.show_mask);\n            shader_->set(\"chroma_target_hue\", transforms.image_transform.chroma.target_hue / 360.0);\n            shader_->set(\"chroma_hue_width\", transforms.image_transform.chroma.hue_width);\n            shader_->set(\"chroma_min_saturation\", transforms.image_transform.chroma.min_saturation);\n            shader_->set(\"chroma_min_brightness\", transforms.image_transform.chroma.min_brightness);\n            shader_->set(\"chroma_softness\", 1.0 + transforms.image_transform.chroma.softness);\n            shader_->set(\"chroma_spill_suppress\", transforms.image_transform.chroma.spill_suppress / 360.0);\n            shader_->set(\"chroma_spill_suppress_saturation\",\n                         transforms.image_transform.chroma.spill_suppress_saturation);\n        } else {\n            shader_->set(\"chroma\", false);\n        }\n\n        // Setup blend_func\n\n        if (transforms.image_transform.is_key) {\n            params.blend_mode = core::blend_mode::normal;\n        }\n\n        params.background->bind(static_cast<int>(texture_id::background));\n        shader_->set(\"background\", texture_id::background);\n        shader_->set(\"blend_mode\", params.blend_mode);\n        shader_->set(\"keyer\", params.keyer);\n\n        // Setup image-adjustments\n        shader_->set(\"invert\", transforms.image_transform.invert);\n\n        if (transforms.image_transform.levels.min_input > epsilon ||\n            transforms.image_transform.levels.max_input < 1.0 - epsilon ||\n            transforms.image_transform.levels.min_output > epsilon ||\n            transforms.image_transform.levels.max_output < 1.0 - epsilon ||\n            std::abs(transforms.image_transform.levels.gamma - 1.0) > epsilon) {\n            shader_->set(\"levels\", true);\n            shader_->set(\"min_input\", transforms.image_transform.levels.min_input);\n            shader_->set(\"max_input\", transforms.image_transform.levels.max_input);\n            shader_->set(\"min_output\", transforms.image_transform.levels.min_output);\n            shader_->set(\"max_output\", transforms.image_transform.levels.max_output);\n            shader_->set(\"gamma\", transforms.image_transform.levels.gamma);\n        } else {\n            shader_->set(\"levels\", false);\n        }\n\n        if (std::abs(transforms.image_transform.brightness - 1.0) > epsilon ||\n            std::abs(transforms.image_transform.saturation - 1.0) > epsilon ||\n            std::abs(transforms.image_transform.contrast - 1.0) > epsilon) {\n            shader_->set(\"csb\", true);\n\n            shader_->set(\"brt\", transforms.image_transform.brightness);\n            shader_->set(\"sat\", transforms.image_transform.saturation);\n            shader_->set(\"con\", transforms.image_transform.contrast);\n        } else {\n            shader_->set(\"csb\", false);\n        }\n\n        // Setup drawing area\n\n        GL(glViewport(0, 0, params.background->width(), params.background->height()));\n        glDisable(GL_DEPTH_TEST);\n\n        // Set render target\n        params.background->attach();\n\n        // Draw\n        GL(glBindVertexArray(vao_));\n        GL(glBindBuffer(GL_ARRAY_BUFFER, vbo_));\n\n        GL(glBufferData(GL_ARRAY_BUFFER,\n                        static_cast<GLsizeiptr>(sizeof(core::frame_geometry::coord)) * coords.size(),\n                        coords.data(),\n                        GL_STATIC_DRAW));\n\n        auto stride = static_cast<GLsizei>(sizeof(core::frame_geometry::coord));\n\n        auto vtx_loc = shader_->get_attrib_location(\"Position\");\n        auto tex_loc = shader_->get_attrib_location(\"TexCoordIn\");\n\n        GL(glEnableVertexAttribArray(vtx_loc));\n        GL(glEnableVertexAttribArray(tex_loc));\n\n        GL(glVertexAttribPointer(vtx_loc, 2, GL_DOUBLE, GL_FALSE, stride, nullptr));\n        GL(glVertexAttribPointer(tex_loc, 4, GL_DOUBLE, GL_FALSE, stride, (GLvoid*)(2 * sizeof(GLdouble))));\n\n        GL(glDrawArrays(GL_TRIANGLE_FAN, 0, static_cast<GLsizei>(coords.size())));\n        GL(glTextureBarrier());\n\n        GL(glDisableVertexAttribArray(vtx_loc));\n        GL(glDisableVertexAttribArray(tex_loc));\n\n        GL(glBindVertexArray(0));\n        GL(glBindBuffer(GL_ARRAY_BUFFER, 0));\n\n        // Cleanup\n        GL(glDisable(GL_SCISSOR_TEST));\n        GL(glDisable(GL_BLEND));\n    }\n};\n\nimage_kernel::image_kernel(const spl::shared_ptr<device>& ogl)\n    : impl_(new impl(ogl))\n{\n}\nimage_kernel::~image_kernel() {}\nvoid image_kernel::draw(const draw_params& params) { impl_->draw(params); }\n\n} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/image/image_kernel.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/mixer/image/blend_modes.h>\n\n#include <common/memory.h>\n\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n\n#include <utility>\n\n#include \"../util/matrix.h\"\n#include \"../util/transforms.h\"\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nenum class keyer\n{\n    linear = 0,\n    additive,\n};\n\nstruct draw_params final\n{\n    core::pixel_format_desc                     pix_desc = core::pixel_format_desc(core::pixel_format::invalid);\n    std::vector<spl::shared_ptr<class texture>> textures;\n    draw_transforms                             transforms;\n    core::frame_geometry                        geometry   = core::frame_geometry::get_default();\n    core::blend_mode                            blend_mode = core::blend_mode::normal;\n    ogl::keyer                                  keyer      = ogl::keyer::linear;\n    std::shared_ptr<class texture>              background;\n    std::shared_ptr<class texture>              local_key;\n    std::shared_ptr<class texture>              layer_key;\n    double                                      aspect_ratio = 1.0;\n    int                                         target_width;\n    int                                         target_height;\n};\n\nclass image_kernel final\n{\n    image_kernel(const image_kernel&);\n    image_kernel& operator=(const image_kernel&);\n\n  public:\n    explicit image_kernel(const spl::shared_ptr<class device>& ogl);\n    ~image_kernel();\n\n    void draw(const draw_params& params);\n\n  private:\n    struct impl;\n    spl::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/image/image_mixer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"image_mixer.h\"\n\n#include \"image_kernel.h\"\n\n#include \"../util/buffer.h\"\n#include \"../util/device.h\"\n#include \"../util/texture.h\"\n\n#ifdef WIN32\n#include \"../../d3d/d3d_texture2d.h\"\n#endif\n\n#include <boost/align/aligned_allocator.hpp>\n\n#include <common/array.h>\n#include <common/bit_depth.h>\n#include <common/future.h>\n#include <common/log.h>\n\n#include <core/frame/frame.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <core/video_format.h>\n\n#include <GL/glew.h>\n\n#include <any>\n#include <vector>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nusing future_texture = std::shared_future<std::shared_ptr<texture>>;\n\nstruct item\n{\n    core::pixel_format_desc     pix_desc = core::pixel_format_desc(core::pixel_format::invalid);\n    std::vector<future_texture> textures;\n    draw_transforms             transforms;\n    core::frame_geometry        geometry = core::frame_geometry::get_default();\n};\n\nstruct layer\n{\n    std::vector<layer> sublayers;\n    std::vector<item>  items;\n    core::blend_mode   blend_mode;\n\n    explicit layer(core::blend_mode blend_mode)\n        : blend_mode(blend_mode)\n    {\n    }\n};\n\nclass image_renderer\n{\n    spl::shared_ptr<device> ogl_;\n    image_kernel            kernel_;\n    const size_t            max_frame_size_;\n    common::bit_depth       depth_;\n\n  public:\n    explicit image_renderer(const spl::shared_ptr<device>& ogl, const size_t max_frame_size, common::bit_depth depth)\n        : ogl_(ogl)\n        , kernel_(ogl_)\n        , max_frame_size_(max_frame_size)\n        , depth_(depth)\n    {\n    }\n\n    std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\n    operator()(std::vector<layer> layers, const core::video_format_desc& format_desc)\n    {\n        if (layers.empty()) { // Bypass GPU with empty frame.\n            static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_,\n                                                                                                       0);\n            return make_ready_future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>(\n                {array<const std::uint8_t>(buffer.data(), format_desc.size, true), nullptr});\n        }\n\n        auto f = std::move(\n            ogl_->dispatch_async([this, format_desc, layers = std::move(layers)]() mutable\n                                 -> std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<core::texture>> {\n                auto target_texture = ogl_->create_texture(format_desc.width, format_desc.height, 4, depth_);\n                draw(target_texture, std::move(layers), format_desc);\n                return {ogl_->copy_async(target_texture), target_texture};\n            }));\n\n        return std::async(\n            std::launch::deferred,\n            [f = std::move(f)]() mutable -> std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>> {\n                auto tuple = std::move(f.get());\n                return {std::move(std::get<0>(tuple).get()), std::move(std::get<1>(tuple))};\n            });\n    }\n\n    common::bit_depth depth() const { return depth_; }\n\n  private:\n    void draw(std::shared_ptr<texture>&      target_texture,\n              std::vector<layer>             layers,\n              const core::video_format_desc& format_desc)\n    {\n        std::shared_ptr<texture> layer_key_texture;\n\n        for (auto& layer : layers) {\n            draw(target_texture, layer.sublayers, format_desc);\n            draw(target_texture, std::move(layer), layer_key_texture, format_desc);\n        }\n    }\n\n    void draw(std::shared_ptr<texture>&      target_texture,\n              layer                          layer,\n              std::shared_ptr<texture>&      layer_key_texture,\n              const core::video_format_desc& format_desc)\n    {\n        if (layer.items.empty())\n            return;\n\n        std::shared_ptr<texture> local_key_texture;\n        std::shared_ptr<texture> local_mix_texture;\n\n        if (layer.blend_mode != core::blend_mode::normal) {\n            auto layer_texture = ogl_->create_texture(target_texture->width(), target_texture->height(), 4, depth_);\n\n            for (auto& item : layer.items)\n                draw(layer_texture,\n                     std::move(item),\n                     layer_key_texture,\n                     local_key_texture,\n                     local_mix_texture,\n                     format_desc);\n\n            draw(layer_texture, std::move(local_mix_texture), format_desc, core::blend_mode::normal);\n            draw(target_texture, std::move(layer_texture), format_desc, layer.blend_mode);\n        } else // fast path\n        {\n            for (auto& item : layer.items)\n                draw(target_texture,\n                     std::move(item),\n                     layer_key_texture,\n                     local_key_texture,\n                     local_mix_texture,\n                     format_desc);\n\n            draw(target_texture, std::move(local_mix_texture), format_desc, core::blend_mode::normal);\n        }\n\n        layer_key_texture = std::move(local_key_texture);\n    }\n\n    void draw(std::shared_ptr<texture>&      target_texture,\n              item                           item,\n              std::shared_ptr<texture>&      layer_key_texture,\n              std::shared_ptr<texture>&      local_key_texture,\n              std::shared_ptr<texture>&      local_mix_texture,\n              const core::video_format_desc& format_desc)\n    {\n        draw_params draw_params;\n        draw_params.target_width  = format_desc.square_width;\n        draw_params.target_height = format_desc.square_height;\n        // TODO: Pass the target color_space\n\n        draw_params.pix_desc   = std::move(item.pix_desc);\n        draw_params.transforms = std::move(item.transforms);\n        draw_params.geometry   = std::move(item.geometry);\n        draw_params.aspect_ratio =\n            static_cast<double>(format_desc.square_width) / static_cast<double>(format_desc.square_height);\n\n        for (auto& future_texture : item.textures) {\n            draw_params.textures.push_back(spl::make_shared_ptr(future_texture.get()));\n        }\n\n        if (draw_params.transforms.image_transform\n                .is_key) { // A key means we will use it for the next non-key item as a mask\n            local_key_texture =\n                local_key_texture ? local_key_texture\n                                  : ogl_->create_texture(target_texture->width(), target_texture->height(), 1, depth_);\n\n            draw_params.background = local_key_texture;\n            draw_params.local_key  = nullptr;\n            draw_params.layer_key  = nullptr;\n\n            kernel_.draw(std::move(draw_params));\n        } else if (draw_params.transforms.image_transform\n                       .is_mix) { // A mix means precomp the items to a texture, before drawing to the channel\n            local_mix_texture =\n                local_mix_texture ? local_mix_texture\n                                  : ogl_->create_texture(target_texture->width(), target_texture->height(), 4, depth_);\n\n            draw_params.background = local_mix_texture;\n            draw_params.local_key  = std::move(local_key_texture); // Use and reset the key\n            draw_params.layer_key  = layer_key_texture;\n\n            draw_params.keyer = keyer::additive;\n\n            kernel_.draw(std::move(draw_params));\n        } else {\n            // If there is a mix, this is the end so draw it and reset\n            draw(target_texture, std::move(local_mix_texture), format_desc, core::blend_mode::normal);\n\n            draw_params.background = target_texture;\n            draw_params.local_key  = std::move(local_key_texture);\n            draw_params.layer_key  = layer_key_texture;\n\n            kernel_.draw(std::move(draw_params));\n        }\n    }\n\n    void draw(std::shared_ptr<texture>&  target_texture,\n              std::shared_ptr<texture>&& source_texture,\n              core::video_format_desc    format_desc,\n              core::blend_mode           blend_mode = core::blend_mode::normal)\n    {\n        if (!source_texture)\n            return;\n\n        draw_params draw_params;\n        draw_params.target_width    = format_desc.square_width;\n        draw_params.target_height   = format_desc.square_height;\n        draw_params.pix_desc.format = core::pixel_format::bgra;\n        draw_params.pix_desc.planes = {core::pixel_format_desc::plane(\n            source_texture->width(), source_texture->height(), 4, source_texture->depth())};\n        draw_params.textures        = {spl::make_shared_ptr(source_texture)};\n        draw_params.blend_mode      = blend_mode;\n        draw_params.background      = target_texture;\n        draw_params.geometry        = core::frame_geometry::get_default();\n\n        kernel_.draw(std::move(draw_params));\n    }\n};\n\nstruct image_mixer::impl\n    : public core::frame_factory\n    , public std::enable_shared_from_this<impl>\n{\n    spl::shared_ptr<device>      ogl_;\n    image_renderer               renderer_;\n    std::vector<draw_transforms> transform_stack_;\n    std::vector<layer>           layers_; // layer/stream/items\n    std::vector<layer*>          layer_stack_;\n\n    double aspect_ratio_ = 1.0;\n\n  public:\n    impl(const spl::shared_ptr<device>& ogl, const int channel_id, const size_t max_frame_size, common::bit_depth depth)\n        : ogl_(ogl)\n        , renderer_(ogl, max_frame_size, depth)\n        , transform_stack_(1)\n    {\n        CASPAR_LOG(info) << L\"Initialized OpenGL Accelerated GPU Image Mixer for channel \" << channel_id;\n    }\n\n    void update_aspect_ratio(double aspect_ratio) { aspect_ratio_ = aspect_ratio; }\n\n    void push(const core::frame_transform& transform)\n    {\n        auto previous_layer_depth = transform_stack_.back().image_transform.layer_depth;\n\n        transform_stack_.push_back(transform_stack_.back().combine_transform(transform.image_transform, aspect_ratio_));\n\n        auto new_layer_depth = transform_stack_.back().image_transform.layer_depth;\n\n        if (previous_layer_depth < new_layer_depth) {\n            layer new_layer(transform_stack_.back().image_transform.blend_mode);\n\n            if (layer_stack_.empty()) {\n                layers_.push_back(std::move(new_layer));\n                layer_stack_.push_back(&layers_.back());\n            } else {\n                layer_stack_.back()->sublayers.push_back(std::move(new_layer));\n                layer_stack_.push_back(&layer_stack_.back()->sublayers.back());\n            }\n        }\n    }\n\n    void visit(const core::const_frame& frame)\n    {\n        if (frame.pixel_format_desc().format == core::pixel_format::invalid)\n            return;\n\n        if (frame.pixel_format_desc().planes.empty())\n            return;\n\n        item item;\n        item.pix_desc   = frame.pixel_format_desc();\n        item.transforms = transform_stack_.back();\n        item.geometry   = frame.geometry();\n\n        auto textures_ptr = std::any_cast<std::shared_ptr<std::vector<future_texture>>>(frame.opaque());\n\n        if (textures_ptr) {\n            item.textures = *textures_ptr;\n        } else {\n            for (int n = 0; n < static_cast<int>(item.pix_desc.planes.size()); ++n) {\n                item.textures.emplace_back(ogl_->copy_async(frame.image_data(n),\n                                                            item.pix_desc.planes[n].width,\n                                                            item.pix_desc.planes[n].height,\n                                                            item.pix_desc.planes[n].stride,\n                                                            item.pix_desc.planes[n].depth));\n            }\n        }\n\n        layer_stack_.back()->items.push_back(item);\n    }\n\n    void pop()\n    {\n        transform_stack_.pop_back();\n        layer_stack_.resize(transform_stack_.back().image_transform.layer_depth);\n    }\n\n    std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\n    render(const core::video_format_desc& format_desc)\n    {\n        return renderer_(std::move(layers_), format_desc);\n    }\n\n    core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override\n    {\n        return create_frame(tag, desc, common::bit_depth::bit8);\n    }\n\n    core::mutable_frame\n    create_frame(const void* tag, const core::pixel_format_desc& desc, common::bit_depth depth) override\n    {\n        std::vector<array<std::uint8_t>> image_data;\n        for (auto& plane : desc.planes) {\n            auto bytes_per_pixel = depth == common::bit_depth::bit8 ? 1 : 2;\n            image_data.push_back(ogl_->create_array(plane.size * bytes_per_pixel));\n        }\n\n        std::weak_ptr<image_mixer::impl> weak_self = shared_from_this();\n        return core::mutable_frame(tag,\n                                   std::move(image_data),\n                                   array<int32_t>{},\n                                   desc,\n                                   [weak_self, desc](std::vector<array<const std::uint8_t>> image_data) -> std::any {\n                                       auto self = weak_self.lock();\n                                       if (!self) {\n                                           return std::any{};\n                                       }\n                                       std::vector<future_texture> textures;\n                                       for (int n = 0; n < static_cast<int>(desc.planes.size()); ++n) {\n                                           textures.emplace_back(self->ogl_->copy_async(image_data[n],\n                                                                                        desc.planes[n].width,\n                                                                                        desc.planes[n].height,\n                                                                                        desc.planes[n].stride,\n                                                                                        desc.planes[n].depth));\n                                       }\n                                       return std::make_shared<decltype(textures)>(std::move(textures));\n                                   });\n    }\n\n#ifdef WIN32\n    core::const_frame import_d3d_texture(const void*                                tag,\n                                         const std::shared_ptr<d3d::d3d_texture2d>& d3d_texture,\n                                         core::pixel_format                         format,\n                                         common::bit_depth                          depth) override\n    {\n        // map directx texture with wgl texture\n        if (d3d_texture->gl_texture_id() == 0)\n            d3d_texture->gen_gl_texture(ogl_);\n\n        // copy directx texture to gl texture\n        auto gl_texture = ogl_->dispatch_sync([this, d3d_texture, depth]() {\n            return ogl_->copy_async(\n                d3d_texture->gl_texture_id(), d3d_texture->width(), d3d_texture->height(), 4, depth);\n        });\n\n        // make gl texture to draw\n        std::vector<future_texture> textures{make_ready_future(gl_texture.get())};\n\n        std::weak_ptr<image_mixer::impl> weak_self = shared_from_this();\n        core::pixel_format_desc          desc(core::pixel_format::bgra);\n        desc.planes.push_back(core::pixel_format_desc::plane(d3d_texture->width(), d3d_texture->height(), 4, depth));\n        auto frame = core::mutable_frame(\n            tag,\n            std::vector<array<uint8_t>>{},\n            array<int32_t>{},\n            desc,\n            [weak_self, texs = std::move(textures)](std::vector<array<const std::uint8_t>> image_data) -> std::any {\n                auto self = weak_self.lock();\n                if (!self) {\n                    return std::any{};\n                }\n\n                return std::make_shared<decltype(textures)>(std::move(texs));\n            });\n\n        return core::const_frame(std::move(frame));\n    }\n#endif\n\n    common::bit_depth depth() const { return renderer_.depth(); }\n};\n\nimage_mixer::image_mixer(const spl::shared_ptr<device>& ogl,\n                         const int                      channel_id,\n                         const size_t                   max_frame_size,\n                         common::bit_depth              depth)\n    : impl_(std::make_unique<impl>(ogl, channel_id, max_frame_size, depth))\n{\n}\nimage_mixer::~image_mixer() {}\nvoid image_mixer::push(const core::frame_transform& transform) { impl_->push(transform); }\nvoid image_mixer::visit(const core::const_frame& frame) { impl_->visit(frame); }\nvoid image_mixer::pop() { impl_->pop(); }\nvoid image_mixer::update_aspect_ratio(double aspect_ratio) { impl_->update_aspect_ratio(aspect_ratio); }\nstd::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\nimage_mixer::render(const core::video_format_desc& format_desc)\n{\n    return impl_->render(format_desc);\n}\ncore::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc)\n{\n    return impl_->create_frame(tag, desc);\n}\ncore::mutable_frame\nimage_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc, common::bit_depth depth)\n{\n    return impl_->create_frame(tag, desc, depth);\n}\n\n#ifdef WIN32\ncore::const_frame image_mixer::import_d3d_texture(const void*                                tag,\n                                                  const std::shared_ptr<d3d::d3d_texture2d>& d3d_texture,\n                                                  core::pixel_format                         format,\n                                                  common::bit_depth                          depth)\n{\n    return impl_->import_d3d_texture(tag, d3d_texture, format, depth);\n}\n#endif\n\ncommon::bit_depth image_mixer::depth() const { return impl_->depth(); }\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/image/image_mixer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/array.h>\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/frame/frame.h>\n#include <core/frame/pixel_format.h>\n#include <core/mixer/image/image_mixer.h>\n#include <core/video_format.h>\n\n#include <future>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nclass image_mixer final : public core::image_mixer\n{\n  public:\n    image_mixer(const spl::shared_ptr<class device>& ogl,\n                int                                  channel_id,\n                const size_t                         max_frame_size,\n                common::bit_depth                    depth);\n    image_mixer(const image_mixer&) = delete;\n\n    ~image_mixer();\n\n    image_mixer& operator=(const image_mixer&) = delete;\n\n    std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\n                        render(const core::video_format_desc& format_desc) override;\n    core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override;\n    core::mutable_frame\n    create_frame(const void* video_stream_tag, const core::pixel_format_desc& desc, common::bit_depth depth) override;\n\n#ifdef WIN32\n    core::const_frame import_d3d_texture(const void*                                tag,\n                                         const std::shared_ptr<d3d::d3d_texture2d>& d3d_texture,\n                                         core::pixel_format                         format,\n                                         common::bit_depth                          depth) override;\n#endif\n\n    void update_aspect_ratio(double aspect_ratio) override;\n\n    // core::image_mixer\n\n    void              push(const core::frame_transform& frame) override;\n    void              visit(const core::const_frame& frame) override;\n    void              pop() override;\n    common::bit_depth depth() const override;\n\n  private:\n    struct impl;\n    std::shared_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/image/image_shader.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"image_shader.h\"\n\n#include \"../util/device.h\"\n#include \"../util/shader.h\"\n\n#include \"ogl_image_fragment.h\"\n#include \"ogl_image_vertex.h\"\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nstd::weak_ptr<shader> g_shader;\nstd::mutex            g_shader_mutex;\n\nstd::shared_ptr<shader> get_image_shader(const spl::shared_ptr<device>& ogl)\n{\n    std::lock_guard<std::mutex> lock(g_shader_mutex);\n    auto                        existing_shader = g_shader.lock();\n\n    if (existing_shader) {\n        return existing_shader;\n    }\n\n    // The deleter is alive until the weak pointer is destroyed, so we have\n    // to weakly reference ogl, to not keep it alive until atexit\n    std::weak_ptr<device> weak_ogl = ogl;\n\n    auto deleter = [weak_ogl](shader* p) {\n        auto ogl = weak_ogl.lock();\n\n        if (ogl) {\n            ogl->dispatch_async([=] { delete p; });\n        }\n    };\n\n    existing_shader.reset(new shader(std::string(reinterpret_cast<const char*>(vertex_shader)),\n                                     std::string(reinterpret_cast<const char*>(fragment_shader))),\n                          deleter);\n    g_shader = existing_shader;\n\n    return existing_shader;\n}\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/image/image_shader.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/memory.h>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nclass shader;\nclass device;\n\nenum class texture_id\n{\n    plane0 = 0,\n    plane1,\n    plane2,\n    plane3,\n    local_key,\n    layer_key,\n    background\n};\n\nstd::shared_ptr<shader> get_image_shader(const spl::shared_ptr<device>& ogl);\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/image/shader.frag",
    "content": "#version 450\nin vec4 TexCoord;\nin vec4 TexCoord2;\nout vec4 fragColor;\n\nuniform sampler2D\tbackground;\nuniform sampler2D\tplane[4];\nuniform sampler2D\tlocal_key;\nuniform sampler2D\tlayer_key;\n\nuniform bool        is_straight_alpha;\n\nuniform mat3\t\tcolor_matrix;\nuniform vec3\t\tluma_coeff;\nuniform bool\t\thas_local_key;\nuniform bool\t\thas_layer_key;\nuniform int\t\t\tblend_mode;\nuniform int\t\t\tkeyer;\nuniform int\t\t\tpixel_format;\n\nuniform bool        invert;\nuniform float\t\topacity;\nuniform bool\t\tlevels;\nuniform float\t\tmin_input;\nuniform float\t\tmax_input;\nuniform float\t\tgamma;\nuniform float\t\tmin_output;\nuniform float\t\tmax_output;\nuniform float\t    precision_factor[4];\n\nuniform bool\t\tcsb;\nuniform float\t\tbrt;\nuniform float\t\tsat;\nuniform float\t\tcon;\n\nuniform bool\t\tchroma;\nuniform bool\t\tchroma_show_mask;\nuniform float\t\tchroma_target_hue;\nuniform float\t\tchroma_hue_width;\nuniform float\t\tchroma_min_saturation;\nuniform float\t\tchroma_min_brightness;\nuniform float\t\tchroma_softness;\nuniform float\t\tchroma_spill_suppress;\nuniform float\t\tchroma_spill_suppress_saturation;\n\n/*\n** Contrast, saturation, brightness\n** Code of this function is from TGM's shader pack\n** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057\n*/\n\nvec3 ContrastSaturationBrightness(vec4 color, float brt, float sat, float con)\n{\n    const float AvgLumR = 0.5;\n    const float AvgLumG = 0.5;\n    const float AvgLumB = 0.5;\n\n    vec3 LumCoeff = luma_coeff.bgr;\n\n    if (color.a > 0.0)\n        color.rgb /= color.a;\n\n    vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);\n    vec3 brtColor = color.rgb * brt;\n    vec3 intensity = vec3(dot(brtColor, LumCoeff));\n    vec3 satColor = mix(intensity, brtColor, sat);\n    vec3 conColor = mix(AvgLumin, satColor, con);\n\n    conColor.rgb *= color.a;\n\n    return conColor;\n}\n\n/*\n** Gamma correction\n** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/\n*/\n#define GammaCorrection(color, gamma)\t\t\t\t\t\t\t\tpow(color, vec3(1.0 / gamma))\n\n/*\n** Levels control (input (+gamma), output)\n** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/\n*/\n\n#define LevelsControlInputRange(color, minInput, maxInput)\t\t\t\tmin(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0))\n#define LevelsControlInput(color, minInput, gamma, maxInput)\t\t\t\tGammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma)\n#define LevelsControlOutputRange(color, minOutput, maxOutput) \t\t\tmix(vec3(minOutput), vec3(maxOutput), color)\n#define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput) \tLevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput)\n\n/*\n** Photoshop & misc math\n** Blending modes, RGB/HSL/Contrast/Desaturate, levels control\n**\n** Romain Dura | Romz\n** Blog: http://blog.mouaif.org\n** Post: http://blog.mouaif.org/?p=94\n*/\n\n\n/*\n** Desaturation\n*/\n\nvec4 Desaturate(vec3 color, float Desaturation)\n{\n    vec3 grayXfer = vec3(0.3, 0.59, 0.11);\n    vec3 gray = vec3(dot(grayXfer, color));\n    return vec4(mix(color, gray, Desaturation), 1.0);\n}\n\n\n/*\n** Hue, saturation, luminance\n*/\n\nvec3 RGBToHSL(vec3 color)\n{\n    vec3 hsl;\n\n    float fmin = min(min(color.r, color.g), color.b);\n    float fmax = max(max(color.r, color.g), color.b);\n    float delta = fmax - fmin;\n\n    hsl.z = (fmax + fmin) / 2.0;\n\n    if (delta == 0.0)\n    {\n        hsl.x = 0.0;\n        hsl.y = 0.0;\n    }\n    else\n    {\n        if (hsl.z < 0.5)\n            hsl.y = delta / (fmax + fmin);\n        else\n            hsl.y = delta / (2.0 - fmax - fmin);\n\n        float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;\n        float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;\n        float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;\n\n        if (color.r == fmax )\n            hsl.x = deltaB - deltaG;\n        else if (color.g == fmax)\n            hsl.x = (1.0 / 3.0) + deltaR - deltaB;\n        else if (color.b == fmax)\n            hsl.x = (2.0 / 3.0) + deltaG - deltaR;\n\n        if (hsl.x < 0.0)\n            hsl.x += 1.0;\n        else if (hsl.x > 1.0)\n            hsl.x -= 1.0;\n    }\n\n    return hsl;\n}\n\nfloat HueToRGB(float f1, float f2, float hue)\n{\n    if (hue < 0.0)\n        hue += 1.0;\n    else if (hue > 1.0)\n        hue -= 1.0;\n    float res;\n    if ((6.0 * hue) < 1.0)\n        res = f1 + (f2 - f1) * 6.0 * hue;\n    else if ((2.0 * hue) < 1.0)\n        res = f2;\n    else if ((3.0 * hue) < 2.0)\n        res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;\n    else\n        res = f1;\n    return res;\n}\n\nvec3 HSLToRGB(vec3 hsl)\n{\n    vec3 rgb;\n\n    if (hsl.y == 0.0)\n        rgb = vec3(hsl.z);\n    else\n    {\n        float f2;\n\n        if (hsl.z < 0.5)\n            f2 = hsl.z * (1.0 + hsl.y);\n        else\n            f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);\n\n        float f1 = 2.0 * hsl.z - f2;\n\n        rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));\n        rgb.g = HueToRGB(f1, f2, hsl.x);\n        rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));\n    }\n\n    return rgb;\n}\n\n\n\n\n/*\n** Float blending modes\n** Adapted from here: http://www.nathanm.com/photoshop-blending-math/\n** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results\n*/\n\n#define BlendLinearDodgef \t\t\t\t\tBlendAddf\n#define BlendLinearBurnf \t\t\t\t\tBlendSubstractf\n#define BlendAddf(base, blend) \t\t\t\tmin(base + blend, 1.0)\n#define BlendSubstractf(base, blend) \t\tmax(base + blend - 1.0, 0.0)\n#define BlendLightenf(base, blend) \t\tmax(blend, base)\n#define BlendDarkenf(base, blend) \t\t\tmin(blend, base)\n#define BlendLinearLightf(base, blend) \t(blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5))))\n#define BlendScreenf(base, blend) \t\t\t(1.0 - ((1.0 - base) * (1.0 - blend)))\n#define BlendOverlayf(base, blend) \t\t(base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))\n#define BlendSoftLightf(base, blend) \t\t((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))\n#define BlendColorDodgef(base, blend) \t\t((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))\n#define BlendColorBurnf(base, blend) \t\t((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))\n#define BlendVividLightf(base, blend)\t\t((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5))))\n#define BlendPinLightf(base, blend) \t\t((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5))))\n#define BlendHardMixf(base, blend) \t\t((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0)\n#define BlendReflectf(base, blend) \t\t((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0))\n\n\n/*\n** Vector3 blending modes\n*/\n\n#define Blend(base, blend, funcf) \t\t\tvec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b))\n\n#define BlendNormal(base, blend) \t\t\t(blend)\n#define BlendLighten\t\t\t\t\t\tBlendLightenf\n#define BlendDarken\t\t\t\t\t\tBlendDarkenf\n#define BlendMultiply(base, blend) \t\t(base * blend)\n#define BlendAverage(base, blend) \t\t\t((base + blend) / 2.0)\n#define BlendAdd(base, blend) \t\t\t\tmin(base + blend, vec3(1.0))\n#define BlendSubstract(base, blend) \t\tmax(base + blend - vec3(1.0), vec3(0.0))\n#define BlendDifference(base, blend) \t\tabs(base - blend)\n#define BlendNegation(base, blend) \t\t(vec3(1.0) - abs(vec3(1.0) - base - blend))\n#define BlendExclusion(base, blend) \t\t(base + blend - 2.0 * base * blend)\n#define BlendScreen(base, blend) \t\t\tBlend(base, blend, BlendScreenf)\n#define BlendOverlay(base, blend) \t\t\tBlend(base, blend, BlendOverlayf)\n#define BlendSoftLight(base, blend) \t\tBlend(base, blend, BlendSoftLightf)\n#define BlendHardLight(base, blend) \t\tBlendOverlay(blend, base)\n#define BlendColorDodge(base, blend) \t\tBlend(base, blend, BlendColorDodgef)\n#define BlendColorBurn(base, blend) \t\tBlend(base, blend, BlendColorBurnf)\n#define BlendLinearDodge\t\t\t\t\tBlendAdd\n#define BlendLinearBurn\t\t\t\t\tBlendSubstract\n#define BlendLinearLight(base, blend) \t\tBlend(base, blend, BlendLinearLightf)\n#define BlendVividLight(base, blend) \t\tBlend(base, blend, BlendVividLightf)\n#define BlendPinLight(base, blend) \t\tBlend(base, blend, BlendPinLightf)\n#define BlendHardMix(base, blend) \t\t\tBlend(base, blend, BlendHardMixf)\n#define BlendReflect(base, blend) \t\t\tBlend(base, blend, BlendReflectf)\n#define BlendGlow(base, blend) \t\t\tBlendReflect(blend, base)\n#define BlendPhoenix(base, blend) \t\t\t(min(base, blend) - max(base, blend) + vec3(1.0))\n#define BlendOpacity(base, blend, F, O) \t(F(base, blend) * O + blend * (1.0 - O))\n\n\nvec3 BlendHue(vec3 base, vec3 blend)\n{\n    vec3 baseHSL = RGBToHSL(base);\n    return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b));\n}\n\nvec3 BlendSaturation(vec3 base, vec3 blend)\n{\n    vec3 baseHSL = RGBToHSL(base);\n    return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b));\n}\n\nvec3 BlendColor(vec3 base, vec3 blend)\n{\n    vec3 blendHSL = RGBToHSL(blend);\n    return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b));\n}\n\nvec3 BlendLuminosity(vec3 base, vec3 blend)\n{\n    vec3 baseHSL = RGBToHSL(base);\n    return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b));\n}\n\n// Chroma keying\n// Author: Tim Eves <timseves@googlemail.com>\n//\n// This implements the Chroma key algorithm described in the paper:\n//      'Software Chroma Keying in an Imersive Virtual Environment'\n//      by F. van den Bergh & V. Lalioti\n// but as a pixel shader algorithm.\n//\nvec4  grey_xfer  = vec4(luma_coeff, 0);\n\n// This allows us to implement the paper's alphaMap curve in software\n// rather than a largeish array\nfloat alpha_map(float d)\n{\n    return 1.0 - smoothstep(1.0, chroma_softness, d);\n}\n\n// http://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 rgb2hsv(vec3 c)\n{\n    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n    float d = q.x - min(q.w, q.y);\n    float e = 1.0e-10;\n    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}\n\n// From the same page\nvec3 hsv2rgb(vec3 c)\n{\n    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nfloat AngleDiff(float angle1, float angle2)\n{\n    return 0.5 - abs(abs(angle1 - angle2) - 0.5);\n}\n\nfloat AngleDiffDirectional(float angle1, float angle2)\n{\n    float diff = angle1 - angle2;\n\n    return diff < -0.5\n            ? diff + 1.0\n            : (diff > 0.5 ? diff - 1.0 : diff);\n}\n\nfloat Distance(float actual, float target)\n{\n    return min(0.0, target - actual);\n}\n\nfloat ColorDistance(vec3 hsv)\n{\n    float hueDiff\t\t\t\t\t= AngleDiff(hsv.x, chroma_target_hue) * 2;\n    float saturationDiff\t\t\t= Distance(hsv.y, chroma_min_saturation);\n    float brightnessDiff\t\t\t= Distance(hsv.z, chroma_min_brightness);\n\n    float saturationBrightnessScore\t= max(brightnessDiff, saturationDiff);\n    float hueScore\t\t\t\t\t= hueDiff - chroma_hue_width;\n\n    return -hueScore * saturationBrightnessScore;\n}\n\nvec3 supress_spill(vec3 c)\n{\n    float hue\t\t= c.x;\n    float diff\t\t= AngleDiffDirectional(hue, chroma_target_hue);\n    float distance\t= abs(diff) / chroma_spill_suppress;\n\n    if (distance < 1)\n    {\n        c.x = diff < 0\n                ? chroma_target_hue - chroma_spill_suppress\n                : chroma_target_hue + chroma_spill_suppress;\n        c.y *= min(1.0, distance + chroma_spill_suppress_saturation);\n    }\n\n    return c;\n}\n\n// Key on any color\nvec4 ChromaOnCustomColor(vec4 c)\n{\n    vec3 hsv\t\t= rgb2hsv(c.rgb);\n    float distance\t= ColorDistance(hsv);\n    float d\t\t\t= distance * -2.0 + 1.0;\n    vec4 suppressed\t= vec4(hsv2rgb(supress_spill(hsv)), 1.0);\n    float alpha\t\t= alpha_map(d);\n\n    suppressed *= alpha;\n\n    return chroma_show_mask ? vec4(suppressed.a, suppressed.a, suppressed.a, 1) : suppressed;\n}\n\n\n\nvec3 get_blend_color(vec3 back, vec3 fore)\n{\n    switch(blend_mode)\n    {\n    case  0: return BlendNormal(back, fore);\n    case  1: return BlendLighten(back, fore);\n    case  2: return BlendDarken(back, fore);\n    case  3: return BlendMultiply(back, fore);\n    case  4: return BlendAverage(back, fore);\n    case  5: return BlendAdd(back, fore);\n    case  6: return BlendSubstract(back, fore);\n    case  7: return BlendDifference(back, fore);\n    case  8: return BlendNegation(back, fore);\n    case  9: return BlendExclusion(back, fore);\n    case 10: return BlendScreen(back, fore);\n    case 11: return BlendOverlay(back, fore);\n//\tcase 12: return BlendSoftLight(back, fore);\n    case 13: return BlendHardLight(back, fore);\n    case 14: return BlendColorDodge(back, fore);\n    case 15: return BlendColorBurn(back, fore);\n    case 16: return BlendLinearDodge(back, fore);\n    case 17: return BlendLinearBurn(back, fore);\n    case 18: return BlendLinearLight(back, fore);\n    case 19: return BlendVividLight(back, fore);\n    case 20: return BlendPinLight(back, fore);\n    case 21: return BlendHardMix(back, fore);\n    case 22: return BlendReflect(back, fore);\n    case 23: return BlendGlow(back, fore);\n    case 24: return BlendPhoenix(back, fore);\n    case 25: return BlendHue(back, fore);\n    case 26: return BlendSaturation(back, fore);\n    case 27: return BlendColor(back, fore);\n    case 28: return BlendLuminosity(back, fore);\n    }\n    return BlendNormal(back, fore);\n}\n\nvec4 blend(vec4 fore)\n{\n    vec4 back = texture(background, TexCoord2.st).bgra;\n    if(blend_mode != 0)\n        fore.rgb = get_blend_color(back.rgb/(back.a+0.0000001), fore.rgb/(fore.a+0.0000001))*fore.a;\n    switch(keyer)\n    {\n        case 1:  return fore + back; // additive\n        default: return fore + (1.0-fore.a)*back; // linear\n    }\n}\n\nvec4 chroma_key(vec4 c)\n{\n    return ChromaOnCustomColor(c.bgra).bgra;\n}\n\nvec4 ycbcra_to_rgba(float Y, float Cb, float Cr, float A)\n{\n    const float luma_coefficient = 255.0/219.0;\n    const float chroma_coefficient = 255.0/224.0;\n\n    vec3 YCbCr = vec3(Y, Cb, Cr) * 255;\n    YCbCr -= vec3(16.0, 128.0, 128.0);\n    YCbCr *= vec3(luma_coefficient, chroma_coefficient, chroma_coefficient);\n\n    return vec4(color_matrix * YCbCr / 255, A).bgra;\n}\n\nvec4 get_sample(sampler2D sampler, vec2 coords)\n{\n    return texture(sampler, coords);\n}\n\nvec4 get_rgba_color()\n{\n    switch(pixel_format)\n    {\n    case 0:\t\t//gray\n        return vec4(get_sample(plane[0], TexCoord.st / TexCoord.q).rrr * precision_factor[0], 1.0);\n    case 1:\t\t//bgra,\n        return get_sample(plane[0], TexCoord.st / TexCoord.q).bgra * precision_factor[0];\n    case 2:\t\t//rgba,\n        return get_sample(plane[0], TexCoord.st / TexCoord.q).rgba * precision_factor[0];\n    case 3:\t\t//argb,\n        return get_sample(plane[0], TexCoord.st / TexCoord.q).argb * precision_factor[0];\n    case 4:\t\t//abgr,\n        return get_sample(plane[0], TexCoord.st / TexCoord.q).gbar * precision_factor[0];\n    case 5:\t\t//ycbcr,\n        {\n            float y  = get_sample(plane[0], TexCoord.st / TexCoord.q).r * precision_factor[0];\n            float cb = get_sample(plane[1], TexCoord.st / TexCoord.q).r * precision_factor[1];\n            float cr = get_sample(plane[2], TexCoord.st / TexCoord.q).r * precision_factor[2];\n            return ycbcra_to_rgba(y, cb, cr, 1.0);\n        }\n    case 6:\t\t//ycbcra\n        {\n            float y  = get_sample(plane[0], TexCoord.st / TexCoord.q).r * precision_factor[0];\n            float cb = get_sample(plane[1], TexCoord.st / TexCoord.q).r * precision_factor[1];\n            float cr = get_sample(plane[2], TexCoord.st / TexCoord.q).r * precision_factor[2];\n            float a  = get_sample(plane[3], TexCoord.st / TexCoord.q).r * precision_factor[3];\n            return ycbcra_to_rgba(y, cb, cr, a);\n        }\n    case 7:\t\t//luma\n        {\n            vec3 y3 = get_sample(plane[0], TexCoord.st / TexCoord.q).rrr * precision_factor[0];\n            return vec4((y3-0.065)/0.859, 1.0);\n        }\n    case 8:\t\t//bgr,\n        return vec4(get_sample(plane[0], TexCoord.st / TexCoord.q).bgr * precision_factor[0], 1.0);\n    case 9:\t\t//rgb,\n        return vec4(get_sample(plane[0], TexCoord.st / TexCoord.q).rgb * precision_factor[0], 1.0);\n\tcase 10:\t// uyvy\n\t\t{\n\t\t\tfloat y = get_sample(plane[0], TexCoord.st / TexCoord.q).g * precision_factor[0];\n\t\t\tfloat cb = get_sample(plane[1], TexCoord.st / TexCoord.q).b * precision_factor[1];\n\t\t\tfloat cr = get_sample(plane[1], TexCoord.st / TexCoord.q).r * precision_factor[1];\n\t\t\treturn ycbcra_to_rgba(y, cb, cr, 1.0);\n\t\t}\n    case 11:    // gbrp\n        {\n            float g  = get_sample(plane[0], TexCoord.st / TexCoord.q).r * precision_factor[0];\n            float b = get_sample(plane[1], TexCoord.st / TexCoord.q).r * precision_factor[1];\n            float r = get_sample(plane[2], TexCoord.st / TexCoord.q).r * precision_factor[2];\n\t\t\treturn vec4(b, g, r, 1.0);\n        }\n    case 12:    // gbrap\n        {\n            float g  = get_sample(plane[0], TexCoord.st / TexCoord.q).r * precision_factor[0];\n            float b = get_sample(plane[1], TexCoord.st / TexCoord.q).r * precision_factor[1];\n            float r = get_sample(plane[2], TexCoord.st / TexCoord.q).r * precision_factor[2];\n            float a  = get_sample(plane[3], TexCoord.st / TexCoord.q).r * precision_factor[3];\n\t\t\treturn vec4(b, g, r, a);\n        }\n    }\n    return vec4(0.0, 0.0, 0.0, 0.0);\n}\n\nvoid main()\n{\n    vec4 color = get_rgba_color();\n    if (is_straight_alpha)\n        color.rgb *= color.a;\n    if (chroma)\n        color = chroma_key(color);\n    if(levels)\n        color.rgb = LevelsControl(color.rgb, min_input, gamma, max_input, min_output, max_output);\n    if(csb)\n        color.rgb = ContrastSaturationBrightness(color, brt, sat, con);\n    if(has_local_key)\n        color *= texture(local_key, TexCoord2.st).r;\n    if(has_layer_key)\n        color *= texture(layer_key, TexCoord2.st).r;\n    color *= opacity;\n    if (invert)\n        color = 1.0 - color;\n    if (blend_mode >= 0)\n        color = blend(color);\n    fragColor = color.bgra;\n}\n"
  },
  {
    "path": "src/accelerator/ogl/image/shader.vert",
    "content": "#version 450\nin vec4 TexCoordIn;\nin vec2 Position;\n\nout vec4 TexCoord;\nout vec4 TexCoord2;\n\nvoid main()\n{\n    TexCoord = TexCoordIn;\n    vec4 pos = vec4(Position, 0, 1);\n    TexCoord2 = vec4(pos.xy, 0.0, 0.0);\n    pos.x = pos.x*2.0 - 1.0;\n    pos.y = pos.y*2.0 - 1.0;\n    gl_Position = pos;\n}\n"
  },
  {
    "path": "src/accelerator/ogl/util/buffer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"buffer.h\"\n\n#include <boost/property_tree/ptree.hpp>\n\n#include <common/gl/gl_check.h>\n\n#include <GL/glew.h>\n\n#include <atomic>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nstatic std::atomic<int>         g_w_total_count;\nstatic std::atomic<std::size_t> g_w_total_size;\nstatic std::atomic<int>         g_r_total_count;\nstatic std::atomic<std::size_t> g_r_total_size;\n\nstruct buffer::impl\n{\n    GLuint     id_     = 0;\n    GLsizei    size_   = 0;\n    void*      data_   = nullptr;\n    bool       write_  = false;\n    GLenum     target_ = 0;\n    GLbitfield flags_  = 0;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n  public:\n    impl(int size, bool write)\n        : size_(size)\n        , write_(write)\n        , target_(!write ? GL_PIXEL_PACK_BUFFER : GL_PIXEL_UNPACK_BUFFER)\n        , flags_(GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | (write ? GL_MAP_WRITE_BIT : GL_MAP_READ_BIT))\n    {\n        GL(glCreateBuffers(1, &id_));\n        GL(glNamedBufferStorage(id_, size_, nullptr, flags_));\n        data_ = GL2(glMapNamedBufferRange(id_, 0, size_, flags_));\n\n        (write ? g_w_total_count : g_r_total_count)++;\n        (write ? g_w_total_size : g_r_total_size) += size_;\n    }\n\n    ~impl()\n    {\n        GL(glUnmapNamedBuffer(id_));\n        glDeleteBuffers(1, &id_);\n\n        (write_ ? g_w_total_size : g_r_total_size) -= size_;\n        (write_ ? g_w_total_count : g_r_total_count)--;\n    }\n\n    void bind() { GL(glBindBuffer(target_, id_)); }\n\n    void unbind() { GL(glBindBuffer(target_, 0)); }\n};\n\nbuffer::buffer(int size, bool write)\n    : impl_(new impl(size, write))\n{\n}\nbuffer::buffer(buffer&& other)\n    : impl_(std::move(other.impl_))\n{\n}\nbuffer::~buffer() {}\nbuffer& buffer::operator=(buffer&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\nvoid* buffer::data() { return impl_->data_; }\nbool  buffer::write() const { return impl_->write_; }\nint   buffer::size() const { return impl_->size_; }\nvoid  buffer::bind() { return impl_->bind(); }\nvoid  buffer::unbind() { return impl_->unbind(); }\nint   buffer::id() const { return impl_->id_; }\n\nboost::property_tree::wptree buffer::info()\n{\n    boost::property_tree::wptree info;\n\n    info.add(L\"total_read_count\", g_r_total_count);\n    info.add(L\"total_write_count\", g_w_total_count);\n    info.add(L\"total_read_size\", g_r_total_size);\n    info.add(L\"total_write_size\", g_w_total_size);\n\n    return info;\n}\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/buffer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <memory>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nclass buffer final\n{\n  public:\n    static boost::property_tree::wptree info();\n\n    buffer(int size, bool write);\n    buffer(const buffer&) = delete;\n    buffer(buffer&& other);\n    ~buffer();\n\n    buffer& operator=(const buffer&) = delete;\n    buffer& operator=(buffer&& other);\n\n    void bind();\n    void unbind();\n\n    int   id() const;\n    void* data();\n    int   size() const;\n    bool  write() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/context.cpp",
    "content": "\n#include \"context.h\"\n\n#include <common/log.h>\n\n#include <SFML/Window/Context.hpp>\n#if SFML_VERSION_MAJOR >= 3\n#include <SFML/Window/ContextSettings.hpp>\n#endif\n\n#include <tuple> // std::ignore\n\n#ifndef _MSC_VER\n#include <EGL/egl.h>\n#include <common/gl/gl_check.h>\n#include <stdlib.h>\n#endif\n\nnamespace caspar::accelerator::ogl {\n\nstruct device_context::impl\n{\n    virtual ~impl() {}\n    virtual void bind()   = 0;\n    virtual void unbind() = 0;\n};\nstruct impl_sfml : public device_context::impl\n{\n    sf::Context device_;\n\n    impl_sfml()\n#if SFML_VERSION_MAJOR >= 3\n        : device_(sf::ContextSettings{.depthBits         = 0,\n                                      .stencilBits       = 0,\n                                      .antiAliasingLevel = 0,\n                                      .majorVersion      = 4,\n                                      .minorVersion      = 5,\n                                      .attributeFlags    = sf::ContextSettings::Attribute::Core},\n                  {1, 1})\n#else\n        : device_(sf::ContextSettings(0, 0, 0, 4, 5, sf::ContextSettings::Attribute::Core), 1, 1)\n#endif\n    {\n        CASPAR_LOG(info) << L\"Initializing OpenGL Device (sfml).\";\n    }\n\n    virtual ~impl_sfml() {}\n\n    virtual void bind() override { std::ignore = device_.setActive(true); }\n    virtual void unbind() override { std::ignore = device_.setActive(false); }\n};\n\n#ifndef _MSC_VER\nstruct impl_egl : public device_context::impl\n{\n    EGLDisplay eglDisplay_;\n    EGLContext eglContext_;\n\n    impl_egl()\n        : eglDisplay_(EGL_NO_DISPLAY)\n        , eglContext_(EGL_NO_CONTEXT)\n    {\n        CASPAR_LOG(info) << L\"Initializing OpenGL Device (EGL).\";\n\n        eglDisplay_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);\n\n        EGLint major, minor;\n        eglInitialize(eglDisplay_, &major, &minor);\n\n        const EGLint configAttribs[] = {EGL_SURFACE_TYPE,\n                                        EGL_PBUFFER_BIT,\n                                        EGL_BLUE_SIZE,\n                                        8,\n                                        EGL_GREEN_SIZE,\n                                        8,\n                                        EGL_RED_SIZE,\n                                        8,\n                                        EGL_RENDERABLE_TYPE,\n                                        EGL_OPENGL_BIT,\n                                        EGL_NONE};\n\n        EGLint    numConfigs;\n        EGLConfig eglConfig;\n        if (!eglChooseConfig(eglDisplay_, configAttribs, &eglConfig, 1, &numConfigs)) {\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize OpenGL: eglChooseConfig\"));\n        }\n\n        if (!eglBindAPI(EGL_OPENGL_API)) {\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize OpenGL: eglBindAPI\"));\n        }\n\n        eglContext_ = eglCreateContext(eglDisplay_, eglConfig, EGL_NO_CONTEXT, NULL);\n        if (eglContext_ == EGL_NO_CONTEXT) {\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize OpenGL: eglCreateContext\"));\n        }\n\n        if (!eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext_)) {\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize OpenGL: eglMakeCurrent\"));\n        }\n    }\n\n    virtual ~impl_egl()\n    {\n        eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);\n\n        if (eglContext_ != EGL_NO_CONTEXT) {\n            eglDestroyContext(eglDisplay_, eglContext_);\n        }\n\n        eglTerminate(eglDisplay_);\n    }\n\n    virtual void bind() override { eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext_); }\n    virtual void unbind() override { eglMakeCurrent(eglDisplay_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); }\n};\n#endif\n\n#ifndef _MSC_VER\ndevice_context::device_context()\n    : impl_(std::getenv(\"DISPLAY\") == nullptr ? spl::make_shared<device_context::impl, impl_egl>()\n                                              : spl::make_shared<device_context::impl, impl_sfml>())\n{\n}\n#else\ndevice_context::device_context()\n    : impl_(new impl_sfml())\n{\n}\n#endif\n\ndevice_context::~device_context() {}\n\nvoid device_context::bind() { impl_->bind(); }\nvoid device_context::unbind() { impl_->unbind(); }\n\n} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/context.h",
    "content": "#pragma once\n\n#include <memory>\n\nnamespace caspar::accelerator::ogl {\n\nclass device_context final\n{\n  public:\n    device_context();\n    ~device_context();\n\n    device_context(const device_context&) = delete;\n\n    device_context& operator=(const device_context&) = delete;\n\n    void bind();\n    void unbind();\n\n    struct impl;\n\n  private:\n    spl::shared_ptr<impl> impl_;\n};\n\n} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/device.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"device.h\"\n\n#include \"buffer.h\"\n#include \"context.h\"\n#include \"shader.h\"\n#include \"texture.h\"\n\n#include <common/array.h>\n#include <common/assert.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/gl/gl_check.h>\n#include <common/os/thread.h>\n\n#include <GL/glew.h>\n\n#ifdef WIN32\n#include \"../../d3d/d3d_device.h\"\n#include <GL/wglew.h>\n#endif\n\n#include <boost/asio/deadline_timer.hpp>\n#include <boost/asio/dispatch.hpp>\n#include <boost/asio/spawn.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <tbb/concurrent_queue.h>\n#include <tbb/concurrent_unordered_map.h>\n\n#include <array>\n#include <future>\n#include <thread>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nusing namespace boost::asio;\n\nstruct device::impl : public std::enable_shared_from_this<impl>\n{\n    using texture_queue_t = tbb::concurrent_bounded_queue<std::shared_ptr<texture>>;\n    using buffer_queue_t  = tbb::concurrent_bounded_queue<std::shared_ptr<buffer>>;\n\n    std::unique_ptr<device_context> context_;\n\n    std::array<std::array<tbb::concurrent_unordered_map<size_t, texture_queue_t>, 4>, 2> device_pools_;\n    std::array<tbb::concurrent_unordered_map<size_t, buffer_queue_t>, 2>                 host_pools_;\n\n    GLuint fbo_;\n\n    std::wstring version_;\n\n#ifdef WIN32\n    std::shared_ptr<d3d::d3d_device> d3d_device_;\n    std::shared_ptr<void>            interop_handle_;\n#endif\n\n    io_context                             io_context_;\n    decltype(make_work_guard(io_context_)) work_;\n    std::thread                            thread_;\n\n    impl()\n        : context_(new device_context())\n        , work_(make_work_guard(io_context_))\n    {\n        CASPAR_LOG(info) << L\"Initializing OpenGL Device.\";\n\n        context_->bind();\n\n        auto err = glewInit();\n        if (err != GLEW_OK && err != 4) { // GLEW_ERROR_NO_GLX_DISPLAY\n            std::stringstream str;\n            str << \"Failed to initialize GLEW (\" << (int)err << \"): \" << glewGetErrorString(err) << std::endl;\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(str.str()));\n        }\n\n#ifdef WIN32\n        if (wglewInit() != GLEW_OK) {\n            CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize GLEW.\"));\n        }\n#endif\n\n        version_ = u16(reinterpret_cast<const char*>(GL2(glGetString(GL_VERSION)))) + L\" \" +\n                   u16(reinterpret_cast<const char*>(GL2(glGetString(GL_VENDOR))));\n\n        CASPAR_LOG(info) << L\"Initialized OpenGL \" << version();\n\n        if (!GLEW_VERSION_4_5 && !glewIsSupported(\"GL_ARB_sync GL_ARB_shader_objects GL_ARB_multitexture \"\n                                                  \"GL_ARB_direct_state_access GL_ARB_texture_barrier\")) {\n            CASPAR_THROW_EXCEPTION(not_supported()\n                                   << msg_info(\"Your graphics card does not meet the minimum hardware requirements \"\n                                               \"since it does not support OpenGL 4.5 or higher.\"));\n        }\n\n        GL(glCreateFramebuffers(1, &fbo_));\n        GL(glBindFramebuffer(GL_FRAMEBUFFER, fbo_));\n\n        context_->unbind();\n\n#ifdef WIN32\n        if (env::properties().get(L\"configuration.html.enable-gpu\", false)) {\n            d3d_device_ = d3d::d3d_device::get_device();\n        }\n        if (d3d_device_) {\n            interop_handle_ = std::shared_ptr<void>(wglDXOpenDeviceNV(d3d_device_->device()), [](void* p) {\n                if (p)\n                    wglDXCloseDeviceNV(p);\n            });\n\n            if (!interop_handle_)\n                CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize d3d interop.\"));\n        }\n#endif\n\n        thread_ = std::thread([&] {\n            context_->bind();\n            set_thread_name(L\"OpenGL Device\");\n            io_context_.run();\n            context_->unbind();\n        });\n    }\n\n    ~impl()\n    {\n        work_.reset();\n        thread_.join();\n\n        context_->bind();\n\n        for (auto& pool : host_pools_)\n            pool.clear();\n\n        for (auto& pools : device_pools_)\n            for (auto& pool : pools)\n                pool.clear();\n\n        GL(glDeleteFramebuffers(1, &fbo_));\n    }\n\n    template <typename Func>\n    auto spawn_async(Func&& func)\n    {\n        using result_type = decltype(func(std::declval<yield_context>()));\n        using task_type   = std::packaged_task<result_type(yield_context)>;\n\n        auto task   = task_type(std::forward<Func>(func));\n        auto future = task.get_future();\n        boost::asio::spawn(io_context_, std::move(task), [](std::exception_ptr e) {\n            if (e)\n                std::rethrow_exception(e);\n        });\n        return future;\n    }\n\n    template <typename Func>\n    auto dispatch_async(Func&& func)\n    {\n        using result_type = decltype(func());\n        using task_type   = std::packaged_task<result_type()>;\n\n        auto task   = task_type(std::forward<Func>(func));\n        auto future = task.get_future();\n        boost::asio::dispatch(io_context_, std::move(task));\n        return future;\n    }\n\n    template <typename Func>\n    auto dispatch_sync(Func&& func) -> decltype(func())\n    {\n        return dispatch_async(std::forward<Func>(func)).get();\n    }\n\n    std::wstring version() { return version_; }\n\n    std::shared_ptr<texture> create_texture(int width, int height, int stride, common::bit_depth depth, bool clear)\n    {\n        CASPAR_VERIFY(stride > 0 && stride < 5);\n        CASPAR_VERIFY(width > 0 && height > 0);\n\n        auto depth_pool_index = depth == common::bit_depth::bit8 ? 0 : 1;\n\n        // TODO (perf) Shared pool.\n        auto pool = &device_pools_[depth_pool_index][stride - 1][(width << 16 & 0xFFFF0000) | (height & 0x0000FFFF)];\n\n        std::shared_ptr<texture> tex;\n        if (!pool->try_pop(tex)) {\n            tex = std::make_shared<texture>(width, height, stride, depth);\n        }\n        tex->set_depth(depth);\n\n        if (clear) {\n            tex->clear();\n        }\n\n        auto ptr = tex.get();\n        return std::shared_ptr<texture>(\n            ptr, [tex = std::move(tex), pool, self = shared_from_this()](texture*) mutable { pool->push(tex); });\n    }\n\n    std::shared_ptr<buffer> create_buffer(int size, bool write)\n    {\n        CASPAR_VERIFY(size > 0);\n\n        // TODO (perf) Shared pool.\n        auto pool = &host_pools_[static_cast<int>(write ? 1 : 0)][size];\n\n        std::shared_ptr<buffer> buf;\n        if (!pool->try_pop(buf)) {\n            // TODO (perf) Avoid blocking in create_array.\n            dispatch_sync([&] { buf = std::make_shared<buffer>(size, write); });\n        }\n\n        auto ptr = buf.get();\n        return std::shared_ptr<buffer>(ptr, [buf = std::move(buf), self = shared_from_this()](buffer*) mutable {\n            auto pool = &self->host_pools_[static_cast<int>(buf->write() ? 1 : 0)][buf->size()];\n            pool->push(std::move(buf));\n        });\n    }\n\n    array<uint8_t> create_array(int size)\n    {\n        auto buf = create_buffer(size, true);\n        auto ptr = reinterpret_cast<uint8_t*>(buf->data());\n        return array<uint8_t>(ptr, buf->size(), std::move(buf));\n    }\n\n    std::future<std::shared_ptr<texture>>\n    copy_async(const array<const uint8_t>& source, int width, int height, int stride, common::bit_depth depth)\n    {\n        return dispatch_async([=, this] {\n            std::shared_ptr<buffer> buf;\n\n            auto tmp = source.storage<std::shared_ptr<buffer>>();\n            if (tmp) {\n                buf = *tmp;\n            } else {\n                buf = create_buffer(static_cast<int>(source.size()), true);\n                // TODO (perf) Copy inside a TBB worker.\n                std::memcpy(buf->data(), source.data(), source.size());\n            }\n\n            auto tex = create_texture(width, height, stride, depth, false);\n            tex->copy_from(*buf);\n            // TODO (perf) save tex on source\n            return tex;\n        });\n    }\n\n    std::future<array<const uint8_t>> copy_async(const std::shared_ptr<texture>& source)\n    {\n        return spawn_async([=, this](yield_context yield) {\n            auto buf = create_buffer(source->size(), false);\n            source->copy_to(*buf);\n\n            auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\n\n            GL(glFlush());\n\n            deadline_timer timer(io_context_);\n            for (auto n = 0; true; ++n) {\n                // TODO (perf) Smarter non-polling solution?\n                timer.expires_from_now(boost::posix_time::milliseconds(2));\n                timer.async_wait(yield);\n\n                auto wait = glClientWaitSync(fence, 0, 1);\n                if (wait == GL_ALREADY_SIGNALED || wait == GL_CONDITION_SATISFIED) {\n                    break;\n                }\n            }\n\n            glDeleteSync(fence);\n\n            auto ptr  = reinterpret_cast<uint8_t*>(buf->data());\n            auto size = buf->size();\n            return array<const uint8_t>(ptr, size, std::move(buf));\n        });\n    }\n\n#ifdef WIN32\n    std::future<std::shared_ptr<texture>>\n    copy_async(GLuint source, int width, int height, int stride, common::bit_depth depth)\n    {\n        return spawn_async([=, this](yield_context yield) {\n            auto tex = create_texture(width, height, stride, depth, false);\n\n            tex->copy_from(source);\n\n            auto fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\n\n            GL(glFlush());\n\n            deadline_timer timer(io_context_);\n            for (auto n = 0; true; ++n) {\n                // TODO (perf) Smarter non-polling solution?\n                timer.expires_from_now(boost::posix_time::milliseconds(2));\n                timer.async_wait(yield);\n\n                auto wait = glClientWaitSync(fence, 0, 1);\n                if (wait == GL_ALREADY_SIGNALED || wait == GL_CONDITION_SATISFIED) {\n                    break;\n                }\n            }\n\n            glDeleteSync(fence);\n\n            return tex;\n        });\n    }\n#endif\n\n    boost::property_tree::wptree info() const\n    {\n        boost::property_tree::wptree info;\n\n        boost::property_tree::wptree pooled_device_buffers;\n        size_t                       total_pooled_device_buffer_size  = 0;\n        size_t                       total_pooled_device_buffer_count = 0;\n\n        for (size_t i = 0; i < device_pools_.size(); ++i) {\n            auto& depth_pools = device_pools_.at(i);\n            for (size_t j = 0; j < depth_pools.size(); ++j) {\n                auto& pools      = depth_pools.at(j);\n                bool  mipmapping = j > 3;\n                auto  stride     = mipmapping ? j - 3 : j + 1;\n\n                for (auto& pool : pools) {\n                    auto width  = pool.first >> 16;\n                    auto height = pool.first & 0x0000FFFF;\n                    auto size   = width * height * stride;\n                    auto count  = pool.second.size();\n\n                    if (count == 0)\n                        continue;\n\n                    boost::property_tree::wptree pool_info;\n\n                    pool_info.add(L\"stride\", stride);\n                    pool_info.add(L\"mipmapping\", mipmapping);\n                    pool_info.add(L\"width\", width);\n                    pool_info.add(L\"height\", height);\n                    pool_info.add(L\"size\", size);\n                    pool_info.add(L\"count\", count);\n\n                    total_pooled_device_buffer_size += size * count;\n                    total_pooled_device_buffer_count += count;\n\n                    pooled_device_buffers.add_child(L\"device_buffer_pool\", pool_info);\n                }\n            }\n        }\n\n        info.add_child(L\"gl.details.pooled_device_buffers\", pooled_device_buffers);\n\n        boost::property_tree::wptree pooled_host_buffers;\n        size_t                       total_read_size   = 0;\n        size_t                       total_write_size  = 0;\n        size_t                       total_read_count  = 0;\n        size_t                       total_write_count = 0;\n\n        for (size_t i = 0; i < host_pools_.size(); ++i) {\n            auto& pools    = host_pools_.at(i);\n            auto  is_write = i == 1;\n\n            for (auto& pool : pools) {\n                auto size  = pool.first;\n                auto count = pool.second.size();\n\n                if (count == 0)\n                    continue;\n\n                boost::property_tree::wptree pool_info;\n\n                pool_info.add(L\"usage\", is_write ? L\"write_only\" : L\"read_only\");\n                pool_info.add(L\"size\", size);\n                pool_info.add(L\"count\", count);\n\n                pooled_host_buffers.add_child(L\"host_buffer_pool\", pool_info);\n\n                (is_write ? total_write_count : total_read_count) += count;\n                (is_write ? total_write_size : total_read_size) += size * count;\n            }\n        }\n\n        info.add_child(L\"gl.details.pooled_host_buffers\", pooled_host_buffers);\n        info.add(L\"gl.summary.pooled_device_buffers.total_count\", total_pooled_device_buffer_count);\n        info.add(L\"gl.summary.pooled_device_buffers.total_size\", total_pooled_device_buffer_size);\n        // info.add_child(L\"gl.summary.all_device_buffers\", texture::info());\n        info.add(L\"gl.summary.pooled_host_buffers.total_read_count\", total_read_count);\n        info.add(L\"gl.summary.pooled_host_buffers.total_write_count\", total_write_count);\n        info.add(L\"gl.summary.pooled_host_buffers.total_read_size\", total_read_size);\n        info.add(L\"gl.summary.pooled_host_buffers.total_write_size\", total_write_size);\n        info.add_child(L\"gl.summary.all_host_buffers\", buffer::info());\n\n        return info;\n    }\n\n    std::future<void> gc()\n    {\n        return spawn_async([this](yield_context yield) {\n            CASPAR_LOG(info) << \" ogl: Running GC.\";\n\n            try {\n                for (auto& depth_pools : device_pools_) {\n                    for (auto& pools : depth_pools) {\n                        for (auto& pool : pools)\n                            pool.second.clear();\n                    }\n                }\n                for (auto& pools : host_pools_) {\n                    for (auto& pool : pools)\n                        pool.second.clear();\n                }\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        });\n    }\n};\n\ndevice::device()\n    : impl_(new impl())\n{\n}\ndevice::~device() {}\nstd::shared_ptr<texture> device::create_texture(int width, int height, int stride, common::bit_depth depth)\n{\n    return impl_->create_texture(width, height, stride, depth, true);\n}\narray<uint8_t> device::create_array(int size) { return impl_->create_array(size); }\nstd::future<std::shared_ptr<texture>>\ndevice::copy_async(const array<const uint8_t>& source, int width, int height, int stride, common::bit_depth depth)\n{\n    return impl_->copy_async(source, width, height, stride, depth);\n}\nstd::future<array<const uint8_t>> device::copy_async(const std::shared_ptr<texture>& source)\n{\n    return impl_->copy_async(source);\n}\n\n#ifdef WIN32\nstd::shared_ptr<void> device::d3d_interop() const { return impl_->interop_handle_; }\nstd::future<std::shared_ptr<texture>>\ndevice::copy_async(GLuint source, int width, int height, int stride, common::bit_depth depth)\n{\n    return impl_->copy_async(source, width, height, stride, depth);\n}\n#endif\n\nvoid device::dispatch(std::function<void()> func) { boost::asio::dispatch(impl_->io_context_, std::move(func)); }\nstd::wstring                 device::version() const { return impl_->version(); }\nboost::property_tree::wptree device::info() const { return impl_->info(); }\nstd::future<void>            device::gc() { return impl_->gc(); }\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/device.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <accelerator/accelerator.h>\n#include <common/array.h>\n#include <common/bit_depth.h>\n\n#include <functional>\n#include <future>\n\n#ifdef WIN32\n#include <GL/glew.h>\n#endif\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nclass device final\n    : public std::enable_shared_from_this<device>\n    , public accelerator_device\n{\n  public:\n    device();\n    ~device();\n\n    device(const device&) = delete;\n\n    device& operator=(const device&) = delete;\n\n    std::shared_ptr<class texture> create_texture(int width, int height, int stride, common::bit_depth depth);\n    array<uint8_t>                 create_array(int size);\n\n    std::future<std::shared_ptr<class texture>>\n    copy_async(const array<const uint8_t>& source, int width, int height, int stride, common::bit_depth depth);\n    std::future<array<const uint8_t>> copy_async(const std::shared_ptr<class texture>& source);\n\n#ifdef WIN32\n    std::shared_ptr<void> d3d_interop() const;\n    std::future<std::shared_ptr<texture>>\n    copy_async(GLuint source, int width, int height, int stride, common::bit_depth depth);\n#endif\n\n    template <typename Func>\n    auto dispatch_async(Func&& func)\n    {\n        using result_type = decltype(func());\n        using task_type   = std::packaged_task<result_type()>;\n\n        auto task   = std::make_shared<task_type>(std::forward<Func>(func));\n        auto future = task->get_future();\n        dispatch([=] { (*task)(); });\n        return future;\n    }\n\n    template <typename Func>\n    auto dispatch_sync(Func&& func)\n    {\n        return dispatch_async(std::forward<Func>(func)).get();\n    }\n\n    std::wstring version() const;\n\n    boost::property_tree::wptree info() const;\n    std::future<void>            gc();\n\n  private:\n    void dispatch(std::function<void()> func);\n    struct impl;\n    std::shared_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/matrix.cpp",
    "content": "\n\n#include <core/frame/frame_transform.h>\n\n#include <common/except.h>\n#include <common/log.h>\n\n#include <cmath>\n#include <utility>\n#include <vector>\n\n#include <boost/numeric/ublas/io.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_vector.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n\n#include \"matrix.h\"\n\nnamespace caspar::accelerator::ogl {\n\nt_matrix create_matrix(std::vector<std::vector<double>> data)\n{\n    if (data.empty())\n        CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(L\"data cannot be empty\"));\n\n    t_matrix matrix(data.size(), data.at(0).size());\n    for (int y = 0; y < matrix.size1(); ++y) {\n        if (data.at(y).size() != matrix.size2())\n            CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(L\"Each row must be of the same length\"));\n\n        for (int x = 0; x < matrix.size2(); ++x)\n            matrix(x, y) = data.at(y).at(x);\n    }\n    return matrix;\n}\n\nt_matrix get_vertex_matrix(const core::image_transform& transform, double aspect_ratio)\n{\n    using namespace boost::numeric::ublas;\n    auto anchor_matrix =\n        create_matrix({{1.0, 0.0, -transform.anchor[0]}, {0.0, 1.0, -transform.anchor[1]}, {0.0, 0.0, 1.0}});\n    auto scale_matrix =\n        create_matrix({{transform.fill_scale[0], 0.0, 0.0}, {0.0, transform.fill_scale[1], 0.0}, {0.0, 0.0, 1.0}});\n    auto aspect_matrix      = create_matrix({{1.0, 0.0, 0.0}, {0.0, 1.0 / aspect_ratio, 0.0}, {0.0, 0.0, 1.0}});\n    auto aspect_inv_matrix  = create_matrix({{1.0, 0.0, 0.0}, {0.0, aspect_ratio, 0.0}, {0.0, 0.0, 1.0}});\n    auto rotation_matrix    = create_matrix({{std::cos(transform.angle), -std::sin(transform.angle), 0.0},\n                                             {std::sin(transform.angle), std::cos(transform.angle), 0.0},\n                                             {0.0, 0.0, 1.0}});\n    auto translation_matrix = create_matrix(\n        {{1.0, 0.0, transform.fill_translation[0]}, {0.0, 1.0, transform.fill_translation[1]}, {0.0, 0.0, 1.0}});\n\n    return anchor_matrix * aspect_matrix * scale_matrix * rotation_matrix * aspect_inv_matrix * translation_matrix;\n}\n\n} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/matrix.h",
    "content": "\n\n#pragma once\n\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_vector.hpp>\n\n#include <core/frame/geometry.h>\n\nnamespace caspar::accelerator::ogl {\n\ntypedef boost::numeric::ublas::matrix<double, boost::numeric::ublas::row_major, std::vector<double>> t_matrix;\n\ntypedef boost::numeric::ublas::vector<double, std::vector<double>> t_point;\n\nt_matrix get_vertex_matrix(const core::image_transform& transform, double aspect_ratio);\n\n} // namespace caspar::accelerator::ogl\n\nnamespace boost::numeric::ublas {\ntemplate <typename T, typename L, typename S>\nboost::numeric::ublas::matrix<T, L, S> operator*(const boost::numeric::ublas::matrix<T, L, S>& lhs,\n                                                 const boost::numeric::ublas::matrix<T, L, S>& rhs)\n{\n    return boost::numeric::ublas::matrix<T>(boost::numeric::ublas::prod(lhs, rhs));\n}\ntemplate <typename T, typename L, typename S1, typename S2>\nboost::numeric::ublas::vector<T, S1> operator*(const boost::numeric::ublas::vector<T, S1>&    lhs,\n                                               const boost::numeric::ublas::matrix<T, L, S2>& rhs)\n{\n    return boost::numeric::ublas::vector<T, S1>(boost::numeric::ublas::prod(lhs, rhs));\n}\ntemplate <typename T, typename L, typename S1, typename S2>\nbool operator==(const boost::numeric::ublas::matrix<T, L, S1>& lhs, const boost::numeric::ublas::matrix<T, L, S2>& rhs)\n{\n    if (lhs.size1() != rhs.size1() || lhs.size2() != rhs.size2())\n        return false;\n    for (int y = 0; y < lhs.size1(); ++y)\n        for (int x = 0; x < lhs.size2(); ++x)\n            if (lhs(y, x) != rhs(y, x))\n                return false;\n    return true;\n}\n} // namespace boost::numeric::ublas"
  },
  {
    "path": "src/accelerator/ogl/util/shader.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"shader.h\"\n\n#include <common/gl/gl_check.h>\n\n#include <GL/glew.h>\n\n#include <unordered_map>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nstruct shader::impl\n{\n    GLuint                                 program_;\n    std::unordered_map<std::string, GLint> uniform_locations_;\n    std::unordered_map<std::string, GLint> attrib_locations_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n  public:\n    impl(const std::string& vertex_source_str, const std::string& fragment_source_str)\n        : program_(0)\n    {\n        GLint success;\n\n        const char* vertex_source = vertex_source_str.c_str();\n\n        auto vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);\n\n        GL(glShaderSourceARB(vertex_shader, 1, &vertex_source, NULL));\n        GL(glCompileShaderARB(vertex_shader));\n\n        GL(glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\n        if (success == GL_FALSE) {\n            char info[2048];\n            GL(glGetInfoLogARB(vertex_shader, sizeof(info), 0, info));\n            GL(glDeleteObjectARB(vertex_shader));\n            std::stringstream str;\n            str << \"Failed to compile vertex shader:\" << std::endl << info << std::endl;\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\n        }\n\n        const char* fragment_source = fragment_source_str.c_str();\n\n        auto fragmemt_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);\n\n        GL(glShaderSourceARB(fragmemt_shader, 1, &fragment_source, NULL));\n        GL(glCompileShaderARB(fragmemt_shader));\n\n        GL(glGetObjectParameterivARB(fragmemt_shader, GL_OBJECT_COMPILE_STATUS_ARB, &success));\n        if (success == GL_FALSE) {\n            char info[2048];\n            GL(glGetInfoLogARB(fragmemt_shader, sizeof(info), 0, info));\n            GL(glDeleteObjectARB(fragmemt_shader));\n            std::stringstream str;\n            str << \"Failed to compile fragment shader:\" << std::endl << info << std::endl;\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\n        }\n\n        program_ = glCreateProgramObjectARB();\n\n        GL(glAttachObjectARB(program_, vertex_shader));\n        GL(glAttachObjectARB(program_, fragmemt_shader));\n\n        GL(glLinkProgramARB(program_));\n\n        GL(glDeleteObjectARB(vertex_shader));\n        GL(glDeleteObjectARB(fragmemt_shader));\n\n        GL(glGetObjectParameterivARB(program_, GL_OBJECT_LINK_STATUS_ARB, &success));\n        if (success == GL_FALSE) {\n            char info[2048];\n            GL(glGetInfoLogARB(program_, sizeof(info), 0, info));\n            GL(glDeleteObjectARB(program_));\n            std::stringstream str;\n            str << \"Failed to link shader program:\" << std::endl << info << std::endl;\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(str.str()));\n        }\n        GL(glUseProgramObjectARB(program_));\n    }\n\n    ~impl() { glDeleteProgram(program_); }\n\n    GLint get_uniform_location(const char* name)\n    {\n        auto it = uniform_locations_.find(name);\n        if (it == uniform_locations_.end())\n            it = uniform_locations_.insert(std::make_pair(name, glGetUniformLocation(program_, name))).first;\n        return it->second;\n    }\n\n    GLint get_attrib_location(const char* name)\n    {\n        auto it = attrib_locations_.find(name);\n        if (it == attrib_locations_.end())\n            it = attrib_locations_.insert(std::make_pair(name, glGetAttribLocation(program_, name))).first;\n        return it->second;\n    }\n\n    void set(const std::string& name, bool value) { set(name, value ? 1 : 0); }\n\n    void set(const std::string& name, int value) { GL(glUniform1i(get_uniform_location(name.c_str()), value)); }\n\n    void set(const std::string& name, float value) { GL(glUniform1f(get_uniform_location(name.c_str()), value)); }\n\n    void set(const std::string& name, double value0, double value1)\n    {\n        GL(glUniform2f(get_uniform_location(name.c_str()), static_cast<float>(value0), static_cast<float>(value1)));\n    }\n    void set(const std::string& name, double value0, double value1, double value2)\n    {\n        GL(glUniform3f(get_uniform_location(name.c_str()),\n                       static_cast<float>(value0),\n                       static_cast<float>(value1),\n                       static_cast<float>(value1)));\n    }\n\n    void set(const std::string& name, double value)\n    {\n        GL(glUniform1f(get_uniform_location(name.c_str()), static_cast<float>(value)));\n    }\n    void set_matrix3(const std::string& name, const float* value)\n    {\n        GL(glUniformMatrix3fv(get_uniform_location(name.c_str()), 1, GL_TRUE, value));\n    }\n\n    void use() { GL(glUseProgramObjectARB(program_)); }\n};\n\nshader::shader(const std::string& vertex_source_str, const std::string& fragment_source_str)\n    : impl_(new impl(vertex_source_str, fragment_source_str))\n{\n}\nshader::~shader() {}\nvoid shader::set(const std::string& name, bool value) { impl_->set(name, value); }\nvoid shader::set(const std::string& name, int value) { impl_->set(name, value); }\nvoid shader::set(const std::string& name, float value) { impl_->set(name, value); }\nvoid shader::set(const std::string& name, double value0, double value1) { impl_->set(name, value0, value1); }\nvoid shader::set(const std::string& name, double value0, double value1, double value2)\n{\n    impl_->set(name, value0, value1, value2);\n}\nvoid  shader::set(const std::string& name, double value) { impl_->set(name, value); }\nvoid  shader::set_matrix3(const std::string& name, const float* value) { impl_->set_matrix3(name, value); }\nGLint shader::get_attrib_location(const char* name) { return impl_->get_attrib_location(name); }\nint   shader::id() const { return impl_->program_; }\nvoid  shader::use() const { impl_->use(); }\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/shader.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <GL/glew.h>\n#include <memory>\n#include <string>\n#include <type_traits>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nclass shader final\n{\n    shader(const shader&);\n    shader& operator=(const shader&);\n\n  public:\n    shader(const std::string& vertex_source_str, const std::string& fragment_source_str);\n    ~shader();\n\n    void set(const std::string& name, bool value);\n    void set(const std::string& name, int value);\n    void set(const std::string& name, float value);\n    void set(const std::string& name, double value0, double value1);\n    void set(const std::string& name, double value0, double value1, double value2);\n    void set(const std::string& name, double value);\n    void set_matrix3(const std::string& name, const float* value);\n\n    GLint get_attrib_location(const char* name);\n\n    template <typename E>\n    typename std::enable_if<std::is_enum<E>::value, void>::type set(const std::string& name, E value)\n    {\n        set(name, static_cast<typename std::underlying_type<E>::type>(value));\n    }\n\n    void use() const;\n\n    int id() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/texture.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"texture.h\"\n\n#include \"buffer.h\"\n\n#include <common/bit_depth.h>\n#include <common/gl/gl_check.h>\n\n#include <GL/glew.h>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nstatic GLenum FORMAT[]             = {0, GL_RED, GL_RG, GL_BGR, GL_BGRA};\nstatic GLenum INTERNAL_FORMAT[][5] = {{0, GL_R8, GL_RG8, GL_RGB8, GL_RGBA8}, {0, GL_R16, GL_RG16, GL_RGB16, GL_RGBA16}};\nstatic GLenum TYPE[][5] = {{0, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT_8_8_8_8_REV},\n                           {0, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT, GL_UNSIGNED_SHORT}};\n\nstruct texture::impl\n{\n    GLuint            id_     = 0;\n    GLsizei           width_  = 0;\n    GLsizei           height_ = 0;\n    GLsizei           stride_ = 0;\n    GLsizei           size_   = 0;\n    common::bit_depth depth_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n  public:\n    impl(int width, int height, int stride, common::bit_depth depth)\n        : width_(width)\n        , height_(height)\n        , stride_(stride)\n        , depth_(depth)\n        , size_(width * height * stride * (depth == common::bit_depth::bit8 ? 1 : 2))\n    {\n        GL(glCreateTextures(GL_TEXTURE_2D, 1, &id_));\n        GL(glTextureParameteri(id_, GL_TEXTURE_MIN_FILTER, GL_LINEAR));\n        GL(glTextureParameteri(id_, GL_TEXTURE_MAG_FILTER, GL_LINEAR));\n        GL(glTextureParameteri(id_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\n        GL(glTextureParameteri(id_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\n        GL(glTextureStorage2D(\n            id_, 1, INTERNAL_FORMAT[depth_ == common::bit_depth::bit8 ? 0 : 1][stride_], width_, height_));\n    }\n\n    ~impl() { glDeleteTextures(1, &id_); }\n\n    void bind() { GL(glBindTexture(GL_TEXTURE_2D, id_)); }\n\n    void bind(int index)\n    {\n        GL(glActiveTexture(GL_TEXTURE0 + index));\n        bind();\n    }\n\n    void unbind() { GL(glBindTexture(GL_TEXTURE_2D, 0)); }\n\n    void attach() { GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + 0, GL_TEXTURE_2D, id_, 0)); }\n\n    void clear()\n    {\n        GL(glClearTexImage(id_, 0, FORMAT[stride_], TYPE[depth_ == common::bit_depth::bit8 ? 0 : 1][stride_], nullptr));\n    }\n\n#ifdef WIN32\n    void copy_from(int texture_id)\n    {\n        GL(glCopyImageSubData(\n            texture_id, GL_TEXTURE_2D, 0, 0, 0, 0, id_, GL_TEXTURE_2D, 0, 0, 0, 0, width_, height_, 1));\n    }\n#endif\n\n    void copy_from(buffer& src)\n    {\n        src.bind();\n\n        if (width_ % 16 > 0) {\n            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);\n        } else {\n            glPixelStorei(GL_UNPACK_ALIGNMENT, 4);\n        }\n\n        GL(glTextureSubImage2D(id_,\n                               0,\n                               0,\n                               0,\n                               width_,\n                               height_,\n                               FORMAT[stride_],\n                               TYPE[depth_ == common::bit_depth::bit8 ? 0 : 1][stride_],\n                               nullptr));\n\n        src.unbind();\n    }\n\n    void copy_to(buffer& dst)\n    {\n        dst.bind();\n        GL(glGetTextureImage(\n            id_, 0, FORMAT[stride_], TYPE[depth_ == common::bit_depth::bit8 ? 0 : 1][stride_], size_, nullptr));\n        dst.unbind();\n    }\n};\n\ntexture::texture(int width, int height, int stride, common::bit_depth depth)\n    : impl_(new impl(width, height, stride, depth))\n{\n}\ntexture::texture(texture&& other)\n    : impl_(std::move(other.impl_))\n{\n}\ntexture::~texture() {}\ntexture& texture::operator=(texture&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\nvoid texture::bind(int index) { impl_->bind(index); }\nvoid texture::unbind() { impl_->unbind(); }\nvoid texture::attach() { impl_->attach(); }\nvoid texture::clear() { impl_->clear(); }\n#ifdef WIN32\nvoid texture::copy_from(int source) { impl_->copy_from(source); }\n#endif\nvoid              texture::copy_from(buffer& source) { impl_->copy_from(source); }\nvoid              texture::copy_to(buffer& dest) { impl_->copy_to(dest); }\nint               texture::width() const { return impl_->width_; }\nint               texture::height() const { return impl_->height_; }\nint               texture::stride() const { return impl_->stride_; }\ncommon::bit_depth texture::depth() const { return impl_->depth_; }\nvoid              texture::set_depth(common::bit_depth depth) { impl_->depth_ = depth; }\nint               texture::size() const { return impl_->size_; }\nint               texture::id() const { return impl_->id_; }\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/texture.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <core/frame/frame.h>\n#include <memory>\n\nnamespace caspar { namespace accelerator { namespace ogl {\n\nclass texture final : public core::texture\n{\n  public:\n    texture(int width, int height, int stride, common::bit_depth depth = common::bit_depth::bit8);\n    texture(const texture&) = delete;\n    texture(texture&& other);\n    ~texture();\n\n    texture& operator=(const texture&) = delete;\n    texture& operator=(texture&& other);\n\n#ifdef WIN32\n    void copy_from(int source);\n#endif\n    void copy_from(class buffer& source);\n    void copy_to(class buffer& dest);\n\n    void attach();\n    void clear();\n\n    virtual void bind(int index) override;\n    virtual void unbind() override;\n\n    int               width() const;\n    int               height() const;\n    int               stride() const;\n    common::bit_depth depth() const;\n    void              set_depth(common::bit_depth depth);\n    int               size() const;\n    int               id() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/transforms.cpp",
    "content": "\n#include \"transforms.h\"\n\n#include <algorithm>\n#include <unordered_set>\n\nnamespace caspar::accelerator::ogl {\n\ndraw_crop_region::draw_crop_region(double left, double top, double right, double bottom)\n{\n    // upper left\n    coords[0]    = t_point(3);\n    coords[0](0) = left;\n    coords[0](1) = top;\n    coords[0](2) = 1;\n\n    // upper right\n    coords[1]    = t_point(3);\n    coords[1](0) = right;\n    coords[1](1) = top;\n    coords[1](2) = 1;\n\n    // lower right\n    coords[2]    = t_point(3);\n    coords[2](0) = right;\n    coords[2](1) = bottom;\n    coords[2](2) = 1;\n\n    // lower left\n    coords[3]    = t_point(3);\n    coords[3](0) = left;\n    coords[3](1) = bottom;\n    coords[3](2) = 1;\n}\n\nvoid draw_crop_region::apply_transform(const caspar::accelerator::ogl::t_matrix& matrix)\n{\n    coords[0] = coords[0] * matrix;\n    coords[1] = coords[1] * matrix;\n    coords[2] = coords[2] * matrix;\n    coords[3] = coords[3] * matrix;\n}\n\nvoid apply_transform_colour_values(core::image_transform& self, const core::image_transform& other)\n{\n    // Note: this intentionally does not affect any geometry-related fields, they follow a separate flow\n\n    self.opacity *= other.opacity;\n    self.brightness *= other.brightness;\n    self.contrast *= other.contrast;\n    self.saturation *= other.saturation;\n\n    self.levels.min_input  = std::max(self.levels.min_input, other.levels.min_input);\n    self.levels.max_input  = std::min(self.levels.max_input, other.levels.max_input);\n    self.levels.min_output = std::max(self.levels.min_output, other.levels.min_output);\n    self.levels.max_output = std::min(self.levels.max_output, other.levels.max_output);\n    self.levels.gamma *= other.levels.gamma;\n    self.chroma.enable |= other.chroma.enable;\n    self.chroma.show_mask |= other.chroma.show_mask;\n    self.chroma.target_hue     = std::max(other.chroma.target_hue, self.chroma.target_hue);\n    self.chroma.min_saturation = std::max(other.chroma.min_saturation, self.chroma.min_saturation);\n    self.chroma.min_brightness = std::max(other.chroma.min_brightness, self.chroma.min_brightness);\n    self.chroma.hue_width      = std::max(other.chroma.hue_width, self.chroma.hue_width);\n    self.chroma.softness       = std::max(other.chroma.softness, self.chroma.softness);\n    self.chroma.spill_suppress = std::max(other.chroma.spill_suppress, self.chroma.spill_suppress);\n    self.chroma.spill_suppress_saturation =\n        std::min(other.chroma.spill_suppress_saturation, self.chroma.spill_suppress_saturation);\n    self.is_key |= other.is_key;\n    self.invert |= other.invert;\n    self.is_mix |= other.is_mix;\n    self.blend_mode = std::max(self.blend_mode, other.blend_mode);\n    self.layer_depth += other.layer_depth;\n}\n\nbool is_default_perspective(const core::corners& perspective)\n{\n    return perspective.ul[0] == 0 && perspective.ul[1] == 0 && perspective.ur[0] == 1 && perspective.ur[1] == 0 &&\n           perspective.ll[0] == 0 && perspective.ll[1] == 1 && perspective.lr[0] == 1 && perspective.lr[1] == 1;\n}\n\ndraw_transforms draw_transforms::combine_transform(const core::image_transform& transform, double aspect_ratio) const\n{\n    draw_transforms new_transform(image_transform, steps);\n\n    auto transform_before = new_transform.current().vertex_matrix;\n\n    // Get matrix for turning coords in 'transform' into the parent frame.\n    auto new_matrix = get_vertex_matrix(transform, aspect_ratio);\n\n    apply_transform_colour_values(new_transform.image_transform, transform);\n    new_transform.current().vertex_matrix = new_matrix * new_transform.current().vertex_matrix;\n\n    // Only enable this for some transforms, to avoid applying crops when a draw_frame is just being used to flatten\n    // other draw_frames\n    if (transform.enable_geometry_modifiers) {\n        // Push the new clip before the new transform applied\n        draw_crop_region new_clip(transform.clip_translation[0],\n                                  transform.clip_translation[1],\n                                  transform.clip_translation[0] + transform.clip_scale[0],\n                                  transform.clip_translation[1] + transform.clip_scale[1]);\n        new_clip.apply_transform(transform_before);\n        new_transform.current().crop_regions.push_back(std::move(new_clip));\n\n        if (!is_default_perspective(transform.perspective)) {\n            // Split into a new step\n            new_transform.steps.emplace_back(transform.perspective,\n                                             boost::numeric::ublas::identity_matrix<double>(3, 3));\n        }\n\n        // Push the new crop region with the new transform applied\n        draw_crop_region new_crop(\n            transform.crop.ul[0], transform.crop.ul[1], transform.crop.lr[0], transform.crop.lr[1]);\n        new_crop.apply_transform(new_transform.current().vertex_matrix);\n        new_transform.current().crop_regions.push_back(std::move(new_crop));\n    }\n\n    return std::move(new_transform);\n}\n\nvoid apply_perspective_to_vertex(t_point& vertex, const core::corners& perspective)\n{\n    const double x = vertex(0);\n    const double y = vertex(1);\n\n    // ul: x' =  (1-y) * a + (1 - a * (1-y)) * x\n    vertex(0) += (1 - y) * perspective.ul[0] + (1 - perspective.ul[0] + perspective.ul[0] * y) * x - x;\n    vertex(1) += (1 - x) * perspective.ul[1] + (1 - perspective.ul[1] + perspective.ul[1] * x) * y - y;\n\n    // ur/ll: x' = x * (a * (1-y) + y)\n    vertex(0) += x * (perspective.ur[0] * (1 - y) + y) - x;\n    vertex(1) += y * (perspective.ll[1] * (1 - x) + x) - y;\n\n    // ur/ll: x' = y * a + x * (1 - a * y)\n    vertex(0) += y * perspective.ll[0] + x * (1 - perspective.ll[0] * y) - x;\n    vertex(1) += x * perspective.ur[1] + y * (1 - perspective.ur[1] * x) - y;\n\n    // lr: x' = x * (y * a + (1-y))\n    vertex(0) += x * (y * perspective.lr[0] + (1 - y)) - x;\n    vertex(1) += y * (x * perspective.lr[1] + (1 - x)) - y;\n}\n\nstruct wrapped_vertex\n{\n    explicit wrapped_vertex(const core::frame_geometry::coord& coord)\n    {\n        vertex(0) = coord.vertex_x;\n        vertex(1) = coord.vertex_y;\n        vertex(2) = 1;\n\n        texture_x = coord.texture_x;\n        texture_y = coord.texture_y;\n        texture_r = coord.texture_r;\n        texture_q = coord.texture_q;\n    }\n\n    explicit wrapped_vertex() { vertex(2) = 1; };\n\n    [[nodiscard]] core::frame_geometry::coord as_geometry() const\n    {\n        core::frame_geometry::coord res = {vertex(0), vertex(1), texture_x, texture_y};\n        res.texture_r                   = texture_r;\n        res.texture_q                   = texture_q;\n        return res;\n    }\n\n    t_point vertex = t_point(3);\n\n    double texture_x = 0.0;\n    double texture_y = 0.0;\n    double texture_r = 0.0;\n    double texture_q = 1.0;\n};\n\nstatic const double epsilon = 0.001;\n\nbool inline point_is_outside_of_line(const t_point& line_1,\n                                     const t_point& line_2,\n                                     const t_point& vertex,\n                                     bool           invert_winding)\n{\n    // use a cross product to check if the point is outside the crop region\n    auto cross = (line_2(0) - line_1(0)) * (vertex(1) - line_1(1)) - (line_2(1) - line_1(1)) * (vertex(0) - line_1(0));\n    return invert_winding ? cross > epsilon : cross < -epsilon;\n}\n\n// http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect\nbool get_intersection_with_crop_line(const t_point& crop0,\n                                     const t_point& crop1,\n                                     const t_point& p0,\n                                     const t_point& p1,\n                                     t_point&       result)\n{\n    double s1_x = crop1(0) - crop0(0);\n    double s1_y = crop1(1) - crop0(1);\n    double s2_x = p1(0) - p0(0);\n    double s2_y = p1(1) - p0(1);\n\n    double s = (-s1_y * (crop0(0) - p0(0)) + s1_x * (crop0(1) - p0(1))) / (-s2_x * s1_y + s1_x * s2_y);\n    double t = (s2_x * (crop0(1) - p0(1)) - s2_y * (crop0(0) - p0(0))) / (-s2_x * s1_y + s1_x * s2_y);\n\n    if (s >= 0 && s <= 1) {\n        // Collision detected\n        result(0) = crop0(0) + t * s1_x;\n        result(1) = crop0(1) + t * s1_y;\n\n        return true;\n    }\n\n    return false; // No collision\n}\n\ndouble hypotenuse(double x1, double y1, double x2, double y2)\n{\n    auto x = x2 - x1;\n    auto y = y2 - y1;\n\n    return std::sqrt(x * x + y * y);\n}\n\ndouble calc_q(double close_diagonal, double distant_diagonal)\n{\n    return (close_diagonal + distant_diagonal) / distant_diagonal;\n}\n\nvoid crop_texture_for_vertex(const wrapped_vertex& line_a, const wrapped_vertex& line_b, wrapped_vertex& vertex)\n{\n    auto delta_point = vertex.vertex - line_a.vertex;\n    auto delta_line  = line_b.vertex - line_a.vertex;\n\n    // Calculate the dot product\n    auto dot_product      = delta_point(0) * delta_line(0) + delta_point(1) * delta_line(1);\n    auto line_len_squared = delta_line(0) * delta_line(0) + delta_line(1) * delta_line(1);\n\n    // Skip if line has no length\n    if (line_len_squared == 0) {\n        vertex.texture_x = line_a.texture_x;\n        vertex.texture_y = line_a.texture_y;\n        return;\n    }\n\n    auto dist_delta = dot_product / line_len_squared;\n\n    vertex.texture_x = line_a.texture_x + dist_delta * (line_b.texture_x - line_a.texture_x);\n    vertex.texture_y = line_a.texture_y + dist_delta * (line_b.texture_y - line_a.texture_y);\n    vertex.texture_q = line_a.texture_q + dist_delta * (line_b.texture_q - line_a.texture_q);\n}\n\nvoid fill_texture_q_for_quad(std::vector<wrapped_vertex>& coords)\n{\n    if (coords.size() != 4)\n        return;\n\n    // Based on formula from:\n    // http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/\n\n    double s1_x = coords[2].vertex(0) - coords[0].vertex(0);\n    double s1_y = coords[2].vertex(1) - coords[0].vertex(1);\n    double s2_x = coords[3].vertex(0) - coords[1].vertex(0);\n    double s2_y = coords[3].vertex(1) - coords[1].vertex(1);\n\n    double s =\n        (-s1_y * (coords[0].vertex(0) - coords[1].vertex(0)) + s1_x * (coords[0].vertex(1) - coords[1].vertex(1))) /\n        (-s2_x * s1_y + s1_x * s2_y);\n    double t =\n        (s2_x * (coords[0].vertex(1) - coords[1].vertex(1)) - s2_y * (coords[0].vertex(0) - coords[1].vertex(0))) /\n        (-s2_x * s1_y + s1_x * s2_y);\n\n    if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {\n        // Collision detected\n        double diagonal_intersection_x = coords[0].vertex(0) + t * s1_x;\n        double diagonal_intersection_y = coords[0].vertex(1) + t * s1_y;\n\n        auto d0 =\n            hypotenuse(coords[3].vertex(0), coords[3].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n        auto d1 =\n            hypotenuse(coords[2].vertex(0), coords[2].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n        auto d2 =\n            hypotenuse(coords[1].vertex(0), coords[1].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n        auto d3 =\n            hypotenuse(coords[0].vertex(0), coords[0].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n\n        auto ulq = calc_q(d3, d1);\n        auto urq = calc_q(d2, d0);\n        auto lrq = calc_q(d1, d3);\n        auto llq = calc_q(d0, d2);\n\n        std::vector<double> q_values = {ulq, urq, lrq, llq};\n\n        int corner = 0;\n        for (auto& coord : coords) {\n            coord.texture_q = q_values[corner];\n            coord.texture_x *= q_values[corner];\n            coord.texture_y *= q_values[corner];\n\n            if (++corner == 4)\n                corner = 0;\n        }\n    }\n}\n\nvoid transform_vertex(const draw_transform_step& step, t_point& vertex)\n{\n    // Apply basic transforms of this step\n    vertex = vertex * step.vertex_matrix;\n\n    // Apply perspective. These rely on x and y of the coord, so can't be done as a shared matrix\n    apply_perspective_to_vertex(vertex, step.perspective);\n}\n\nstd::vector<core::frame_geometry::coord>\ndraw_transforms::transform_coords(const std::vector<core::frame_geometry::coord>& coords) const\n{\n    // Convert to matrix representations\n    std::vector<wrapped_vertex> cropped_coords;\n    cropped_coords.reserve(coords.size());\n\n    for (const auto& coord : coords) {\n        cropped_coords.emplace_back(coord);\n    }\n\n    std::vector<draw_crop_region> transformed_regions;\n\n    // Apply the transforms\n    for (int i = (int)steps.size() - 1; i >= 0; i--) {\n        for (auto& coord : cropped_coords) {\n            transform_vertex(steps[i], coord.vertex);\n        }\n\n        // Transform existing regions\n        for (auto& region : transformed_regions) {\n            for (int l = 0; l < 4; ++l) {\n                transform_vertex(steps[i], region.coords[l]);\n            }\n        }\n\n        // Push new regions\n        for (auto& region : steps[i].crop_regions) {\n            draw_crop_region new_region = region;\n            for (int l = 0; l < 4; ++l) {\n                // Only apply perspective for new ones\n                apply_perspective_to_vertex(new_region.coords[l], steps[i].perspective);\n            }\n\n            transformed_regions.push_back(new_region);\n        }\n    }\n\n    // Apply the perspective correction\n    fill_texture_q_for_quad(cropped_coords);\n\n    // Perform the crop\n    for (auto& crop_region : transformed_regions) {\n        // Determine the winding order of the crop region\n        // Calculate the signed area to determine if the region is clockwise or counter-clockwise\n        double signed_area = 0.0;\n        for (int l = 0; l < 4; ++l) {\n            int next_l = (l + 1) % 4;\n            signed_area += (crop_region.coords[next_l](0) - crop_region.coords[l](0)) *\n                           (crop_region.coords[next_l](1) + crop_region.coords[l](1));\n        }\n        // In screen coordinates (Y down), normal clockwise winding gives negative signed area\n        // We need to invert the test when the winding is flipped (positive signed area)\n        bool invert_winding = signed_area > 0;\n\n        for (int l = 0; l < 4; ++l) {\n            // Apply the crop, one edge at a time\n            int     to_index   = l == 3 ? 0 : l + 1;\n            t_point from_point = crop_region.coords[l];\n            t_point to_point   = crop_region.coords[to_index];\n\n            std::unordered_set<size_t> points_outside_of_line;\n\n            // Figure out which points are outside the crop region\n            for (size_t j = 0; j < cropped_coords.size(); ++j) {\n                bool v = point_is_outside_of_line(from_point, to_point, cropped_coords[j].vertex, invert_winding);\n                if (v)\n                    points_outside_of_line.insert(j);\n            }\n\n            if (points_outside_of_line.empty()) {\n                // Line has no effect, skip\n                continue;\n            } else if (points_outside_of_line.size() == cropped_coords.size()) {\n                // All are outside, shape has no geometry\n                return {};\n            }\n\n            std::vector<wrapped_vertex> new_coords;\n            new_coords.reserve(cropped_coords.size() * 2); // Avoid reallocs for complex shapes\n\n            // Iterate through the coords\n            for (size_t j = 0; j < cropped_coords.size(); ++j) {\n                if (points_outside_of_line.count(j) == 0) {\n                    new_coords.push_back(cropped_coords[j]);\n                    continue;\n                }\n\n                size_t prev_index = j == 0 ? cropped_coords.size() - 1 : j - 1;\n                size_t next_index = j == cropped_coords.size() - 1 ? 0 : j + 1;\n\n                bool prev_is_outside = points_outside_of_line.count(prev_index) == 1;\n                bool next_is_outside = points_outside_of_line.count(next_index) == 1;\n\n                if (prev_is_outside && next_is_outside) {\n                    // Vertex and its edges are completely outside, skip\n                    continue;\n                }\n\n                if (!prev_is_outside) {\n                    // This edge intersects the crop line, calculate the new coordinates\n                    wrapped_vertex new_coord;\n                    if (get_intersection_with_crop_line(to_point,\n                                                        from_point,\n                                                        cropped_coords[prev_index].vertex,\n                                                        cropped_coords[j].vertex,\n                                                        new_coord.vertex)) {\n                        crop_texture_for_vertex(cropped_coords[prev_index], cropped_coords[j], new_coord);\n                        new_coords.emplace_back(std::move(new_coord));\n                    } else {\n                        // Geometry error! skip coordinate\n                    }\n                }\n\n                if (!next_is_outside) {\n                    // This edge intersects the crop line, calculate the new coordinates\n                    wrapped_vertex new_coord;\n                    if (get_intersection_with_crop_line(to_point,\n                                                        from_point,\n                                                        cropped_coords[j].vertex,\n                                                        cropped_coords[next_index].vertex,\n                                                        new_coord.vertex)) {\n                        crop_texture_for_vertex(cropped_coords[j], cropped_coords[next_index], new_coord);\n                        new_coords.emplace_back(std::move(new_coord));\n                    } else {\n                        // Geometry error! skip coordinate\n                    }\n                }\n            }\n\n            // Polygon is cropped, update state\n            cropped_coords = new_coords;\n        }\n\n        {\n            static const double pixel_epsilon = 0.0001; // less than a pixel at 8k\n\n            // Prune duplicate coords\n            std::vector<wrapped_vertex> new_coords;\n            new_coords.reserve(cropped_coords.size()); // Avoid reallocs\n\n            for (size_t j = 0; j < cropped_coords.size(); ++j) {\n                size_t prev_index = j == 0 ? cropped_coords.size() - 1 : j - 1;\n\n                auto delta = cropped_coords[j].vertex - cropped_coords[prev_index].vertex;\n                if (std::abs(delta(0)) > pixel_epsilon || std::abs(delta(1)) > pixel_epsilon) {\n                    new_coords.emplace_back(cropped_coords[j]);\n                }\n            }\n\n            if (new_coords.size() < 3) {\n                // Not enough coords to draw anything\n                return {};\n            }\n            cropped_coords = new_coords;\n        }\n    }\n\n    // Convert back to frame_geometry types\n    std::vector<core::frame_geometry::coord> result;\n    result.reserve(cropped_coords.size());\n    for (auto& coord : cropped_coords) {\n        result.push_back(coord.as_geometry());\n    }\n\n    return result;\n}\n\n} // namespace caspar::accelerator::ogl\n"
  },
  {
    "path": "src/accelerator/ogl/util/transforms.h",
    "content": "#pragma once\n\n#include <core/mixer/image/blend_modes.h>\n\n#include <common/memory.h>\n\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n\n#include <utility>\n\n#include \"matrix.h\"\n\nnamespace caspar::accelerator::ogl {\n\nstruct draw_crop_region\n{\n    explicit draw_crop_region(double left, double top, double right, double bottom);\n\n    void apply_transform(const t_matrix& matrix);\n\n    std::array<t_point, 4> coords;\n};\n\nstruct draw_transform_step\n{\n    draw_transform_step()\n        : vertex_matrix(boost::numeric::ublas::identity_matrix<double>(3, 3))\n    {\n    }\n\n    draw_transform_step(const core::corners& perspective, const t_matrix& vertex_matrix)\n        : perspective(perspective)\n        , vertex_matrix(vertex_matrix)\n    {\n    }\n\n    core::corners perspective;\n\n    std::vector<draw_crop_region> crop_regions;\n\n    t_matrix vertex_matrix;\n};\n\nstruct draw_transforms\n{\n    std::vector<draw_transform_step> steps;\n\n    draw_transforms()\n        : image_transform(core::image_transform())\n        , steps({draw_transform_step()})\n    {\n    }\n\n    explicit draw_transforms(core::image_transform transform, std::vector<draw_transform_step> steps)\n        : image_transform(transform)\n        , steps(std::move(steps))\n    {\n    }\n\n    core::image_transform image_transform;\n\n    draw_transform_step& current() { return steps.back(); }\n\n    [[nodiscard]] draw_transforms combine_transform(const core::image_transform& transform, double aspect_ratio) const;\n\n    [[nodiscard]] std::vector<core::frame_geometry::coord>\n    transform_coords(const std::vector<core::frame_geometry::coord>& coords) const;\n};\n\n} // namespace caspar::accelerator::ogl"
  },
  {
    "path": "src/accelerator/vulkan/image/fragment_shader.frag",
    "content": "#version 450\n\n#extension GL_ARB_fragment_shader_interlock : enable\n#extension GL_EXT_nonuniform_qualifier : enable\n\nlayout(location = 0) in vec4 TexCoord;\nlayout(location = 1) in vec4 TexCoord2;\n\nlayout(location = 0) out vec4 fragColor;\n\n// bindless texture array\nlayout(binding = 0) uniform sampler2D\ttextures[8];\n\nlayout(binding = 1, input_attachment_index = 0) uniform subpassInput background;\n\nconst uint PLANE0 = 0;\nconst uint PLANE1 = 1;\nconst uint PLANE2 = 2;\nconst uint PLANE3 = 3;\nconst uint LOCAL_KEY = 4;\nconst uint LAYER_KEY = 5;\n\nconst uint is_straight_alpha_mask = 1u << 0;\nconst uint has_local_key_mask = 1u << 1;\nconst uint has_layer_key_mask = 1u << 2;\nconst uint invert_mask = 1u << 3;\nconst uint levels_mask = 1u << 4;\nconst uint csb_mask = 1u << 5;\nconst uint chroma_mask = 1u << 6;\nconst uint chroma_show_mask_mask = 1u << 7;\n\nlayout(push_constant) uniform ParamsBlock {\n    uint color_space_index;\n    float precision_factor[4];\n    int blend_mode;\n    int keyer;\n    int pixel_format;\n    float opacity;\n\n/* levels */\n    float min_input;\n    float max_input;\n    float gamma;\n    float min_output;\n    float max_output;\n    \n/* contrast, saturation & brightness */\n    float brt;\n    float sat;\n    float con;\n\n/* Chroma */\n    float chroma_target_hue;\n    float chroma_hue_width;\n    float chroma_min_saturation;\n    float chroma_min_brightness;\n    float chroma_softness;\n    float chroma_spill_suppress;\n    float chroma_spill_suppress_saturation;\n\n    uint flags;\n};\n\nconst mat3[3] color_matrices = mat3[3](\n                    mat3(1.0, 0.0, 1.402, 1.0, -0.344, -0.509, 1.0, 1.772, 0.0),\n                    mat3(1.0, 0.0, 1.5748, 1.0, -0.1873, -0.4681, 1.0, 1.8556, 0.0),\n                    mat3(1.0, 0.0, 1.4746, 1.0, -0.16455312684366, -0.57135312684366, 1.0, 1.8814, 0.0)\n                ); \nconst vec3[3] luma_coefficients = vec3[3](\n                    vec3(0.299, 0.587, 0.114), // Rec. 601\n                    vec3(0.2126, 0.7152, 0.0722),  // Rec. 709\n                    vec3(0.2627, 0.6780, 0.0593)   // Rec. 2020\n                );\n\n/*\n** Contrast, saturation, brightness\n** Code of this function is from TGM's shader pack\n** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057\n*/\n\nvec3 ContrastSaturationBrightness(vec4 color, float brt, float sat, float con)\n{\n    vec3 luma_coeff = luma_coefficients[color_space_index];\n    \n    const float AvgLumR = 0.5;\n    const float AvgLumG = 0.5;\n    const float AvgLumB = 0.5;\n\n    if (color.a > 0.0)\n        color.rgb /= color.a;\n\n    vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);\n    vec3 brtColor = color.rgb * brt;\n    vec3 intensity = vec3(dot(brtColor, luma_coeff));\n    vec3 satColor = mix(intensity, brtColor, sat);\n    vec3 conColor = mix(AvgLumin, satColor, con);\n\n    conColor.rgb *= color.a;\n\n    return conColor;\n}\n\n/*\n** Gamma correction\n** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/\n*/\n#define GammaCorrection(color, gamma)\t\t\t\t\t\t\t\tpow(color, vec3(1.0 / gamma))\n\n/*\n** Levels control (input (+gamma), output)\n** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/\n*/\n\n#define LevelsControlInputRange(color, minInput, maxInput)\t\t\t\tmin(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0))\n#define LevelsControlInput(color, minInput, gamma, maxInput)\t\t\t\tGammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma)\n#define LevelsControlOutputRange(color, minOutput, maxOutput) \t\t\tmix(vec3(minOutput), vec3(maxOutput), color)\n#define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput) \tLevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput)\n\n/*\n** Photoshop & misc math\n** Blending modes, RGB/HSL/Contrast/Desaturate, levels control\n**\n** Romain Dura | Romz\n** Blog: http://blog.mouaif.org\n** Post: http://blog.mouaif.org/?p=94\n*/\n\n\n/*\n** Desaturation\n*/\n\nvec4 Desaturate(vec3 color, float Desaturation)\n{\n    vec3 grayXfer = vec3(0.3, 0.59, 0.11);\n    vec3 gray = vec3(dot(grayXfer, color));\n    return vec4(mix(color, gray, Desaturation), 1.0);\n}\n\n\n/*\n** Hue, saturation, luminance\n*/\n\nvec3 RGBToHSL(vec3 color)\n{\n    vec3 hsl;\n\n    float fmin = min(min(color.r, color.g), color.b);\n    float fmax = max(max(color.r, color.g), color.b);\n    float delta = fmax - fmin;\n\n    hsl.z = (fmax + fmin) / 2.0;\n\n    if (delta == 0.0)\n    {\n        hsl.x = 0.0;\n        hsl.y = 0.0;\n    }\n    else\n    {\n        if (hsl.z < 0.5)\n            hsl.y = delta / (fmax + fmin);\n        else\n            hsl.y = delta / (2.0 - fmax - fmin);\n\n        float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;\n        float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;\n        float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;\n\n        if (color.r == fmax )\n            hsl.x = deltaB - deltaG;\n        else if (color.g == fmax)\n            hsl.x = (1.0 / 3.0) + deltaR - deltaB;\n        else if (color.b == fmax)\n            hsl.x = (2.0 / 3.0) + deltaG - deltaR;\n\n        if (hsl.x < 0.0)\n            hsl.x += 1.0;\n        else if (hsl.x > 1.0)\n            hsl.x -= 1.0;\n    }\n\n    return hsl;\n}\n\nfloat HueToRGB(float f1, float f2, float hue)\n{\n    if (hue < 0.0)\n        hue += 1.0;\n    else if (hue > 1.0)\n        hue -= 1.0;\n    float res;\n    if ((6.0 * hue) < 1.0)\n        res = f1 + (f2 - f1) * 6.0 * hue;\n    else if ((2.0 * hue) < 1.0)\n        res = f2;\n    else if ((3.0 * hue) < 2.0)\n        res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;\n    else\n        res = f1;\n    return res;\n}\n\nvec3 HSLToRGB(vec3 hsl)\n{\n    vec3 rgb;\n\n    if (hsl.y == 0.0)\n        rgb = vec3(hsl.z);\n    else\n    {\n        float f2;\n\n        if (hsl.z < 0.5)\n            f2 = hsl.z * (1.0 + hsl.y);\n        else\n            f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);\n\n        float f1 = 2.0 * hsl.z - f2;\n\n        rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));\n        rgb.g = HueToRGB(f1, f2, hsl.x);\n        rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));\n    }\n\n    return rgb;\n}\n\n\n\n\n/*\n** Float blending modes\n** Adapted from here: http://www.nathanm.com/photoshop-blending-math/\n** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results\n*/\n\n#define BlendLinearDodgef \t\t\t\t\tBlendAddf\n#define BlendLinearBurnf \t\t\t\t\tBlendSubstractf\n#define BlendAddf(base, blend) \t\t\t\tmin(base + blend, 1.0)\n#define BlendSubstractf(base, blend) \t\tmax(base + blend - 1.0, 0.0)\n#define BlendLightenf(base, blend) \t\tmax(blend, base)\n#define BlendDarkenf(base, blend) \t\t\tmin(blend, base)\n#define BlendLinearLightf(base, blend) \t(blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5))))\n#define BlendScreenf(base, blend) \t\t\t(1.0 - ((1.0 - base) * (1.0 - blend)))\n#define BlendOverlayf(base, blend) \t\t(base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)))\n#define BlendSoftLightf(base, blend) \t\t((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)))\n#define BlendColorDodgef(base, blend) \t\t((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0))\n#define BlendColorBurnf(base, blend) \t\t((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0))\n#define BlendVividLightf(base, blend)\t\t((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5))))\n#define BlendPinLightf(base, blend) \t\t((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5))))\n#define BlendHardMixf(base, blend) \t\t((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0)\n#define BlendReflectf(base, blend) \t\t((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0))\n\n\n/*\n** Vector3 blending modes\n*/\n\n#define Blend(base, blend, funcf) \t\t\tvec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b))\n\n#define BlendNormal(base, blend) \t\t\t(blend)\n#define BlendLighten\t\t\t\t\t\tBlendLightenf\n#define BlendDarken\t\t\t\t\t\tBlendDarkenf\n#define BlendMultiply(base, blend) \t\t(base * blend)\n#define BlendAverage(base, blend) \t\t\t((base + blend) / 2.0)\n#define BlendAdd(base, blend) \t\t\t\tmin(base + blend, vec3(1.0))\n#define BlendSubstract(base, blend) \t\tmax(base + blend - vec3(1.0), vec3(0.0))\n#define BlendDifference(base, blend) \t\tabs(base - blend)\n#define BlendNegation(base, blend) \t\t(vec3(1.0) - abs(vec3(1.0) - base - blend))\n#define BlendExclusion(base, blend) \t\t(base + blend - 2.0 * base * blend)\n#define BlendScreen(base, blend) \t\t\tBlend(base, blend, BlendScreenf)\n#define BlendOverlay(base, blend) \t\t\tBlend(base, blend, BlendOverlayf)\n#define BlendSoftLight(base, blend) \t\tBlend(base, blend, BlendSoftLightf)\n#define BlendHardLight(base, blend) \t\tBlendOverlay(blend, base)\n#define BlendColorDodge(base, blend) \t\tBlend(base, blend, BlendColorDodgef)\n#define BlendColorBurn(base, blend) \t\tBlend(base, blend, BlendColorBurnf)\n#define BlendLinearDodge\t\t\t\t\tBlendAdd\n#define BlendLinearBurn\t\t\t\t\tBlendSubstract\n#define BlendLinearLight(base, blend) \t\tBlend(base, blend, BlendLinearLightf)\n#define BlendVividLight(base, blend) \t\tBlend(base, blend, BlendVividLightf)\n#define BlendPinLight(base, blend) \t\tBlend(base, blend, BlendPinLightf)\n#define BlendHardMix(base, blend) \t\t\tBlend(base, blend, BlendHardMixf)\n#define BlendReflect(base, blend) \t\t\tBlend(base, blend, BlendReflectf)\n#define BlendGlow(base, blend) \t\t\tBlendReflect(blend, base)\n#define BlendPhoenix(base, blend) \t\t\t(min(base, blend) - max(base, blend) + vec3(1.0))\n#define BlendOpacity(base, blend, F, O) \t(F(base, blend) * O + blend * (1.0 - O))\n\n\nvec3 BlendHue(vec3 base, vec3 blend)\n{\n    vec3 baseHSL = RGBToHSL(base);\n    return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b));\n}\n\nvec3 BlendSaturation(vec3 base, vec3 blend)\n{\n    vec3 baseHSL = RGBToHSL(base);\n    return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b));\n}\n\nvec3 BlendColor(vec3 base, vec3 blend)\n{\n    vec3 blendHSL = RGBToHSL(blend);\n    return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b));\n}\n\nvec3 BlendLuminosity(vec3 base, vec3 blend)\n{\n    vec3 baseHSL = RGBToHSL(base);\n    return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b));\n}\n\n// Chroma keying\n// Author: Tim Eves <timseves@googlemail.com>\n//\n// This implements the Chroma key algorithm described in the paper:\n//      'Software Chroma Keying in an Imersive Virtual Environment'\n//      by F. van den Bergh & V. Lalioti\n// but as a pixel shader algorithm.\n//\n\n// This allows us to implement the paper's alphaMap curve in software\n// rather than a largeish array\nfloat alpha_map(float d)\n{\n    return 1.0 - smoothstep(1.0, chroma_softness, d);\n}\n\n// http://stackoverflow.com/questions/15095909/from-rgb-to-hsv-in-opengl-glsl\nvec3 rgb2hsv(vec3 c)\n{\n    vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);\n    vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));\n    vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));\n\n    float d = q.x - min(q.w, q.y);\n    float e = 1.0e-10;\n    return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);\n}\n\n// From the same page\nvec3 hsv2rgb(vec3 c)\n{\n    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);\n    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);\n    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);\n}\n\nfloat AngleDiff(float angle1, float angle2)\n{\n    return 0.5 - abs(abs(angle1 - angle2) - 0.5);\n}\n\nfloat AngleDiffDirectional(float angle1, float angle2)\n{\n    float diff = angle1 - angle2;\n\n    return diff < -0.5\n            ? diff + 1.0\n            : (diff > 0.5 ? diff - 1.0 : diff);\n}\n\nfloat Distance(float actual, float target)\n{\n    return min(0.0, target - actual);\n}\n\nfloat ColorDistance(vec3 hsv)\n{\n    float hueDiff\t\t\t\t\t= AngleDiff(hsv.x, chroma_target_hue) * 2;\n    float saturationDiff\t\t\t= Distance(hsv.y, chroma_min_saturation);\n    float brightnessDiff\t\t\t= Distance(hsv.z, chroma_min_brightness);\n\n    float saturationBrightnessScore\t= max(brightnessDiff, saturationDiff);\n    float hueScore\t\t\t\t\t= hueDiff - chroma_hue_width;\n\n    return -hueScore * saturationBrightnessScore;\n}\n\nvec3 supress_spill(vec3 c)\n{\n    float hue\t\t= c.x;\n    float diff\t\t= AngleDiffDirectional(hue, chroma_target_hue);\n    float distance\t= abs(diff) / chroma_spill_suppress;\n\n    if (distance < 1)\n    {\n        c.x = diff < 0\n                ? chroma_target_hue - chroma_spill_suppress\n                : chroma_target_hue + chroma_spill_suppress;\n        c.y *= min(1.0, distance + chroma_spill_suppress_saturation);\n    }\n\n    return c;\n}\n\n// Key on any color\nvec4 ChromaOnCustomColor(vec4 c, bool show_mask)\n{\n    vec3 hsv\t\t= rgb2hsv(c.rgb);\n    float distance\t= ColorDistance(hsv);\n    float d\t\t\t= distance * -2.0 + 1.0;\n    vec4 suppressed\t= vec4(hsv2rgb(supress_spill(hsv)), 1.0);\n    float alpha\t\t= alpha_map(d);\n\n    suppressed *= alpha;\n\n    return show_mask ? vec4(suppressed.a, suppressed.a, suppressed.a, 1) : suppressed;\n}\n\n\n\nvec3 get_blend_color(vec3 back, vec3 fore)\n{\n    switch(blend_mode)\n    {\n    case  0: return BlendNormal(back, fore);\n    case  1: return BlendLighten(back, fore);\n    case  2: return BlendDarken(back, fore);\n    case  3: return BlendMultiply(back, fore);\n    case  4: return BlendAverage(back, fore);\n    case  5: return BlendAdd(back, fore);\n    case  6: return BlendSubstract(back, fore);\n    case  7: return BlendDifference(back, fore);\n    case  8: return BlendNegation(back, fore);\n    case  9: return BlendExclusion(back, fore);\n    case 10: return BlendScreen(back, fore);\n    case 11: return BlendOverlay(back, fore);\n//\tcase 12: return BlendSoftLight(back, fore);\n    case 13: return BlendHardLight(back, fore);\n    case 14: return BlendColorDodge(back, fore);\n    case 15: return BlendColorBurn(back, fore);\n    case 16: return BlendLinearDodge(back, fore);\n    case 17: return BlendLinearBurn(back, fore);\n    case 18: return BlendLinearLight(back, fore);\n    case 19: return BlendVividLight(back, fore);\n    case 20: return BlendPinLight(back, fore);\n    case 21: return BlendHardMix(back, fore);\n    case 22: return BlendReflect(back, fore);\n    case 23: return BlendGlow(back, fore);\n    case 24: return BlendPhoenix(back, fore);\n    case 25: return BlendHue(back, fore);\n    case 26: return BlendSaturation(back, fore);\n    case 27: return BlendColor(back, fore);\n    case 28: return BlendLuminosity(back, fore);\n    }\n    return BlendNormal(back, fore);\n}\n\nvec4 blend(vec4 fore)\n{\n    // attachments have bgra format to match opengl accelerator\n    vec4 back = subpassLoad(background).bgra;\n    if(blend_mode != 0)\n       fore.rgb = get_blend_color(back.rgb/(back.a+0.0000001), fore.rgb/(fore.a+0.0000001))*fore.a;\n   switch(keyer)\n   {\n       case 1:  return fore + back; // additive\n       default: return fore + (1.0-fore.a)*back; // linear\n   }\n}\n\nvec4 ycbcra_to_rgba(float Y, float Cb, float Cr, float A)\n{\n    mat3 color_matrix = transpose(color_matrices[color_space_index]);\n\n    const float luma_coefficient = 255.0/219.0;\n    const float chroma_coefficient = 255.0/224.0;\n\n    vec3 YCbCr = vec3(Y, Cb, Cr) * 255;\n    YCbCr -= vec3(16.0, 128.0, 128.0);\n    YCbCr *= vec3(luma_coefficient, chroma_coefficient, chroma_coefficient);\n\n    return vec4(color_matrix * YCbCr / 255, A);\n}\n\nvec4 get_sample(sampler2D texSampler, vec2 coords)\n{\n    return texture(texSampler, coords);\n}\n\nvec4 get_rgba_color()\n{\n    vec2 uv = TexCoord.st / TexCoord.q;\n\n    switch(pixel_format)\n    {\n    case 0:\t\t//gray\n        return vec4(get_sample(textures[PLANE0], uv).rrr * precision_factor[0], 1.0);\n    case 1:\t\t//bgra,\n        return get_sample(textures[PLANE0], uv).bgra * precision_factor[0];\n    case 2:\t\t//rgba,\n        return get_sample(textures[PLANE0], uv).rgba * precision_factor[0];\n    case 3:\t\t//argb,\n        return get_sample(textures[PLANE0], uv).argb * precision_factor[0];\n    case 4:\t\t//abgr,\n        return get_sample(textures[PLANE0], uv).gbar * precision_factor[0];\n    case 5:\t\t//ycbcr,\n        {\n            float y  = get_sample(textures[PLANE0], uv).r * precision_factor[0];\n            float cb = get_sample(textures[PLANE1], uv).r * precision_factor[1];\n            float cr = get_sample(textures[PLANE2], uv).r * precision_factor[2];\n            return ycbcra_to_rgba(y, cb, cr, 1.0);\n        }\n    case 6:\t\t//ycbcra\n        {\n            float y  = get_sample(textures[PLANE0], uv).r * precision_factor[0];\n            float cb = get_sample(textures[PLANE1], uv).r * precision_factor[1];\n            float cr = get_sample(textures[PLANE2], uv).r * precision_factor[2];\n            float a  = get_sample(textures[PLANE3], uv).r * precision_factor[3];\n            return ycbcra_to_rgba(y, cb, cr, a);\n        }\n    case 7:\t\t//luma\n        {\n            vec3 y3 = get_sample(textures[PLANE0], uv).rrr * precision_factor[0];\n            return vec4((y3-0.065)/0.859, 1.0);\n        }\n    case 8:\t\t//bgr,\n        return vec4(get_sample(textures[PLANE0], uv).bgr * precision_factor[0], 1.0);\n    case 9:\t\t//rgb,\n        return vec4(get_sample(textures[PLANE0], uv).rgb * precision_factor[0], 1.0);\n\tcase 10:\t// uyvy\n\t\t{\n\t\t\tfloat y  = get_sample(textures[PLANE0], uv).g * precision_factor[0];\n\t\t\tfloat cb = get_sample(textures[PLANE1], uv).b * precision_factor[1];\n\t\t\tfloat cr = get_sample(textures[PLANE1], uv).r * precision_factor[1];\n\t\t\treturn ycbcra_to_rgba(y, cb, cr, 1.0);\n\t\t}\n    case 11:    // gbrp\n        {\n            float g = get_sample(textures[PLANE0], uv).r * precision_factor[0];\n            float b = get_sample(textures[PLANE1], uv).r * precision_factor[1];\n            float r = get_sample(textures[PLANE2], uv).r * precision_factor[2];\n\t\t\treturn vec4(b, g, r, 1.0);\n        }\n    case 12:    // gbrap\n        {\n            float g = get_sample(textures[PLANE0], uv).r * precision_factor[0];\n            float b = get_sample(textures[PLANE1], uv).r * precision_factor[1];\n            float r = get_sample(textures[PLANE2], uv).r * precision_factor[2];\n            float a = get_sample(textures[PLANE3], uv).r * precision_factor[3];\n\t\t\treturn vec4(b, g, r, a);\n        }\n    }\n    return vec4(0.0, 0.0, 0.0, 0.0);\n}\n\nvoid main()\n{\n    bool is_straight_alpha = (flags & is_straight_alpha_mask) == is_straight_alpha_mask;\n    bool has_local_key = (flags & has_local_key_mask) == has_local_key_mask;\n    bool has_layer_key  = (flags & has_layer_key_mask) == has_layer_key_mask;\n    bool invert = (flags & invert_mask) == invert_mask;\n    bool levels = (flags & levels_mask) == levels_mask;\n    bool csb = (flags & csb_mask) == csb_mask;\n    bool chroma = (flags & chroma_mask) == chroma_mask;\n    bool chroma_show_mask = (flags & chroma_show_mask_mask) == chroma_show_mask_mask;\n\n    vec4 color = get_rgba_color();\n    if (is_straight_alpha)\n        color.rgb *= color.a;\n    if (chroma)\n        color = ChromaOnCustomColor(color, chroma_show_mask);\n    if(levels)\n        color.rgb = LevelsControl(color.rgb, min_input, gamma, max_input, min_output, max_output);\n    if(csb)\n        color.rgb = ContrastSaturationBrightness(color, brt, sat, con);\n    if(has_local_key)\n        color *= texture(textures[LOCAL_KEY], TexCoord2.st).r;\n    if(has_layer_key)\n        color *= texture(textures[LAYER_KEY], TexCoord2.st).r;\n    color *= opacity;\n    if (invert)\n        color = 1.0 - color;\n    if (blend_mode >= 0)\n        color = blend(color);\n\n    // attachments store color in bgra format to match opengl accelerator\n    fragColor = color.bgra;\n}\n"
  },
  {
    "path": "src/accelerator/vulkan/image/image_kernel.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#include \"image_kernel.h\"\n\n#include \"../util/device.h\"\n#include \"../util/pipeline.h\"\n#include \"../util/renderpass.h\"\n#include \"../util/texture.h\"\n\n#include <common/assert.h>\n\n#include <core/frame/frame_transform.h>\n#include <core/frame/pixel_format.h>\n\n#include <boost/algorithm/cxx11/all_of.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n\n#include <array>\n#include <cmath>\n\nnamespace caspar::accelerator::vulkan {\n\nfloat get_precision_factor(common::bit_depth depth)\n{\n    switch (depth) {\n        case common::bit_depth::bit8:\n            return 1.0f;\n        case common::bit_depth::bit10:\n            return 64.0f;\n        case common::bit_depth::bit12:\n            return 16.0f;\n        case common::bit_depth::bit16:\n        default:\n            return 1.0f;\n    }\n}\n\nbool is_above_screen(double y) { return y < 0.0; }\n\nbool is_below_screen(double y) { return y > 1.0; }\n\nbool is_left_of_screen(double x) { return x < 0.0; }\n\nbool is_right_of_screen(double x) { return x > 1.0; }\n\nbool is_outside_screen(const std::vector<core::frame_geometry::coord>& coords)\n{\n    auto x_coords =\n        coords | boost::adaptors::transformed([](const core::frame_geometry::coord& c) { return c.vertex_x; });\n    auto y_coords =\n        coords | boost::adaptors::transformed([](const core::frame_geometry::coord& c) { return c.vertex_y; });\n\n    return boost::algorithm::all_of(x_coords, &is_left_of_screen) ||\n           boost::algorithm::all_of(x_coords, &is_right_of_screen) ||\n           boost::algorithm::all_of(y_coords, &is_above_screen) || boost::algorithm::all_of(y_coords, &is_below_screen);\n}\n\nstatic const double epsilon = 0.001;\n\nstatic const uint32_t frame_buffer_size = 3;\n\nstruct image_kernel::impl\n{\n    spl::shared_ptr<device> vulkan_;\n    common::bit_depth       depth_;\n\n    struct frame_data : public frame_context\n    {\n        image_kernel::impl* parent = nullptr;\n\n        vk::Buffer       buffer = nullptr;\n        void*            data   = nullptr;\n        vk::DeviceMemory memory = nullptr;\n        size_t           size   = 0;\n\n        vk::CommandBuffer cmd_buffer = nullptr;\n        vk::Fence         fence      = nullptr;\n\n        explicit frame_data(image_kernel::impl* parent)\n            : parent(parent)\n        {\n        }\n\n        virtual vk::Buffer upload_vertex_data(const std::vector<float>& src)\n        {\n            return parent->upload_vertex_buffer(*this, (void*)src.data(), src.size() * sizeof(float));\n        }\n        virtual draw_data create_draw_data(const draw_params& params) { return parent->draw(params); }\n        virtual std::shared_ptr<class pipeline> get_pipeline() { return parent->vulkan_->get_pipeline(parent->depth_); }\n        virtual vk::CommandBuffer               get_command_buffer() { return cmd_buffer; }\n        virtual void                            submit()\n        {\n            fence = parent->vulkan_->getVkDevice().createFence({});\n            vk::SubmitInfo submitInfo{};\n            submitInfo.setCommandBuffers(cmd_buffer);\n            parent->vulkan_->submit(submitInfo, fence);\n        }\n        virtual std::shared_ptr<class texture>\n        create_attachment(uint32_t width, uint32_t height, uint32_t components_count)\n        {\n            return parent->vulkan_->create_attachment(width, height, parent->depth_, components_count);\n        }\n    };\n\n    frame_data frames_[frame_buffer_size];\n    uint32_t   current_frame_index_ = 0;\n\n    explicit impl(const spl::shared_ptr<device>& vulkan, common::bit_depth depth)\n        : vulkan_(vulkan)\n        , depth_(depth)\n        , frames_{frame_data{this}, frame_data{this}, frame_data{this}}\n    {\n        auto cmd_buffers = vulkan_->allocateCommandBuffers(frame_buffer_size);\n        for (uint32_t i = 0; i < frame_buffer_size; ++i) {\n            frames_[i].cmd_buffer = cmd_buffers[i];\n        }\n    }\n\n    ~impl()\n    {\n        auto vk_device = vulkan_->getVkDevice();\n\n        for (auto& frame : frames_) {\n            if (frame.buffer) {\n                vk_device.unmapMemory(frame.memory);\n                vk_device.destroyBuffer(frame.buffer);\n                vk_device.freeMemory(frame.memory);\n                if (frame.fence) {\n                    vk_device.destroyFence(frame.fence);\n                }\n            }\n        }\n    }\n\n    spl::shared_ptr<renderpass> create_renderpass(uint32_t width, uint32_t height)\n    {\n        auto  device = vulkan_->getVkDevice();\n        auto& ctx    = frames_[(++current_frame_index_) % frame_buffer_size];\n        if (ctx.fence) {\n            auto result = device.waitForFences(ctx.fence, true, 1000000000); // wait up to one second\n            if (result == vk::Result::eTimeout) {\n                CASPAR_LOG(warning) << L\"[Vulkan image_kernel] Timeout waiting for fence\";\n            }\n            device.destroyFence(ctx.fence);\n            ctx.fence = nullptr;\n        }\n\n        ctx.cmd_buffer.reset({});\n        return spl::make_shared<renderpass>(&ctx, width, height);\n    }\n\n    uint32_t findDedicatedMemoryType(uint32_t typeMask, vk::MemoryPropertyFlags properties)\n    {\n        auto memProperties = vulkan_->getMemoryProperties();\n        for (uint32_t i = 0; i < memProperties.memoryTypeCount; ++i) {\n            if ((typeMask & (1 << i)) && ((memProperties.memoryTypes[i].propertyFlags & properties) == properties)) {\n                return i;\n            }\n        }\n        throw std::runtime_error(\"[Vulkan image_kernel] Failed to find suitable memory type\");\n    }\n\n    vk::Buffer upload_vertex_buffer(frame_data& vb, void* data, size_t size)\n    {\n        if (vb.size < size) {\n            auto vk_device = vulkan_->getVkDevice();\n\n            if (vb.buffer) {\n                vk_device.unmapMemory(vb.memory);\n                vk_device.destroyBuffer(vb.buffer);\n                vk_device.freeMemory(vb.memory);\n            }\n\n            // staging buffer\n            vk::BufferCreateInfo stagingInfo{};\n            stagingInfo.size        = size;\n            stagingInfo.usage       = vk::BufferUsageFlagBits::eVertexBuffer;\n            stagingInfo.sharingMode = vk::SharingMode::eExclusive;\n\n            vb.buffer = vk_device.createBuffer(stagingInfo);\n\n            auto stagingMemReq = vk_device.getBufferMemoryRequirements(vb.buffer);\n\n            vk::MemoryAllocateInfo stagingAlloc{};\n            stagingAlloc.allocationSize  = stagingMemReq.size;\n            stagingAlloc.memoryTypeIndex = findDedicatedMemoryType(stagingMemReq.memoryTypeBits,\n                                                                   vk::MemoryPropertyFlagBits::eHostVisible |\n                                                                       vk::MemoryPropertyFlagBits::eHostCoherent);\n\n            vb.memory = vk_device.allocateMemory(stagingAlloc);\n            vk_device.bindBufferMemory(vb.buffer, vb.memory, 0);\n\n            vb.data = vk_device.mapMemory(vb.memory, 0, size);\n            vb.size = size;\n        }\n        memcpy(vb.data, data, size);\n\n        return vb.buffer;\n    }\n\n    std::pair<std::vector<core::frame_geometry::coord>, uniform_block> draw(const draw_params& params)\n    {\n        CASPAR_ASSERT(params.pix_desc.planes.size() == params.textures.size());\n\n        if (params.textures.empty() || !params.background) {\n            return {};\n        }\n\n        if (params.transforms.image_transform.opacity < epsilon) {\n            return {};\n        }\n\n        if (params.geometry.data().empty()) {\n            return {};\n        }\n\n        auto coords     = params.geometry.data();\n        auto transforms = params.transforms;\n\n        auto const first_plane = params.pix_desc.planes.at(0);\n        if (params.geometry.mode() != core::frame_geometry::scale_mode::stretch && first_plane.width > 0 &&\n            first_plane.height > 0) {\n            auto width_scale  = static_cast<double>(params.target_width) / static_cast<double>(first_plane.width);\n            auto height_scale = static_cast<double>(params.target_height) / static_cast<double>(first_plane.height);\n\n            core::image_transform transform;\n            double                target_scale;\n            switch (params.geometry.mode()) {\n                case core::frame_geometry::scale_mode::fit:\n                    target_scale = std::min(width_scale, height_scale);\n\n                    transform.fill_scale[0] *= target_scale / width_scale;\n                    transform.fill_scale[1] *= target_scale / height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::fill:\n                    target_scale = std::max(width_scale, height_scale);\n                    transform.fill_scale[0] *= target_scale / width_scale;\n                    transform.fill_scale[1] *= target_scale / height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::original:\n                    transform.fill_scale[0] /= width_scale;\n                    transform.fill_scale[1] /= height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::hfill:\n                    transform.fill_scale[1] *= width_scale / height_scale;\n                    break;\n\n                case core::frame_geometry::scale_mode::vfill:\n                    transform.fill_scale[0] *= height_scale / width_scale;\n                    break;\n\n                default:;\n            }\n\n            transforms = transforms.combine_transform(transform, params.aspect_ratio);\n        }\n\n        coords = transforms.transform_coords(coords);\n\n        // Skip drawing if all the coordinates will be outside the screen.\n        if (coords.size() < 3 || is_outside_screen(coords)) {\n            return {};\n        }\n\n        uniform_block uniforms;\n\n        for (int n = 0; n < params.textures.size(); ++n) {\n            uniforms.precision_factor[n] = get_precision_factor(params.textures[n]->depth());\n        }\n\n        const auto is_hd           = params.pix_desc.planes.at(0).height > 700;\n        const auto color_space     = is_hd ? params.pix_desc.color_space : core::color_space::bt601;\n        uniforms.color_space_index = static_cast<uint32_t>(color_space);\n\n        if (params.pix_desc.is_straight_alpha) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::is_straight_alpha);\n        }\n\n        if (static_cast<bool>(params.local_key)) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::has_local_key);\n        }\n        if (static_cast<bool>(params.layer_key)) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::has_layer_key);\n        }\n        uniforms.pixel_format = static_cast<uint32_t>(params.pix_desc.format);\n\n        uniforms.opacity =\n            transforms.image_transform.is_key ? 1.0f : static_cast<float>(transforms.image_transform.opacity);\n\n        if (transforms.image_transform.chroma.enable) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::chroma);\n\n            if (transforms.image_transform.chroma.show_mask)\n                uniforms.flags |= static_cast<uint32_t>(shader_flags::chroma_show_mask);\n\n            uniforms.chroma_target_hue     = static_cast<float>(transforms.image_transform.chroma.target_hue) / 360.0f;\n            uniforms.chroma_hue_width      = static_cast<float>(transforms.image_transform.chroma.hue_width);\n            uniforms.chroma_min_saturation = static_cast<float>(transforms.image_transform.chroma.min_saturation);\n            uniforms.chroma_min_brightness = static_cast<float>(transforms.image_transform.chroma.min_brightness);\n            uniforms.chroma_softness       = 1.0f + static_cast<float>(transforms.image_transform.chroma.softness);\n            uniforms.chroma_spill_suppress =\n                static_cast<float>(transforms.image_transform.chroma.spill_suppress) / 360.0f;\n            uniforms.chroma_spill_suppress_saturation =\n                static_cast<float>(transforms.image_transform.chroma.spill_suppress_saturation);\n        }\n\n        // Setup blend_func\n        auto blend_mode = params.blend_mode;\n        if (transforms.image_transform.is_key) {\n            blend_mode = core::blend_mode::normal;\n        }\n\n        uniforms.blend_mode = static_cast<uint32_t>(blend_mode);\n        uniforms.keyer      = static_cast<uint32_t>(params.keyer);\n\n        if (transforms.image_transform.invert) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::invert);\n        }\n\n        if (transforms.image_transform.levels.min_input > epsilon ||\n            transforms.image_transform.levels.max_input < 1.0 - epsilon ||\n            transforms.image_transform.levels.min_output > epsilon ||\n            transforms.image_transform.levels.max_output < 1.0 - epsilon ||\n            std::abs(transforms.image_transform.levels.gamma - 1.0) > epsilon) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::levels);\n            uniforms.min_input  = static_cast<float>(transforms.image_transform.levels.min_input);\n            uniforms.max_input  = static_cast<float>(transforms.image_transform.levels.max_input);\n            uniforms.min_output = static_cast<float>(transforms.image_transform.levels.min_output);\n            uniforms.max_output = static_cast<float>(transforms.image_transform.levels.max_output);\n            uniforms.gamma      = static_cast<float>(transforms.image_transform.levels.gamma);\n        }\n\n        if (std::abs(transforms.image_transform.brightness - 1.0) > epsilon ||\n            std::abs(transforms.image_transform.saturation - 1.0) > epsilon ||\n            std::abs(transforms.image_transform.contrast - 1.0) > epsilon) {\n            uniforms.flags |= static_cast<uint32_t>(shader_flags::csb);\n\n            uniforms.brt = static_cast<float>(transforms.image_transform.brightness);\n            uniforms.sat = static_cast<float>(transforms.image_transform.saturation);\n            uniforms.con = static_cast<float>(transforms.image_transform.contrast);\n        }\n\n        return {std::move(coords), uniforms};\n    }\n};\n\nimage_kernel::image_kernel(const spl::shared_ptr<device>& device, common::bit_depth depth)\n    : impl_(new impl(device, depth))\n{\n}\nimage_kernel::~image_kernel() {}\n\nspl::shared_ptr<renderpass> image_kernel::create_renderpass(uint32_t width, uint32_t height)\n{\n    return impl_->create_renderpass(width, height);\n}\n\n} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/image/image_kernel.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include <core/mixer/image/blend_modes.h>\n\n#include <common/memory.h>\n#include <utility>\n#include <vulkan/vulkan.hpp>\n\n#include \"../util/draw_params.h\"\n#include \"../util/matrix.h\"\n#include \"../util/transforms.h\"\n#include \"../util/uniform_block.h\"\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nclass image_kernel final : public std::enable_shared_from_this<image_kernel>\n{\n    image_kernel(const image_kernel&);\n    image_kernel& operator=(const image_kernel&);\n\n  public:\n    image_kernel(const spl::shared_ptr<class device>& device, common::bit_depth depth);\n    ~image_kernel();\n\n    spl::shared_ptr<class renderpass> create_renderpass(uint32_t width, uint32_t height);\n\n  private:\n    struct impl;\n    spl::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/image/image_mixer.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n#include \"image_mixer.h\"\n\n#include \"image_kernel.h\"\n\n#include \"../util/buffer.h\"\n#include \"../util/device.h\"\n#include \"../util/renderpass.h\"\n#include \"../util/texture.h\"\n\n#ifdef WIN32\n#include \"../../d3d/d3d_texture2d.h\"\n#endif\n\n#include <boost/align/aligned_allocator.hpp>\n\n#include <common/array.h>\n#include <common/bit_depth.h>\n#include <common/future.h>\n#include <common/log.h>\n\n#include <core/frame/frame.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <core/video_format.h>\n\n#include <any>\n#include <vector>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nusing future_texture = std::shared_future<std::shared_ptr<texture>>;\n\nstruct item\n{\n    core::pixel_format_desc     pix_desc = core::pixel_format_desc(core::pixel_format::invalid);\n    std::vector<future_texture> textures;\n    draw_transforms             transforms;\n    core::frame_geometry        geometry = core::frame_geometry::get_default();\n};\n\nstruct layer\n{\n    std::vector<layer> sublayers;\n    std::vector<item>  items;\n    core::blend_mode   blend_mode;\n\n    explicit layer(core::blend_mode blend_mode)\n        : blend_mode(blend_mode)\n    {\n    }\n};\n\nclass image_renderer\n{\n    spl::shared_ptr<device> vulkan_;\n    image_kernel            kernel_;\n    const size_t            max_frame_size_;\n    common::bit_depth       depth_;\n\n  public:\n    explicit image_renderer(const spl::shared_ptr<device>& vulkan, const size_t max_frame_size, common::bit_depth depth)\n        : vulkan_(vulkan)\n        , kernel_(vulkan_, depth)\n        , max_frame_size_(max_frame_size)\n        , depth_(depth)\n    {\n    }\n\n    std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\n    operator()(std::vector<layer> layers, const core::video_format_desc& format_desc)\n    {\n        if (layers.empty()) { // Bypass GPU with empty frame.\n            static const std::vector<uint8_t, boost::alignment::aligned_allocator<uint8_t, 32>> buffer(max_frame_size_,\n                                                                                                       0);\n            return make_ready_future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>(\n                {array<const std::uint8_t>(buffer.data(), format_desc.size, true), nullptr});\n        }\n\n        auto f = std::move(vulkan_->dispatch_async(\n            [this, format_desc, layers = std::move(layers)]() mutable\n            -> std::tuple<std::future<array<const std::uint8_t>>, std::shared_ptr<core::texture>> {\n                auto pass   = kernel_.create_renderpass(format_desc.square_width, format_desc.square_height);\n                auto target = pass->default_attachment();\n                draw(target, std::move(layers), format_desc, pass);\n\n                pass->commit();\n\n                return {vulkan_->copy_async(target), nullptr};\n            }));\n\n        return std::async(\n            std::launch::deferred,\n            [f = std::move(f)]() mutable -> std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>> {\n                auto tuple = std::move(f.get());\n                return {std::move(std::get<0>(tuple).get()), std::move(std::get<1>(tuple))};\n            });\n    }\n\n    common::bit_depth depth() const { return depth_; }\n\n  private:\n    void draw(std::shared_ptr<texture>&      target_texture,\n              std::vector<layer>             layers,\n              const core::video_format_desc& format_desc,\n              spl::shared_ptr<renderpass>    pass)\n    {\n        std::shared_ptr<texture> layer_key_texture;\n\n        for (auto& layer : layers) {\n            draw(target_texture, layer.sublayers, format_desc, pass);\n            draw(target_texture, std::move(layer), layer_key_texture, format_desc, pass);\n        }\n    }\n\n    void draw(std::shared_ptr<texture>&      target_texture,\n              layer                          layer,\n              std::shared_ptr<texture>&      layer_key_texture,\n              const core::video_format_desc& format_desc,\n              spl::shared_ptr<renderpass>    pass)\n    {\n        if (layer.items.empty())\n            return;\n\n        std::shared_ptr<texture> local_key_texture;\n        std::shared_ptr<texture> local_mix_texture;\n\n        if (layer.blend_mode != core::blend_mode::normal) {\n            auto layer_texture = pass->create_attachment();\n\n            for (auto& item : layer.items)\n                draw(layer_texture,\n                     std::move(item),\n                     layer_key_texture,\n                     local_key_texture,\n                     local_mix_texture,\n                     format_desc,\n                     pass);\n\n            draw(layer_texture, std::move(local_mix_texture), format_desc, pass, core::blend_mode::normal);\n            draw(target_texture, std::move(layer_texture), format_desc, pass, layer.blend_mode);\n        } else // fast path\n        {\n            for (auto& item : layer.items)\n                draw(target_texture,\n                     std::move(item),\n                     layer_key_texture,\n                     local_key_texture,\n                     local_mix_texture,\n                     format_desc,\n                     pass);\n\n            draw(target_texture, std::move(local_mix_texture), format_desc, pass, core::blend_mode::normal);\n        }\n\n        layer_key_texture = std::move(local_key_texture);\n    }\n\n    void draw(std::shared_ptr<texture>&      target_texture,\n              item                           item,\n              std::shared_ptr<texture>&      layer_key_texture,\n              std::shared_ptr<texture>&      local_key_texture,\n              std::shared_ptr<texture>&      local_mix_texture,\n              const core::video_format_desc& format_desc,\n              spl::shared_ptr<renderpass>    pass)\n    {\n        draw_params draw_params;\n        draw_params.target_width  = format_desc.square_width;\n        draw_params.target_height = format_desc.square_height;\n        // TODO: Pass the target color_space\n\n        draw_params.pix_desc   = std::move(item.pix_desc);\n        draw_params.transforms = std::move(item.transforms);\n        draw_params.geometry   = std::move(item.geometry);\n        draw_params.aspect_ratio =\n            static_cast<double>(format_desc.square_width) / static_cast<double>(format_desc.square_height);\n\n        for (auto& future_texture : item.textures) {\n            draw_params.textures.push_back(spl::make_shared_ptr(future_texture.get()));\n        }\n\n        if (draw_params.transforms.image_transform\n                .is_key) { // A key means we will use it for the next non-key item as a mask\n            local_key_texture = local_key_texture ? local_key_texture : pass->create_attachment();\n\n            draw_params.background = local_key_texture;\n            draw_params.local_key  = nullptr;\n            draw_params.layer_key  = nullptr;\n\n            pass->draw(std::move(draw_params));\n        } else if (draw_params.transforms.image_transform\n                       .is_mix) { // A mix means precomp the items to a texture, before drawing to the channel\n            local_mix_texture = local_mix_texture ? local_mix_texture : pass->create_attachment();\n\n            draw_params.background = local_mix_texture;\n            draw_params.local_key  = std::move(local_key_texture); // Use and reset the key\n            draw_params.layer_key  = layer_key_texture;\n\n            draw_params.keyer = keyer::additive;\n\n            pass->draw(std::move(draw_params));\n        } else {\n            // If there is a mix, this is the end so draw it and reset\n            draw(target_texture, std::move(local_mix_texture), format_desc, pass, core::blend_mode::normal);\n\n            draw_params.background = target_texture;\n            draw_params.local_key  = std::move(local_key_texture);\n            draw_params.layer_key  = layer_key_texture;\n\n            pass->draw(std::move(draw_params));\n        }\n    }\n\n    void draw(std::shared_ptr<texture>&   target_texture,\n              std::shared_ptr<texture>&&  source_texture,\n              core::video_format_desc     format_desc,\n              spl::shared_ptr<renderpass> pass,\n              core::blend_mode            blend_mode = core::blend_mode::normal)\n    {\n        if (!source_texture)\n            return;\n\n        draw_params draw_params;\n        draw_params.target_width    = format_desc.square_width;\n        draw_params.target_height   = format_desc.square_height;\n        draw_params.pix_desc.format = core::pixel_format::bgra;\n        draw_params.pix_desc.planes = {core::pixel_format_desc::plane(\n            source_texture->width(), source_texture->height(), 4, source_texture->depth())};\n        draw_params.textures        = {spl::make_shared_ptr(source_texture)};\n        draw_params.blend_mode      = blend_mode;\n        draw_params.background      = target_texture;\n        draw_params.geometry        = core::frame_geometry::get_default();\n\n        pass->draw(std::move(draw_params));\n    }\n};\n\nstruct image_mixer::impl\n    : public core::frame_factory\n    , public std::enable_shared_from_this<impl>\n{\n    spl::shared_ptr<device>      vulkan_;\n    image_renderer               renderer_;\n    std::vector<draw_transforms> transform_stack_;\n    std::vector<layer>           layers_; // layer/stream/items\n    std::vector<layer*>          layer_stack_;\n\n    double aspect_ratio_ = 1.0;\n\n  public:\n    impl(const spl::shared_ptr<device>& device,\n         const int                      channel_id,\n         const size_t                   max_frame_size,\n         common::bit_depth              depth)\n        : vulkan_(device)\n        , renderer_(device, max_frame_size, depth)\n        , transform_stack_(1)\n    {\n        CASPAR_LOG(info) << L\"Initialized Vulkan Accelerated GPU Image Mixer for channel \" << channel_id;\n    }\n\n    void update_aspect_ratio(double aspect_ratio) { aspect_ratio_ = aspect_ratio; }\n\n    void push(const core::frame_transform& transform)\n    {\n        auto previous_layer_depth = transform_stack_.back().image_transform.layer_depth;\n\n        transform_stack_.push_back(transform_stack_.back().combine_transform(transform.image_transform, aspect_ratio_));\n\n        auto new_layer_depth = transform_stack_.back().image_transform.layer_depth;\n\n        if (previous_layer_depth < new_layer_depth) {\n            layer new_layer(transform_stack_.back().image_transform.blend_mode);\n\n            if (layer_stack_.empty()) {\n                layers_.push_back(std::move(new_layer));\n                layer_stack_.push_back(&layers_.back());\n            } else {\n                layer_stack_.back()->sublayers.push_back(std::move(new_layer));\n                layer_stack_.push_back(&layer_stack_.back()->sublayers.back());\n            }\n        }\n    }\n\n    void visit(const core::const_frame& frame)\n    {\n        if (frame.pixel_format_desc().format == core::pixel_format::invalid)\n            return;\n\n        if (frame.pixel_format_desc().planes.empty())\n            return;\n\n        item item;\n        item.pix_desc   = frame.pixel_format_desc();\n        item.transforms = transform_stack_.back();\n        item.geometry   = frame.geometry();\n\n        auto textures_ptr = std::any_cast<std::shared_ptr<std::vector<future_texture>>>(frame.opaque());\n\n        if (textures_ptr) {\n            item.textures = *textures_ptr;\n        } else {\n            for (int n = 0; n < static_cast<int>(item.pix_desc.planes.size()); ++n) {\n                item.textures.emplace_back(vulkan_->copy_async(frame.image_data(n),\n                                                               item.pix_desc.planes[n].width,\n                                                               item.pix_desc.planes[n].height,\n                                                               item.pix_desc.planes[n].stride,\n                                                               item.pix_desc.planes[n].depth));\n            }\n        }\n\n        layer_stack_.back()->items.push_back(item);\n    }\n\n    void pop()\n    {\n        transform_stack_.pop_back();\n        layer_stack_.resize(transform_stack_.back().image_transform.layer_depth);\n    }\n\n    std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\n    render(const core::video_format_desc& format_desc)\n    {\n        return renderer_(std::move(layers_), format_desc);\n    }\n\n    core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override\n    {\n        return create_frame(tag, desc, common::bit_depth::bit8);\n    }\n\n    core::mutable_frame\n    create_frame(const void* tag, const core::pixel_format_desc& desc, common::bit_depth depth) override\n    {\n        std::vector<array<std::uint8_t>> image_data;\n        for (auto& plane : desc.planes) {\n            auto bytes_per_pixel = depth == common::bit_depth::bit8 ? 1 : 2;\n            image_data.push_back(vulkan_->create_array(plane.size * bytes_per_pixel));\n        }\n\n        std::weak_ptr<image_mixer::impl> weak_self = shared_from_this();\n        return core::mutable_frame(tag,\n                                   std::move(image_data),\n                                   array<int32_t>{},\n                                   desc,\n                                   [weak_self, desc](std::vector<array<const std::uint8_t>> image_data) -> std::any {\n                                       auto self = weak_self.lock();\n                                       if (!self) {\n                                           return std::any{};\n                                       }\n                                       std::vector<future_texture> textures;\n                                       for (int n = 0; n < static_cast<int>(desc.planes.size()); ++n) {\n                                           textures.emplace_back(self->vulkan_->copy_async(image_data[n],\n                                                                                           desc.planes[n].width,\n                                                                                           desc.planes[n].height,\n                                                                                           desc.planes[n].stride,\n                                                                                           desc.planes[n].depth));\n                                       }\n                                       return std::make_shared<decltype(textures)>(std::move(textures));\n                                   });\n    }\n\n#ifdef WIN32\n    core::const_frame import_d3d_texture(const void*                                tag,\n                                         const std::shared_ptr<d3d::d3d_texture2d>& d3d_texture,\n                                         core::pixel_format                         format,\n                                         common::bit_depth                          depth) override\n    {\n        throw std::runtime_error(\"d3d texture import not supported on vulkan accelerator\");\n    }\n#endif\n\n    common::bit_depth depth() const { return renderer_.depth(); }\n};\n\nimage_mixer::image_mixer(const spl::shared_ptr<device>& vulkan,\n                         const int                      channel_id,\n                         const size_t                   max_frame_size,\n                         common::bit_depth              depth)\n    : impl_(std::make_unique<impl>(vulkan, channel_id, max_frame_size, depth))\n{\n}\nimage_mixer::~image_mixer() {}\nvoid image_mixer::push(const core::frame_transform& transform) { impl_->push(transform); }\nvoid image_mixer::visit(const core::const_frame& frame) { impl_->visit(frame); }\nvoid image_mixer::pop() { impl_->pop(); }\nvoid image_mixer::update_aspect_ratio(double aspect_ratio) { impl_->update_aspect_ratio(aspect_ratio); }\nstd::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\nimage_mixer::render(const core::video_format_desc& format_desc)\n{\n    return impl_->render(format_desc);\n}\ncore::mutable_frame image_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc)\n{\n    return impl_->create_frame(tag, desc);\n}\ncore::mutable_frame\nimage_mixer::create_frame(const void* tag, const core::pixel_format_desc& desc, common::bit_depth depth)\n{\n    return impl_->create_frame(tag, desc, depth);\n}\n\n\n#ifdef WIN32\ncore::const_frame image_mixer::import_d3d_texture(const void*                                tag,\n                                                  const std::shared_ptr<d3d::d3d_texture2d>& d3d_texture,\n                                                  core::pixel_format                         format,\n                                                  common::bit_depth                          depth)\n{\n    return impl_->import_d3d_texture(tag, d3d_texture, format, depth);\n}\n#endif\n\ncommon::bit_depth image_mixer::depth() const { return impl_->depth(); }\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/image/image_mixer.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include <common/array.h>\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/frame/frame.h>\n#include <core/frame/pixel_format.h>\n#include <core/mixer/image/image_mixer.h>\n#include <core/video_format.h>\n\n#include <future>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nclass image_mixer final : public core::image_mixer\n{\n  public:\n    image_mixer(const spl::shared_ptr<class device>& vulkan,\n                int                                  channel_id,\n                const size_t                         max_frame_size,\n                common::bit_depth                    depth);\n    image_mixer(const image_mixer&) = delete;\n\n    ~image_mixer();\n\n    image_mixer& operator=(const image_mixer&) = delete;\n\n    std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<core::texture>>>\n                        render(const core::video_format_desc& format_desc) override;\n    core::mutable_frame create_frame(const void* tag, const core::pixel_format_desc& desc) override;\n    core::mutable_frame\n    create_frame(const void* video_stream_tag, const core::pixel_format_desc& desc, common::bit_depth depth) override;\n\n#ifdef WIN32\n    core::const_frame import_d3d_texture(const void*                                tag,\n                                         const std::shared_ptr<d3d::d3d_texture2d>& d3d_texture,\n                                         core::pixel_format                         format,\n                                         common::bit_depth                          depth) override;\n#endif\n\n    void update_aspect_ratio(double aspect_ratio) override;\n\n    // core::image_mixer\n\n    void              push(const core::frame_transform& frame) override;\n    void              visit(const core::const_frame& frame) override;\n    void              pop() override;\n    common::bit_depth depth() const override;\n\n  private:\n    struct impl;\n    std::shared_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/image/vertex_shader.vert",
    "content": "#version 450\nlayout(location = 0) in vec2 Position;\nlayout(location = 1) in vec4 TexCoordIn;\n\nlayout(location = 0) out vec4 TexCoord;\nlayout(location = 1) out vec4 TexCoord2;\n\nvoid main()\n{\n    TexCoord = TexCoordIn;\n    vec4 pos = vec4(Position, 0, 1);\n    TexCoord2 = vec4(pos.xy, 0.0, 0.0);\n    pos.x = pos.x*2.0 - 1.0;\n    pos.y = pos.y*2.0 - 1.0;\n    gl_Position = pos;\n}\n"
  },
  {
    "path": "src/accelerator/vulkan/util/buffer.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#include \"buffer.h\"\n\n#include <boost/property_tree/ptree.hpp>\n\n#include <vulkan/vulkan.hpp>\n\n#pragma warning(push)\n#pragma warning(disable : 4189)\n#include <vk_mem_alloc.h>\n#pragma warning(pop)\n\n#include <atomic>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nstatic std::atomic<int>         g_w_total_count;\nstatic std::atomic<std::size_t> g_w_total_size;\nstatic std::atomic<int>         g_r_total_count;\nstatic std::atomic<std::size_t> g_r_total_size;\n\nstruct buffer::impl\n{\n    int  size_  = 0;\n    bool write_ = false;\n\n    VkBuffer          buf;\n    VmaAllocation     alloc;\n    VmaAllocationInfo allocInfo;\n\n    VmaAllocator allocator_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n  public:\n    impl(int size, bool write, VmaAllocator allocator)\n        : size_(size)\n        , write_(write)\n        , allocator_(allocator)\n    {\n        VkBufferCreateInfo bufCreateInfo = {VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO};\n        bufCreateInfo.size               = size;\n        bufCreateInfo.usage              = write ? VK_BUFFER_USAGE_TRANSFER_SRC_BIT : VK_BUFFER_USAGE_TRANSFER_DST_BIT;\n\n        VmaAllocationCreateInfo allocCreateInfo = {};\n        allocCreateInfo.usage                   = VMA_MEMORY_USAGE_AUTO;\n        allocCreateInfo.flags =\n            write ? VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT\n                  : VMA_ALLOCATION_CREATE_HOST_ACCESS_RANDOM_BIT | VMA_ALLOCATION_CREATE_MAPPED_BIT;\n\n        vmaCreateBuffer(allocator_, &bufCreateInfo, &allocCreateInfo, &buf, &alloc, &allocInfo);\n\n        (write ? g_w_total_count : g_r_total_count)++;\n        (write ? g_w_total_size : g_r_total_size) += size_;\n    }\n\n    ~impl()\n    {\n        vmaDestroyBuffer(allocator_, buf, alloc);\n\n        (write_ ? g_w_total_size : g_r_total_size) -= size_;\n        (write_ ? g_w_total_count : g_r_total_count)--;\n    }\n};\n\nbuffer::buffer(int size, bool write, VmaAllocator allocator)\n    : impl_(new impl(size, write, allocator))\n{\n}\nbuffer::buffer(buffer&& other)\n    : impl_(std::move(other.impl_))\n{\n}\nbuffer::~buffer() {}\nbuffer& buffer::operator=(buffer&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\nvoid*    buffer::data() { return impl_->allocInfo.pMappedData; }\nbool     buffer::write() const { return impl_->write_; }\nint      buffer::size() const { return static_cast<int>(impl_->allocInfo.size); }\nVkBuffer buffer::id() const { return impl_->buf; }\n\nboost::property_tree::wptree buffer::info()\n{\n    boost::property_tree::wptree info;\n\n    info.add(L\"total_read_count\", g_r_total_count);\n    info.add(L\"total_write_count\", g_w_total_count);\n    info.add(L\"total_read_size\", g_r_total_size);\n    info.add(L\"total_write_size\", g_w_total_size);\n\n    return info;\n}\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/buffer.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <memory>\n\n#include <vk_mem_alloc.h>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nclass buffer final\n{\n  public:\n    static boost::property_tree::wptree info();\n\n    buffer(int size, bool write, VmaAllocator allocator);\n    buffer(const buffer&) = delete;\n    buffer(buffer&& other);\n    ~buffer();\n\n    buffer& operator=(const buffer&) = delete;\n    buffer& operator=(buffer&& other);\n\n    VkBuffer id() const;\n    void*    data();\n    int      size() const;\n    bool     write() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/device.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#include \"device.h\"\n\n#include \"../image/image_kernel.h\"\n#include \"buffer.h\"\n#include \"pipeline.h\"\n#include \"texture.h\"\n\n#include <common/array.h>\n#include <common/assert.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/os/thread.h>\n\n#include <VkBootstrap.h>\n#include <vulkan/vulkan.hpp>\n\nVULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE\n\n#define VMA_STATIC_VULKAN_FUNCTIONS 0\n#define VMA_DYNAMIC_VULKAN_FUNCTIONS 1\n#define VMA_IMPLEMENTATION\n#pragma warning(push)\n#pragma warning(disable : 4189)\n#include <vk_mem_alloc.h>\n#pragma warning(pop)\n\n#include <boost/asio/deadline_timer.hpp>\n#include <boost/asio/dispatch.hpp>\n#include <boost/asio/spawn.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <tbb/concurrent_queue.h>\n#include <tbb/concurrent_unordered_map.h>\n\n#include <array>\n#include <deque>\n#include <future>\n#include <thread>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nusing namespace boost::asio;\n\ninline VKAPI_ATTR VkBool32 VKAPI_CALL default_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,\n                                                             VkDebugUtilsMessageTypeFlagsEXT        messageType,\n                                                             const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,\n                                                             void*)\n{\n    auto ms = vkb::to_string_message_severity(messageSeverity);\n    auto mt = vkb::to_string_message_type(messageType);\n    if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {\n        CASPAR_LOG(info) << \"[\" << ms << \": \" << mt << \"] - \" << pCallbackData->pMessageIdName << \", \"\n                         << pCallbackData->pMessage;\n        // printf(\"[%s: %s] - %s\\n%s\\n\", ms, mt, pCallbackData->pMessageIdName, pCallbackData->pMessage);\n    } else {\n        if (pCallbackData->pMessage != nullptr) {\n            CASPAR_LOG(info) << \"[\" << ms << \": \" << mt << \"] \" << pCallbackData->pMessage;\n            // printf(\"[%s: %s]\\n%s\\n\", ms, mt, pCallbackData->pMessage);\n        }\n    }\n\n    return VK_FALSE; // Applications must return false here (Except Validation, if return true, will skip calling to\n                     // driver)\n}\n\nvoid transitionImageLayout(const vk::Image&        image,\n                           vk::ImageLayout         oldLayout,\n                           vk::AccessFlags2        srcAccessMask,\n                           vk::PipelineStageFlags2 srcStage,\n                           vk::ImageLayout         newLayout,\n                           vk::AccessFlags2        dstAccessMask,\n                           vk::PipelineStageFlags2 dstStage,\n                           vk::CommandBuffer       cmdBuffer)\n{\n    auto range = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1);\n\n    vk::ImageMemoryBarrier2 barrier{};\n    barrier.oldLayout = oldLayout, barrier.newLayout = newLayout, barrier.srcQueueFamilyIndex = vk::QueueFamilyIgnored,\n    barrier.dstQueueFamilyIndex = vk::QueueFamilyIgnored, barrier.image = image, barrier.subresourceRange = range;\n\n    barrier.srcAccessMask = srcAccessMask;\n    barrier.srcStageMask  = srcStage;\n\n    barrier.dstAccessMask = dstAccessMask;\n    barrier.dstStageMask  = dstStage;\n\n    vk::DependencyInfo dep_info;\n    dep_info.setImageMemoryBarriers(barrier);\n\n    cmdBuffer.pipelineBarrier2(dep_info);\n}\n\nstruct device::impl : public std::enable_shared_from_this<impl>\n{\n    using texture_queue_t = tbb::concurrent_bounded_queue<std::shared_ptr<texture>>;\n    using buffer_queue_t  = tbb::concurrent_bounded_queue<std::shared_ptr<buffer>>;\n\n    std::array<tbb::concurrent_unordered_map<size_t, texture_queue_t>, 2>                attachment_pools_;\n    std::array<std::array<tbb::concurrent_unordered_map<size_t, texture_queue_t>, 4>, 2> device_pools_;\n    std::array<tbb::concurrent_unordered_map<size_t, buffer_queue_t>, 2>                 host_pools_;\n\n    std::wstring version_;\n\n    vkb::Instance                      _vkb_instance;\n    vkb::PhysicalDevice                _vkb_physical_device;\n    vk::PhysicalDeviceMemoryProperties _memoryProperties;\n    vk::PhysicalDevice                 _physical_device;\n    vk::Device                         _device;\n    vk::Queue                          _queue;\n    vk::CommandPool                    _command_pool;\n    VmaAllocator                       _allocator;\n\n    std::array<std::shared_ptr<pipeline>, 2> _pipelines;\n\n    struct inflight_command_buffer\n    {\n        vk::CommandBuffer cmd;\n        uint64_t          semaphore_value;\n    };\n    std::deque<inflight_command_buffer> _transfer_cmd_buffers;\n    vk::Semaphore                       _semaphore;\n    uint64_t                            _semaphore_value{0};\n\n    io_context                             io_context_;\n    decltype(make_work_guard(io_context_)) work_;\n    std::thread                            thread_;\n\n    impl()\n        : work_(make_work_guard(io_context_))\n    {\n        CASPAR_LOG(info) << L\"Initializing Vulkan Device.\";\n\n        auto instance_builder = vkb::InstanceBuilder()\n#ifdef _DEBUG\n                                    .enable_validation_layers(true)\n                                    .set_debug_messenger_severity(VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |\n                                                                  VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT)\n                                    .set_debug_messenger_type(VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |\n                                                              VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |\n                                                              VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)\n                                    .set_debug_callback(default_debug_callback)\n#endif\n                                    .set_app_name(\"CasparCG\")\n                                    .set_headless(true)\n                                    .set_engine_name(\"CasparCG\")\n                                    .require_api_version(VK_API_VERSION_1_3);\n        auto instance_ret = instance_builder.build();\n        if (!instance_ret) {\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(\"Failed to create Vulkan instance: \" + instance_ret.error().message()));\n        }\n        _vkb_instance = instance_ret.value();\n\n        VULKAN_HPP_DEFAULT_DISPATCHER.init(_vkb_instance.fp_vkGetInstanceProcAddr);\n        VULKAN_HPP_DEFAULT_DISPATCHER.init(vk::Instance(_vkb_instance.instance));\n\n        // Find suitable physical device\n        auto gpu_selector = vkb::PhysicalDeviceSelector(_vkb_instance);\n\n        vk::PhysicalDeviceVulkan12Features features12;\n        features12.descriptorIndexing                        = true;\n        features12.descriptorBindingPartiallyBound           = true;\n        features12.runtimeDescriptorArray                    = true;\n        features12.shaderSampledImageArrayNonUniformIndexing = true;\n        features12.timelineSemaphore                         = true;\n\n        vk::PhysicalDeviceVulkan13Features features13;\n        features13.dynamicRendering = true;\n        features13.synchronization2 = true;\n\n        vk::PhysicalDeviceDynamicRenderingLocalReadFeaturesKHR localReadFeatures;\n        localReadFeatures.dynamicRenderingLocalRead = true;\n\n        auto gpu_res = gpu_selector.set_minimum_version(1, 3)\n                           .set_required_features_12(features12)\n                           .set_required_features_13(features13)\n                           .add_required_extension(VK_KHR_DYNAMIC_RENDERING_LOCAL_READ_EXTENSION_NAME)\n                           .add_required_extension_features(localReadFeatures)\n                           .prefer_gpu_device_type(vkb::PreferredDeviceType::discrete)\n                           .select();\n        if (!gpu_res) {\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(\"Failed to select physical device: \" + gpu_res.error().message()));\n        }\n        _vkb_physical_device = gpu_res.value();\n\n        CASPAR_LOG(info) << \"Selected Vulkan device: \" << _vkb_physical_device.properties.deviceName;\n\n        vk::PhysicalDeviceRobustness2FeaturesEXT robustness2Features;\n        robustness2Features.nullDescriptor = true;\n        _vkb_physical_device.enable_extension_features_if_present(robustness2Features);\n\n        // Create the logical device\n        auto device_builder = vkb::DeviceBuilder(_vkb_physical_device);\n        _physical_device    = vk::PhysicalDevice(_vkb_physical_device.physical_device);\n\n        auto device_res = device_builder.build();\n        if (!device_res) {\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(\"Failed to create device: \" + device_res.error().message()));\n        }\n        auto vkb_device = device_res.value();\n        _device         = vk::Device(vkb_device.device);\n        VULKAN_HPP_DEFAULT_DISPATCHER.init(_device);\n        _queue            = vk::Queue(vkb_device.get_queue(vkb::QueueType::graphics).value());\n        auto queue_family = vkb_device.get_queue_index(vkb::QueueType::graphics).value();\n\n        vk::CommandPoolCreateInfo pool_info;\n        pool_info.flags            = vk::CommandPoolCreateFlagBits::eResetCommandBuffer;\n        pool_info.queueFamilyIndex = queue_family;\n\n        _command_pool = _device.createCommandPool(pool_info);\n\n        vk::SemaphoreTypeCreateInfo timeline_info{};\n        timeline_info.semaphoreType = vk::SemaphoreType::eTimeline;\n        timeline_info.initialValue  = 0;\n        vk::SemaphoreCreateInfo semaphore_info{};\n        semaphore_info.pNext = &timeline_info;\n        _semaphore           = _device.createSemaphore(semaphore_info);\n\n        VmaVulkanFunctions vulkanFunctions    = {};\n        vulkanFunctions.vkGetInstanceProcAddr = _vkb_instance.fp_vkGetInstanceProcAddr;\n        vulkanFunctions.vkGetDeviceProcAddr   = vkb_device.fp_vkGetDeviceProcAddr;\n\n        VmaAllocatorCreateInfo allocatorCreateInfo = {};\n        allocatorCreateInfo.flags                  = VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;\n        allocatorCreateInfo.vulkanApiVersion       = VK_API_VERSION_1_3;\n        allocatorCreateInfo.physicalDevice         = _physical_device;\n        allocatorCreateInfo.device                 = _device;\n        allocatorCreateInfo.instance               = _vkb_instance.instance;\n        allocatorCreateInfo.pVulkanFunctions       = &vulkanFunctions;\n\n        vmaCreateAllocator(&allocatorCreateInfo, &_allocator);\n\n        _memoryProperties = _physical_device.getMemoryProperties();\n\n        _pipelines[0] = std::make_shared<pipeline>(_device, vk::Format::eR8G8B8A8Unorm);\n        _pipelines[1] = std::make_shared<pipeline>(_device, vk::Format::eR16G16B16A16Unorm);\n\n        thread_ = std::thread([&] {\n            set_thread_name(L\"Vulkan Device\");\n            io_context_.run();\n        });\n    }\n\n    ~impl()\n    {\n        work_.reset();\n        thread_.join();\n\n        _device.waitIdle();\n\n        for (auto& pool : host_pools_)\n            pool.clear();\n\n        for (auto& pool : attachment_pools_)\n            pool.clear();\n\n        for (auto& pools : device_pools_)\n            for (auto& pool : pools)\n                pool.clear();\n\n        _transfer_cmd_buffers.clear();\n        _device.destroySemaphore(_semaphore);\n\n        _device.destroyCommandPool(_command_pool);\n        vmaDestroyAllocator(_allocator);\n        for (auto& pipeline : _pipelines) {\n            pipeline.reset();\n        }\n\n        _device.destroy();\n        vkb::destroy_instance(_vkb_instance);\n    }\n\n    template <typename Func>\n    auto spawn_async(Func&& func)\n    {\n        using result_type = decltype(func(std::declval<yield_context>()));\n        using task_type   = std::packaged_task<result_type(yield_context)>;\n\n        auto task   = task_type(std::forward<Func>(func));\n        auto future = task.get_future();\n        boost::asio::spawn(io_context_,\n                           std::move(task)\n#if BOOST_VERSION >= 108000\n                               ,\n                           [](std::exception_ptr e) {\n                               if (e)\n                                   std::rethrow_exception(e);\n                           }\n#endif\n        );\n        return future;\n    }\n\n    template <typename Func>\n    auto dispatch_async(Func&& func)\n    {\n        using result_type = decltype(func());\n        using task_type   = std::packaged_task<result_type()>;\n\n        auto task   = task_type(std::forward<Func>(func));\n        auto future = task.get_future();\n        boost::asio::dispatch(io_context_, std::move(task));\n        return future;\n    }\n\n    template <typename Func>\n    auto dispatch_sync(Func&& func) -> decltype(func())\n    {\n        return dispatch_async(std::forward<Func>(func)).get();\n    }\n\n    std::wstring version() { return version_; }\n\n    uint32_t findDedicatedMemoryType(uint32_t typeMask, vk::MemoryPropertyFlags properties)\n    {\n        for (uint32_t i = 0; i < _memoryProperties.memoryTypeCount; ++i) {\n            if ((typeMask & (1 << i)) &&\n                ((_memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)) {\n                return i;\n            }\n        }\n        throw std::runtime_error(\"Failed to find suitable memory type\");\n    }\n\n    uint64_t submitSingleTimeCommands(std::function<void(const vk::CommandBuffer&)> func)\n    {\n        vk::CommandBuffer cmd_buffer = nullptr;\n        if (_transfer_cmd_buffers.size() > 1) {\n            auto completed = _device.getSemaphoreCounterValue(_semaphore);\n\n            // try to reuse the oldest existing command buffer\n            if (_transfer_cmd_buffers.front().semaphore_value <= completed) {\n                cmd_buffer = _transfer_cmd_buffers.front().cmd;\n                cmd_buffer.reset();\n                _transfer_cmd_buffers.pop_front();\n            }\n        }\n\n        if (!cmd_buffer) {\n            // create a new command buffer\n            vk::CommandBufferAllocateInfo allocInfo{};\n            allocInfo.commandPool        = _command_pool;\n            allocInfo.level              = vk::CommandBufferLevel::ePrimary;\n            allocInfo.commandBufferCount = 1;\n\n            cmd_buffer = _device.allocateCommandBuffers(allocInfo)[0];\n        }\n\n        cmd_buffer.begin(vk::CommandBufferBeginInfo{vk::CommandBufferUsageFlagBits::eOneTimeSubmit});\n        func(cmd_buffer);\n        cmd_buffer.end();\n\n        auto                            signal_value = ++_semaphore_value;\n        vk::TimelineSemaphoreSubmitInfo timelineInfo{};\n        timelineInfo.setSignalSemaphoreValues(signal_value);\n\n        vk::SubmitInfo submitInfo{};\n        submitInfo.setCommandBuffers(cmd_buffer);\n        submitInfo.setSignalSemaphores(_semaphore);\n        submitInfo.pNext = &timelineInfo;\n        _queue.submit(submitInfo);\n\n        _transfer_cmd_buffers.push_back({cmd_buffer, signal_value});\n\n        return signal_value;\n    }\n\n    std::vector<vk::CommandBuffer> allocateCommandBuffers(uint32_t count)\n    {\n        return _device.allocateCommandBuffers(\n            vk::CommandBufferAllocateInfo(_command_pool, vk::CommandBufferLevel::ePrimary, count));\n    }\n    void submit(const vk::SubmitInfo& submitInfo, vk::Fence fence) { _queue.submit(submitInfo, fence); }\n\n    std::shared_ptr<texture>\n    create_attachment(int width, int height, common::bit_depth depth, uint32_t components_count)\n    {\n        CASPAR_VERIFY(width > 0 && height > 0);\n\n        auto depth_pool_index = depth == common::bit_depth::bit8 ? 0 : 1;\n        auto format = depth == common::bit_depth::bit8 ? vk::Format::eR8G8B8A8Unorm : vk::Format::eR16G16B16A16Unorm;\n\n        // TODO (perf) Shared pool.\n        auto pool   = &attachment_pools_[depth_pool_index][(width << 16 & 0xFFFF0000) | (height & 0x0000FFFF)];\n        auto extent = vk::Extent3D{static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1};\n\n        std::shared_ptr<texture> tex;\n        if (!pool->try_pop(tex)) {\n            vk::ImageCreateInfo imageInfo{};\n            imageInfo.imageType     = vk::ImageType::e2D;\n            imageInfo.format        = format;\n            imageInfo.extent        = extent;\n            imageInfo.mipLevels     = 1;\n            imageInfo.arrayLayers   = 1;\n            imageInfo.initialLayout = vk::ImageLayout::eUndefined;\n            imageInfo.samples       = vk::SampleCountFlagBits::e1;\n            imageInfo.tiling        = vk::ImageTiling::eOptimal;\n            imageInfo.usage         = vk::ImageUsageFlagBits::eTransferSrc | vk::ImageUsageFlagBits::eInputAttachment |\n                              vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eTransferDst |\n                              vk::ImageUsageFlagBits::eSampled;\n            imageInfo.sharingMode = vk::SharingMode::eExclusive;\n            auto image            = _device.createImage(imageInfo);\n\n            auto memReq = _device.getImageMemoryRequirements(image);\n\n            vk::MemoryAllocateInfo allocInfo{};\n            allocInfo.allocationSize = memReq.size;\n            allocInfo.memoryTypeIndex =\n                findDedicatedMemoryType(memReq.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal);\n\n            auto imageMemory = _device.allocateMemory(allocInfo);\n            _device.bindImageMemory(image, imageMemory, 0);\n            auto range = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1);\n\n            vk::ImageViewCreateInfo createInfo(\n                {}, image, vk::ImageViewType::e2D, format, vk::ComponentMapping(), range);\n\n            auto imageView = _device.createImageView(createInfo);\n\n            tex = std::make_shared<texture>(\n                width, height, components_count, depth, image, imageMemory, imageView, _device);\n        }\n\n        submitSingleTimeCommands([&](vk::CommandBuffer cmd) {\n            transitionImageLayout(\n                tex->id(),\n                vk::ImageLayout::eUndefined,\n                vk::AccessFlagBits2::eNone,\n                vk::PipelineStageFlagBits2::eTopOfPipe,\n                vk::ImageLayout::eRenderingLocalRead,\n                vk::AccessFlagBits2::eColorAttachmentWrite | vk::AccessFlagBits2::eInputAttachmentRead,\n                vk::PipelineStageFlagBits2::eColorAttachmentOutput | vk::PipelineStageFlagBits2::eFragmentShader,\n                cmd);\n        });\n\n        tex->set_depth(depth);\n\n        auto ptr = tex.get();\n        return std::shared_ptr<texture>(\n            ptr, [tex = std::move(tex), pool, self = shared_from_this()](texture*) mutable { pool->push(tex); });\n    }\n\n    std::shared_ptr<texture> create_texture(int width, int height, int stride, common::bit_depth depth, bool clear)\n    {\n        CASPAR_VERIFY(stride > 0 && stride < 5);\n        CASPAR_VERIFY(width > 0 && height > 0);\n\n        static vk::Format INTERNAL_FORMAT[][5] = {{vk::Format::eUndefined,\n                                                   vk::Format::eR8Unorm,\n                                                   vk::Format::eR8G8Unorm,\n                                                   vk::Format::eR8G8B8Unorm,\n                                                   vk::Format::eR8G8B8A8Unorm},\n                                                  {vk::Format::eUndefined,\n                                                   vk::Format::eR16Unorm,\n                                                   vk::Format::eR16G16Unorm,\n                                                   vk::Format::eR16G16B16Unorm,\n                                                   vk::Format::eR16G16B16A16Unorm}};\n\n        auto depth_pool_index = depth == common::bit_depth::bit8 ? 0 : 1;\n        auto format           = INTERNAL_FORMAT[depth_pool_index][stride];\n\n        auto pool   = &device_pools_[depth_pool_index][stride - 1][(width << 16 & 0xFFFF0000) | (height & 0x0000FFFF)];\n        auto extent = vk::Extent3D{static_cast<uint32_t>(width), static_cast<uint32_t>(height), 1};\n        std::shared_ptr<texture> tex;\n        if (!pool->try_pop(tex)) {\n            vk::ImageCreateInfo imageInfo{};\n            imageInfo.imageType     = vk::ImageType::e2D;\n            imageInfo.format        = format;\n            imageInfo.extent        = extent;\n            imageInfo.mipLevels     = 1;\n            imageInfo.arrayLayers   = 1;\n            imageInfo.initialLayout = vk::ImageLayout::eUndefined;\n            imageInfo.samples       = vk::SampleCountFlagBits::e1;\n            imageInfo.tiling        = vk::ImageTiling::eOptimal;\n            imageInfo.usage         = vk::ImageUsageFlagBits::eTransferDst | vk::ImageUsageFlagBits::eSampled;\n            imageInfo.sharingMode   = vk::SharingMode::eExclusive;\n            auto image              = _device.createImage(imageInfo);\n\n            auto memReq = _device.getImageMemoryRequirements(image);\n\n            vk::MemoryAllocateInfo allocInfo{};\n            allocInfo.allocationSize = memReq.size;\n            allocInfo.memoryTypeIndex =\n                findDedicatedMemoryType(memReq.memoryTypeBits, vk::MemoryPropertyFlagBits::eDeviceLocal);\n\n            auto imageMemory = _device.allocateMemory(allocInfo);\n            _device.bindImageMemory(image, imageMemory, 0);\n            auto clearValue = vk::ClearColorValue(std::array<float, 4>{0.0f, 0.0f, 0.0f, 1.0f});\n            auto range      = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1);\n\n            vk::ImageViewCreateInfo createInfo(\n                {}, image, vk::ImageViewType::e2D, format, vk::ComponentMapping(), range);\n\n            auto imageView = _device.createImageView(createInfo);\n\n            tex = std::make_shared<texture>(width, height, stride, depth, image, imageMemory, imageView, _device);\n        }\n        tex->set_depth(depth);\n\n        auto ptr = tex.get();\n        return std::shared_ptr<texture>(\n            ptr, [tex = std::move(tex), pool, self = shared_from_this()](texture*) mutable { pool->push(tex); });\n    }\n\n    std::shared_ptr<buffer> create_buffer(int size, bool write)\n    {\n        CASPAR_VERIFY(size > 0);\n\n        // TODO (perf) Shared pool.\n        auto pool = &host_pools_[static_cast<int>(write ? 1 : 0)][size];\n\n        std::shared_ptr<buffer> buf;\n        if (!pool->try_pop(buf)) {\n            buf = std::make_shared<buffer>(size, write, _allocator);\n        }\n\n        auto ptr = buf.get();\n        return std::shared_ptr<buffer>(ptr, [buf = std::move(buf), self = shared_from_this()](buffer*) mutable {\n            auto pool = &self->host_pools_[static_cast<int>(buf->write() ? 1 : 0)][buf->size()];\n            pool->push(std::move(buf));\n        });\n    }\n\n    array<uint8_t> create_array(int size)\n    {\n        auto buf = create_buffer(size, true);\n        auto ptr = reinterpret_cast<uint8_t*>(buf->data());\n        return array<uint8_t>(ptr, buf->size(), std::move(buf));\n    }\n\n    std::future<std::shared_ptr<texture>>\n    copy_async(const array<const uint8_t>& source, int width, int height, int stride, common::bit_depth depth)\n    {\n        return dispatch_async([this, source, width, height, stride, depth]() {\n            std::shared_ptr<buffer> buf;\n\n            auto tmp = source.storage<std::shared_ptr<buffer>>();\n            if (tmp) {\n                buf = *tmp;\n            } else {\n                buf = create_buffer(static_cast<int>(source.size()), true);\n                std::memcpy(buf->data(), source.data(), source.size());\n            }\n\n            auto tex = create_texture(width, height, stride, depth, false);\n\n            vk::BufferImageCopy region(0,\n                                       0,\n                                       0,\n                                       vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1),\n                                       vk::Offset3D(0, 0, 0),\n                                       vk::Extent3D(width, height, 1));\n\n            submitSingleTimeCommands([&](vk::CommandBuffer cmd) {\n                transitionImageLayout(tex->id(),\n                                      vk::ImageLayout::eUndefined,\n                                      vk::AccessFlagBits2::eNone,\n                                      vk::PipelineStageFlagBits2::eTopOfPipe,\n\n                                      vk::ImageLayout::eTransferDstOptimal,\n                                      vk::AccessFlagBits2::eTransferWrite,\n                                      vk::PipelineStageFlagBits2::eTransfer,\n                                      cmd);\n\n                cmd.copyBufferToImage(buf->id(), tex->id(), vk::ImageLayout::eTransferDstOptimal, region);\n\n                transitionImageLayout(tex->id(),\n                                      vk::ImageLayout::eTransferDstOptimal,\n                                      vk::AccessFlagBits2::eTransferWrite,\n                                      vk::PipelineStageFlagBits2::eTransfer,\n\n                                      vk::ImageLayout::eShaderReadOnlyOptimal,\n                                      vk::AccessFlagBits2::eShaderRead,\n                                      vk::PipelineStageFlagBits2::eFragmentShader,\n                                      cmd);\n            });\n\n            // No need to wait here, GPU-GPU deps (the usage of this texture on the device) are enforced by the memory\n            // barriers\n            return tex;\n        });\n    }\n\n    std::future<array<const uint8_t>> copy_async(const std::shared_ptr<texture>& source)\n    {\n        auto f = dispatch_async([this, source]() -> std::pair<std::shared_ptr<buffer>, uint64_t> {\n            auto buf = create_buffer(source->size(), false);\n\n            vk::CopyImageToBufferInfo2 copyInfo{};\n            copyInfo.dstBuffer      = buf->id();\n            copyInfo.srcImage       = source->id();\n            copyInfo.srcImageLayout = vk::ImageLayout::eTransferSrcOptimal;\n\n            vk::BufferImageCopy2 region{};\n            region.bufferOffset     = 0;\n            region.imageSubresource = vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1);\n            region.imageOffset      = vk::Offset3D{0, 0, 0};\n            region.imageExtent =\n                vk::Extent3D{static_cast<uint32_t>(source->width()), static_cast<uint32_t>(source->height()), 1};\n            copyInfo.setRegions(region);\n\n            auto signal_value = submitSingleTimeCommands([&](vk::CommandBuffer cmd) {\n                transitionImageLayout(source->id(),\n                                      vk::ImageLayout::eRenderingLocalRead,\n                                      vk::AccessFlagBits2::eColorAttachmentWrite,\n                                      vk::PipelineStageFlagBits2::eColorAttachmentOutput,\n\n                                      vk::ImageLayout::eTransferSrcOptimal,\n                                      vk::AccessFlagBits2::eHostRead,\n                                      vk::PipelineStageFlagBits2::eHost,\n                                      cmd);\n                cmd.copyImageToBuffer2(copyInfo);\n            });\n\n            return {buf, signal_value};\n        });\n\n        return std::async(std::launch::deferred, [this, f = std::move(f)]() mutable {\n            auto [buf, signal_value] = f.get();\n            vk::SemaphoreWaitInfo waitInfo{};\n            waitInfo.setSemaphores(_semaphore);\n            waitInfo.setValues(signal_value);\n            auto res = _device.waitSemaphores(waitInfo, 1000000000);\n            if (res != vk::Result::eSuccess) {\n                CASPAR_LOG(warning) << L\"[Vulkan] Timeout waiting for readback semaphore\";\n            }\n\n            auto ptr  = reinterpret_cast<uint8_t*>(buf->data());\n            auto size = buf->size();\n            return array<const uint8_t>(ptr, size, std::move(buf));\n        });\n    }\n\n    boost::property_tree::wptree info() const\n    {\n        boost::property_tree::wptree info;\n\n        boost::property_tree::wptree pooled_device_buffers;\n        size_t                       total_pooled_device_buffer_size  = 0;\n        size_t                       total_pooled_device_buffer_count = 0;\n\n        for (size_t i = 0; i < device_pools_.size(); ++i) {\n            auto& depth_pools = device_pools_.at(i);\n            for (size_t j = 0; j < depth_pools.size(); ++j) {\n                auto& pools      = depth_pools.at(j);\n                bool  mipmapping = j > 3;\n                auto  stride     = mipmapping ? j - 3 : j + 1;\n\n                for (auto& pool : pools) {\n                    auto width  = pool.first >> 16;\n                    auto height = pool.first & 0x0000FFFF;\n                    auto size   = width * height * stride;\n                    auto count  = pool.second.size();\n\n                    if (count == 0)\n                        continue;\n\n                    boost::property_tree::wptree pool_info;\n\n                    pool_info.add(L\"stride\", stride);\n                    pool_info.add(L\"mipmapping\", mipmapping);\n                    pool_info.add(L\"width\", width);\n                    pool_info.add(L\"height\", height);\n                    pool_info.add(L\"size\", size);\n                    pool_info.add(L\"count\", count);\n\n                    total_pooled_device_buffer_size += size * count;\n                    total_pooled_device_buffer_count += count;\n\n                    pooled_device_buffers.add_child(L\"device_buffer_pool\", pool_info);\n                }\n            }\n        }\n\n        info.add_child(L\"gl.details.pooled_device_buffers\", pooled_device_buffers);\n\n        boost::property_tree::wptree pooled_host_buffers;\n        size_t                       total_read_size   = 0;\n        size_t                       total_write_size  = 0;\n        size_t                       total_read_count  = 0;\n        size_t                       total_write_count = 0;\n\n        for (size_t i = 0; i < host_pools_.size(); ++i) {\n            auto& pools    = host_pools_.at(i);\n            auto  is_write = i == 1;\n\n            for (auto& pool : pools) {\n                auto size  = pool.first;\n                auto count = pool.second.size();\n\n                if (count == 0)\n                    continue;\n\n                boost::property_tree::wptree pool_info;\n\n                pool_info.add(L\"usage\", is_write ? L\"write_only\" : L\"read_only\");\n                pool_info.add(L\"size\", size);\n                pool_info.add(L\"count\", count);\n\n                pooled_host_buffers.add_child(L\"host_buffer_pool\", pool_info);\n\n                (is_write ? total_write_count : total_read_count) += count;\n                (is_write ? total_write_size : total_read_size) += size * count;\n            }\n        }\n\n        info.add_child(L\"gl.details.pooled_host_buffers\", pooled_host_buffers);\n        info.add(L\"gl.summary.pooled_device_buffers.total_count\", total_pooled_device_buffer_count);\n        info.add(L\"gl.summary.pooled_device_buffers.total_size\", total_pooled_device_buffer_size);\n        // info.add_child(L\"gl.summary.all_device_buffers\", texture::info());\n        info.add(L\"gl.summary.pooled_host_buffers.total_read_count\", total_read_count);\n        info.add(L\"gl.summary.pooled_host_buffers.total_write_count\", total_write_count);\n        info.add(L\"gl.summary.pooled_host_buffers.total_read_size\", total_read_size);\n        info.add(L\"gl.summary.pooled_host_buffers.total_write_size\", total_write_size);\n        info.add_child(L\"gl.summary.all_host_buffers\", buffer::info());\n\n        return info;\n    }\n\n    std::future<void> gc()\n    {\n        return spawn_async([this](yield_context yield) {\n            CASPAR_LOG(info) << \" vulkan: Running GC.\";\n\n            try {\n                for (auto& depth_pools : device_pools_) {\n                    for (auto& pools : depth_pools) {\n                        for (auto& pool : pools)\n                            pool.second.clear();\n                    }\n                }\n                for (auto& pools : host_pools_) {\n                    for (auto& pool : pools)\n                        pool.second.clear();\n                }\n                for (auto& pools : attachment_pools_) {\n                    for (auto& pool : pools)\n                        pool.second.clear();\n                }\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        });\n    }\n};\n\ndevice::device()\n    : impl_(new impl())\n{\n}\ndevice::~device() {}\n\nvk::PhysicalDeviceMemoryProperties device::getMemoryProperties() { return impl_->_memoryProperties; }\nstd::vector<vk::CommandBuffer>     device::allocateCommandBuffers(uint32_t count)\n{\n    return impl_->allocateCommandBuffers(count);\n}\nvoid       device::submit(const vk::SubmitInfo& submitInfo, vk::Fence fence) { impl_->submit(submitInfo, fence); }\nvk::Device device::getVkDevice() const { return impl_->_device; }\nstd::shared_ptr<pipeline> device::get_pipeline(common::bit_depth depth)\n{\n    return impl_->_pipelines[depth == common::bit_depth::bit8 ? 0 : 1];\n}\n\nstd::shared_ptr<texture>\ndevice::create_attachment(int width, int height, common::bit_depth depth, uint32_t components_count)\n{\n    return impl_->create_attachment(width, height, depth, components_count);\n}\n\nstd::shared_ptr<texture> device::create_texture(int width, int height, int stride, common::bit_depth depth)\n{\n    return impl_->create_texture(width, height, stride, depth, true);\n}\narray<uint8_t> device::create_array(int size) { return impl_->create_array(size); }\nstd::future<std::shared_ptr<texture>>\ndevice::copy_async(const array<const uint8_t>& source, int width, int height, int stride, common::bit_depth depth)\n{\n    return impl_->copy_async(source, width, height, stride, depth);\n}\nstd::future<array<const uint8_t>> device::copy_async(const std::shared_ptr<texture>& source)\n{\n    return impl_->copy_async(source);\n}\nvoid device::dispatch(std::function<void()> func) { boost::asio::dispatch(impl_->io_context_, std::move(func)); }\nstd::wstring                 device::version() const { return impl_->version(); }\nboost::property_tree::wptree device::info() const { return impl_->info(); }\nstd::future<void>            device::gc() { return impl_->gc(); }\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/device.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include <accelerator/accelerator.h>\n#include <common/array.h>\n#include <common/bit_depth.h>\n#include <core/frame/geometry.h>\n\n#include <functional>\n#include <future>\n\n#include <vulkan/vulkan.hpp>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nstruct draw_params;\n\nclass image_kernel;\n\nclass device final\n    : public std::enable_shared_from_this<device>\n    , public accelerator_device\n{\n  public:\n    device();\n    ~device();\n\n    device(const device&) = delete;\n\n    device& operator=(const device&) = delete;\n\n    std::shared_ptr<class pipeline> get_pipeline(common::bit_depth depth);\n    std::pair<vk::Buffer, vk::DeviceMemory>\n    upload_vertex_buffer(const std::vector<core::frame_geometry::coord>& coords);\n\n    vk::PhysicalDeviceMemoryProperties getMemoryProperties();\n    std::vector<vk::CommandBuffer>     allocateCommandBuffers(uint32_t count);\n    void                               submit(const vk::SubmitInfo& submitInfo, vk::Fence fence);\n    vk::Device                         getVkDevice() const;\n\n    std::shared_ptr<class texture>\n    create_attachment(int width, int height, common::bit_depth depth, uint32_t components_count);\n    std::shared_ptr<class texture> create_texture(int width, int height, int stride, common::bit_depth depth);\n    array<uint8_t>                 create_array(int size);\n\n    std::future<std::shared_ptr<class texture>>\n    copy_async(const array<const uint8_t>& source, int width, int height, int stride, common::bit_depth depth);\n    std::future<array<const uint8_t>> copy_async(const std::shared_ptr<class texture>& source);\n    template <typename Func>\n    auto dispatch_async(Func&& func)\n    {\n        using result_type = decltype(func());\n        using task_type   = std::packaged_task<result_type()>;\n\n        auto task   = std::make_shared<task_type>(std::forward<Func>(func));\n        auto future = task->get_future();\n        dispatch([=] { (*task)(); });\n        return future;\n    }\n\n    template <typename Func>\n    auto dispatch_sync(Func&& func)\n    {\n        return dispatch_async(std::forward<Func>(func)).get();\n    }\n\n    std::wstring version() const;\n\n    boost::property_tree::wptree info() const;\n    std::future<void>            gc();\n\n  private:\n    void dispatch(std::function<void()> func);\n    struct impl;\n    std::shared_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/draw_params.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include \"transforms.h\"\n#include <common/memory.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <vector>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nenum class keyer\n{\n    linear = 0,\n    additive,\n};\n\nstruct draw_params final\n{\n    core::pixel_format_desc                     pix_desc = core::pixel_format_desc(core::pixel_format::invalid);\n    std::vector<spl::shared_ptr<class texture>> textures;\n    draw_transforms                             transforms;\n    core::frame_geometry                        geometry   = core::frame_geometry::get_default();\n    core::blend_mode                            blend_mode = core::blend_mode::normal;\n    vulkan::keyer                               keyer      = vulkan::keyer::linear;\n    std::shared_ptr<class texture>              background;\n    std::shared_ptr<class texture>              local_key;\n    std::shared_ptr<class texture>              layer_key;\n    double                                      aspect_ratio = 1.0;\n    int                                         target_width;\n    int                                         target_height;\n};\n\n}}} // namespace caspar::accelerator::vulkan"
  },
  {
    "path": "src/accelerator/vulkan/util/matrix.cpp",
    "content": "#include <core/frame/frame_transform.h>\n\n#include <common/except.h>\n#include <common/log.h>\n\n#include <cmath>\n#include <utility>\n#include <vector>\n\n#include <boost/numeric/ublas/io.hpp>\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_vector.hpp>\n#include <boost/numeric/ublas/vector.hpp>\n\n#include \"matrix.h\"\n\nnamespace caspar::accelerator::vulkan {\n\nt_matrix create_matrix(std::vector<std::vector<double>> data)\n{\n    if (data.empty())\n        CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(L\"data cannot be empty\"));\n\n    t_matrix matrix(data.size(), data.at(0).size());\n    for (int y = 0; y < matrix.size1(); ++y) {\n        if (data.at(y).size() != matrix.size2())\n            CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(L\"Each row must be of the same length\"));\n\n        for (int x = 0; x < matrix.size2(); ++x)\n            matrix(x, y) = data.at(y).at(x);\n    }\n    return matrix;\n}\n\nt_matrix get_vertex_matrix(const core::image_transform& transform, double aspect_ratio)\n{\n    using namespace boost::numeric::ublas;\n    auto anchor_matrix =\n        create_matrix({{1.0, 0.0, -transform.anchor[0]}, {0.0, 1.0, -transform.anchor[1]}, {0.0, 0.0, 1.0}});\n    auto scale_matrix =\n        create_matrix({{transform.fill_scale[0], 0.0, 0.0}, {0.0, transform.fill_scale[1], 0.0}, {0.0, 0.0, 1.0}});\n    auto aspect_matrix      = create_matrix({{1.0, 0.0, 0.0}, {0.0, 1.0 / aspect_ratio, 0.0}, {0.0, 0.0, 1.0}});\n    auto aspect_inv_matrix  = create_matrix({{1.0, 0.0, 0.0}, {0.0, aspect_ratio, 0.0}, {0.0, 0.0, 1.0}});\n    auto rotation_matrix    = create_matrix({{std::cos(transform.angle), -std::sin(transform.angle), 0.0},\n                                             {std::sin(transform.angle), std::cos(transform.angle), 0.0},\n                                             {0.0, 0.0, 1.0}});\n    auto translation_matrix = create_matrix(\n        {{1.0, 0.0, transform.fill_translation[0]}, {0.0, 1.0, transform.fill_translation[1]}, {0.0, 0.0, 1.0}});\n\n    return anchor_matrix * aspect_matrix * scale_matrix * rotation_matrix * aspect_inv_matrix * translation_matrix;\n}\n\n} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/matrix.h",
    "content": "#pragma once\n\n#include <boost/numeric/ublas/matrix.hpp>\n#include <boost/numeric/ublas/matrix_vector.hpp>\n\n#include <core/frame/geometry.h>\n\nnamespace caspar::accelerator::vulkan {\n\ntypedef boost::numeric::ublas::matrix<double, boost::numeric::ublas::row_major, std::vector<double>> t_matrix;\n\ntypedef boost::numeric::ublas::vector<double, std::vector<double>> t_point;\n\nt_matrix get_vertex_matrix(const core::image_transform& transform, double aspect_ratio);\n\n} // namespace caspar::accelerator::vulkan\n\nnamespace boost::numeric::ublas {\ntemplate <typename T, typename L, typename S>\nboost::numeric::ublas::matrix<T, L, S> operator*(const boost::numeric::ublas::matrix<T, L, S>& lhs,\n                                                 const boost::numeric::ublas::matrix<T, L, S>& rhs)\n{\n    return boost::numeric::ublas::matrix<T>(boost::numeric::ublas::prod(lhs, rhs));\n}\ntemplate <typename T, typename L, typename S1, typename S2>\nboost::numeric::ublas::vector<T, S1> operator*(const boost::numeric::ublas::vector<T, S1>&    lhs,\n                                               const boost::numeric::ublas::matrix<T, L, S2>& rhs)\n{\n    return boost::numeric::ublas::vector<T, S1>(boost::numeric::ublas::prod(lhs, rhs));\n}\ntemplate <typename T, typename L, typename S1, typename S2>\nbool operator==(const boost::numeric::ublas::matrix<T, L, S1>& lhs, const boost::numeric::ublas::matrix<T, L, S2>& rhs)\n{\n    if (lhs.size1() != rhs.size1() || lhs.size2() != rhs.size2())\n        return false;\n    for (int y = 0; y < lhs.size1(); ++y)\n        for (int x = 0; x < lhs.size2(); ++x)\n            if (lhs(y, x) != rhs(y, x))\n                return false;\n    return true;\n}\n} // namespace boost::numeric::ublas"
  },
  {
    "path": "src/accelerator/vulkan/util/pipeline.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#include \"pipeline.h\"\n#include \"../image/image_kernel.h\"\n#include \"texture.h\"\n\n#include \"vulkan_image_fragment.h\"\n#include \"vulkan_image_vertex.h\"\n#include <core/frame/geometry.h>\n\n#include <vulkan/vulkan.hpp>\n\n#include <unordered_map>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nstd::vector<vk::PipelineShaderStageCreateInfo> create_shader_program(vk::Device device)\n{\n    // Helper to create shader module\n    auto createShaderModule = [&](const uint8_t* code, size_t size) {\n        vk::ShaderModuleCreateInfo createInfo{};\n        createInfo.codeSize = size;\n        createInfo.pCode    = reinterpret_cast<const uint32_t*>(code);\n        return device.createShaderModule(createInfo);\n    };\n\n    auto vertShaderModule = createShaderModule(vertex_shader, sizeof(vertex_shader) - 1);\n    auto fragShaderModule = createShaderModule(fragment_shader, sizeof(fragment_shader) - 1);\n\n    vk::PipelineShaderStageCreateInfo vertShaderStageInfo;\n    vertShaderStageInfo.stage  = vk::ShaderStageFlagBits::eVertex;\n    vertShaderStageInfo.module = vertShaderModule;\n    vertShaderStageInfo.pName  = \"main\";\n\n    vk::PipelineShaderStageCreateInfo fragShaderStageInfo;\n    fragShaderStageInfo.stage  = vk::ShaderStageFlagBits::eFragment;\n    fragShaderStageInfo.module = fragShaderModule;\n    fragShaderStageInfo.pName  = \"main\";\n\n    return {vertShaderStageInfo, fragShaderStageInfo};\n}\n\nstd::array<vk::VertexInputAttributeDescription, 2> get_attribute_descriptions(uint32_t binding)\n{\n    std::array<vk::VertexInputAttributeDescription, 2> attributeDescriptions{\n        {{0, binding, vk::Format::eR32G32Sfloat, 0}, {1, binding, vk::Format::eR32G32B32A32Sfloat, 2 * sizeof(float)}}};\n\n    return attributeDescriptions;\n}\n\nconst int DescriptorPoolSize = 64;\nconst int BindlessTextureCount = 8;\n\nstruct pipeline::impl\n{\n    vk::Device device_;\n    vk::Format format_;\n\n    vk::Sampler                    textureSampler_;\n    vk::Sampler                    keySampler_;\n    vk::DescriptorSetLayout        descriptorSetLayout_;\n    vk::DescriptorPool             descriptorPool_;\n    std::vector<vk::DescriptorSet> descriptorSets_;\n\n    vk::PipelineLayout pipelineLayout_;\n    vk::Pipeline       pipeline_;\n\n    size_t currentDescriptorSet_ = 0;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n    void setup_descriptors()\n    {\n        // Binding 0: bindless texture array for planes (up to 4), local_key, and layer_key\n        vk::DescriptorSetLayoutBinding texturesLayoutBinding{};\n        texturesLayoutBinding.binding         = 0;\n        texturesLayoutBinding.descriptorType  = vk::DescriptorType::eCombinedImageSampler;\n        texturesLayoutBinding.descriptorCount = BindlessTextureCount;\n        texturesLayoutBinding.stageFlags      = vk::ShaderStageFlagBits::eFragment;\n\n        // Binding 1: input attachment for background\n        vk::DescriptorSetLayoutBinding backgroundLayoutBinding{};\n        backgroundLayoutBinding.binding         = 1;\n        backgroundLayoutBinding.descriptorType  = vk::DescriptorType::eInputAttachment;\n        backgroundLayoutBinding.descriptorCount = 1;\n        backgroundLayoutBinding.stageFlags      = vk::ShaderStageFlagBits::eFragment;\n\n        vk::DescriptorSetLayoutCreateInfo layoutInfo{};\n        std::array bindings{texturesLayoutBinding, backgroundLayoutBinding};\n        layoutInfo.setBindings(bindings);\n\n        std::array<vk::DescriptorBindingFlags, 2> bindingFlags{vk::DescriptorBindingFlagBits::ePartiallyBound,\n                                                                vk::DescriptorBindingFlags{}};\n        vk::DescriptorSetLayoutBindingFlagsCreateInfo bindingFlagsInfo;\n        bindingFlagsInfo.setBindingFlags(bindingFlags);\n        layoutInfo.pNext = &bindingFlagsInfo;\n\n        descriptorSetLayout_ = device_.createDescriptorSetLayout(layoutInfo);\n\n        // Create descriptor pool\n        vk::DescriptorPoolSize samplerPoolSize(vk::DescriptorType::eCombinedImageSampler, BindlessTextureCount * DescriptorPoolSize);\n        vk::DescriptorPoolSize inputAttachmentPoolSize(vk::DescriptorType::eInputAttachment, 1 * DescriptorPoolSize);\n\n        std::array poolSizes{samplerPoolSize, inputAttachmentPoolSize};\n\n        vk::DescriptorPoolCreateInfo poolInfo{};\n        poolInfo.maxSets = DescriptorPoolSize;\n\n        poolInfo.setPoolSizes(poolSizes);\n        descriptorPool_ = device_.createDescriptorPool(poolInfo);\n\n        // Allocate descriptor sets\n        std::vector<vk::DescriptorSetLayout> layouts(DescriptorPoolSize, descriptorSetLayout_);\n        vk::DescriptorSetAllocateInfo        allocInfo;\n        allocInfo.descriptorPool = descriptorPool_;\n        allocInfo.setSetLayouts(layouts);\n\n        descriptorSets_ = device_.allocateDescriptorSets(allocInfo);\n    }\n\n    void setup_sampler()\n    {\n        vk::SamplerCreateInfo samplerInfo{};\n\n        samplerInfo.magFilter               = vk::Filter::eLinear;\n        samplerInfo.minFilter               = vk::Filter::eLinear;\n        samplerInfo.mipmapMode              = vk::SamplerMipmapMode::eLinear;\n        samplerInfo.addressModeU            = vk::SamplerAddressMode::eRepeat;\n        samplerInfo.addressModeV            = vk::SamplerAddressMode::eRepeat;\n        samplerInfo.addressModeW            = vk::SamplerAddressMode::eRepeat;\n        samplerInfo.mipLodBias              = 0.0f;\n        samplerInfo.anisotropyEnable        = VK_FALSE;\n        samplerInfo.maxAnisotropy           = 2;\n        samplerInfo.compareEnable           = VK_FALSE;\n        samplerInfo.compareOp               = vk::CompareOp::eAlways;\n        samplerInfo.minLod                  = 0.0f;\n        samplerInfo.maxLod                  = 0.0f;\n        samplerInfo.borderColor             = vk::BorderColor::eIntOpaqueBlack;\n        samplerInfo.unnormalizedCoordinates = VK_FALSE;\n\n        textureSampler_ = device_.createSampler(samplerInfo);\n\n        samplerInfo.magFilter  = vk::Filter::eNearest;\n        samplerInfo.minFilter  = vk::Filter::eNearest;\n        samplerInfo.mipmapMode = vk::SamplerMipmapMode::eNearest;\n        keySampler_            = device_.createSampler(samplerInfo);\n    }\n\n  public:\n    impl(vk::Device device, vk::Format format)\n        : device_(device)\n        , format_(format)\n    {\n        setup_descriptors();\n\n        setup_sampler();\n\n        // Vertex input\n        auto attributeDescriptions = get_attribute_descriptions(0);\n\n        auto vertexBindings = vk::VertexInputBindingDescription(0, sizeof(float) * 6, vk::VertexInputRate::eVertex);\n        vk::PipelineVertexInputStateCreateInfo vertexInputInfo;\n        vertexInputInfo.setVertexBindingDescriptions(vertexBindings);\n        vertexInputInfo.setVertexAttributeDescriptions(attributeDescriptions);\n\n        // Input assembly\n        vk::PipelineInputAssemblyStateCreateInfo inputAssembly{};\n        inputAssembly.topology               = vk::PrimitiveTopology::eTriangleFan;\n        inputAssembly.primitiveRestartEnable = VK_TRUE;\n\n        vk::PipelineViewportStateCreateInfo viewportState{};\n        viewportState.scissorCount  = 1;\n        viewportState.viewportCount = 1;\n        vk::DynamicState dynamicStates[]{vk::DynamicState::eViewport, vk::DynamicState::eScissor};\n\n        // Rasterizer\n        vk::PipelineRasterizationStateCreateInfo rasterizer{};\n        rasterizer.depthClampEnable        = VK_FALSE;\n        rasterizer.rasterizerDiscardEnable = VK_FALSE;\n        rasterizer.polygonMode             = vk::PolygonMode::eFill;\n        rasterizer.cullMode                = vk::CullModeFlagBits::eNone;\n        rasterizer.frontFace               = vk::FrontFace::eClockwise;\n        rasterizer.depthBiasEnable         = VK_FALSE;\n        rasterizer.lineWidth               = 1.0f;\n\n        // Multisampling\n        vk::PipelineMultisampleStateCreateInfo multisampling{};\n        multisampling.rasterizationSamples = vk::SampleCountFlagBits::e1;\n        multisampling.sampleShadingEnable  = VK_FALSE;\n\n        // Color blending\n        vk::PipelineColorBlendAttachmentState colorBlendAttachment{};\n        colorBlendAttachment.blendEnable = vk::False;\n\n        colorBlendAttachment.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG |\n                                              vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA;\n\n        vk::PipelineColorBlendStateCreateInfo colorBlending{};\n        colorBlending.logicOpEnable = vk::False;\n        colorBlending.logicOp       = vk::LogicOp::eCopy;\n        colorBlending.setAttachments(colorBlendAttachment);\n\n        vk::PushConstantRange range{};\n        range.stageFlags = vk::ShaderStageFlagBits::eFragment;\n        range.offset     = 0;\n        range.size       = sizeof(uniform_block);\n\n        // Pipeline layout\n        vk::PipelineLayoutCreateInfo pipelineLayoutInfo{};\n        pipelineLayoutInfo.setSetLayouts(descriptorSetLayout_);\n        pipelineLayoutInfo.setPushConstantRanges(range);\n\n        pipelineLayout_ = device_.createPipelineLayout(pipelineLayoutInfo);\n\n        vk::PipelineDynamicStateCreateInfo dynamicState{};\n        dynamicState.setDynamicStates(dynamicStates);\n\n        // Graphics pipeline\n        vk::GraphicsPipelineCreateInfo pipelineInfo{};\n        pipelineInfo.pVertexInputState   = &vertexInputInfo;\n        pipelineInfo.pInputAssemblyState = &inputAssembly;\n        pipelineInfo.pViewportState      = &viewportState;\n        pipelineInfo.pRasterizationState = &rasterizer;\n        pipelineInfo.pDynamicState       = &dynamicState;\n        pipelineInfo.pMultisampleState   = &multisampling;\n        pipelineInfo.pColorBlendState    = &colorBlending;\n        pipelineInfo.layout              = pipelineLayout_;\n        pipelineInfo.renderPass          = nullptr;\n        pipelineInfo.subpass             = 0;\n\n        auto shaderStages = std::move(create_shader_program(device_));\n        pipelineInfo.setStages(shaderStages);\n\n        vk::PipelineRenderingCreateInfo rendering_info{};\n        rendering_info.setColorAttachmentFormats({format});\n\n        pipelineInfo.pNext = &rendering_info;\n\n        pipeline_ = device_.createGraphicsPipeline(nullptr, pipelineInfo).value;\n\n        // Cleanup shader modules after pipeline creation\n        for (auto& shaderStage : shaderStages) {\n            device_.destroyShaderModule(shaderStage.module);\n        }\n    }\n\n    vk::DescriptorSet acquire_descriptor_set(const std::array<vk::ImageView, 7>& textures)\n    {\n        // C++ textures array layout:\n        //   [0] = background attachment, [1..4] = planes, [5] = local_key, [6] = layer_key\n\n        // Shader bindless textures[N] layout:\n        //   [0..3] = planes, [4] = local_key, [5] = layer_key\n\n        auto descriptorSet    = descriptorSets_[currentDescriptorSet_];\n        currentDescriptorSet_ = (currentDescriptorSet_ + 1) % DescriptorPoolSize;\n\n        // Bind planes, local_key, and layer_key to the bindless texture array\n        std::array<vk::DescriptorImageInfo, 6> textureInfos;\n        for (int i = 0; i < 6; ++i) {\n            textureInfos[i].sampler     = textureSampler_;\n            textureInfos[i].imageView   = textures[i + 1];\n            textureInfos[i].imageLayout = vk::ImageLayout::eShaderReadOnlyOptimal;\n        }\n\n        // Override samplers for local_key and layer_key to use nearest filtering\n        textureInfos[4].sampler = keySampler_;\n        textureInfos[5].sampler = keySampler_;\n\n        vk::WriteDescriptorSet texturesWrite{};\n        texturesWrite.dstSet          = descriptorSet;\n        texturesWrite.dstBinding      = 0;\n        texturesWrite.dstArrayElement = 0;\n        texturesWrite.descriptorType  = vk::DescriptorType::eCombinedImageSampler;\n        texturesWrite.setImageInfo(textureInfos);\n        texturesWrite.descriptorCount = 6;\n\n        // Bind background attachment as input attachment\n        vk::DescriptorImageInfo backgroundInfo{};\n        backgroundInfo.imageLayout = vk::ImageLayout::eRenderingLocalRead;\n        backgroundInfo.imageView   = textures[0];\n\n        vk::WriteDescriptorSet backgroundWrite{};\n        backgroundWrite.dstSet                    = descriptorSet;\n        backgroundWrite.dstBinding                = 1;\n        backgroundWrite.dstArrayElement           = 0;\n        backgroundWrite.descriptorType            = vk::DescriptorType::eInputAttachment;\n        backgroundWrite.setImageInfo(backgroundInfo);\n\n\n        vk::WriteDescriptorSet descriptorWrites[]{ backgroundWrite, texturesWrite };\n        device_.updateDescriptorSets(descriptorWrites, nullptr);\n\n        return descriptorSet;\n    }\n\n    void draw(vk::CommandBuffer                   commandBuffer,\n              vk::Buffer                          vertexBuffer,\n              uint32_t                            coords_count,\n              uint32_t                            vertex_buffer_offset,\n              const uniform_block&                params,\n              const std::array<vk::ImageView, 7>& textures)\n    {\n        auto descriptorSet = acquire_descriptor_set(textures);\n        commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline_);\n        commandBuffer.bindVertexBuffers(0, vertexBuffer, {vertex_buffer_offset});\n        commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, pipelineLayout_, 0, descriptorSet, nullptr);\n        commandBuffer.pushConstants(\n            pipelineLayout_, vk::ShaderStageFlagBits::eFragment, 0, sizeof(uniform_block), &params);\n        commandBuffer.draw(coords_count, 1, 0, 0);\n    }\n\n    ~impl()\n    {\n        device_.destroyDescriptorPool(descriptorPool_);\n        device_.destroyDescriptorSetLayout(descriptorSetLayout_);\n        device_.destroySampler(textureSampler_);\n        device_.destroySampler(keySampler_);\n\n        device_.destroyPipeline(pipeline_);\n        device_.destroyPipelineLayout(pipelineLayout_);\n    }\n};\n\npipeline::pipeline(vk::Device device, vk::Format format)\n    : impl_(new impl(device, format))\n{\n}\npipeline::~pipeline() {}\n\nvoid pipeline::draw(vk::CommandBuffer                   commandBuffer,\n                    vk::Buffer                          vertexBuffer,\n                    uint32_t                            coords_count,\n                    uint32_t                            vertex_buffer_offset,\n                    const uniform_block&                params,\n                    const std::array<vk::ImageView, 7>& textures)\n{\n    impl_->draw(commandBuffer, vertexBuffer, coords_count, vertex_buffer_offset, params, textures);\n}\n\nvk::Pipeline pipeline::id() const { return impl_->pipeline_; }\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/pipeline.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include \"uniform_block.h\"\n#include <vulkan/vulkan.hpp>\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nenum class shader_flags : uint32_t\n{\n    none              = 0,\n    is_straight_alpha = 1 << 0,\n    has_local_key     = 1 << 1,\n    has_layer_key     = 1 << 2,\n    invert            = 1 << 3,\n    levels            = 1 << 4,\n    csb               = 1 << 5,\n    chroma            = 1 << 6,\n    chroma_show_mask  = 1 << 7\n};\n\nclass pipeline final\n{\n    pipeline(const pipeline&);\n    pipeline& operator=(const pipeline&);\n\n  public:\n    pipeline(vk::Device device, vk::Format format);\n    ~pipeline();\n\n    void         draw(vk::CommandBuffer                   commandBuffer,\n                      vk::Buffer                          vertexBuffer,\n                      uint32_t                            coords_count,\n                      uint32_t                            vertex_buffer_offset,\n                      const uniform_block&                params,\n                      const std::array<vk::ImageView, 7>& textures);\n    vk::Pipeline id() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/renderpass.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#include \"renderpass.h\"\n#include \"../image/image_kernel.h\"\n#include \"device.h\"\n#include \"pipeline.h\"\n#include \"texture.h\"\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nvk::Buffer renderpass::upload_vertex_buffers()\n{\n    uint32_t total_coords = 0;\n    for (auto& layer : layers_) {\n        layer.vertex_buffer_offset = total_coords * 6 * sizeof(float);\n        total_coords += static_cast<uint32_t>(layer.coords.size());\n    }\n    std::vector<float> fl(total_coords * 6);\n\n    size_t idx = 0;\n    for (auto& layer : layers_) {\n        for (auto& c : layer.coords) {\n            fl[idx * 6 + 0] = static_cast<float>(c.vertex_x);\n            fl[idx * 6 + 1] = static_cast<float>(c.vertex_y);\n            fl[idx * 6 + 2] = static_cast<float>(c.texture_x);\n            fl[idx * 6 + 3] = static_cast<float>(c.texture_y);\n            fl[idx * 6 + 4] = static_cast<float>(c.texture_r);\n            fl[idx * 6 + 5] = static_cast<float>(c.texture_q);\n            ++idx;\n        }\n    }\n\n    return _ctx->upload_vertex_data(fl);\n}\n\nrenderpass::renderpass(frame_context* ctx, uint32_t width, uint32_t height)\n    : _ctx(ctx)\n    , _pipeline(ctx->get_pipeline())\n    , _width(width)\n    , _height(height)\n    , _default_attachment(ctx->create_attachment(width, height, 4))\n{\n}\n\nrenderpass::~renderpass() {}\n\nstd::shared_ptr<texture> renderpass::create_attachment(uint32_t components_count)\n{\n    return _ctx->create_attachment(_width, _height, components_count);\n}\n\nvoid renderpass::draw(const draw_params& params)\n{\n    auto attachment         = params.background;\n    auto [coords, uniforms] = _ctx->create_draw_data(params);\n\n    if (coords.empty()) {\n        return;\n    }\n\n    std::array<vk::ImageView, 7> textures = {attachment->view(),\n                                             nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};\n\n    for (int n = 0; n < params.textures.size(); ++n) {\n        textures[1+n] = params.textures[n]->view();\n    }\n    if (params.local_key) {\n        textures[5] = params.local_key->view();\n    }\n    if (params.layer_key) {\n        textures[6] = params.layer_key->view();\n    }\n\n    layers_.push_back({\n        attachment,\n        params.local_key,\n        params.layer_key,\n        std::move(textures),\n        std::move(coords),\n        uniforms,\n    });\n}\n\nvoid renderpass::commit()\n{\n    auto vertex_buffer = upload_vertex_buffers();\n\n    auto cmd_buffer = _ctx->get_command_buffer();\n    cmd_buffer.begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit));\n\n    vk::ClearValue clearColor{vk::ClearColorValue(std::array<float, 4>{0.0f, 0.0f, 0.0f, 0.0f})};\n\n    // Viewport and scissor\n    vk::Viewport viewport{0.0f, 0.0f, static_cast<float>(_width), static_cast<float>(_height), 0.0f, 1.0f};\n\n    vk::Extent2D extent = {_width, _height};\n    vk::Rect2D   scissor{{0, 0}, extent};\n\n    if (layers_.empty()) {\n        // No layers, just clear the default attachment\n        vk::RenderingAttachmentInfo attachment_info{};\n        attachment_info.imageView   = _default_attachment->view();\n        attachment_info.imageLayout = vk::ImageLayout::eRenderingLocalRead;\n        attachment_info.loadOp      = vk::AttachmentLoadOp::eClear;\n        attachment_info.storeOp     = vk::AttachmentStoreOp::eStore;\n\n        vk::RenderingInfo rendering_info{};\n        rendering_info.renderArea = scissor;\n        rendering_info.layerCount = 1;\n        rendering_info.setColorAttachments(attachment_info);\n\n        cmd_buffer.beginRendering(rendering_info);\n        cmd_buffer.setViewport(0, viewport);\n        cmd_buffer.setScissor(0, scissor);\n    } else {\n        // create a renderpass for each layer\n        bool                     default_cleared = false;\n        std::shared_ptr<texture> previous_attachment;\n        for (auto& layer : layers_) {\n            if (layer.attachment != previous_attachment) {\n                // We need to start a new render pass\n\n                if (previous_attachment) {\n                    // If this is not the first pass, end the previous render pass\n                    cmd_buffer.endRendering();\n\n                    if (previous_attachment != _default_attachment) {\n                        // If we're done with a non-default attachment, we need to transition it to a shader read layout\n                        vk::ImageMemoryBarrier2 memoryBarrier{};\n                        auto range = vk::ImageSubresourceRange(vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1);\n                        memoryBarrier.subresourceRange = range;\n                        memoryBarrier.srcStageMask     = vk::PipelineStageFlagBits2::eColorAttachmentOutput;\n                        memoryBarrier.srcAccessMask    = vk::AccessFlagBits2::eColorAttachmentWrite;\n                        memoryBarrier.dstStageMask     = vk::PipelineStageFlagBits2::eFragmentShader;\n                        memoryBarrier.dstAccessMask    = vk::AccessFlagBits2::eInputAttachmentRead;\n                        memoryBarrier.oldLayout        = vk::ImageLayout::eRenderingLocalRead;\n                        memoryBarrier.newLayout        = vk::ImageLayout::eShaderReadOnlyOptimal;\n                        memoryBarrier.image            = previous_attachment->id();\n\n                        vk::DependencyInfo dependencyInfo{};\n                        dependencyInfo.setImageMemoryBarriers(memoryBarrier);\n                        cmd_buffer.pipelineBarrier2(dependencyInfo);\n                    }\n                }\n\n                // We only want to clear the default attachment once\n                bool do_clear = (layer.attachment != _default_attachment) || !default_cleared;\n\n                vk::RenderingAttachmentInfo attachment_info{};\n                attachment_info.imageView   = layer.attachment->view();\n                attachment_info.imageLayout = vk::ImageLayout::eRenderingLocalRead;\n                attachment_info.loadOp      = do_clear ? vk::AttachmentLoadOp::eClear : vk::AttachmentLoadOp::eLoad;\n                attachment_info.storeOp     = vk::AttachmentStoreOp::eStore;\n\n                if (layer.attachment == _default_attachment) {\n                    default_cleared = true;\n                }\n\n                previous_attachment = layer.attachment;\n\n                vk::RenderingInfo rendering_info{};\n                rendering_info.renderArea = scissor;\n                rendering_info.layerCount = 1;\n                rendering_info.setColorAttachments(attachment_info);\n\n                cmd_buffer.beginRendering(rendering_info);\n                cmd_buffer.setViewport(0, viewport);\n                cmd_buffer.setScissor(0, scissor);\n            } else {\n                // We are continuing in the same render pass, so we need a barrier to ensure the attachment is ready\n                vk::MemoryBarrier2 memoryBarrier{};\n                memoryBarrier.srcStageMask  = vk::PipelineStageFlagBits2::eColorAttachmentOutput;\n                memoryBarrier.srcAccessMask = vk::AccessFlagBits2::eColorAttachmentWrite;\n                memoryBarrier.dstStageMask  = vk::PipelineStageFlagBits2::eFragmentShader;\n                memoryBarrier.dstAccessMask = vk::AccessFlagBits2::eInputAttachmentRead;\n\n                vk::DependencyInfo dependencyInfo{};\n                dependencyInfo.dependencyFlags    = vk::DependencyFlagBits::eByRegion;\n                dependencyInfo.memoryBarrierCount = 1;\n                dependencyInfo.pMemoryBarriers    = &memoryBarrier;\n                cmd_buffer.pipelineBarrier2(dependencyInfo);\n            }\n\n            _pipeline->draw(cmd_buffer,\n                            vertex_buffer,\n                            static_cast<uint32_t>(layer.coords.size()),\n                            layer.vertex_buffer_offset,\n                            layer.uniforms,\n                            layer.textures);\n        }\n    }\n\n    cmd_buffer.endRendering();\n    cmd_buffer.end();\n\n    _ctx->submit();\n}\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/renderpass.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n#include <tbb/concurrent_queue.h>\n#include <tbb/concurrent_unordered_map.h>\n#include <vector>\n#include <vulkan/vulkan.hpp>\n\n#include \"draw_params.h\"\n#include \"uniform_block.h\"\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nusing draw_data = std::pair<std::vector<core::frame_geometry::coord>, uniform_block>;\nstruct frame_context\n{\n    virtual vk::Buffer                      upload_vertex_data(const std::vector<float>& data) = 0;\n    virtual draw_data                       create_draw_data(const draw_params& params)        = 0;\n    virtual std::shared_ptr<class pipeline> get_pipeline()                                     = 0;\n    virtual vk::CommandBuffer               get_command_buffer()                               = 0;\n    virtual void                            submit()                                           = 0;\n    virtual std::shared_ptr<class texture>\n    create_attachment(uint32_t width, uint32_t height, uint32_t components_count) = 0;\n};\n\nclass renderpass\n{\n    frame_context*                  _ctx;\n    std::shared_ptr<class pipeline> _pipeline;\n    uint32_t                        _width;\n    uint32_t                        _height;\n\n    std::shared_ptr<class texture> _default_attachment;\n\n    struct layer_info\n    {\n        std::shared_ptr<class texture>           attachment;\n        std::shared_ptr<class texture>           local_key_attachment;\n        std::shared_ptr<class texture>           layer_key_attachment;\n        std::array<vk::ImageView, 7>             textures;\n        std::vector<core::frame_geometry::coord> coords;\n        uniform_block                            uniforms;\n        uint32_t                                 vertex_buffer_offset = 0;\n    };\n    std::vector<layer_info> layers_;\n\n  public:\n    renderpass(frame_context* ctx, uint32_t width, uint32_t height);\n\n    renderpass()                             = delete;\n    renderpass(const renderpass&)            = delete;\n    renderpass& operator=(const renderpass&) = delete;\n\n    ~renderpass();\n    std::shared_ptr<class texture> create_attachment(uint32_t components_count = 4);\n    void                           draw(const draw_params& params);\n    virtual void                   commit();\n\n    std::shared_ptr<class texture> default_attachment() const { return _default_attachment; }\n\n  private:\n    vk::Buffer upload_vertex_buffers();\n};\n\n}}} // namespace caspar::accelerator::vulkan"
  },
  {
    "path": "src/accelerator/vulkan/util/texture.cpp",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#include \"texture.h\"\n#include \"buffer.h\"\n\n#include <common/bit_depth.h>\n#include <vulkan/vulkan.hpp>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nstruct texture::impl\n{\n    vk::Image         image_;\n    vk::DeviceMemory  memory_;\n    vk::ImageView     imageView_;\n    vk::Device        device_;\n    int               width_  = 0;\n    int               height_ = 0;\n    int               stride_ = 0;\n    int               size_   = 0;\n    common::bit_depth depth_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n  public:\n    impl(int               width,\n         int               height,\n         int               stride,\n         common::bit_depth depth,\n         vk::Image         image,\n         vk::DeviceMemory  memory,\n         vk::ImageView     imageView,\n         vk::Device        device)\n        : image_(image)\n        , memory_(memory)\n        , imageView_(imageView)\n        , device_(device)\n        , width_(width)\n        , height_(height)\n        , stride_(stride)\n        , depth_(depth)\n        , size_(width * height * stride * (depth == common::bit_depth::bit8 ? 1 : 2))\n    {\n    }\n\n    ~impl()\n    {\n        device_.destroyImageView(imageView_);\n        device_.freeMemory(memory_);\n        device_.destroyImage(image_);\n    }\n};\n\ntexture::texture(int               width,\n                 int               height,\n                 int               stride,\n                 common::bit_depth depth,\n                 vk::Image         image,\n                 vk::DeviceMemory  memory,\n                 vk::ImageView     imageView,\n                 vk::Device        device)\n    : impl_(new impl(width, height, stride, depth, image, memory, imageView, device))\n{\n}\ntexture::texture(texture&& other)\n    : impl_(std::move(other.impl_))\n{\n}\ntexture::~texture() {}\ntexture& texture::operator=(texture&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\n\nvk::ImageView texture::view() const { return impl_->imageView_; }\n\nint               texture::width() const { return impl_->width_; }\nint               texture::height() const { return impl_->height_; }\nint               texture::stride() const { return impl_->stride_; }\ncommon::bit_depth texture::depth() const { return impl_->depth_; }\nvoid              texture::set_depth(common::bit_depth depth) { impl_->depth_ = depth; }\nint               texture::size() const { return impl_->size_; }\nVkImage           texture::id() const { return impl_->image_; }\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/texture.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <core/frame/frame.h>\n#include <memory>\n#include <vulkan/vulkan.hpp>\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nclass texture final\n{\n  public:\n    texture(int               width,\n            int               height,\n            int               stride,\n            common::bit_depth depth,\n            vk::Image         image,\n            vk::DeviceMemory  memory,\n            vk::ImageView     imageView,\n            vk::Device        device);\n    texture(const texture&) = delete;\n    texture(texture&& other);\n    ~texture();\n\n    texture& operator=(const texture&) = delete;\n    texture& operator=(texture&& other);\n\n    vk::ImageView view() const;\n\n    int               width() const;\n    int               height() const;\n    int               stride() const;\n    common::bit_depth depth() const;\n    void              set_depth(common::bit_depth depth);\n    int               size() const;\n    VkImage           id() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/transforms.cpp",
    "content": "#include \"transforms.h\"\n\n#include <algorithm>\n#include <unordered_set>\n\nnamespace caspar::accelerator::vulkan {\n\ndraw_crop_region::draw_crop_region(double left, double top, double right, double bottom)\n{\n    // upper left\n    coords[0]    = t_point(3);\n    coords[0](0) = left;\n    coords[0](1) = top;\n    coords[0](2) = 1;\n\n    // upper right\n    coords[1]    = t_point(3);\n    coords[1](0) = right;\n    coords[1](1) = top;\n    coords[1](2) = 1;\n\n    // lower right\n    coords[2]    = t_point(3);\n    coords[2](0) = right;\n    coords[2](1) = bottom;\n    coords[2](2) = 1;\n\n    // lower left\n    coords[3]    = t_point(3);\n    coords[3](0) = left;\n    coords[3](1) = bottom;\n    coords[3](2) = 1;\n}\n\nvoid draw_crop_region::apply_transform(const caspar::accelerator::vulkan::t_matrix& matrix)\n{\n    coords[0] = coords[0] * matrix;\n    coords[1] = coords[1] * matrix;\n    coords[2] = coords[2] * matrix;\n    coords[3] = coords[3] * matrix;\n}\n\nvoid apply_transform_colour_values(core::image_transform& self, const core::image_transform& other)\n{\n    // Note: this intentionally does not affect any geometry-related fields, they follow a separate flow\n\n    self.opacity *= other.opacity;\n    self.brightness *= other.brightness;\n    self.contrast *= other.contrast;\n    self.saturation *= other.saturation;\n\n    self.levels.min_input  = std::max(self.levels.min_input, other.levels.min_input);\n    self.levels.max_input  = std::min(self.levels.max_input, other.levels.max_input);\n    self.levels.min_output = std::max(self.levels.min_output, other.levels.min_output);\n    self.levels.max_output = std::min(self.levels.max_output, other.levels.max_output);\n    self.levels.gamma *= other.levels.gamma;\n    self.chroma.enable |= other.chroma.enable;\n    self.chroma.show_mask |= other.chroma.show_mask;\n    self.chroma.target_hue     = std::max(other.chroma.target_hue, self.chroma.target_hue);\n    self.chroma.min_saturation = std::max(other.chroma.min_saturation, self.chroma.min_saturation);\n    self.chroma.min_brightness = std::max(other.chroma.min_brightness, self.chroma.min_brightness);\n    self.chroma.hue_width      = std::max(other.chroma.hue_width, self.chroma.hue_width);\n    self.chroma.softness       = std::max(other.chroma.softness, self.chroma.softness);\n    self.chroma.spill_suppress = std::max(other.chroma.spill_suppress, self.chroma.spill_suppress);\n    self.chroma.spill_suppress_saturation =\n        std::min(other.chroma.spill_suppress_saturation, self.chroma.spill_suppress_saturation);\n    self.is_key |= other.is_key;\n    self.invert |= other.invert;\n    self.is_mix |= other.is_mix;\n    self.blend_mode = std::max(self.blend_mode, other.blend_mode);\n    self.layer_depth += other.layer_depth;\n}\n\nbool is_default_perspective(const core::corners& perspective)\n{\n    return perspective.ul[0] == 0 && perspective.ul[1] == 0 && perspective.ur[0] == 1 && perspective.ur[1] == 0 &&\n           perspective.ll[0] == 0 && perspective.ll[1] == 1 && perspective.lr[0] == 1 && perspective.lr[1] == 1;\n}\n\ndraw_transforms draw_transforms::combine_transform(const core::image_transform& transform, double aspect_ratio) const\n{\n    draw_transforms new_transform(image_transform, steps);\n\n    auto transform_before = new_transform.current().vertex_matrix;\n\n    // Get matrix for turning coords in 'transform' into the parent frame.\n    auto new_matrix = get_vertex_matrix(transform, aspect_ratio);\n\n    apply_transform_colour_values(new_transform.image_transform, transform);\n    new_transform.current().vertex_matrix = new_matrix * new_transform.current().vertex_matrix;\n\n    // Only enable this for some transforms, to avoid applying crops when a draw_frame is just being used to flatten\n    // other draw_frames\n    if (transform.enable_geometry_modifiers) {\n        // Push the new clip before the new transform applied\n        draw_crop_region new_clip(transform.clip_translation[0],\n                                  transform.clip_translation[1],\n                                  transform.clip_translation[0] + transform.clip_scale[0],\n                                  transform.clip_translation[1] + transform.clip_scale[1]);\n        new_clip.apply_transform(transform_before);\n        new_transform.current().crop_regions.push_back(std::move(new_clip));\n\n        if (!is_default_perspective(transform.perspective)) {\n            // Split into a new step\n            new_transform.steps.emplace_back(transform.perspective,\n                                             boost::numeric::ublas::identity_matrix<double>(3, 3));\n        }\n\n        // Push the new crop region with the new transform applied\n        draw_crop_region new_crop(\n            transform.crop.ul[0], transform.crop.ul[1], transform.crop.lr[0], transform.crop.lr[1]);\n        new_crop.apply_transform(new_transform.current().vertex_matrix);\n        new_transform.current().crop_regions.push_back(std::move(new_crop));\n    }\n\n    return std::move(new_transform);\n}\n\nvoid apply_perspective_to_vertex(t_point& vertex, const core::corners& perspective)\n{\n    const double x = vertex(0);\n    const double y = vertex(1);\n\n    // ul: x' =  (1-y) * a + (1 - a * (1-y)) * x\n    vertex(0) += (1 - y) * perspective.ul[0] + (1 - perspective.ul[0] + perspective.ul[0] * y) * x - x;\n    vertex(1) += (1 - x) * perspective.ul[1] + (1 - perspective.ul[1] + perspective.ul[1] * x) * y - y;\n\n    // ur/ll: x' = x * (a * (1-y) + y)\n    vertex(0) += x * (perspective.ur[0] * (1 - y) + y) - x;\n    vertex(1) += y * (perspective.ll[1] * (1 - x) + x) - y;\n\n    // ur/ll: x' = y * a + x * (1 - a * y)\n    vertex(0) += y * perspective.ll[0] + x * (1 - perspective.ll[0] * y) - x;\n    vertex(1) += x * perspective.ur[1] + y * (1 - perspective.ur[1] * x) - y;\n\n    // lr: x' = x * (y * a + (1-y))\n    vertex(0) += x * (y * perspective.lr[0] + (1 - y)) - x;\n    vertex(1) += y * (x * perspective.lr[1] + (1 - x)) - y;\n}\n\nstruct wrapped_vertex\n{\n    explicit wrapped_vertex(const core::frame_geometry::coord& coord)\n    {\n        vertex(0) = coord.vertex_x;\n        vertex(1) = coord.vertex_y;\n        vertex(2) = 1;\n\n        texture_x = coord.texture_x;\n        texture_y = coord.texture_y;\n        texture_r = coord.texture_r;\n        texture_q = coord.texture_q;\n    }\n\n    explicit wrapped_vertex() { vertex(2) = 1; };\n\n    [[nodiscard]] core::frame_geometry::coord as_geometry() const\n    {\n        core::frame_geometry::coord res = {vertex(0), vertex(1), texture_x, texture_y};\n        res.texture_r                   = texture_r;\n        res.texture_q                   = texture_q;\n        return res;\n    }\n\n    t_point vertex = t_point(3);\n\n    double texture_x = 0.0;\n    double texture_y = 0.0;\n    double texture_r = 0.0;\n    double texture_q = 1.0;\n};\n\nstatic const double epsilon = 0.001;\n\nbool inline point_is_to_left_of_line(const t_point& line_1, const t_point& line_2, const t_point& vertex)\n{\n    // use a cross product to check if the point is on the right side of the line\n    return (line_2(0) - line_1(0)) * (vertex(1) - line_1(1)) - (line_2(1) - line_1(1)) * (vertex(0) - line_1(0)) <\n           -epsilon;\n}\n\n// http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect\nbool get_intersection_with_crop_line(const t_point& crop0,\n                                     const t_point& crop1,\n                                     const t_point& p0,\n                                     const t_point& p1,\n                                     t_point&       result)\n{\n    double s1_x = crop1(0) - crop0(0);\n    double s1_y = crop1(1) - crop0(1);\n    double s2_x = p1(0) - p0(0);\n    double s2_y = p1(1) - p0(1);\n\n    double s = (-s1_y * (crop0(0) - p0(0)) + s1_x * (crop0(1) - p0(1))) / (-s2_x * s1_y + s1_x * s2_y);\n    double t = (s2_x * (crop0(1) - p0(1)) - s2_y * (crop0(0) - p0(0))) / (-s2_x * s1_y + s1_x * s2_y);\n\n    if (s >= 0 && s <= 1) {\n        // Collision detected\n        result(0) = crop0(0) + t * s1_x;\n        result(1) = crop0(1) + t * s1_y;\n\n        return true;\n    }\n\n    return false; // No collision\n}\n\ndouble hypotenuse(double x1, double y1, double x2, double y2)\n{\n    auto x = x2 - x1;\n    auto y = y2 - y1;\n\n    return std::sqrt(x * x + y * y);\n}\n\ndouble calc_q(double close_diagonal, double distant_diagonal)\n{\n    return (close_diagonal + distant_diagonal) / distant_diagonal;\n}\n\nvoid crop_texture_for_vertex(const wrapped_vertex& line_a, const wrapped_vertex& line_b, wrapped_vertex& vertex)\n{\n    auto delta_point = vertex.vertex - line_a.vertex;\n    auto delta_line  = line_b.vertex - line_a.vertex;\n\n    // Calculate the dot product\n    auto dot_product      = delta_point(0) * delta_line(0) + delta_point(1) * delta_line(1);\n    auto line_len_squared = delta_line(0) * delta_line(0) + delta_line(1) * delta_line(1);\n\n    // Skip if line has no length\n    if (line_len_squared == 0) {\n        vertex.texture_x = line_a.texture_x;\n        vertex.texture_y = line_a.texture_y;\n        return;\n    }\n\n    auto dist_delta = dot_product / line_len_squared;\n\n    vertex.texture_x = line_a.texture_x + dist_delta * (line_b.texture_x - line_a.texture_x);\n    vertex.texture_y = line_a.texture_y + dist_delta * (line_b.texture_y - line_a.texture_y);\n    vertex.texture_q = line_a.texture_q + dist_delta * (line_b.texture_q - line_a.texture_q);\n}\n\nvoid fill_texture_q_for_quad(std::vector<wrapped_vertex>& coords)\n{\n    if (coords.size() != 4)\n        return;\n\n    // Based on formula from:\n    // http://www.reedbeta.com/blog/2012/05/26/quadrilateral-interpolation-part-1/\n\n    double s1_x = coords[2].vertex(0) - coords[0].vertex(0);\n    double s1_y = coords[2].vertex(1) - coords[0].vertex(1);\n    double s2_x = coords[3].vertex(0) - coords[1].vertex(0);\n    double s2_y = coords[3].vertex(1) - coords[1].vertex(1);\n\n    double s =\n        (-s1_y * (coords[0].vertex(0) - coords[1].vertex(0)) + s1_x * (coords[0].vertex(1) - coords[1].vertex(1))) /\n        (-s2_x * s1_y + s1_x * s2_y);\n    double t =\n        (s2_x * (coords[0].vertex(1) - coords[1].vertex(1)) - s2_y * (coords[0].vertex(0) - coords[1].vertex(0))) /\n        (-s2_x * s1_y + s1_x * s2_y);\n\n    if (s >= 0 && s <= 1 && t >= 0 && t <= 1) {\n        // Collision detected\n        double diagonal_intersection_x = coords[0].vertex(0) + t * s1_x;\n        double diagonal_intersection_y = coords[0].vertex(1) + t * s1_y;\n\n        auto d0 =\n            hypotenuse(coords[3].vertex(0), coords[3].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n        auto d1 =\n            hypotenuse(coords[2].vertex(0), coords[2].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n        auto d2 =\n            hypotenuse(coords[1].vertex(0), coords[1].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n        auto d3 =\n            hypotenuse(coords[0].vertex(0), coords[0].vertex(1), diagonal_intersection_x, diagonal_intersection_y);\n\n        auto ulq = calc_q(d3, d1);\n        auto urq = calc_q(d2, d0);\n        auto lrq = calc_q(d1, d3);\n        auto llq = calc_q(d0, d2);\n\n        std::vector<double> q_values = {ulq, urq, lrq, llq};\n\n        int corner = 0;\n        for (auto& coord : coords) {\n            coord.texture_q = q_values[corner];\n            coord.texture_x *= q_values[corner];\n            coord.texture_y *= q_values[corner];\n\n            if (++corner == 4)\n                corner = 0;\n        }\n    }\n}\n\nvoid transform_vertex(const draw_transform_step& step, t_point& vertex)\n{\n    // Apply basic transforms of this step\n    vertex = vertex * step.vertex_matrix;\n\n    // Apply perspective. These rely on x and y of the coord, so can't be done as a shared matrix\n    apply_perspective_to_vertex(vertex, step.perspective);\n}\n\nstd::vector<core::frame_geometry::coord>\ndraw_transforms::transform_coords(const std::vector<core::frame_geometry::coord>& coords) const\n{\n    // Convert to matrix representations\n    std::vector<wrapped_vertex> cropped_coords;\n    cropped_coords.reserve(coords.size());\n\n    for (const auto& coord : coords) {\n        cropped_coords.emplace_back(coord);\n    }\n\n    std::vector<draw_crop_region> transformed_regions;\n\n    // Apply the transforms\n    for (int i = (int)steps.size() - 1; i >= 0; i--) {\n        for (auto& coord : cropped_coords) {\n            transform_vertex(steps[i], coord.vertex);\n        }\n\n        // Transform existing regions\n        for (auto& region : transformed_regions) {\n            for (int l = 0; l < 4; ++l) {\n                transform_vertex(steps[i], region.coords[l]);\n            }\n        }\n\n        // Push new regions\n        for (auto& region : steps[i].crop_regions) {\n            draw_crop_region new_region = region;\n            for (int l = 0; l < 4; ++l) {\n                // Only apply perspective for new ones\n                apply_perspective_to_vertex(new_region.coords[l], steps[i].perspective);\n            }\n\n            transformed_regions.push_back(new_region);\n        }\n    }\n\n    // Apply the perspective correction\n    fill_texture_q_for_quad(cropped_coords);\n\n    // Perform the crop\n    for (auto& crop_region : transformed_regions) {\n        for (int l = 0; l < 4; ++l) {\n            // Apply the crop, one edge at a time\n            int     to_index   = l == 3 ? 0 : l + 1;\n            t_point from_point = crop_region.coords[l];\n            t_point to_point   = crop_region.coords[to_index];\n\n            std::unordered_set<size_t> points_to_left_of_line;\n\n            // Figure out which points are 'left' of the line (outside the crop region)\n            for (size_t j = 0; j < cropped_coords.size(); ++j) {\n                bool v = point_is_to_left_of_line(from_point, to_point, cropped_coords[j].vertex);\n                if (v)\n                    points_to_left_of_line.insert(j);\n            }\n\n            if (points_to_left_of_line.empty()) {\n                // Line has no effect, skip\n                continue;\n            } else if (points_to_left_of_line.size() == cropped_coords.size()) {\n                // All are to the left, shape has no geometry\n                return {};\n            }\n\n            std::vector<wrapped_vertex> new_coords;\n            new_coords.reserve(cropped_coords.size() * 2); // Avoid reallocs for complex shapes\n\n            // Iterate through the coords\n            for (size_t j = 0; j < cropped_coords.size(); ++j) {\n                if (points_to_left_of_line.count(j) == 0) {\n                    new_coords.push_back(cropped_coords[j]);\n                    continue;\n                }\n\n                size_t prev_index = j == 0 ? cropped_coords.size() - 1 : j - 1;\n                size_t next_index = j == cropped_coords.size() - 1 ? 0 : j + 1;\n\n                bool prev_is_left_of_line = points_to_left_of_line.count(prev_index) == 1;\n                bool next_is_left_of_line = points_to_left_of_line.count(next_index) == 1;\n\n                if (prev_is_left_of_line && next_is_left_of_line) {\n                    // Vertex and its edges are completely left of the line, skip\n                    continue;\n                }\n\n                if (!prev_is_left_of_line) {\n                    // This edge intersects the crop line, calculate the new coordinates\n                    wrapped_vertex new_coord;\n                    if (get_intersection_with_crop_line(to_point,\n                                                        from_point,\n                                                        cropped_coords[prev_index].vertex,\n                                                        cropped_coords[j].vertex,\n                                                        new_coord.vertex)) {\n                        crop_texture_for_vertex(cropped_coords[prev_index], cropped_coords[j], new_coord);\n                        new_coords.emplace_back(std::move(new_coord));\n                    } else {\n                        // Geometry error! skip coordinate\n                    }\n                }\n\n                if (!next_is_left_of_line) {\n                    // This edge intersects the crop line, calculate the new coordinates\n                    wrapped_vertex new_coord;\n                    if (get_intersection_with_crop_line(to_point,\n                                                        from_point,\n                                                        cropped_coords[j].vertex,\n                                                        cropped_coords[next_index].vertex,\n                                                        new_coord.vertex)) {\n                        crop_texture_for_vertex(cropped_coords[j], cropped_coords[next_index], new_coord);\n                        new_coords.emplace_back(std::move(new_coord));\n                    } else {\n                        // Geometry error! skip coordinate\n                    }\n                }\n            }\n\n            // Polygon is cropped, update state\n            cropped_coords = new_coords;\n        }\n\n        {\n            static const double pixel_epsilon = 0.0001; // less than a pixel at 8k\n\n            // Prune duplicate coords\n            std::vector<wrapped_vertex> new_coords;\n            new_coords.reserve(cropped_coords.size()); // Avoid reallocs\n\n            for (size_t j = 0; j < cropped_coords.size(); ++j) {\n                size_t prev_index = j == 0 ? cropped_coords.size() - 1 : j - 1;\n\n                auto delta = cropped_coords[j].vertex - cropped_coords[prev_index].vertex;\n                if (std::abs(delta(0)) > pixel_epsilon || std::abs(delta(1)) > pixel_epsilon) {\n                    new_coords.emplace_back(cropped_coords[j]);\n                }\n            }\n\n            if (new_coords.size() < 3) {\n                // Not enough coords to draw anything\n                return {};\n            }\n            cropped_coords = new_coords;\n        }\n    }\n\n    // Convert back to frame_geometry types\n    std::vector<core::frame_geometry::coord> result;\n    result.reserve(cropped_coords.size());\n    for (auto& coord : cropped_coords) {\n        result.push_back(coord.as_geometry());\n    }\n\n    return result;\n}\n\n} // namespace caspar::accelerator::vulkan\n"
  },
  {
    "path": "src/accelerator/vulkan/util/transforms.h",
    "content": "#pragma once\n\n#include <core/mixer/image/blend_modes.h>\n\n#include <common/memory.h>\n\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n\n#include <utility>\n\n#include \"matrix.h\"\n\nnamespace caspar::accelerator::vulkan {\n\nstruct draw_crop_region\n{\n    explicit draw_crop_region(double left, double top, double right, double bottom);\n\n    void apply_transform(const t_matrix& matrix);\n\n    std::array<t_point, 4> coords;\n};\n\nstruct draw_transform_step\n{\n    draw_transform_step()\n        : vertex_matrix(boost::numeric::ublas::identity_matrix<double>(3, 3))\n    {\n    }\n\n    draw_transform_step(const core::corners& perspective, const t_matrix& vertex_matrix)\n        : perspective(perspective)\n        , vertex_matrix(vertex_matrix)\n    {\n    }\n\n    core::corners perspective;\n\n    std::vector<draw_crop_region> crop_regions;\n\n    t_matrix vertex_matrix;\n};\n\nstruct draw_transforms\n{\n    std::vector<draw_transform_step> steps;\n\n    draw_transforms()\n        : image_transform(core::image_transform())\n        , steps({draw_transform_step()})\n    {\n    }\n\n    explicit draw_transforms(core::image_transform transform, std::vector<draw_transform_step> steps)\n        : image_transform(transform)\n        , steps(std::move(steps))\n    {\n    }\n\n    core::image_transform image_transform;\n\n    draw_transform_step& current() { return steps.back(); }\n\n    [[nodiscard]] draw_transforms combine_transform(const core::image_transform& transform, double aspect_ratio) const;\n\n    [[nodiscard]] std::vector<core::frame_geometry::coord>\n    transform_coords(const std::vector<core::frame_geometry::coord>& coords) const;\n};\n\n} // namespace caspar::accelerator::vulkan"
  },
  {
    "path": "src/accelerator/vulkan/util/uniform_block.h",
    "content": "/*\n * Copyright 2025\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@niklaspandersson.se\n */\n\n#pragma once\n\nnamespace caspar { namespace accelerator { namespace vulkan {\n\nstruct uniform_block\n{\n    uint32_t color_space_index   = 0;\n    float    precision_factor[4] = {1.0f, 1.0f, 1.0f, 1.0f};\n    int32_t  blend_mode          = 0;\n    int32_t  keyer               = 0;\n    int32_t  pixel_format        = 0;\n    float    opacity             = 1.0;\n\n    /* levels */\n    float min_input  = 0;\n    float max_input  = 0;\n    float gamma      = 0;\n    float min_output = 0;\n    float max_output = 0;\n\n    /* contrast, saturation & brightness */\n    float brt = 0;\n    float sat = 0;\n    float con = 0;\n\n    /* Chroma */\n    float chroma_target_hue                = 0;\n    float chroma_hue_width                 = 0;\n    float chroma_min_saturation            = 0;\n    float chroma_min_brightness            = 0;\n    float chroma_softness                  = 0;\n    float chroma_spill_suppress            = 0;\n    float chroma_spill_suppress_saturation = 0;\n\n    uint32_t flags = 0;\n};\n\n}}} // namespace caspar::accelerator::vulkan"
  },
  {
    "path": "src/common/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (common)\n\nset(SOURCES\n\t\tdiagnostics/graph.cpp\n\n\t\tgl/gl_check.cpp\n\n\t\tbase64.cpp\n\t\tenv.cpp\n\t\tfilesystem.cpp\n\t\tlog.cpp\n\t\ttweener.cpp\n\t\tutf.cpp\n)\nif (MSVC)\n\tlist(APPEND SOURCES\n\t\t\tcompiler/vs/disable_silly_warnings.h\n\n\t\t\tos/windows/filesystem.cpp\n\t\t\tos/windows/prec_timer.cpp\n\t\t\tos/windows/thread.cpp\n\t\t\tos/windows/windows.h\n\t)\nelse ()\n\tlist(APPEND SOURCES\n\t\t\tos/linux/filesystem.cpp\n\t\t\tos/linux/prec_timer.cpp\n\t\t\tos/linux/thread.cpp\n\t)\nendif ()\nset(HEADERS\n\t\tdiagnostics/graph.h\n\n\t\tgl/gl_check.h\n\n\t\tos/filesystem.h\n\t\tos/thread.h\n\n\t\tarray.h\n\t\tassert.h\n\t\tbase64.h\n\t\tendian.h\n\t\tenum_class.h\n\t\tenv.h\n\t\texecutor.h\n\t\texcept.h\n\t\tfilesystem.h\n\t\tfuture.h\n\t\tlog.h\n\t\tmemory.h\n\t\tmemshfl.h\n\t\tparam.h\n\t\tprec_timer.h\n\t\tptree.h\n\t\tscope_exit.h\n\t\tstdafx.h\n\t\ttimer.h\n\t\ttweener.h\n\t\tutf.h\n)\n\ncasparcg_add_library(common SOURCES ${SOURCES} ${HEADERS})\ntarget_include_directories(common PRIVATE ..)\ntarget_precompile_headers(common PRIVATE stdafx.h)\ntarget_link_libraries(common PRIVATE GLEW::glew)\n\nsource_group(sources ./*)\nsource_group(sources\\\\gl gl/*)\nsource_group(sources\\\\diagnostics diagnostics/*)\nsource_group(sources\\\\compiler\\\\vs compiler/vs/*)\nsource_group(sources\\\\os\\\\windows os/windows/*)\nsource_group(sources\\\\os os/*)\n"
  },
  {
    "path": "src/common/array.h",
    "content": "#pragma once\n\n#include <any>\n#include <cstddef>\n#include <cstdlib>\n#include <cstring>\n#include <memory>\n#include <vector>\n\nnamespace caspar {\n\ntemplate <typename T>\nclass array final\n{\n    template <typename>\n    friend class array;\n\n  public:\n    using iterator       = T*;\n    using const_iterator = const T*;\n\n    array() = default;\n\n    explicit array(std::size_t size)\n        : size_(size)\n    {\n        if (size_ > 0) {\n            auto storage = std::shared_ptr<void>(std::malloc(size), std::free);\n            ptr_         = reinterpret_cast<T*>(storage.get());\n            std::memset(ptr_, 0, size_);\n            storage_ = std::make_shared<std::any>(std::move(storage));\n        }\n    }\n\n    array(std::vector<T> other)\n    {\n        auto storage = std::make_shared<std::vector<T>>(std::move(other));\n        ptr_         = storage->data();\n        size_        = storage->size();\n        storage_     = std::make_shared<std::any>(std::move(storage));\n    }\n\n    template <typename S>\n    explicit array(T* ptr, std::size_t size, S&& storage)\n        : ptr_(ptr)\n        , size_(size)\n        , storage_(std::make_shared<std::any>(std::forward<S>(storage)))\n    {\n    }\n\n    array(const array<T>&) = delete;\n\n    array(array&& other)\n        : ptr_(other.ptr_)\n        , size_(other.size_)\n        , storage_(std::move(other.storage_))\n    {\n        other.ptr_  = nullptr;\n        other.size_ = 0;\n    }\n\n    array& operator=(const array<T>&) = delete;\n\n    array& operator=(array&& other)\n    {\n        ptr_     = std::move(other.ptr_);\n        size_    = std::move(other.size_);\n        storage_ = std::move(other.storage_);\n\n        return *this;\n    }\n\n    T*          begin() const { return ptr_; }\n    T*          data() const { return ptr_; }\n    T*          end() const { return ptr_ + size_; }\n    std::size_t size() const { return size_; }\n\n    explicit operator bool() const { return size_ > 0; };\n\n    template <typename S>\n    S* storage() const\n    {\n        return std::any_cast<S>(storage_.get());\n    }\n\n  private:\n    T*                        ptr_  = nullptr;\n    std::size_t               size_ = 0;\n    std::shared_ptr<std::any> storage_;\n};\n\ntemplate <typename T>\nclass array<const T> final\n{\n  public:\n    using iterator       = const T*;\n    using const_iterator = const T*;\n\n    array() = default;\n\n    array(std::size_t size)\n        : size_(size)\n    {\n        if (size_ > 0) {\n            auto storage = std::shared_ptr<void>(std::malloc(size), std::free);\n            ptr_         = reinterpret_cast<T*>(storage.get());\n            std::memset(ptr_, 0, size_);\n            storage_ = std::make_shared<std::any>(storage);\n        }\n    }\n\n    array(const std::vector<T>& other)\n    {\n        auto storage = std::make_shared<std::vector<T>>(std::move(other));\n        ptr_         = storage->data();\n        size_        = storage->size();\n        storage_     = std::make_shared<std::any>(std::move(storage));\n    }\n\n    template <typename S>\n    explicit array(const T* ptr, std::size_t size, S&& storage)\n        : ptr_(ptr)\n        , size_(size)\n        , storage_(std::make_shared<std::any>(std::forward<S>(storage)))\n    {\n    }\n\n    array(const array& other)\n        : ptr_(other.ptr_)\n        , size_(other.size_)\n        , storage_(other.storage_)\n    {\n    }\n\n    array(array<T>&& other)\n        : ptr_(other.ptr_)\n        , size_(other.size_)\n        , storage_(other.storage_)\n    {\n        other.ptr_     = nullptr;\n        other.size_    = 0;\n        other.storage_ = nullptr;\n    }\n\n    array& operator=(const array& other)\n    {\n        ptr_     = other.ptr_;\n        size_    = other.size_;\n        storage_ = other.storage_;\n        return *this;\n    }\n\n    const T*    begin() const { return ptr_; }\n    const T*    data() const { return ptr_; }\n    const T*    end() const { return ptr_ + size_; }\n    std::size_t size() const { return size_; }\n\n    explicit operator bool() const { return size_ > 0; }\n\n    template <typename S>\n    S* storage() const\n    {\n        return std::any_cast<S>(storage_.get());\n    }\n\n  private:\n    const T*                  ptr_  = nullptr;\n    std::size_t               size_ = 0;\n    std::shared_ptr<std::any> storage_;\n};\n\n} // namespace caspar\n\nnamespace std {\n\ntemplate <typename T>\nvoid swap(caspar::array<const T>& lhs, caspar::array<const T>& rhs)\n{\n    lhs.swap(rhs);\n}\n\n} // namespace std\n"
  },
  {
    "path": "src/common/assert.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"except.h\"\n#include \"log.h\"\n\n#ifdef _MSC_VER\n#define _CASPAR_DBG_BREAK _CrtDbgBreak()\n#else\n#define _CASPAR_DBG_BREAK\n#endif\n\n#define CASPAR_VERIFY_EXPR_STR(str) #str\n\n#define CASPAR_VERIFY(expr)                                                                                            \\\n    do {                                                                                                               \\\n        if (!(expr)) {                                                                                                 \\\n            CASPAR_LOG(warning) << \"Assertion Failed: \" << CASPAR_VERIFY_EXPR_STR(expr) << \" \" << \"file:\" << __FILE__  \\\n                                << \" \" << \"line:\" << __LINE__ << \" \";                                                  \\\n            _CASPAR_DBG_BREAK;                                                                                         \\\n        }                                                                                                              \\\n    } while (0);\n\n#define CASPAR_ENSURE(expr)                                                                                            \\\n    do {                                                                                                               \\\n        if (!(expr)) {                                                                                                 \\\n            CASPAR_THROW_EXCEPTION(programming_error()                                                                 \\\n                                   << msg_info(std::string(\"Assertion Failed: \") + CASPAR_VERIFY_EXPR_STR(expr)));     \\\n        }                                                                                                              \\\n    } while (0);\n\n#ifdef _DEBUG\n#define CASPAR_ASSERT(expr) CASPAR_VERIFY(expr)\n#else\n#define CASPAR_ASSERT(expr)\n#endif\n"
  },
  {
    "path": "src/common/base64.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n#include \"base64.h\"\n\n#include <algorithm>\n#include <cstring>\n#include <vector>\n\n#include <boost/archive/iterators/base64_from_binary.hpp>\n#include <boost/archive/iterators/binary_from_base64.hpp>\n#include <boost/archive/iterators/insert_linebreaks.hpp>\n#include <boost/archive/iterators/remove_whitespace.hpp>\n#include <boost/archive/iterators/transform_width.hpp>\n#include <boost/range/adaptor/sliced.hpp>\n#include <boost/range/join.hpp>\n\n#include \"except.h\"\n\nnamespace caspar {\n\nstd::string to_base64(const char* data, size_t length)\n{\n    using namespace boost::archive::iterators;\n    // From http://www.webbiscuit.co.uk/2012/04/02/base64-encoder-and-boost/\n\n    using base64_iterator = insert_linebreaks<            // insert line breaks every 76 characters\n        base64_from_binary<                               // convert binary values to base64 characters\n            transform_width<const unsigned char*, 6, 8>>, // retrieve 6 bit integers from a sequence of 8 bit bytes\n        76>;                                              // compose all the above operations in to a new iterator\n    std::vector<char> bytes;\n    bytes.resize(length);\n    std::memcpy(bytes.data(), data, length);\n\n    int padding = 0;\n\n    while (bytes.size() % 3 != 0) {\n        ++padding;\n        bytes.push_back(0x00);\n    }\n\n    std::string result(base64_iterator(bytes.data()), base64_iterator(bytes.data() + length));\n    result.insert(result.end(), padding, '=');\n\n    return std::move(result);\n}\n\nstd::vector<unsigned char> from_base64(const std::string& data)\n{\n    using namespace boost::archive::iterators;\n\n    // The boost base64 iterator will over-iterate the string if not a multiple\n    // of 4, so we have to short circuit before.\n    auto length = std::count_if(\n        data.begin(), data.end(), [](char c) { return std::isspace(static_cast<unsigned char>(c)) == 0; });\n\n    if (length % 4 != 0)\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(\"The length of a base64 sequence must be a multiple of 4\"));\n\n    int         padding = 0;\n    std::string zero_padding;\n\n    // binary_from_base64 does not support padding characters so we have to append base64 0 -> 'A' and then remove it\n    // after decoding\n    if (data.length() >= 2) {\n        if (data[data.length() - 1] == '=') {\n            ++padding;\n            zero_padding += 'A';\n        }\n\n        if (data[data.length() - 2] == '=') {\n            ++padding;\n            zero_padding += 'A';\n        }\n    }\n\n    if (padding > 0) {\n        auto concatenated = boost::join(data | boost::adaptors::sliced(0, data.length() - padding),\n                                        boost::make_iterator_range(zero_padding.cbegin(), zero_padding.cend()));\n\n        // From https://svn.boost.org/trac/boost/ticket/5624\n        using base64_iterator =\n            transform_width<binary_from_base64<remove_whitespace<decltype(concatenated.begin())>>, 8, 6>;\n        std::vector<unsigned char> result(base64_iterator(concatenated.begin()), base64_iterator(concatenated.end()));\n\n        result.resize(result.size() - padding);\n        return std::move(result);\n    }\n    // From https://svn.boost.org/trac/boost/ticket/5624\n    using base64_iterator = transform_width<binary_from_base64<remove_whitespace<std::string::const_iterator>>, 8, 6>;\n    std::vector<unsigned char> result(base64_iterator(data.begin()), base64_iterator(data.end()));\n    return std::move(result);\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/base64.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <string>\n#include <vector>\n\nnamespace caspar {\n\nstd::string                to_base64(const char* data, size_t length);\nstd::vector<unsigned char> from_base64(const std::string& data);\n\n} // namespace caspar"
  },
  {
    "path": "src/common/bit_depth.h",
    "content": "#pragma once\n\n#include <cstdint>\n#include <memory>\n\nnamespace caspar { namespace common {\n\nenum class bit_depth : uint8_t\n{\n    bit8 = 0,\n    bit10,\n    bit12,\n    // bit14,\n    bit16,\n};\n\n}} // namespace caspar::common\n"
  },
  {
    "path": "src/common/compiler/vs/disable_silly_warnings.h",
    "content": "/*\n* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\n*\n*  This file is part of CasparCG.\n*\n*    CasparCG 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*    CasparCG 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 CasparCG.  If not, see <http://www.gnu.org/licenses/>.\n*\n*/\n#pragma once\n\n#pragma warning(disable : 4100) // unreferenced formal parameter\n#pragma warning(disable : 4127) // conditional expression is constant\n#pragma warning(disable : 4180) // qualifier applied to function type has no meaning; ignored\n#pragma warning(disable : 4244) // conversion from 'type1' to 'type2', possible loss of data\n#pragma warning(disable : 4245) // conversion from 'type1' to 'type2', signed/unsigned mismatch\n#pragma warning(disable : 4324) // padding a structure for alignment\n#pragma warning(disable : 4355) // 'this' : used in base member initializer list\n#pragma warning(disable : 4503) // decorated name length exceeded, name was truncated\n#pragma warning(disable : 4505) // unreferenced local function has been\n#pragma warning(disable : 4512) // assignment operator could not be generated\n#pragma warning(disable : 4702) // unreachable code\n#pragma warning(disable : 4714) // marked as __forceinline not inlined\n#pragma warning(disable : 4996) // function call with parameters that may be unsafe\n"
  },
  {
    "path": "src/common/diagnostics/graph.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"graph.h\"\n\n#include <mutex>\n#include <vector>\n\nnamespace caspar { namespace diagnostics {\n\nint color(float r, float g, float b, float a)\n{\n    int code = 0;\n    code |= static_cast<int>(r * 255.0f + 0.5f) << 24;\n    code |= static_cast<int>(g * 255.0f + 0.5f) << 16;\n    code |= static_cast<int>(b * 255.0f + 0.5f) << 8;\n    code |= static_cast<int>(a * 255.0f + 0.5f) << 0;\n    return code;\n}\n\nstd::tuple<float, float, float, float> color(int code)\n{\n    float r = static_cast<float>(code >> 24 & 255) / 255.0f;\n    float g = static_cast<float>(code >> 16 & 255) / 255.0f;\n    float b = static_cast<float>(code >> 8 & 255) / 255.0f;\n    float a = static_cast<float>(code >> 0 & 255) / 255.0f;\n    return std::make_tuple(r, g, b, a);\n}\n\nusing sink_factories_t = std::vector<spi::sink_factory_t>;\nstatic std::mutex       g_sink_factories_mutex;\nstatic sink_factories_t g_sink_factories;\n\nstd::vector<spl::shared_ptr<spi::graph_sink>> create_sinks()\n{\n    std::lock_guard<std::mutex> lock(g_sink_factories_mutex);\n\n    std::vector<spl::shared_ptr<spi::graph_sink>> result;\n    for (auto sink : g_sink_factories) {\n        result.push_back(sink());\n    }\n    return result;\n}\n\nstruct graph::impl\n{\n    std::vector<spl::shared_ptr<spi::graph_sink>> sinks_ = create_sinks();\n\n  public:\n    impl() {}\n\n    void activate()\n    {\n        for (auto& sink : sinks_)\n            sink->activate();\n    }\n\n    void set_text(const std::wstring& value)\n    {\n        for (auto& sink : sinks_)\n            sink->set_text(value);\n    }\n\n    void set_value(const std::string& name, double value)\n    {\n        for (auto& sink : sinks_)\n            sink->set_value(name, value);\n    }\n\n    void set_tag(tag_severity severity, const std::string& name)\n    {\n        for (auto& sink : sinks_)\n            sink->set_tag(severity, name);\n    }\n\n    void set_color(const std::string& name, int color)\n    {\n        for (auto& sink : sinks_)\n            sink->set_color(name, color);\n    }\n\n    void auto_reset()\n    {\n        for (auto& sink : sinks_)\n            sink->auto_reset();\n    }\n\n  private:\n    impl(impl&);\n    impl& operator=(impl&);\n};\n\ngraph::graph()\n    : impl_(new impl)\n{\n}\n\nvoid graph::set_text(const std::wstring& value) { impl_->set_text(value); }\nvoid graph::set_value(const std::string& name, double value) { impl_->set_value(name, value); }\nvoid graph::set_color(const std::string& name, int color) { impl_->set_color(name, color); }\nvoid graph::set_tag(tag_severity severity, const std::string& name) { impl_->set_tag(severity, name); }\nvoid graph::auto_reset() { impl_->auto_reset(); }\n\nvoid register_graph(const spl::shared_ptr<graph>& graph) { graph->impl_->activate(); }\n\nnamespace spi {\n\nvoid register_sink_factory(sink_factory_t factory)\n{\n    std::lock_guard<std::mutex> lock(g_sink_factories_mutex);\n\n    g_sink_factories.push_back(std::move(factory));\n}\n\n} // namespace spi\n\n}} // namespace caspar::diagnostics\n"
  },
  {
    "path": "src/common/diagnostics/graph.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../memory.h\"\n\n#include <functional>\n#include <string>\n#include <tuple>\n\nnamespace caspar { namespace diagnostics {\n\nint                                    color(float r, float g, float b, float a = 1.0f);\nstd::tuple<float, float, float, float> color(int code);\n\nenum class tag_severity\n{\n    WARNING,\n    INFO,\n    SILENT,\n};\n\nclass graph\n{\n    friend void register_graph(const spl::shared_ptr<graph>& graph);\n\n  public:\n    graph();\n    void set_text(const std::wstring& value);\n    void set_value(const std::string& name, double value);\n    void set_color(const std::string& name, int color);\n    void set_tag(tag_severity severity, const std::string& name);\n    void auto_reset();\n\n  private:\n    struct impl;\n    std::shared_ptr<impl> impl_;\n\n    graph(const graph&)            = delete;\n    graph& operator=(const graph&) = delete;\n};\n\nvoid register_graph(const spl::shared_ptr<graph>& graph);\n\nnamespace spi {\n\nclass graph_sink\n{\n    graph_sink(const graph_sink&)            = delete;\n    graph_sink& operator=(const graph_sink&) = delete;\n\n  public:\n    graph_sink() = default;\n    virtual ~graph_sink() {};\n    virtual void activate()                                              = 0;\n    virtual void set_text(const std::wstring& value)                     = 0;\n    virtual void set_value(const std::string& name, double value)        = 0;\n    virtual void set_color(const std::string& name, int color)           = 0;\n    virtual void set_tag(tag_severity severity, const std::string& name) = 0;\n    virtual void auto_reset()                                            = 0;\n};\n\nusing sink_factory_t = std::function<spl::shared_ptr<graph_sink>()>;\nvoid register_sink_factory(sink_factory_t factory);\n\n} // namespace spi\n\n}} // namespace caspar::diagnostics\n"
  },
  {
    "path": "src/common/endian.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <cstdint>\n#include <type_traits>\n\nnamespace caspar {\n\ntemplate <typename T>\ntypename std::enable_if<sizeof(T) == sizeof(std::uint8_t), T>::type swap_byte_order(const T& value)\n{\n    return value;\n}\n\ntemplate <typename T>\ntypename std::enable_if<sizeof(T) == sizeof(std::uint16_t), T>::type swap_byte_order(const T& value)\n{\n#ifdef _MSC_VER\n    auto swapped = _byteswap_ushort(reinterpret_cast<const unsigned short&>(value));\n#elif __GNUC__\n    auto swapped = __builtin_bswap16(value);\n#endif\n\n    return reinterpret_cast<const T&>(swapped);\n}\n\ntemplate <typename T>\ntypename std::enable_if<sizeof(T) == sizeof(std::uint32_t), T>::type swap_byte_order(const T& value)\n{\n#ifdef _MSC_VER\n    auto swapped = _byteswap_ulong(reinterpret_cast<const unsigned long&>(value));\n#elif __GNUC__\n    auto swapped = __builtin_bswap32(value);\n#endif\n\n    return reinterpret_cast<const T&>(swapped);\n}\n\ntemplate <typename T>\ntypename std::enable_if<sizeof(T) == sizeof(std::uint64_t), T>::type swap_byte_order(const T& value)\n{\n#ifdef _MSC_VER\n    auto swapped = _byteswap_uint64(reinterpret_cast<const unsigned long long&>(value));\n#elif __GNUC__\n    auto swapped = __builtin_bswap64(value);\n#endif\n\n    return reinterpret_cast<const T&>(swapped);\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/enum_class.h",
    "content": "#pragma once\n\n#include <type_traits>\n#include <vector>\n\n#define ENUM_ENABLE_BITWISE(enum_class)                                                                                \\\n    static enum_class operator&(enum_class lhs, enum_class rhs)                                                        \\\n    {                                                                                                                  \\\n        return static_cast<enum_class>(static_cast<std::underlying_type<enum_class>::type>(lhs) &                      \\\n                                       static_cast<std::underlying_type<enum_class>::type>(rhs));                      \\\n    };                                                                                                                 \\\n    static enum_class& operator&=(enum_class& lhs, enum_class rhs)                                                     \\\n    {                                                                                                                  \\\n        lhs = lhs & rhs;                                                                                               \\\n        return lhs;                                                                                                    \\\n    };                                                                                                                 \\\n    static enum_class operator|(enum_class lhs, enum_class rhs)                                                        \\\n    {                                                                                                                  \\\n        return static_cast<enum_class>(static_cast<std::underlying_type<enum_class>::type>(lhs) |                      \\\n                                       static_cast<std::underlying_type<enum_class>::type>(rhs));                      \\\n    };                                                                                                                 \\\n    static enum_class& operator|=(enum_class& lhs, enum_class rhs)                                                     \\\n    {                                                                                                                  \\\n        lhs = lhs | rhs;                                                                                               \\\n        return lhs;                                                                                                    \\\n    };                                                                                                                 \\\n    static enum_class operator^(enum_class lhs, enum_class rhs)                                                        \\\n    {                                                                                                                  \\\n        return static_cast<enum_class>(static_cast<std::underlying_type<enum_class>::type>(lhs) ^                      \\\n                                       static_cast<std::underlying_type<enum_class>::type>(rhs));                      \\\n    };                                                                                                                 \\\n    static enum_class& operator^=(enum_class& lhs, enum_class rhs)                                                     \\\n    {                                                                                                                  \\\n        lhs = lhs ^ rhs;                                                                                               \\\n        return lhs;                                                                                                    \\\n    };                                                                                                                 \\\n    static enum_class operator~(enum_class e)                                                                          \\\n    {                                                                                                                  \\\n        return static_cast<enum_class>(~static_cast<std::underlying_type<enum_class>::type>(e));                       \\\n    };\n\nnamespace caspar {\n\ntemplate <typename E>\nconst std::vector<E>& enum_constants()\n{\n    using integer = typename std::underlying_type<E>::type;\n\n    static auto res = [] {\n        std::vector<E> result;\n        for (auto n = 0; n < static_cast<int>(E::count); ++n) {\n            result.push_back(static_cast<E>(n));\n        }\n        return result;\n    }();\n    return res;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/env.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"env.h\"\n\n#include \"version.h\"\n\n#include \"except.h\"\n#include \"log.h\"\n#include \"os/filesystem.h\"\n#include \"ptree.h\"\n\n#include <boost/filesystem.hpp>\n#include <boost/filesystem/fstream.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/property_tree/xml_parser.hpp>\n\n#include <boost/algorithm/string.hpp>\n#include <fstream>\n\nnamespace caspar { namespace env {\n\nstd::wstring                 initial;\nstd::wstring                 media;\nstd::wstring                 log;\nbool                         log_enabled = true;\nstd::wstring                 ftemplate;\nstd::wstring                 data;\nboost::property_tree::wptree pt;\n\nvoid check_is_configured()\n{\n    if (pt.empty())\n        CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(L\"Environment properties has not been configured\"));\n}\n\nstd::wstring resolve_or_create(const std::wstring& folder)\n{\n    auto found_path = find_case_insensitive(folder);\n\n    if (found_path)\n        return *found_path;\n    boost::system::error_code ec;\n    boost::filesystem::create_directories(folder, ec);\n\n    if (ec)\n        CASPAR_THROW_EXCEPTION(user_error()\n                               << msg_info(\"Failed to create directory \" + u8(folder) + \" (\" + ec.message() + \")\"));\n\n    return folder;\n}\n\nvoid ensure_writable(const std::wstring& folder)\n{\n    static const std::wstring CREATE_FILE_TEST = L\"casparcg_test_writable.empty\";\n\n    boost::system::error_code   ec;\n    boost::filesystem::path     test_file(folder + L\"/\" + CREATE_FILE_TEST);\n    boost::filesystem::ofstream out(folder + L\"/\" + CREATE_FILE_TEST);\n\n    if (out.fail()) {\n        boost::filesystem::remove(test_file, ec);\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Directory \" + folder + L\" is not writable.\"));\n    }\n\n    out.close();\n    boost::filesystem::remove(test_file, ec);\n}\n\nvoid configure(const std::wstring& filename)\n{\n    initial = clean_path(boost::filesystem::initial_path().wstring());\n\n    std::wstring fullpath = filename;\n    if (!boost::filesystem::exists(fullpath)) {\n        fullpath = initial + L\"/\" + filename;\n    }\n\n    if (!boost::filesystem::exists(fullpath)) {\n        CASPAR_LOG(fatal) << L\"### Configuration file \" + filename + L\" was not found. ###\";\n        CASPAR_THROW_EXCEPTION(expected_user_error()\n                               << msg_info(L\"Configuration file \" + fullpath + L\" was not found.\"));\n    }\n\n    try {\n        boost::filesystem::wifstream file(fullpath);\n        boost::property_tree::read_xml(file,\n                                       pt,\n                                       boost::property_tree::xml_parser::trim_whitespace |\n                                           boost::property_tree::xml_parser::no_comments);\n\n        auto paths = ptree_get_child(pt, L\"configuration.paths\");\n        media      = clean_path(paths.get(L\"media-path\", initial + L\"/media/\"));\n\n        auto log_path_node = paths.get_child(L\"log-path\");\n        log_enabled        = !log_path_node.get(L\"<xmlattr>.disabled\", false);\n        if (log_enabled) {\n            log = clean_path(log_path_node.get_value(initial + L\"/log/\"));\n        }\n\n        ftemplate =\n            clean_path(boost::filesystem::absolute(paths.get(L\"template-path\", initial + L\"/template/\")).wstring());\n        data = clean_path(paths.get(L\"data-path\", initial + L\"/data/\"));\n    } catch (...) {\n        CASPAR_LOG(error) << L\" ### Invalid configuration file. ###\";\n        throw;\n    }\n\n    media     = ensure_trailing_slash(resolve_or_create(media));\n    ftemplate = ensure_trailing_slash(resolve_or_create(ftemplate));\n    data      = ensure_trailing_slash(resolve_or_create(data));\n\n    if (log_enabled) {\n        log = ensure_trailing_slash(resolve_or_create(log));\n        ensure_writable(log);\n    }\n\n    ensure_writable(ftemplate);\n    ensure_writable(data);\n}\n\nconst std::wstring& initial_folder()\n{\n    check_is_configured();\n    return initial;\n}\n\nconst std::wstring& media_folder()\n{\n    check_is_configured();\n    return media;\n}\n\nconst std::wstring& log_folder()\n{\n    check_is_configured();\n    return log;\n}\n\nbool log_to_file()\n{\n    check_is_configured();\n    return log_enabled;\n}\n\nconst std::wstring& template_folder()\n{\n    check_is_configured();\n    return ftemplate;\n}\n\nconst std::wstring& data_folder()\n{\n    check_is_configured();\n    return data;\n}\n\n#define QUOTE(str) #str\n#define EXPAND_AND_QUOTE(str) QUOTE(str)\n\nconst std::wstring& version()\n{\n    static std::wstring ver = u16(EXPAND_AND_QUOTE(CASPAR_GEN) \".\" EXPAND_AND_QUOTE(CASPAR_MAJOR) \".\" EXPAND_AND_QUOTE(\n        CASPAR_MINOR) \" \" CASPAR_HASH \" \" CASPAR_TAG);\n    return ver;\n}\n\nconst boost::property_tree::wptree& properties()\n{\n    check_is_configured();\n    return pt;\n}\n\nvoid log_configuration_warnings()\n{\n    if (pt.empty())\n        return;\n}\n\n}} // namespace caspar::env\n"
  },
  {
    "path": "src/common/env.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <string>\n\nnamespace caspar { namespace env {\n\nvoid configure(const std::wstring& filename);\n\nconst std::wstring& initial_folder();\nconst std::wstring& media_folder();\nconst std::wstring& log_folder();\nconst std::wstring& template_folder();\nconst std::wstring& data_folder();\nconst std::wstring& version();\n\nbool log_to_file();\n\nconst boost::property_tree::wptree& properties();\n\nvoid log_configuration_warnings();\n\n}} // namespace caspar::env\n"
  },
  {
    "path": "src/common/except.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"utf.h\"\n\n#include \"log.h\"\n\n#include <exception>\n\n#include <boost/exception/all.hpp>\n#include <boost/throw_exception.hpp>\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <boost/stacktrace.hpp>\n\nnamespace caspar {\n\nusing arg_name_info_t   = boost::error_info<struct tag_arg_name_info, std::string>;\nusing arg_value_info_t  = boost::error_info<struct tag_arg_value_info, std::string>;\nusing msg_info_t        = boost::error_info<struct tag_msg_info, std::string>;\nusing error_info_t      = boost::error_info<struct tag_error_info, std::string>;\nusing source_info_t     = boost::error_info<struct tag_source_info, std::string>;\nusing file_name_info_t  = boost::error_info<struct tag_file_name_info, std::string>;\nusing stacktrace_info_t = boost::error_info<struct tag_stacktrace_info, boost::stacktrace::stacktrace>;\n\ntemplate <typename T>\narg_name_info_t arg_name_info(const T& str)\n{\n    return arg_name_info_t(u8(str));\n}\ntemplate <typename T>\narg_value_info_t arg_value_info(const T& str)\n{\n    return arg_value_info_t(u8(str));\n}\ntemplate <typename T>\nmsg_info_t msg_info(const T& str)\n{\n    return msg_info_t(u8(str));\n}\ntemplate <typename T>\nerror_info_t error_info(const T& str)\n{\n    return error_info_t(u8(str));\n}\ntemplate <typename T>\nsource_info_t source_info(const T& str)\n{\n    return source_info_t(u8(str));\n}\ntemplate <typename T>\nfile_name_info_t file_name_info(const T& str)\n{\n    return file_name_info_t(u8(str));\n}\n\ninline stacktrace_info_t stacktrace_info() { return stacktrace_info_t(boost::stacktrace::stacktrace()); }\n\nusing line_info        = boost::error_info<struct tag_line_info, size_t>;\nusing nested_exception = boost::error_info<struct tag_nested_exception_, std::exception_ptr>;\n\nstruct caspar_exception\n    : virtual boost::exception\n    , virtual std::exception\n{\n    caspar_exception() {}\n    const char* what() const throw() override { return boost::diagnostic_information_what(*this); }\n};\n\nstruct io_error : virtual caspar_exception\n{\n};\nstruct directory_not_found : virtual io_error\n{\n};\nstruct file_not_found : virtual io_error\n{\n};\nstruct file_read_error : virtual io_error\n{\n};\nstruct file_write_error : virtual io_error\n{\n};\n\nstruct invalid_argument : virtual caspar_exception\n{\n};\nstruct null_argument : virtual invalid_argument\n{\n};\nstruct out_of_range : virtual invalid_argument\n{\n};\nstruct programming_error : virtual caspar_exception\n{\n};\nstruct bad_alloc : virtual caspar_exception\n{\n};\n\nstruct invalid_operation : virtual caspar_exception\n{\n};\nstruct operation_failed : virtual caspar_exception\n{\n};\nstruct timed_out : virtual caspar_exception\n{\n};\n\nstruct not_implemented : virtual caspar_exception\n{\n};\n\nstruct user_error : virtual caspar_exception\n{\n};\nstruct expected_user_error : virtual user_error\n{\n};\nstruct not_supported : virtual user_error\n{\n};\n\n#define CASPAR_THROW_EXCEPTION(x)                                                                                      \\\n    ::boost::throw_exception(::boost::enable_error_info(x)                                                             \\\n                             << ::boost::throw_function(BOOST_CURRENT_FUNCTION) << ::boost::throw_file(__FILE__)       \\\n                             << ::boost::throw_line((int)__LINE__) << stacktrace_info())\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/executor.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"except.h\"\n#include \"log.h\"\n#include \"os/thread.h\"\n\n#include <tbb/concurrent_queue.h>\n\n#include <atomic>\n#include <functional>\n#include <future>\n\nnamespace caspar {\n\nclass executor final\n{\n    executor(const executor&);\n    executor& operator=(const executor&);\n\n    using task_t  = std::function<void()>;\n    using queue_t = tbb::concurrent_bounded_queue<task_t>;\n\n    std::wstring      name_;\n    std::atomic<bool> is_running_{true};\n    queue_t           queue_;\n    std::thread       thread_;\n\n  public:\n    executor(const std::wstring& name)\n        : name_(name)\n        , thread_(std::thread([this] { run(); }))\n    {\n    }\n\n    ~executor() { stop_and_wait(); }\n\n    template <typename Func>\n    auto begin_invoke(Func&& func)\n    {\n        if (!is_running_) {\n            CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(\"executor not running.\"));\n        }\n\n        using result_type = decltype(func());\n\n        auto task = std::make_shared<std::packaged_task<result_type()>>(std::forward<Func>(func));\n\n        queue_.push([=]() mutable { (*task)(); });\n\n        return task->get_future();\n    }\n\n    template <typename Func>\n    auto invoke(Func&& func)\n    {\n        if (is_current()) { // Avoids potential deadlock.\n            return func();\n        }\n\n        return begin_invoke(std::forward<Func>(func)).get();\n    }\n\n    template <typename Func>\n    typename std::enable_if<std::is_same<void, decltype(std::declval<Func>())>::value, void>::type invoke(Func&& func)\n    {\n        if (is_current()) { // Avoids potential deadlock.\n            func();\n            return;\n        }\n\n        begin_invoke(std::forward<Func>(func)).wait();\n    }\n\n    void set_capacity(queue_t::size_type capacity) { queue_.set_capacity(capacity); }\n\n    queue_t::size_type capacity() const { return queue_.capacity(); }\n\n    void clear() { queue_.clear(); }\n\n    void stop()\n    {\n        if (!is_running_) {\n            return;\n        }\n        is_running_ = false;\n        queue_.push(nullptr);\n    }\n\n    void stop_and_wait()\n    {\n        stop();\n\n        if (thread_.joinable())\n            thread_.join();\n    }\n\n    void wait()\n    {\n        invoke([] {});\n    }\n\n    queue_t::size_type size() const { return queue_.size(); }\n\n    bool is_running() const { return is_running_; }\n\n    bool is_current() const { return std::this_thread::get_id() == thread_.get_id(); }\n\n    const std::wstring& name() const { return name_; }\n\n  private:\n    void run()\n    {\n        set_thread_name(name_);\n\n        task_t task;\n\n        while (true) {\n            try {\n                queue_.pop(task);\n                do {\n                    if (!task) {\n                        return;\n                    }\n                    task();\n                } while (queue_.try_pop(task));\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        }\n    }\n};\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/filesystem.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n#include \"except.h\"\n\n#include \"./os/filesystem.h\"\n#include \"filesystem.h\"\n\n#include <boost/algorithm/string.hpp>\n#include <boost/filesystem/directory.hpp>\n#include <boost/filesystem/operations.hpp>\n#include <boost/filesystem/path.hpp>\n\nnamespace caspar {\n\nstd::optional<boost::filesystem::path>\nprobe_path(const boost::filesystem::path&                             full_path,\n           const std::function<bool(const boost::filesystem::path&)>& is_valid_file)\n{\n    auto parent = find_case_insensitive(full_path.parent_path().wstring());\n\n    if (!parent)\n        return {};\n\n    auto dir = boost::filesystem::path(*parent);\n    auto loc = std::locale(\"\"); // Use system locale\n\n    auto leaf_name     = full_path.filename().stem().wstring();\n    auto has_extension = !full_path.filename().extension().wstring().empty();\n    auto leaf_filename = full_path.filename().wstring();\n\n    for (auto it = boost::filesystem::directory_iterator(dir); it != boost::filesystem::directory_iterator(); ++it) {\n        if (has_extension) {\n            auto it_path = it->path().filename().wstring();\n            if (boost::iequals(it_path, leaf_filename, loc) && is_valid_file(it->path().wstring()))\n                return it->path();\n        }\n        if (boost::iequals(it->path().stem().wstring(), leaf_filename, loc) && is_valid_file(it->path().wstring()))\n            return it->path();\n    }\n\n    return {};\n}\n\nstd::optional<boost::filesystem::path>\nfind_file_within_dir_or_absolute(const std::wstring&                                        parent_dir,\n                                 const std::wstring&                                        filename,\n                                 const std::function<bool(const boost::filesystem::path&)>& is_valid_file)\n{\n    // Try it assuming an absolute path was given\n    auto file_path       = boost::filesystem::path(filename);\n    auto file_path_match = probe_path(file_path, is_valid_file);\n    if (file_path_match) {\n        return file_path_match;\n    }\n\n    // Try and find within the default parent directory\n    auto full_path = boost::filesystem::path(parent_dir) / boost::filesystem::path(filename);\n    return probe_path(full_path, is_valid_file);\n}\n\nboost::filesystem::path get_relative(const boost::filesystem::path& file, const boost::filesystem::path& relative_to)\n{\n    auto result       = file.filename();\n    auto current_path = file;\n\n    if (boost::filesystem::equivalent(current_path, relative_to))\n        return L\"\";\n\n    while (true) {\n        current_path = current_path.parent_path();\n\n        if (boost::filesystem::equivalent(current_path, relative_to))\n            break;\n\n        if (current_path.empty())\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"File \" + file.string() + \" not relative to folder \" +\n                                                                  relative_to.string()));\n\n        result = current_path.filename() / result;\n    }\n\n    return result;\n}\n\nboost::filesystem::path get_relative_without_extension(const boost::filesystem::path& file,\n                                                       const boost::filesystem::path& relative_to)\n{\n    return get_relative(file.parent_path() / file.stem(), relative_to);\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/filesystem.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <boost/filesystem/path.hpp>\n\n#include <optional>\n\nnamespace caspar {\n\nstd::optional<boost::filesystem::path>\nfind_file_within_dir_or_absolute(const std::wstring&                                        parent_dir,\n                                 const std::wstring&                                        filename,\n                                 const std::function<bool(const boost::filesystem::path&)>& is_valid_file);\n\nboost::filesystem::path get_relative(const boost::filesystem::path& file, const boost::filesystem::path& relative_to);\nboost::filesystem::path get_relative_without_extension(const boost::filesystem::path& file,\n                                                       const boost::filesystem::path& relative_to);\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/future.h",
    "content": "#pragma once\n\n#include <chrono>\n#include <future>\n#include <type_traits>\n\nnamespace caspar {\n\ntemplate <typename F>\nauto flatten(F&& f)\n{\n    return std::async(std::launch::deferred, [f = std::forward<F>(f)]() mutable { return f.get().get(); });\n}\n\ntemplate <typename F>\nbool is_ready(const F& future)\n{\n    return future.wait_for(std::chrono::seconds(0)) == std::future_status::ready;\n}\n\ntemplate <class T>\nauto make_ready_future(T&& value)\n{\n    std::promise<typename std::decay<T>::type> p;\n    p.set_value(std::forward<T>(value));\n    return p.get_future();\n}\n\nstatic std::future<void> make_ready_future()\n{\n    std::promise<void> p;\n    p.set_value();\n    return p.get_future();\n}\n\n} // namespace caspar"
  },
  {
    "path": "src/common/gl/gl_check.cpp",
    "content": "///////////////////////////\n//\n// SFML - Simple and Fast Multimedia Library\n// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\n//\n// This software is provided 'as-is', without any express or implied warranty.\n// In no event will the authors be held liable for any damages arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it freely,\n// subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented;\n//    you must not claim that you wrote the original software.\n//    If you use this software in a product, an acknowledgment\n//    in the product documentation would be appreciated but is not required.\n//\n// 2. Altered source versions must be plainly marked as such,\n//    and must not be misrepresented as being the original software.\n//\n// 3. This notice may not be removed or altered from any source distribution.\n//\n///////////////////////////\n#include \"gl_check.h\"\n\n#include \"../except.h\"\n#include \"../log.h\"\n\n#include <GL/glew.h>\n\nnamespace caspar { namespace gl {\n\nvoid SMFL_GLCheckError(const std::string& /*unused*/, const char* func, const char* file, unsigned int line)\n{\n    // Get the last error\n    GLenum LastErrorCode = GL_NO_ERROR;\n\n    for (GLenum ErrorCode = glGetError(); ErrorCode != GL_NO_ERROR; ErrorCode = glGetError()) {\n        std::string str(reinterpret_cast<const char*>(glewGetErrorString(ErrorCode)));\n        CASPAR_LOG(error) << \"OpenGL Error: \" << ErrorCode << L\" \" << str;\n        LastErrorCode = ErrorCode;\n    }\n\n    if (LastErrorCode != GL_NO_ERROR) {\n        // Decode the error code\n        switch (LastErrorCode) {\n            case GL_INVALID_ENUM:\n                CASPAR_THROW_EXCEPTION(ogl_invalid_enum()\n                                       << msg_info(\n                                              \"an unacceptable value has been specified for an enumerated argument\")\n                                       << error_info(\"GL_INVALID_ENUM\"));\n\n            case GL_INVALID_VALUE:\n                CASPAR_THROW_EXCEPTION(ogl_invalid_value() << msg_info(\"a numeric argument is out of range\")\n                                                           << error_info(\"GL_INVALID_VALUE\"));\n\n            case GL_INVALID_OPERATION:\n                CASPAR_THROW_EXCEPTION(ogl_invalid_operation()\n                                       << msg_info(\"the specified operation is not allowed in the current state\")\n                                       << error_info(\"GL_INVALID_OPERATION\"));\n\n            case GL_STACK_OVERFLOW:\n                CASPAR_THROW_EXCEPTION(ogl_stack_overflow() << msg_info(\"this command would cause a stack overflow\")\n                                                            << error_info(\"GL_STACK_OVERFLOW\"));\n\n            case GL_STACK_UNDERFLOW:\n                CASPAR_THROW_EXCEPTION(ogl_stack_underflow() << msg_info(\"this command would cause a stack underflow\")\n                                                             << error_info(\"GL_STACK_UNDERFLOW\"));\n\n            case GL_OUT_OF_MEMORY:\n                CASPAR_THROW_EXCEPTION(ogl_out_of_memory()\n                                       << msg_info(\"there is not enough memory left to execute the command\")\n                                       << error_info(\"GL_OUT_OF_MEMORY\"));\n\n            case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:\n                CASPAR_THROW_EXCEPTION(\n                    ogl_invalid_framebuffer_operation_ext()\n                    << msg_info(\"the object bound to FRAMEBUFFER_BINDING_EXT is not \\\"framebuffer complete\\\"\")\n                    << error_info(\"GL_INVALID_FRAMEBUFFER_OPERATION_EXT\"));\n        }\n    }\n}\n\n}} // namespace caspar::gl\n"
  },
  {
    "path": "src/common/gl/gl_check.h",
    "content": "///////////////////////////\n//\n// SFML - Simple and Fast Multimedia Library\n// Copyright (C) 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\n//\n// This software is provided 'as-is', without any express or implied warranty.\n// In no event will the authors be held liable for any damages arising from the use of this software.\n//\n// Permission is granted to anyone to use this software for any purpose,\n// including commercial applications, and to alter it and redistribute it freely,\n// subject to the following restrictions:\n//\n// 1. The origin of this software must not be misrepresented;\n//    you must not claim that you wrote the original software.\n//    If you use this software in a product, an acknowledgment\n//    in the product documentation would be appreciated but is not required.\n//\n// 2. Altered source versions must be plainly marked as such,\n//    and must not be misrepresented as being the original software.\n//\n// 3. This notice may not be removed or altered from any source distribution.\n//\n///////////////////////////\n\n#pragma once\n\n#include \"../except.h\"\n\nnamespace caspar { namespace gl {\n\nstruct ogl_exception : virtual caspar_exception\n{\n};\nstruct ogl_invalid_enum : virtual ogl_exception\n{\n};\nstruct ogl_invalid_value : virtual ogl_exception\n{\n};\nstruct ogl_invalid_operation : virtual ogl_exception\n{\n};\nstruct ogl_stack_overflow : virtual ogl_exception\n{\n};\nstruct ogl_stack_underflow : virtual ogl_exception\n{\n};\nstruct ogl_out_of_memory : virtual ogl_exception\n{\n};\nstruct ogl_invalid_framebuffer_operation_ext : virtual ogl_exception\n{\n};\n\nvoid SMFL_GLCheckError(const std::string& expr, const char* func, const char* file, unsigned int line);\n\n// #ifdef _DEBUG\n\n#define CASPAR_GL_EXPR_STR(expr) #expr\n\n#define GL(expr)                                                                                                       \\\n    if (false) {                                                                                                       \\\n    } else {                                                                                                           \\\n        (expr);                                                                                                        \\\n        caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FUNCTION__, __FILE__, __LINE__);                     \\\n    }\n\n// TODO: decltype version does not play well with gcc\n#define GL2(expr)                                                                                                      \\\n    [&]() {                                                                                                            \\\n        auto ret = (expr);                                                                                             \\\n        caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FUNCTION__, __FILE__, __LINE__);                     \\\n        return ret;                                                                                                    \\\n    }()\n/*#define GL2(expr) \\\n    [&]() -> decltype(expr) \\\n    { \\\n        auto ret = (expr); \\\n        caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr), __FILE__, __LINE__); \\\n        return ret; \\\n    }()*/\n// #define GL2(expr) [&]() -> decltype(expr) { auto ret = (expr);\n// caspar::gl::SMFL_GLCheckError(CASPAR_GL_EXPR_STR(expr),\n//__FILE__, __LINE__); return ret; }() #else #define GL(expr) expr #endif\n\n}} // namespace caspar::gl\n"
  },
  {
    "path": "src/common/log.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"log.h\"\n\n#include \"except.h\"\n\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/algorithm/string/replace.hpp>\n#include <boost/bind/bind.hpp>\n#include <boost/core/null_deleter.hpp>\n#include <boost/filesystem/operations.hpp>\n#include <boost/lexical_cast.hpp>\n#include <boost/locale.hpp>\n#include <boost/log/attributes/function.hpp>\n#include <boost/log/core.hpp>\n#include <boost/log/expressions.hpp>\n#include <boost/log/sinks/async_frontend.hpp>\n#include <boost/log/sinks/sync_frontend.hpp>\n#include <boost/log/sinks/text_file_backend.hpp>\n#include <boost/log/sinks/text_ostream_backend.hpp>\n#include <boost/log/sources/logger.hpp>\n#include <boost/log/trivial.hpp>\n#include <boost/log/utility/setup/common_attributes.hpp>\n#include <boost/log/utility/setup/file.hpp>\n#include <boost/smart_ptr/make_shared_object.hpp>\n#include <boost/smart_ptr/shared_ptr.hpp>\n\n#include <atomic>\n#include <iostream>\n\nnamespace logging  = boost::log;\nnamespace src      = boost::log::sources;\nnamespace sinks    = boost::log::sinks;\nnamespace keywords = boost::log::keywords;\n\nusing namespace boost::placeholders;\n\nnamespace caspar { namespace log {\n\nlogging_config current_config;\n\nstd::string current_exception_diagnostic_information()\n{\n    {\n        auto e = boost::current_exception_cast<const char*>();\n        if (e != nullptr) {\n            return std::string(\"[char *] = \") + *e + \"\\n\";\n        }\n    }\n    {\n        auto e = boost::current_exception_cast<const wchar_t*>();\n        if (e != nullptr) {\n            return std::string(\"[char *] = \") + u8(*e) + \"\\n\";\n        }\n    }\n    {\n        auto e = boost::current_exception_cast<std::string>();\n        if (e != nullptr) {\n            return std::string(\"[char *] = \") + *e + \"\\n\";\n        }\n    }\n    {\n        auto e = boost::current_exception_cast<std::wstring>();\n        if (e != nullptr) {\n            return std::string(\"[char *] = \") + u8(*e) + \"\\n\";\n        }\n    }\n\n    return boost::current_exception_diagnostic_information(true);\n}\n\ntemplate <typename Stream>\nvoid append_timestamp(Stream& stream, boost::posix_time::ptime timestamp)\n{\n    auto date         = timestamp.date();\n    auto time         = timestamp.time_of_day();\n    auto milliseconds = time.fractional_seconds() / 1000; // microseconds to milliseconds\n\n    std::wstringstream buffer;\n\n    buffer << std::setfill(L'0') << L\"[\" << std::setw(4) << date.year() << L\"-\" << std::setw(2)\n           << date.month().as_number() << \"-\" << std::setw(2) << date.day().as_number() << L\" \" << std::setw(2)\n           << time.hours() << L\":\" << std::setw(2) << time.minutes() << L\":\" << std::setw(2) << time.seconds() << L\".\"\n           << std::setw(3) << milliseconds << L\"] \";\n\n    stream << buffer.str();\n}\n\nclass column_writer\n{\n    std::atomic<int> column_width_;\n\n  public:\n    explicit column_writer(int initial_width = 0)\n        : column_width_(initial_width)\n    {\n    }\n\n    template <typename Stream, typename Val>\n    void write(Stream& out, const Val& value)\n    {\n        std::wstring to_string = boost::lexical_cast<std::wstring>(value);\n\n        if (!current_config.align_columns) {\n            out << L\"[\" << to_string << L\"] \";\n        } else {\n            int length = static_cast<int>(to_string.size());\n            int read_width;\n\n            while (true) {\n                read_width = column_width_;\n                if (read_width >= length || column_width_.compare_exchange_strong(length, read_width)) {\n                    break;\n                }\n            }\n\n            read_width = column_width_;\n\n            out << L\"[\" << to_string << L\"] \";\n\n            for (int n = 0; n < read_width - length; ++n) {\n                out << L\" \";\n            }\n        }\n    }\n};\n\ntemplate <typename Stream>\nvoid my_formatter(bool print_all_characters, const boost::log::record_view& rec, Stream& strm)\n{\n    // static column_writer thread_id_column;\n    static column_writer severity_column(7);\n    namespace expr = boost::log::expressions;\n\n    std::wstringstream pre_message_stream;\n    append_timestamp(pre_message_stream, boost::log::extract<boost::posix_time::ptime>(\"TimestampMillis\", rec).get());\n    // thread_id_column.write(pre_message_stream, boost::log::extract<std::int64_t>(\"NativeThreadId\", rec));\n    severity_column.write(pre_message_stream,\n                          boost::log::extract<boost::log::trivial::severity_level>(\"Severity\", rec));\n\n    auto pre_message = pre_message_stream.str();\n\n    strm << pre_message;\n\n    auto line_break_replacement = L\"\\n\" + pre_message;\n\n    if (print_all_characters) {\n        strm << boost::replace_all_copy(rec[expr::message].get<std::wstring>(), \"\\n\", line_break_replacement);\n    } else {\n        strm << boost::replace_all_copy(\n            replace_nonprintable_copy(rec[expr::message].get<std::wstring>(), L'?'), L\"\\n\", line_break_replacement);\n    }\n}\n\nvoid add_file_sink(const std::wstring& file)\n{\n    using file_sink_type = boost::log::sinks::synchronous_sink<boost::log::sinks::text_file_backend>;\n\n    try {\n        if (!boost::filesystem::is_directory(boost::filesystem::path(file).parent_path())) {\n            CASPAR_THROW_EXCEPTION(directory_not_found());\n        }\n\n        auto file_sink = boost::make_shared<file_sink_type>(\n            boost::log::keywords::file_name           = file + L\"_%Y-%m-%d.log\",\n            boost::log::keywords::time_based_rotation = boost::log::sinks::file::rotation_at_time_point(0, 0, 0),\n            boost::log::keywords::auto_flush          = true,\n            boost::log::keywords::open_mode           = std::ios::app);\n\n        file_sink->set_formatter(boost::bind(&my_formatter<boost::log::formatting_ostream>, true, _1, _2));\n\n        boost::log::core::get()->add_sink(file_sink);\n    } catch (...) {\n        std::wcerr << L\"Failed to Setup File Logging Sink\" << std::endl << std::endl;\n    }\n}\n\nvoid add_cout_sink()\n{\n    boost::log::add_common_attributes();\n    // boost::log::core::get()->add_global_attribute(\"NativeThreadId\",\n    // boost::log::attributes::make_function(&std::this_thread::get_id));\n    boost::log::core::get()->add_global_attribute(\"TimestampMillis\", boost::log::attributes::make_function([] {\n                                                      return boost::posix_time::microsec_clock::local_time();\n                                                  }));\n\n    using stream_sink_type = sinks::asynchronous_sink<sinks::wtext_ostream_backend>;\n\n    auto stream_backend = boost::make_shared<boost::log::sinks::wtext_ostream_backend>();\n    stream_backend->add_stream(boost::shared_ptr<std::wostream>(&std::wcout, boost::null_deleter()));\n    stream_backend->auto_flush(true);\n\n    auto stream_sink = boost::make_shared<stream_sink_type>(stream_backend);\n\n    stream_sink->set_formatter(boost::bind(&my_formatter<boost::log::wformatting_ostream>, false, _1, _2));\n\n    logging::core::get()->add_sink(stream_sink);\n}\n\nbool set_log_level(const std::wstring& lvl)\n{\n    if (boost::iequals(lvl, L\"trace\"))\n        logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::trace);\n    else if (boost::iequals(lvl, L\"debug\"))\n        logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::debug);\n    else if (boost::iequals(lvl, L\"info\"))\n        logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::info);\n    else if (boost::iequals(lvl, L\"warning\"))\n        logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::warning);\n    else if (boost::iequals(lvl, L\"error\"))\n        logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::error);\n    else if (boost::iequals(lvl, L\"fatal\"))\n        logging::core::get()->set_filter(logging::trivial::severity >= boost::log::trivial::fatal);\n    else\n        return false;\n\n    // TODO is this a race condition?\n    current_config.current_level = lvl;\n    return true;\n}\n\nstd::wstring& get_log_level() { return current_config.current_level; }\n\nvoid set_log_column_alignment(bool align_columns) { current_config.align_columns = align_columns; }\n\n}} // namespace caspar::log\n"
  },
  {
    "path": "src/common/log.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"utf.h\"\n\n#include <boost/log/sources/global_logger_storage.hpp>\n#include <boost/log/sources/severity_feature.hpp>\n#include <boost/log/sources/severity_logger.hpp>\n#include <boost/log/trivial.hpp>\n#ifndef NOMINMAX\n#define NOMINMAX\n#endif\n#ifndef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n#endif\n#include <boost/stacktrace.hpp>\n\n#include <atomic>\n#include <string>\n\nnamespace caspar { namespace log {\n\ntemplate <typename T>\nvoid replace_nonprintable(std::basic_string<T, std::char_traits<T>, std::allocator<T>>& str, T with)\n{\n    std::locale loc(\"\"); // Use system locale\n    std::replace_if(\n        str.begin(), str.end(), [&](T c) -> bool { return (!std::isprint(c, loc) && c != '\\r' && c != '\\n'); }, with);\n}\n\ntemplate <typename T>\nstd::basic_string<T> replace_nonprintable_copy(std::basic_string<T, std::char_traits<T>, std::allocator<T>> str, T with)\n{\n    replace_nonprintable(str, with);\n    return str;\n}\n\nstd::string current_exception_diagnostic_information();\n\nusing caspar_logger = boost::log::sources::wseverity_logger<boost::log::trivial::severity_level>;\n\nBOOST_LOG_INLINE_GLOBAL_LOGGER_DEFAULT(logger, caspar_logger)\n#define CASPAR_LOG(lvl) BOOST_LOG_SEV(::caspar::log::logger::get(), boost::log::trivial::severity_level::lvl)\n\nstruct logging_config\n{\n    std::atomic<bool> align_columns = {false};\n    std::wstring      current_level;\n};\n\nvoid          add_file_sink(const std::wstring& file);\nvoid          add_cout_sink();\nbool          set_log_level(const std::wstring& lvl);\nstd::wstring& get_log_level();\nvoid          set_log_column_alignment(bool align_columns);\n\ninline std::wstring get_stack_trace()\n{\n    auto bt = boost::stacktrace::stacktrace();\n    if (bt) {\n        return caspar::u16(boost::stacktrace::detail::to_string(&bt.as_vector()[0], bt.size()));\n    }\n    return L\"\";\n}\n\n#define CASPAR_LOG_CURRENT_EXCEPTION()                                                                                 \\\n    try {                                                                                                              \\\n        CASPAR_LOG(error) << L\"Exception: \" << caspar::u16(::caspar::log::current_exception_diagnostic_information())  \\\n                          << L\"\\r\\n\"                                                                                   \\\n                          << caspar::log::get_stack_trace();                                                           \\\n    } catch (...) {                                                                                                    \\\n    }\n\n#define CASPAR_LOG_CURRENT_CALL_STACK() // TODO (fix)\n\n}} // namespace caspar::log\n"
  },
  {
    "path": "src/common/memory.h",
    "content": "/*\n * Copyright (c) 2011,2018 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <memory>\n#include <stdexcept>\n#include <type_traits>\n\nnamespace caspar { namespace spl {\n\n// unique_ptr\n\n/**\n * A wrapper around std::unique_ptr ensuring that the pointer is never null\n * except in the case of a moved from instance.\n *\n * The default constructor will point the wrapped pointer to a default\n * constructed instance of T.\n *\n * Use the make_unique overloads for perfectly forwarding the constructor\n * arguments of T and creating a unique_ptr to the created T instance.\n */\ntemplate <typename T, typename D = std::default_delete<T>>\nclass unique_ptr\n{\n    unique_ptr(const unique_ptr&);\n    unique_ptr& operator=(const unique_ptr&);\n\n    template <typename, typename>\n    friend class unique_ptr;\n    template <typename>\n    friend class shared_ptr;\n\n  public:\n    using element_type = T;\n    using deleter_type = D;\n\n    unique_ptr()\n        : p_(new T())\n    {\n    }\n\n    template <typename T2, typename D2>\n    unique_ptr(unique_ptr<T2, D2>&& p,\n               typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(p.p_.release(), p.p_.get_deleter())\n    {\n    }\n\n    template <typename T2, typename D2>\n    explicit unique_ptr(std::unique_ptr<T2, D2>&& p,\n                        typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(std::move(p))\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    template <typename T2>\n    explicit unique_ptr(T2* p, typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(p)\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    template <typename T2>\n    explicit unique_ptr(T2*                                                  p,\n                        typename std::remove_reference /*unused*/<D>::type&& d,\n                        typename std::enable_if<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(p, d)\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    unique_ptr<T>& operator=(unique_ptr&& other)\n    {\n        other.swap(*this);\n        return *this;\n    }\n\n    T& operator*() const { return *p_.get(); }\n\n    T* operator->() const { return p_.get(); }\n\n    T* get() const { return p_.get(); }\n\n    void swap(unique_ptr& other) { p_.swap(other.p_); }\n\n    D& get_deleter() { return p_.get_deleter(); }\n\n  private:\n    T* release() { return p_.release(); }\n\n    std::unique_ptr<T, D> p_;\n};\n\ntemplate <class T, class T2>\nbool operator==(const unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() == b.get();\n}\n\ntemplate <class T, class T2>\nbool operator==(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() == b.get();\n}\n\ntemplate <class T, class T2>\nbool operator==(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)\n{\n    return a.get() == b.get();\n}\n\ntemplate <class T, class T2>\nbool operator!=(const unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() != b.get();\n}\n\ntemplate <class T, class T2>\nbool operator!=(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() != b.get();\n}\n\ntemplate <class T, class T2>\nbool operator!=(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)\n{\n    return a.get() != b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<(const unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() < b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() < b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)\n{\n    return a.get() < b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>(const unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() > b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() > b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)\n{\n    return a.get() > b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>=(const unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() >= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>=(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() >= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>=(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)\n{\n    return a.get() >= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<=(const unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() <= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<=(const std::unique_ptr<T>& a, const unique_ptr<T2>& b)\n{\n    return a.get() <= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<=(const unique_ptr<T>& a, const std::unique_ptr<T2>& b)\n{\n    return a.get() <= b.get();\n}\n\ntemplate <class E, class T, class T2>\nstd::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& oT2t, const unique_ptr<T2>& p)\n{\n    return oT2t << p.get();\n}\n\ntemplate <class T>\nvoid swap(unique_ptr<T>& a, unique_ptr<T>& b)\n{\n    a.swap(b);\n}\n\ntemplate <class T>\nT* get_pointer(unique_ptr<T> const& p)\n{\n    return p.get();\n}\n\ntemplate <class T, class T2>\nunique_ptr<T> static_pointer_cast(const unique_ptr<T2>& p)\n{\n    return unique_ptr<T>(std::static_pointer_cast<T>(std::unique_ptr<T2>(p)));\n}\n\ntemplate <class T, class T2>\nunique_ptr<T> const_pointer_cast(const unique_ptr<T2>& p)\n{\n    return unique_ptr<T>(std::const_pointer_cast<T>(std::unique_ptr<T2>(p)));\n}\n\ntemplate <class T, class T2>\nunique_ptr<T> dynamic_pointer_cast(const unique_ptr<T2>& p)\n{\n    auto temp = std::dynamic_pointer_cast<T>(std::unique_ptr<T2>(p));\n    if (!temp)\n        throw std::bad_cast();\n    return unique_ptr<T>(std::move(temp));\n}\n\ntemplate <typename T>\nunique_ptr<T> make_unique_ptr(std::unique_ptr<T>&& ptr)\n{\n    return unique_ptr<T>(std::move(ptr));\n}\n\ntemplate <typename T>\nunique_ptr<T> make_unique()\n{\n    return unique_ptr<T>(new T());\n}\n\ntemplate <typename T, typename P0>\nunique_ptr<T> make_unique(P0&& p0)\n{\n    return unique_ptr<T>(new T(std::forward<P0>(p0)));\n}\n\ntemplate <typename T, typename P0, typename P1>\nunique_ptr<T> make_unique(P0&& p0, P1&& p1)\n{\n    return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2>\nunique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2)\n{\n    return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3>\nunique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3)\n{\n    return unique_ptr<T>(new T(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3, typename P4>\nunique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)\n{\n    return unique_ptr<T>(new T(\n        std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>\nunique_ptr<T> make_unique(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)\n{\n    return unique_ptr<T>(new T(std::forward<P0>(p0),\n                               std::forward<P1>(p1),\n                               std::forward<P2>(p2),\n                               std::forward<P3>(p3),\n                               std::forward<P4>(p4),\n                               std::forward<P5>(p5)));\n}\n\n// shared_ptr\n\n/**\n * A wrapper around std::shared_ptr ensuring that it never points to a null\n * pointer except in the case of a moved from instance.\n *\n * A default constructed shared_ptr will point to a default constructed T.\n *\n * Use the make_shared overloads for perfect forwarding of the constructor\n * arguments of T which will return a shared_ptr pointing to the constructed T.\n */\ntemplate <typename T>\nclass shared_ptr\n{\n    template <typename>\n    friend class shared_ptr;\n\n  public:\n    using element_type = T;\n\n    shared_ptr(); // will constrT2ct new T object T2sing make_shared<T>()\n\n    template <typename T2>\n    shared_ptr(shared_ptr<T2> other,\n               typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(std::move(other.p_))\n    {\n    }\n\n    template <typename T2>\n    explicit shared_ptr(std::unique_ptr<T2>&& p,\n                        typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(std::move(p))\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    template <typename T2>\n    explicit shared_ptr(spl::unique_ptr<T2>&& p,\n                        typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(p.release(), p.get_deleter())\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    template <typename T2>\n    explicit shared_ptr(std::shared_ptr<T2> p,\n                        typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(std::move(p))\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    template <typename T2>\n    explicit shared_ptr(T2* p, typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(p)\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    template <typename T2, typename D>\n    explicit shared_ptr(T2* p,\n                        D   d,\n                        typename std::enable_if /*unused*/<std::is_convertible<T2*, T*>::value, void*>::type = 0)\n        : p_(p, d)\n    {\n        if (!p_)\n            throw std::invalid_argument(\"p\");\n    }\n\n    shared_ptr operator=(shared_ptr other)\n    {\n        other.swap(*this);\n        return *this;\n    }\n\n    T& operator*() const { return *p_.get(); }\n\n    T* operator->() const { return p_.get(); }\n\n    T* get() const { return p_.get(); }\n\n    long use_count() const { return p_.use_count(); }\n\n    void swap(shared_ptr& other) { p_.swap(other.p_); }\n\n    template <typename T2>\n    operator std::shared_ptr<T2>() const\n    {\n        return p_;\n    }\n\n    template <typename T2>\n    operator std::weak_ptr<T2>() const\n    {\n        return std::weak_ptr<T2>(p_);\n    }\n\n    template <class T2>\n    bool owner_before(const shared_ptr& ptr)\n    {\n        return p_.owner_before(ptr.p_);\n    }\n\n    template <class T2>\n    bool owner_before(const std::shared_ptr<T2>& ptr)\n    {\n        return p_.owner_before(ptr);\n    }\n\n  private:\n    std::shared_ptr<T> p_;\n};\n\ntemplate <class D, class T>\nD* get_deleter(shared_ptr<T> const& ptr)\n{\n    return ptr.get_deleter();\n}\n\ntemplate <class T, class T2>\nbool operator==(const shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() == b.get();\n}\n\ntemplate <class T, class T2>\nbool operator==(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() == b.get();\n}\n\ntemplate <class T, class T2>\nbool operator==(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)\n{\n    return a.get() == b.get();\n}\n\ntemplate <class T, class T2>\nbool operator!=(const shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() != b.get();\n}\n\ntemplate <class T, class T2>\nbool operator!=(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() != b.get();\n}\n\ntemplate <class T, class T2>\nbool operator!=(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)\n{\n    return a.get() != b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<(const shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() < b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() < b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)\n{\n    return a.get() < b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>(const shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() > b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() > b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)\n{\n    return a.get() > b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>=(const shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() >= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>=(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() >= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator>=(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)\n{\n    return a.get() >= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<=(const shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() <= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<=(const std::shared_ptr<T>& a, const shared_ptr<T2>& b)\n{\n    return a.get() <= b.get();\n}\n\ntemplate <class T, class T2>\nbool operator<=(const shared_ptr<T>& a, const std::shared_ptr<T2>& b)\n{\n    return a.get() <= b.get();\n}\n\ntemplate <class E, class T, class T2>\nstd::basic_ostream<E, T>& operator<<(std::basic_ostream<E, T>& oT2t, const shared_ptr<T2>& p)\n{\n    return oT2t << p.get();\n}\n\ntemplate <class T>\nvoid swap(shared_ptr<T>& a, shared_ptr<T>& b)\n{\n    a.swap(b);\n}\n\ntemplate <class T>\nT* get_pointer(shared_ptr<T> const& p)\n{\n    return p.get();\n}\n\ntemplate <class T, class T2>\nshared_ptr<T> static_pointer_cast(const shared_ptr<T2>& p)\n{\n    return shared_ptr<T>(std::static_pointer_cast<T>(std::shared_ptr<T2>(p)));\n}\n\ntemplate <class T, class T2>\nshared_ptr<T> const_pointer_cast(const shared_ptr<T2>& p)\n{\n    return shared_ptr<T>(std::const_pointer_cast<T>(std::shared_ptr<T2>(p)));\n}\n\ntemplate <class T, class T2>\nshared_ptr<T> dynamic_pointer_cast(const shared_ptr<T2>& p)\n{\n    auto temp = std::dynamic_pointer_cast<T>(std::shared_ptr<T2>(p));\n    if (!temp)\n        throw std::bad_cast();\n    return shared_ptr<T>(std::move(temp));\n}\n\ntemplate <class T, class T2>\nbool instance_of(const shared_ptr<T2>& p)\n{\n    auto temp = std::dynamic_pointer_cast<T>(std::shared_ptr<T2>(p));\n    return temp != nullptr;\n}\n\n//\n// enable_safe_this\n//\n// A shared_ptr version of enable_shared_from_this.\n// So that an object may get shared_ptr objects to itself.\n//\n\ntemplate <class T>\nclass enable_shared_from_this : public std::enable_shared_from_this<T>\n{\n  public:\n    shared_ptr<T> shared_from_this() { return shared_ptr<T>(std::enable_shared_from_this<T>::shared_from_this()); }\n\n    shared_ptr<T const> shared_from_this() const\n    {\n        return shared_ptr<T const>(std::enable_shared_from_this<T>::shared_from_this());\n    }\n\n  protected:\n    enable_shared_from_this() {}\n\n    enable_shared_from_this(const enable_shared_from_this& /*unused*/) {}\n\n    enable_shared_from_this& operator=(const enable_shared_from_this& /*unused*/) { return *this; }\n\n    ~enable_shared_from_this() {}\n};\n\n//\n// make_shared\n//\n// shared_ptr eqT2ivalents to make_shared\n//\n\ntemplate <typename T>\nshared_ptr<T> make_shared_ptr(std::unique_ptr<T>&& ptr)\n{\n    return shared_ptr<T>(std::move(ptr));\n}\n\ntemplate <typename T>\nshared_ptr<T> make_shared_ptr(std::shared_ptr<T> ptr)\n{\n    return shared_ptr<T>(std::move(ptr));\n}\n\ntemplate <typename T>\nshared_ptr<T> make_shared()\n{\n    return shared_ptr<T>(std::make_shared<T>());\n}\n\ntemplate <typename T, typename U>\nshared_ptr<T> make_shared()\n{\n    return shared_ptr<T>(std::make_shared<U>());\n}\ntemplate <typename T, typename U, typename P0>\nshared_ptr<T> make_shared(P0&& p0)\n{\n    return shared_ptr<T>(std::make_shared<U>(std::forward<P0>(p0)));\n}\ntemplate <typename T, typename U, typename P0, typename P1>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1)\n{\n    return shared_ptr<T>(std::make_shared<U>(std::forward<P0>(p0), std::forward<P1>(p1)));\n}\n\ntemplate <typename T, typename P0>\nshared_ptr<T> make_shared(P0&& p0)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0)));\n}\n\ntemplate <typename T, typename P0, typename P1>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3)\n{\n    return shared_ptr<T>(\n        std::make_shared<T>(std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3, typename P4>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4)\n{\n    return shared_ptr<T>(std::make_shared<T>(\n        std::forward<P0>(p0), std::forward<P1>(p1), std::forward<P2>(p2), std::forward<P3>(p3), std::forward<P4>(p4)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5)));\n}\n\ntemplate <typename T, typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5),\n                                             std::forward<P6>(p6)));\n}\n\ntemplate <typename T,\n          typename P0,\n          typename P1,\n          typename P2,\n          typename P3,\n          typename P4,\n          typename P5,\n          typename P6,\n          typename P7>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5),\n                                             std::forward<P6>(p6),\n                                             std::forward<P7>(p7)));\n}\n\ntemplate <typename T,\n          typename P0,\n          typename P1,\n          typename P2,\n          typename P3,\n          typename P4,\n          typename P5,\n          typename P6,\n          typename P7,\n          typename P8>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5),\n                                             std::forward<P6>(p6),\n                                             std::forward<P7>(p7),\n                                             std::forward<P8>(p8)));\n}\n\ntemplate <typename T,\n          typename P0,\n          typename P1,\n          typename P2,\n          typename P3,\n          typename P4,\n          typename P5,\n          typename P6,\n          typename P7,\n          typename P8,\n          typename P9>\nshared_ptr<T> make_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5),\n                                             std::forward<P6>(p6),\n                                             std::forward<P7>(p7),\n                                             std::forward<P8>(p8),\n                                             std::forward<P9>(p9)));\n}\n\ntemplate <typename T,\n          typename P0,\n          typename P1,\n          typename P2,\n          typename P3,\n          typename P4,\n          typename P5,\n          typename P6,\n          typename P7,\n          typename P8,\n          typename P9,\n          typename P10>\nshared_ptr<T>\nmake_shared(P0&& p0, P1&& p1, P2&& p2, P3&& p3, P4&& p4, P5&& p5, P6&& p6, P7&& p7, P8&& p8, P9&& p9, P10&& p10)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5),\n                                             std::forward<P6>(p6),\n                                             std::forward<P7>(p7),\n                                             std::forward<P8>(p8),\n                                             std::forward<P9>(p9),\n                                             std::forward<P10>(p10)));\n}\n\ntemplate <typename T,\n          typename P0,\n          typename P1,\n          typename P2,\n          typename P3,\n          typename P4,\n          typename P5,\n          typename P6,\n          typename P7,\n          typename P8,\n          typename P9,\n          typename P10,\n          typename P11>\nshared_ptr<T> make_shared(P0&&  p0,\n                          P1&&  p1,\n                          P2&&  p2,\n                          P3&&  p3,\n                          P4&&  p4,\n                          P5&&  p5,\n                          P6&&  p6,\n                          P7&&  p7,\n                          P8&&  p8,\n                          P9&&  p9,\n                          P10&& p10,\n                          P11&& p11)\n{\n    return shared_ptr<T>(std::make_shared<T>(std::forward<P0>(p0),\n                                             std::forward<P1>(p1),\n                                             std::forward<P2>(p2),\n                                             std::forward<P3>(p3),\n                                             std::forward<P4>(p4),\n                                             std::forward<P5>(p5),\n                                             std::forward<P6>(p6),\n                                             std::forward<P7>(p7),\n                                             std::forward<P8>(p8),\n                                             std::forward<P9>(p9),\n                                             std::forward<P10>(p10),\n                                             std::forward<P11>(p11)));\n}\n\ntemplate <typename T>\nshared_ptr<T>::shared_ptr()\n    : p_(make_shared<T>())\n{\n}\n\n}} // namespace caspar::spl\n"
  },
  {
    "path": "src/common/memshfl.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#ifdef USE_SIMDE\n#define SIMDE_ENABLE_NATIVE_ALIASES\n#include <simde/x86/ssse3.h>\n#else\n#ifdef _MSC_VER\n#include <intrin.h>\n#include <tbb/scalable_allocator.h>\n#else\n#include <tmmintrin.h>\n#endif\n#endif\n\nnamespace caspar {\n\n#ifdef _MSC_VER\nstatic std::shared_ptr<void> create_aligned_buffer(size_t size, size_t alignment = 64)\n{\n    return std::shared_ptr<void>(scalable_aligned_malloc(size, alignment), scalable_aligned_free);\n}\n#else\nstatic std::shared_ptr<void> create_aligned_buffer(size_t size, size_t alignment = 64)\n{\n    return std::shared_ptr<void>(aligned_alloc(alignment, size), free);\n}\n#endif\n\nstatic void* aligned_memshfl(void* dest, const void* source, size_t count, int m1, int m2, int m3, int m4)\n{\n    __m128i*       dest128   = reinterpret_cast<__m128i*>(dest);\n    const __m128i* source128 = reinterpret_cast<const __m128i*>(source);\n\n    count /= 16; // 128 bit\n\n    const __m128i mask128 = _mm_set_epi32(m1, m2, m3, m4);\n    for (size_t n = 0; n < count / 4; ++n) {\n        __m128i xmm0 = _mm_load_si128(source128++);\n        __m128i xmm1 = _mm_load_si128(source128++);\n        __m128i xmm2 = _mm_load_si128(source128++);\n        __m128i xmm3 = _mm_load_si128(source128++);\n\n        _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm0, mask128));\n        _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm1, mask128));\n        _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm2, mask128));\n        _mm_stream_si128(dest128++, _mm_shuffle_epi8(xmm3, mask128));\n    }\n    return dest;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/filesystem.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <optional>\n#include <string>\n\nnamespace caspar {\n\nstd::optional<std::wstring> find_case_insensitive(const std::wstring& case_insensitive);\n\nstd::wstring clean_path(std::wstring path);\n\nstd::wstring ensure_trailing_slash(std::wstring folder);\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/linux/filesystem.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../../stdafx.h\"\n\n#include \"../filesystem.h\"\n\n#include <boost/algorithm/string.hpp>\n#include <boost/filesystem.hpp>\n\nusing namespace boost::filesystem;\n\nnamespace caspar {\n\nstd::optional<std::wstring> find_case_insensitive(const std::wstring& case_insensitive)\n{\n    path p(case_insensitive);\n\n    if (exists(p))\n        return case_insensitive;\n\n    p = absolute(p);\n    path result;\n\n    auto loc = std::locale(\"\"); // Use system locale\n\n    for (auto part : p) {\n        auto concatenated = result / part;\n\n        if (exists(concatenated)) {\n            result = concatenated;\n        } else {\n            bool found = false;\n\n            for (auto it = directory_iterator(absolute(result)); it != directory_iterator(); ++it) {\n                auto leaf = it->path().filename();\n\n                if (boost::algorithm::iequals(part.wstring(), leaf.wstring(), loc)) {\n                    result = result / leaf;\n                    found  = true;\n                    break;\n                }\n            }\n\n            if (!found)\n                return {};\n        }\n    }\n\n    return result.wstring();\n}\n\nstd::wstring clean_path(std::wstring path)\n{\n    boost::replace_all(path, L\"\\\\\\\\\", L\"/\");\n    boost::replace_all(path, L\"\\\\\", L\"/\");\n\n    return path;\n}\n\nstd::wstring ensure_trailing_slash(std::wstring folder)\n{\n    auto last_char = folder.at(folder.length() - 1);\n    if (last_char != L'/')\n        folder.append(L\"/\");\n\n    return folder;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/linux/prec_timer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../stdafx.h\"\n\n#include \"../../prec_timer.h\"\n\n#include <time.h>\n\n#include <chrono>\n\nusing namespace std::chrono;\n\nnamespace caspar {\n\nprec_timer::prec_timer()\n    : time_(0)\n{\n}\n\nvoid prec_timer::tick_nanos(int64_t ticks_to_wait)\n{\n    auto t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();\n\n    if (time_ != 0) {\n        bool done = 0;\n        do {\n            auto ticks_passed = t - time_;\n            auto ticks_left   = ticks_to_wait - ticks_passed;\n\n            if (t < time_) // time wrap\n                done = 1;\n            if (ticks_passed >= ticks_to_wait)\n                done = 1;\n\n            if (!done) {\n                timespec spec;\n\n                if (ticks_left > 2000000) {\n                    spec.tv_sec  = ticks_left / 1000000000;\n                    spec.tv_nsec = 1000000;\n                } else {\n                    spec.tv_sec  = 0;\n                    spec.tv_nsec = ticks_left / 100;\n                }\n\n                nanosleep(&spec, nullptr);\n            }\n\n            t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();\n        } while (!done);\n    }\n\n    time_ = t;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/linux/thread.cpp",
    "content": "#include \"../thread.h\"\n#include \"../../utf.h\"\n#include <pthread.h>\n#include <sched.h>\n\nnamespace caspar {\n\nvoid set_thread_name(const std::wstring& name) { pthread_setname_np(pthread_self(), u8(name).c_str()); }\n\nvoid set_thread_realtime_priority()\n{\n    pthread_t          handle = pthread_self();\n    int                policy;\n    struct sched_param param;\n    if (pthread_getschedparam(handle, &policy, &param) != 0)\n        return;\n    param.sched_priority = 2;\n    pthread_setschedparam(handle, SCHED_FIFO, &param);\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/thread.h",
    "content": "#pragma once\n\n#include <string>\n\nnamespace caspar {\n\nvoid set_thread_name(const std::wstring& name);\nvoid set_thread_realtime_priority();\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/windows/filesystem.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../../stdafx.h\"\n\n#include \"../filesystem.h\"\n\n#include <boost/algorithm/string/trim.hpp>\n#include <boost/filesystem.hpp>\n\nnamespace caspar {\n\nstd::optional<std::wstring> find_case_insensitive(const std::wstring& case_insensitive)\n{\n    if (boost::filesystem::exists(case_insensitive))\n        return case_insensitive;\n\n    return {};\n}\n\nstd::wstring clean_path(std::wstring path) { return path; }\n\nstd::wstring ensure_trailing_slash(std::wstring folder)\n{\n    auto last_char = folder.at(folder.length() - 1);\n    if (last_char != L'/' && last_char != L'\\\\')\n        folder.append(L\"/\");\n\n    return folder;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/windows/prec_timer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../stdafx.h\"\n\n#include \"../../prec_timer.h\"\n\n#include <chrono>\n\nusing namespace std::chrono;\n\nnamespace caspar {\n\nprec_timer::prec_timer()\n    : time_(0)\n{\n}\n\nvoid prec_timer::tick_nanos(int64_t ticks_to_wait)\n{\n    auto t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();\n\n    if (time_ != 0) {\n        bool done = false;\n        do {\n            auto ticks_passed = t - time_;\n            auto ticks_left   = ticks_to_wait - ticks_passed;\n\n            if (t < time_) // time wrap\n                done = true;\n            if (ticks_passed >= ticks_to_wait)\n                done = true;\n\n            if (!done) {\n                // if > 0.002s left, do Sleep(1), which will actually sleep some\n                //   steady amount, probably 1-2 ms,\n                //   and do so in a nice way (cpu meter drops; laptop battery spared).\n                // otherwise, do a few Sleep(0)'s, which just give up the timeslice,\n                //   but don't really save cpu or battery, but do pass a tiny\n                //   amount of time.\n                if (ticks_left > 2000000)\n                    Sleep(1);\n                else\n                    for (int i = 0; i < 10; ++i)\n                        Sleep(0); // causes thread to give up its timeslice\n            }\n\n            t = duration_cast<nanoseconds>(high_resolution_clock::now().time_since_epoch()).count();\n        } while (!done);\n    }\n\n    time_ = t;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/windows/thread.cpp",
    "content": "#include \"../thread.h\"\n\n#include <thread>\n\n#include <windows.h>\n\n#include \"../../utf.h\"\n\nnamespace caspar {\n\ntypedef struct tagTHREADNAME_INFO\n{\n    DWORD  dwType;     // must be 0x1000\n    LPCSTR szName;     // pointer to name (in user addr space)\n    DWORD  dwThreadID; // thread ID (-1=caller thread)\n    DWORD  dwFlags;    // reserved for future use, must be zero\n} THREADNAME_INFO;\n\ninline void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)\n{\n    THREADNAME_INFO info;\n    {\n        info.dwType     = 0x1000;\n        info.szName     = szThreadName;\n        info.dwThreadID = dwThreadID;\n        info.dwFlags    = 0;\n    }\n    __try {\n        RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);\n    } __except (EXCEPTION_CONTINUE_EXECUTION) {\n    }\n}\n\nvoid set_thread_name(const std::wstring& name) { SetThreadName(GetCurrentThreadId(), u8(name).c_str()); }\n\nvoid set_thread_realtime_priority() { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); }\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/os/windows/windows.h",
    "content": "#pragma once\n\n#undef _UNICODE\n#define _UNICODE\n#undef UNICODE\n#define UNICODE\n\n#undef NOMINMAX\n#define NOMINMAX\n\n#undef NOSERVICE\n#define NOSERVICE\n#undef NOMCX\n#define NOMCX\n\n#ifdef _MSC_VER\n#include <SDKDDKVer.h>\n#endif\n#ifndef _WIN32_WINNT\n#define _WIN32_WINNT _WIN32_WINNT_WIN7\n#endif\n\n#undef WIN32_LEAN_AND_MEAN\n#define WIN32_LEAN_AND_MEAN\n\n#include <windows.h>\n"
  },
  {
    "path": "src/common/param.h",
    "content": "#pragma once\n\n#include \"except.h\"\n\n#include <boost/algorithm/string.hpp>\n#include <boost/lexical_cast.hpp>\n\n#include <string>\n#include <type_traits>\n\nnamespace caspar {\n\nclass param_comparer\n{\n    const std::wstring& lhs;\n\n  public:\n    explicit param_comparer(const std::wstring& p)\n        : lhs(p)\n    {\n    }\n    bool operator()(const std::wstring& rhs) { return boost::iequals(lhs, rhs); }\n};\n\ntemplate <typename C>\nbool contains_param(const std::wstring& name, C&& params)\n{\n    return std::find_if(params.begin(), params.end(), param_comparer(name)) != params.end();\n}\n\ntemplate <typename C>\nbool get_and_consume_flag(const std::wstring& flag_param, C& params)\n{\n    auto flag_it = std::find_if(params.begin(), params.end(), param_comparer(flag_param));\n    bool flag    = false;\n\n    if (flag_it != params.end()) {\n        flag = true;\n        params.erase(flag_it);\n    }\n\n    return flag;\n}\n\ntemplate <typename C>\nvoid replace_placeholders(const std::wstring& placeholder, const std::wstring& replacement, C&& params)\n{\n    for (auto& param : params)\n        boost::ireplace_all(param, placeholder, replacement);\n}\n\nstatic std::pair<std::wstring, std::wstring> protocol_split(const std::wstring& s)\n{\n    size_t pos;\n    if ((pos = s.find(L\"://\")) != std::wstring::npos) {\n        return std::make_pair(s.substr(0, pos), s.substr(pos + 3));\n    }\n\n    return std::make_pair(L\"\", s);\n}\n\ntemplate <typename T, typename C>\ntypename std::enable_if<!std::is_convertible<T, std::wstring>::value, typename std::decay<T>::type>::type\nget_param(const std::wstring& name, C&& params, T fail_value = T())\n{\n    auto it = std::find_if(std::begin(params), std::end(params), param_comparer(name));\n    if (it == params.end())\n        return fail_value;\n\n    try {\n        if (++it == params.end())\n            throw std::out_of_range(\"\");\n\n        return boost::lexical_cast<typename std::decay<T>::type>(*it);\n    } catch (...) {\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Failed to parse param \" + name)\n                                            << nested_exception(std::current_exception()));\n    }\n}\n\ntemplate <typename C>\nstd::wstring get_param(const std::wstring& name, C&& params, const std::wstring& fail_value = L\"\")\n{\n    auto it = std::find_if(std::begin(params), std::end(params), param_comparer(name));\n    if (it == params.end())\n        return fail_value;\n\n    try {\n        if (++it == params.end())\n            throw std::out_of_range(\"\");\n\n        return *it;\n    } catch (...) {\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Failed to parse param \" + name)\n                                            << nested_exception(std::current_exception()));\n    }\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/prec_timer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <cstdint>\n\nnamespace caspar {\n\nclass prec_timer\n{\n  public:\n    prec_timer();\n\n    void tick(double interval) { tick_nanos(static_cast<int64_t>(interval * 1000000000.0)); }\n\n    void tick_millis(int64_t interval) { tick_nanos(interval * 1000000); }\n\n    // Author: Ryan M. Geiss\n    // http://www.geisswerks.com/ryan/FAQS/timing.html\n    void tick_nanos(int64_t interval);\n\n  private:\n    int64_t time_;\n};\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/ptree.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include \"except.h\"\n\n#include <boost/algorithm/string/replace.hpp>\n#include <boost/iterator/iterator_facade.hpp>\n#include <boost/property_tree/exceptions.hpp>\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n\n#include <map>\n\nnamespace caspar {\n\nstruct ptree_exception : virtual user_error\n{\n};\n\nstatic std::string to_xpath(std::string path)\n{\n    path.insert(path.begin(), '/');\n    boost::replace_all(path, \"<xmlattr>.\", \"@\");\n    boost::replace_all(path, \".\", \"/\");\n    return path;\n}\n\ntemplate <typename T, typename Ptree>\nT ptree_get(const Ptree& ptree, const typename Ptree::key_type& path)\n{\n    try {\n        return ptree.template get<T>(path);\n    } catch (boost::property_tree::ptree_bad_path&) {\n        CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info(\"No such element: \" + to_xpath(u8(path))));\n    } catch (const boost::property_tree::ptree_bad_data& e) {\n        CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info(e.what()));\n    }\n}\n\ntemplate <typename T, typename Ptree>\nT ptree_get_value(const Ptree& ptree)\n{\n    try {\n        return ptree.template get_value<T>();\n    } catch (const boost::property_tree::ptree_bad_data& e) {\n        CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info(e.what()));\n    }\n}\n\ntemplate <typename Ptree>\nconst Ptree& ptree_get_child(const Ptree& ptree, const typename Ptree::key_type& path)\n{\n    try {\n        return ptree.get_child(path);\n    } catch (boost::property_tree::ptree_bad_path&) {\n        CASPAR_THROW_EXCEPTION(ptree_exception() << msg_info(\"No such element: \" + to_xpath(u8(path))));\n    }\n}\n\ntemplate <typename Ptree>\nclass scope_aware_ptree_child_range\n{\n    const Ptree& child_;\n\n    using type = std::pair<const typename Ptree::key_type, Ptree>;\n\n  public:\n    class scoped_const_iterator\n        : public boost::iterator_facade<scoped_const_iterator, type const, boost::forward_traversal_tag>\n    {\n        typename Ptree::const_iterator wrapped_;\n\n      public:\n        explicit scoped_const_iterator(typename Ptree::const_iterator it)\n            : wrapped_(std::move(it))\n        {\n        }\n\n        void increment() { ++wrapped_; }\n\n        bool equal(const scoped_const_iterator& other) const { return wrapped_ == other.wrapped_; }\n\n        const type& dereference() const { return *wrapped_; }\n    };\n\n    using iterator       = scoped_const_iterator;\n    using const_iterator = scoped_const_iterator;\n\n    scope_aware_ptree_child_range(const Ptree& parent, const typename Ptree::key_type& path)\n        : child_(ptree_get_child(parent, path))\n    {\n    }\n\n    scoped_const_iterator begin() const { return scoped_const_iterator(child_.begin()); }\n\n    scoped_const_iterator end() const { return scoped_const_iterator(child_.end()); }\n};\n\ntemplate <typename Key>\nstruct iterate_children_tag\n{\n    Key val;\n\n    explicit iterate_children_tag(Key val_)\n        : val(std::move(val_))\n    {\n    }\n};\n\nusing witerate_children = iterate_children_tag<std::wstring>;\nusing iterate_children  = iterate_children_tag<std::string>;\n\ntemplate <typename Ptree>\nscope_aware_ptree_child_range<Ptree> operator|(const Ptree& ptree, iterate_children_tag<typename Ptree::key_type> path)\n{\n    return scope_aware_ptree_child_range<Ptree>(ptree, path.val);\n}\n\ntemplate <typename Ptree>\nstruct basic_scoped_element_translator\n{\n    mutable std::map<typename Ptree::key_type, int> by_name;\n\n    using result_type = const std::pair<const typename Ptree::key_type, Ptree>&;\n\n    result_type operator()(result_type pair) const { return pair; }\n};\n\ntemplate <typename Ptree>\nstruct element_context_iteration_tag\n{\n};\nstatic element_context_iteration_tag<boost::property_tree::wptree> welement_context_iteration;\nstatic element_context_iteration_tag<boost::property_tree::ptree>  element_context_iteration;\n\ntemplate <typename Range, typename Ptree>\nauto operator|(const Range& rng, element_context_iteration_tag<Ptree> tag)\n    -> decltype(rng | boost::adaptors::transformed(basic_scoped_element_translator<Ptree>()))\n{\n    return rng | boost::adaptors::transformed(basic_scoped_element_translator<Ptree>());\n}\n\ntemplate <typename Key, typename Ptree, typename Str>\nvoid ptree_verify_element_name(const std::pair<const Key, Ptree>& elem, const Str& expected)\n{\n    if (elem.first != expected)\n        CASPAR_THROW_EXCEPTION(ptree_exception()\n                               << msg_info(\"Expected element named \" + u8(expected) + \". Was \" + u8(elem.first)));\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/scope_exit.h",
    "content": "#pragma once\n\n#include \"except.h\"\n\nnamespace caspar {\n\nnamespace detail {\ntemplate <typename T>\nclass scope_exit\n{\n    scope_exit(const scope_exit&);\n    scope_exit& operator=(const scope_exit&);\n\n  public:\n    template <typename T2>\n    explicit scope_exit(T2&& func)\n        : func_(std::forward<T2>(func))\n        , valid_(true)\n    {\n    }\n\n    scope_exit(scope_exit&& other)\n        : func_(std::move(other.func_))\n        , valid_(std::move(other.valid_))\n    {\n        other.valid_ = false;\n    }\n\n    scope_exit& operator=(scope_exit&& other)\n    {\n        func_  = std::move(other.func_);\n        valid_ = std::move(other.valid_);\n\n        other.valid_ = false;\n\n        return *this;\n    }\n\n    ~scope_exit()\n    {\n        try {\n            if (valid_)\n                func_();\n        } catch (...) {\n            if (!std::uncaught_exceptions())\n#pragma warning(push)\n#pragma warning(disable : 4297)\n                throw;\n#pragma warning(pop)\n            else\n                CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n    }\n\n  private:\n    T    func_;\n    bool valid_;\n};\n\nclass scope_exit_helper\n{\n};\n\ntemplate <typename T>\nscope_exit<typename std::decay<T>::type> operator+(scope_exit_helper /*unused*/, T&& exitScope)\n{\n    return scope_exit<typename std::decay<T>::type>(std::forward<T>(exitScope));\n}\n} // namespace detail\n\n#define _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line) name##line\n#define _CASPAR_EXIT_SCOPE_LINENAME(name, line) _CASPAR_EXIT_SCOPE_LINENAME_CAT(name, line)\n#define CASPAR_SCOPE_EXIT                                                                                              \\\n    auto _CASPAR_EXIT_SCOPE_LINENAME(EXIT, __LINE__) = ::caspar::detail::scope_exit_helper() + [&]() mutable\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/stdafx.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"stdafx.h\"\n"
  },
  {
    "path": "src/common/stdafx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include <algorithm>\n#include <atomic>\n// #include <boost/algorithm/string.hpp>\n// #include <boost/algorithm/string/replace.hpp>\n// #include <boost/any.hpp>\n// #include <boost/archive/iterators/base64_from_binary.hpp>\n// #include <boost/archive/iterators/binary_from_base64.hpp>\n// #include <boost/archive/iterators/insert_linebreaks.hpp>\n// #include <boost/archive/iterators/remove_whitespace.hpp>\n// #include <boost/archive/iterators/transform_width.hpp>\n#include <boost/core/null_deleter.hpp>\n#include <boost/date_time/posix_time/posix_time.hpp>\n#include <boost/exception/all.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/filesystem/fstream.hpp>\n#include <boost/filesystem/operations.hpp>\n#include <boost/filesystem/path.hpp>\n// #include <boost/function.hpp>\n// #include <boost/iterator/iterator_facade.hpp>\n// #include <boost/lambda/lambda.hpp>\n// #include <boost/lexical_cast.hpp>\n// #include <boost/locale.hpp>\n// #include <boost/log/attributes/attribute_value.hpp>\n// #include <boost/log/attributes/function.hpp>\n// #include <boost/log/core.hpp>\n// #include <boost/log/core/record.hpp>\n// #include <boost/log/expressions.hpp>\n// #include <boost/log/sinks/async_frontend.hpp>\n// #include <boost/log/sinks/sync_frontend.hpp>\n// #include <boost/log/sinks/text_file_backend.hpp>\n// #include <boost/log/sinks/text_ostream_backend.hpp>\n// #include <boost/log/sources/global_logger_storage.hpp>\n// #include <boost/log/sources/severity_channel_logger.hpp>\n// #include <boost/log/trivial.hpp>\n// #include <boost/log/utility/setup/common_attributes.hpp>\n#include <GL/glew.h>\n#include <boost/make_shared.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <boost/property_tree/xml_parser.hpp>\n#include <boost/range/adaptor/sliced.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n#include <boost/range/join.hpp>\n#include <boost/regex.hpp>\n#include <boost/shared_ptr.hpp>\n#include <boost/thread.hpp>\n#include <boost/throw_exception.hpp>\n#include <cmath>\n#include <cstddef>\n#include <cstdint>\n#include <cstring>\n#include <ctime>\n#include <exception>\n#include <fstream>\n#include <functional>\n#include <future>\n#include <initializer_list>\n#include <iomanip>\n#include <ios>\n#include <iostream>\n#include <list>\n#include <locale>\n#include <map>\n#include <memory>\n#include <mutex>\n#include <optional>\n#include <ostream>\n#include <stdexcept>\n#include <string>\n#include <tbb/concurrent_queue.h>\n#include <tuple>\n#include <type_traits>\n#include <unordered_map>\n#include <vector>\n"
  },
  {
    "path": "src/common/timer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <chrono>\n\nnamespace caspar {\n\nclass timer\n{\n    std::int_least64_t start_time_;\n\n  public:\n    timer() { start_time_ = now(); }\n\n    void restart() { start_time_ = now(); }\n\n    double elapsed() const { return static_cast<double>(now() - start_time_) / 1000.0; }\n\n  private:\n    static std::int_least64_t now()\n    {\n        using namespace std::chrono;\n\n        return duration_cast<milliseconds>(high_resolution_clock::now().time_since_epoch()).count();\n    }\n};\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/tweener.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n// The following code is based on Tweener for actionscript, http://code.google.com/p/tweener/\n//\n// Disclaimer for Robert Penner's Easing Equations license:\n//\n// TERMS OF USE - EASING EQUATIONS\n//\n// Open source under the BSD License.\n//\n// Copyright � 2001 Robert Penner\n// All rights reserved.\n//\n// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the\n// following conditions are met:\n//\n//    * Redistributions of source code must retain the above copyright notice, this list of conditions and the following\n//    disclaimer.\n//    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the\n//    following disclaimer in the documentation and/or other materials provided with the distribution.\n//    * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived\n//    from this software without specific prior written permission.\n//\n// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES,\n// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\n// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#include \"tweener.h\"\n\n#include \"except.h\"\n\n#include <boost/regex.hpp>\n\n#include <algorithm>\n#include <cmath>\n#include <functional>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\nnamespace caspar {\n\nusing tweener_t = std::function<double(double, double, double, double)>;\n\nstatic const double PI   = std::atan(1.0) * 4.0;\nstatic const double H_PI = std::atan(1.0) * 2.0;\n\ndouble ease_none(double t, double b, double c, double d, const std::vector<double>& params) { return c * t / d + b; }\n\ndouble ease_in_quad(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    return c * t * t + b;\n}\n\ndouble ease_out_quad(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    return -c * t * (t - 2) + b;\n}\n\ndouble ease_in_out_quad(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d / 2;\n    if (t < 1)\n        return c / 2 * t * t + b;\n\n    return -c / 2 * ((t - 1) * (t - 3) - 1) + b;\n}\n\ndouble ease_out_in_quad(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_quad(t * 2, b, c / 2, d, params);\n\n    return ease_in_quad(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_cubic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    return c * t * t * t + b;\n}\n\ndouble ease_out_cubic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t = t / d - 1;\n    return c * (t * t * t + 1) + b;\n}\n\ndouble ease_in_out_cubic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d / 2;\n    if (t < 1)\n        return c / 2 * t * t * t + b;\n\n    t -= 2;\n    return c / 2 * (t * t * t + 2) + b;\n}\n\ndouble ease_out_in_cubic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_cubic(t * 2, b, c / 2, d, params);\n    return ease_in_cubic(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_quart(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    return c * t * t * t * t + b;\n}\n\ndouble ease_out_quart(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t = t / d - 1;\n    return -c * (t * t * t * t - 1) + b;\n}\n\ndouble ease_in_out_quart(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d / 2;\n    if (t < 1)\n        return c / 2 * t * t * t * t + b;\n\n    t -= 2;\n    return -c / 2 * (t * t * t * t - 2) + b;\n}\n\ndouble ease_out_in_quart(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_quart(t * 2, b, c / 2, d, params);\n\n    return ease_in_quart(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_quint(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    return c * t * t * t * t * t + b;\n}\n\ndouble ease_out_quint(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t = t / d - 1;\n    return c * (t * t * t * t * t + 1) + b;\n}\n\ndouble ease_in_out_quint(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d / 2;\n    if (t < 1)\n        return c / 2 * t * t * t * t * t + b;\n\n    t -= 2;\n    return c / 2 * (t * t * t * t * t + 2) + b;\n}\n\ndouble ease_out_in_quint(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_quint(t * 2, b, c / 2, d, params);\n\n    return ease_in_quint(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_sine(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    return -c * std::cos(t / d * (PI / 2)) + c + b;\n}\n\ndouble ease_out_sine(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    return c * std::sin(t / d * (PI / 2)) + b;\n}\n\ndouble ease_in_out_sine(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    return -c / 2 * (std::cos(PI * t / d) - 1) + b;\n}\n\ndouble ease_out_in_sine(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_sine(t * 2, b, c / 2, d, params);\n\n    return ease_in_sine(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_expo(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    return t == 0 ? b : c * std::pow(2, 10 * (t / d - 1)) + b - c * 0.001;\n}\n\ndouble ease_out_expo(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    return t == d ? b + c : c * 1.001 * (-std::pow(2, -10 * t / d) + 1) + b;\n}\n\ndouble ease_in_out_expo(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t == 0)\n        return b;\n    if (t == d)\n        return b + c;\n    t /= d / 2;\n    if (t < 1)\n        return c / 2 * std::pow(2, 10 * (t - 1)) + b - c * 0.0005;\n\n    return c / 2 * 1.0005 * (-std::pow(2, -10 * (t - 1)) + 2) + b;\n}\n\ndouble ease_out_in_expo(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_expo(t * 2, b, c / 2, d, params);\n\n    return ease_in_expo(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_circ(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    return -c * (std::sqrt(1 - t * t) - 1) + b;\n}\n\ndouble ease_out_circ(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t = t / d - 1;\n    return c * std::sqrt(1 - t * t) + b;\n}\n\ndouble ease_in_out_circ(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d / 2;\n    if (t < 1)\n        return -c / 2 * (std::sqrt(1 - t * t) - 1) + b;\n\n    t -= 2;\n    return c / 2 * (std::sqrt(1 - t * t) + 1) + b;\n}\n\ndouble ease_out_in_circ(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_circ(t * 2, b, c / 2, d, params);\n    return ease_in_circ(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_elastic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t == 0)\n        return b;\n    t /= d;\n    if (t == 1)\n        return b + c;\n    // var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;\n    // var s:Number;\n    // var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;\n    double p = !params.empty() ? params[0] : d * 0.3;\n    double s;\n    double a = params.size() > 1 ? params[1] : 0.0;\n    if (a == 0.0 || a < std::abs(c)) {\n        a = c;\n        s = p / 4;\n    } else\n        s = p / (2 * PI) * std::asin(c / a);\n\n    t--;\n    return -(a * std::pow(2, 10 * t) * std::sin((t * d - s) * (2 * PI) / p)) + b;\n}\n\ndouble ease_out_elastic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t == 0)\n        return b;\n    t /= d;\n    if (t == 1)\n        return b + c;\n    // var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*.3 : p_params.period;\n    // var s:Number;\n    // var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;\n    double p = !params.empty() ? params[0] : d * 0.3;\n    double s;\n    double a = params.size() > 1 ? params[1] : 0.0;\n    if (a == 0.0 || a < std::abs(c)) {\n        a = c;\n        s = p / 4;\n    } else\n        s = p / (2 * PI) * std::asin(c / a);\n\n    return a * std::pow(2, -10 * t) * std::sin((t * d - s) * (2 * PI) / p) + c + b;\n}\n\ndouble ease_in_out_elastic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t == 0)\n        return b;\n    t /= d / 2;\n    if (t == 2)\n        return b + c;\n    // var p:Number = !Boolean(p_params) || isNaN(p_params.period) ? d*(.3*1.5) : p_params.period;\n    // var s:Number;\n    // var a:Number = !Boolean(p_params) || isNaN(p_params.amplitude) ? 0 : p_params.amplitude;\n    double p = !params.empty() ? params[0] : d * 0.3 * 1.5;\n    double s;\n    double a = params.size() > 1 ? params[1] : 0.0;\n    if (a == 0.0 || a < std::abs(c)) {\n        a = c;\n        s = p / 4;\n    } else\n        s = p / (2 * PI) * std::asin(c / a);\n\n    if (t-- < 1) {\n        return -.5 * (a * std::pow(2, 10 * t) * std::sin((t * d - s) * (2 * PI) / p)) + b;\n    }\n    return a * std::pow(2, -10 * t) * std::sin((t * d - s) * (2 * PI) / p) * .5 + c + b;\n}\n\ndouble ease_out_in_elastic(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_elastic(t * 2, b, c / 2, d, params);\n    return ease_in_elastic(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_in_back(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    // var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;\n    double s = !params.empty() ? params[0] : 1.70158;\n    t /= d;\n    return c * t * t * ((s + 1) * t - s) + b;\n}\n\ndouble ease_out_back(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    // var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;\n    double s = !params.empty() ? params[0] : 1.70158;\n    t        = t / d - 1;\n    return c * (t * t * ((s + 1) * t + s) + 1) + b;\n}\n\ndouble ease_in_out_back(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    // var s:Number = !Boolean(p_params) || isNaN(p_params.overshoot) ? 1.70158 : p_params.overshoot;\n    double s = !params.empty() ? params[0] : 1.70158;\n    t /= d / 2;\n    s *= 1.525;\n    if (t < 1)\n        return c / 2 * (t * t * ((s + 1) * t - s)) + b;\n    t -= 2;\n    return c / 2 * (t * t * ((s + 1) * t + s) + 2) + b;\n}\n\ndouble ease_out_int_back(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_back(t * 2, b, c / 2, d, params);\n    return ease_in_back(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\ndouble ease_out_bounce(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    t /= d;\n    if (t < 1 / 2.75)\n        return c * (7.5625 * t * t) + b;\n    if (t < 2 / 2.75) {\n        t -= 1.5 / 2.75;\n        return c * (7.5625 * t * t + .75) + b;\n    }\n    if (t < 2.5 / 2.75) {\n        t -= 2.25 / 2.75;\n        return c * (7.5625 * t * t + .9375) + b;\n    }\n    t -= 2.625 / 2.75;\n    return c * (7.5625 * t * t + .984375) + b;\n}\n\ndouble ease_in_bounce(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    return c - ease_out_bounce(d - t, 0, c, d, params) + b;\n}\n\ndouble ease_in_out_bounce(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_in_bounce(t * 2, 0, c, d, params) * .5 + b;\n    return ease_out_bounce(t * 2 - d, 0, c, d, params) * .5 + c * .5 + b;\n}\n\ndouble ease_out_in_bounce(double t, double b, double c, double d, const std::vector<double>& params)\n{\n    if (t < d / 2)\n        return ease_out_bounce(t * 2, b, c / 2, d, params);\n    return ease_in_bounce(t * 2 - d, b + c / 2, c / 2, d, params);\n}\n\nusing tween_t = std::function<double(double, double, double, double, const std::vector<double>&)>;\n\nconst std::unordered_map<std::wstring, tween_t>& get_tweens()\n{\n    static const std::unordered_map<std::wstring, tween_t> tweens = {{L\"\", ease_none},\n                                                                     {L\"linear\", ease_none},\n                                                                     {L\"easenone\", ease_none},\n                                                                     {L\"easeinquad\", ease_in_quad},\n                                                                     {L\"easeoutquad\", ease_out_quad},\n                                                                     {L\"easeinoutquad\", ease_in_out_quad},\n                                                                     {L\"easeoutinquad\", ease_out_in_quad},\n                                                                     {L\"easeincubic\", ease_in_cubic},\n                                                                     {L\"easeoutcubic\", ease_out_cubic},\n                                                                     {L\"easeinoutcubic\", ease_in_out_cubic},\n                                                                     {L\"easeoutincubic\", ease_out_in_cubic},\n                                                                     {L\"easeinquart\", ease_in_quart},\n                                                                     {L\"easeoutquart\", ease_out_quart},\n                                                                     {L\"easeinoutquart\", ease_in_out_quart},\n                                                                     {L\"easeoutinquart\", ease_out_in_quart},\n                                                                     {L\"easeinquint\", ease_in_quint},\n                                                                     {L\"easeoutquint\", ease_out_quint},\n                                                                     {L\"easeinoutquint\", ease_in_out_quint},\n                                                                     {L\"easeoutinquint\", ease_out_in_quint},\n                                                                     {L\"easeinsine\", ease_in_sine},\n                                                                     {L\"easeoutsine\", ease_out_sine},\n                                                                     {L\"easeinoutsine\", ease_in_out_sine},\n                                                                     {L\"easeoutinsine\", ease_out_in_sine},\n                                                                     {L\"easeinexpo\", ease_in_expo},\n                                                                     {L\"easeoutexpo\", ease_out_expo},\n                                                                     {L\"easeinoutexpo\", ease_in_out_expo},\n                                                                     {L\"easeoutinexpo\", ease_out_in_expo},\n                                                                     {L\"easeincirc\", ease_in_circ},\n                                                                     {L\"easeoutcirc\", ease_out_circ},\n                                                                     {L\"easeinoutcirc\", ease_in_out_circ},\n                                                                     {L\"easeoutincirc\", ease_out_in_circ},\n                                                                     {L\"easeinelastic\", ease_in_elastic},\n                                                                     {L\"easeoutelastic\", ease_out_elastic},\n                                                                     {L\"easeinoutelastic\", ease_in_out_elastic},\n                                                                     {L\"easeoutinelastic\", ease_out_in_elastic},\n                                                                     {L\"easeinback\", ease_in_back},\n                                                                     {L\"easeoutback\", ease_out_back},\n                                                                     {L\"easeinoutback\", ease_in_out_back},\n                                                                     {L\"easeoutintback\", ease_out_int_back},\n                                                                     {L\"easeoutbounce\", ease_out_bounce},\n                                                                     {L\"easeinbounce\", ease_in_bounce},\n                                                                     {L\"easeinoutbounce\", ease_in_out_bounce},\n                                                                     {L\"easeoutinbounce\", ease_out_in_bounce}};\n\n    return tweens;\n}\n\ntweener_t get_tweener(std::wstring name)\n{\n    std::transform(name.begin(), name.end(), name.begin(), std::towlower);\n\n    if (name == L\"linear\")\n        return [](double t, double b, double c, double d) { return ease_none(t, b, c, d, std::vector<double>()); };\n\n    std::vector<double> params;\n\n    static const boost::wregex expr(\n        LR\"((?<NAME>\\w*)(:(?<V0>\\d+\\.?\\d?))?(:(?<V1>\\d+\\.?\\d?))?)\"); // boost::regex has no repeated captures?\n    boost::wsmatch what;\n    if (boost::regex_match(name, what, expr)) {\n        name = what[\"NAME\"].str();\n        if (what[\"V0\"].matched)\n            params.push_back(std::stod(what[\"V0\"].str()));\n        if (what[\"V1\"].matched)\n            params.push_back(std::stod(what[\"V1\"].str()));\n    }\n\n    auto it = get_tweens().find(name);\n    if (it == get_tweens().end())\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Could not find tween \" + name));\n\n    auto tween = it->second;\n    return [=](double t, double b, double c, double d) { return tween(t, b, c, d, params); };\n};\n\ntweener::tweener(const std::wstring& name)\n    : func_(get_tweener(name))\n    , name_(name)\n{\n}\n\ndouble tweener::operator()(double t, double b, double c, double d) const { return func_(t, b, c, d); }\n\nbool tweener::operator==(const tweener& other) const { return name_ == other.name_; }\n\nbool tweener::operator!=(const tweener& other) const { return !(*this == other); }\n\nconst std::vector<std::wstring>& tweener::names()\n{\n    static auto result = [] {\n        std::vector<std::wstring> tweens;\n\n        for (auto& tween : get_tweens())\n            tweens.push_back(tween.first);\n\n        return tweens;\n    }();\n    return result;\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/tweener.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <functional>\n#include <string>\n#include <vector>\n\nnamespace caspar {\n\n/**\n * A tweener can be used for creating any kind of (image position, image fade\n * in/out, audio volume etc) transition, by invoking it for each temporal\n * timepoint when a tweened value is needed.\n *\n * For audio the smoothest transitions will be generated by using the samplerate\n * as temporal resolution, but using the video frame/field rate is probably fine\n * most of the times and much less time consuming.\n */\nclass tweener\n{\n  public:\n    /**\n     * Constructor.\n     *\n     * @param name The name of the tween function to use.\n     */\n    tweener(const std::wstring& name = L\"linear\");\n\n    /**\n     * @return The possible tween function names. Some of them may also support\n     * \t\t   additional parameters appended to the name.\n     */\n    static const std::vector<std::wstring>& names();\n\n    /**\n     * Calculate a tweened value given a timepoint within the total duration\n     * and the starting value and the destination delta value.\n     *\n     * Usually b, c and d remains constant during a transition, while t changes\n     * for each temporal tweened value.\n     *\n     * @param t\tThe timepoint within the total duration (0 <= n <= d).\n     * @param b\tThe starting value.\n     * @param c\tThe destination value delta from the starting value\n     * \t        (absolute destination value - b).\n     * @param d The total duration (when t = d, the destination value should\n     * \t        have been reached).\n     *\n     * @return The tweened value for the given timepoint. Can sometimes be less\n     * \t       than b or greater than b + c for some tweener functions.\n     */\n    double operator()(double t, double b, double c, double d) const;\n\n    bool operator==(const tweener& other) const;\n    bool operator!=(const tweener& other) const;\n\n  private:\n    std::function<double(double, double, double, double)> func_;\n    std::wstring                                          name_;\n};\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/utf.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"utf.h\"\n\n#include <boost/locale.hpp>\n\nnamespace caspar {\n\nstd::wstring u16(const std::string& str)\n{\n    return boost::locale::conv::utf_to_utf<wchar_t>(str); // std::wstring(str.begin(), str.end());\n}\n\nstd::wstring u16(const std::wstring& str) { return str; }\n\nstd::string u8(const std::wstring& str)\n{\n    return boost::locale::conv::utf_to_utf<char>(str); // std::string(str.begin(), str.end());\n}\n\nstd::string u8(const std::string& str) { return str; }\n\n} // namespace caspar\n"
  },
  {
    "path": "src/common/utf.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <string>\n\nnamespace caspar {\n\nstd::wstring u16(const std::string& str);\nstd::wstring u16(const std::wstring& str);\nstd::string  u8(const std::wstring& str);\nstd::string  u8(const std::string& str);\n\n} // namespace caspar"
  },
  {
    "path": "src/core/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (core)\n\nset(SOURCES\n\t\tconsumer/frame_consumer.cpp\n\t\tconsumer/frame_consumer_registry.cpp\n\t\tconsumer/output.cpp\n\n\t\tdiagnostics/call_context.cpp\n\t\tdiagnostics/osd_graph.cpp\n\n\t\tframe/draw_frame.cpp\n\t\tframe/frame.cpp\n\t\tframe/frame_transform.cpp\n\t\tframe/geometry.cpp\n\n\t\tmixer/audio/audio_mixer.cpp\n\t\tmixer/image/blend_modes.cpp\n\t\tmixer/mixer.cpp\n\n\t\tproducer/color/color_producer.cpp\n\t\tproducer/separated/separated_producer.cpp\n\t\tproducer/transition/transition_producer.cpp\n\t\tproducer/transition/sting_producer.cpp\n\t\tproducer/route/route_producer.cpp\n\n\t\tproducer/cg_proxy.cpp\n\t\tproducer/frame_producer.cpp\n\t\tproducer/frame_producer_registry.cpp\n\t\tproducer/layer.cpp\n\t\tproducer/stage.cpp\n\n\t\tvideo_channel.cpp\n\t\tvideo_format.cpp\n)\nset(HEADERS\n\t\tconsumer/frame_consumer.h\n\t\tconsumer/frame_consumer_registry.h\n\t\tconsumer/output.h\n\n\t\tdiagnostics/call_context.h\n\t\tdiagnostics/osd_graph.h\n\n\t\tframe/draw_frame.h\n\t\tframe/frame.h\n\t\tframe/frame_factory.h\n\t\tframe/frame_transform.h\n\t\tframe/frame_visitor.h\n\t\tframe/geometry.h\n\t\tframe/pixel_format.h\n\n\t\tmixer/audio/audio_mixer.h\n\n\t\tmixer/image/blend_modes.h\n\t\tmixer/image/image_mixer.h\n\n\t\tmixer/mixer.h\n\n\t\tmonitor/monitor.h\n\n\t\tproducer/color/color_producer.h\n\t\tproducer/separated/separated_producer.h\n\t\tproducer/transition/transition_producer.h\n\t\tproducer/transition/sting_producer.h\n\t\tproducer/route/route_producer.h\n\n\t\tproducer/cg_proxy.h\n\t\tproducer/frame_producer.h\n\t\tproducer/frame_producer_registry.h\n\t\tproducer/layer.h\n\t\tproducer/stage.h\n\n\t\tfwd.h\n\t\tmodule_dependencies.h\n\t\tStdAfx.h\n\t\tvideo_channel.h\n\t\tvideo_format.h\n\t\tconsumer/channel_info.h\n)\n\ncasparcg_add_library(core SOURCES ${SOURCES} ${HEADERS})\ntarget_include_directories(core PRIVATE ..)\ntarget_precompile_headers(core PRIVATE StdAfx.h)\ntarget_link_libraries(core PRIVATE common GLEW::glew sfml-graphics)\n\nsource_group(sources ./*)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources\\\\diagnostics diagnostics/*)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources\\\\monitor monitor/*)\nsource_group(sources\\\\frame frame/*)\nsource_group(sources\\\\mixer mixer/*)\nsource_group(sources\\\\mixer\\\\audio mixer/audio/*)\nsource_group(sources\\\\mixer\\\\image mixer/image/*)\nsource_group(sources\\\\producer\\\\color producer/color/*)\nsource_group(sources\\\\producer\\\\route producer/route/*)\nsource_group(sources\\\\producer\\\\transition producer/transition/*)\nsource_group(sources\\\\producer\\\\separated producer/separated/*)\n"
  },
  {
    "path": "src/core/StdAfx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include <common/compiler/vs/disable_silly_warnings.h>\n\n#include <GL/glew.h>\n#include <SFML/Graphics.hpp>\n#include <algorithm>\n#include <atomic>\n#include <boost/algorithm/string.hpp>\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/circular_buffer.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/lexical_cast.hpp>\n#include <boost/range/adaptors.hpp>\n#include <boost/range/algorithm.hpp>\n#include <boost/range/algorithm/equal.hpp>\n#include <boost/range/distance.hpp>\n#include <boost/range/iterator_range.hpp>\n#include <boost/rational.hpp>\n#include <boost/variant.hpp>\n#include <common/array.h>\n#include <common/assert.h>\n#include <common/diagnostics/graph.h>\n#include <common/enum_class.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/future.h>\n#include <common/log.h>\n#include <common/memory.h>\n#include <common/memshfl.h>\n#include <common/os/filesystem.h>\n#include <common/prec_timer.h>\n#include <common/timer.h>\n#include <common/tweener.h>\n#include <cstddef>\n#include <cstdint>\n#include <functional>\n#include <future>\n#include <list>\n#include <map>\n#include <memory>\n#include <mutex>\n#include <numeric>\n#include <optional>\n#include <queue>\n#include <set>\n#include <sstream>\n#include <stack>\n#include <string>\n#include <tbb/concurrent_queue.h>\n#include <tbb/concurrent_unordered_map.h>\n#include <tuple>\n#include <type_traits>\n#include <unordered_map>\n#include <vector>\n"
  },
  {
    "path": "src/core/consumer/channel_info.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include \"../frame/pixel_format.h\"\n#include \"common/bit_depth.h\"\n\nnamespace caspar::core {\n\nstruct channel_info\n{\n    channel_info(int channel_index, common::bit_depth depth, color_space color_space)\n        : index(channel_index)\n        , depth(depth)\n        , default_color_space(color_space)\n    {\n    }\n\n    int               index;\n    common::bit_depth depth;\n    color_space       default_color_space;\n};\n\n} // namespace caspar::core\n"
  },
  {
    "path": "src/core/consumer/frame_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"frame_consumer.h\"\n\n#include <common/future.h>\n\n#include <core/frame/frame.h>\n#include <core/video_format.h>\n\n#include <future>\n\nnamespace caspar { namespace core {\n\nconst spl::shared_ptr<frame_consumer>& frame_consumer::empty()\n{\n    class empty_frame_consumer : public frame_consumer\n    {\n      public:\n        std::future<bool> send(const core::video_field field, const_frame) override { return make_ready_future(false); }\n        void              initialize(const video_format_desc&, const core::channel_info&, int port_index) override {}\n        std::wstring      print() const override { return L\"empty\"; }\n        std::wstring      name() const override { return L\"empty\"; }\n        bool              has_synchronization_clock() const override { return false; }\n        int               index() const override { return -1; }\n        core::monitor::state state() const override\n        {\n            static const monitor::state empty;\n            return empty;\n        }\n    };\n    static spl::shared_ptr<frame_consumer> consumer = spl::make_shared<empty_frame_consumer>();\n    return consumer;\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/consumer/frame_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <common/future.h>\n#include <core/video_format.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <functional>\n#include <future>\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nclass frame_consumer\n{\n    frame_consumer(const frame_consumer&);\n    frame_consumer& operator=(const frame_consumer&);\n\n  public:\n    static const spl::shared_ptr<frame_consumer>& empty();\n\n    frame_consumer() {}\n    virtual ~frame_consumer() {}\n\n    virtual std::future<bool> send(const core::video_field field, const_frame frame) = 0;\n    virtual void\n    initialize(const video_format_desc& format_desc, const core::channel_info& channel_info, int port_index) = 0;\n    virtual std::future<bool> call(const std::vector<std::wstring>& params) { return caspar::make_ready_future(false); }\n\n    virtual core::monitor::state state() const = 0;\n\n    virtual std::wstring print() const = 0;\n    virtual std::wstring name() const  = 0;\n    virtual bool         has_synchronization_clock() const { return false; }\n    virtual int          index() const = 0;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/consumer/frame_consumer_registry.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"frame_consumer.h\"\n#include \"frame_consumer_registry.h\"\n\n#include <core/frame/frame.h>\n\n#include <boost/circular_buffer.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <future>\n#include <map>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nstd::atomic<bool>& destroy_consumers_in_separate_thread()\n{\n    static std::atomic<bool> state;\n\n    return state;\n}\n\nvoid destroy_consumers_synchronously() { destroy_consumers_in_separate_thread() = false; }\n\nclass destroy_consumer_proxy : public frame_consumer\n{\n    std::shared_ptr<frame_consumer> consumer_;\n\n  public:\n    destroy_consumer_proxy(spl::shared_ptr<frame_consumer>&& consumer)\n        : consumer_(std::move(consumer))\n    {\n        destroy_consumers_in_separate_thread() = true;\n    }\n\n    ~destroy_consumer_proxy()\n    {\n        static std::atomic<int> counter;\n        static std::once_flag   counter_init_once;\n        std::call_once(counter_init_once, [] { counter = 0; });\n\n        if (!destroy_consumers_in_separate_thread())\n            return;\n\n        ++counter;\n        CASPAR_VERIFY(counter < 8);\n\n        auto consumer = new std::shared_ptr<frame_consumer>(std::move(consumer_));\n        std::thread([=] {\n            std::unique_ptr<std::shared_ptr<frame_consumer>> pointer_guard(consumer);\n            auto                                             str = (*consumer)->print();\n\n            try {\n                if (consumer->use_count() != 1)\n                    CASPAR_LOG(debug) << str << L\" Not destroyed on asynchronous destruction thread: \"\n                                      << consumer->use_count();\n                else\n                    CASPAR_LOG(debug) << str << L\" Destroying on asynchronous destruction thread.\";\n            } catch (...) {\n            }\n\n            pointer_guard.reset();\n            counter--;\n        }).detach();\n    }\n\n    std::future<bool> send(const core::video_field field, const_frame frame) override\n    {\n        return consumer_->send(field, std::move(frame));\n    }\n    void\n    initialize(const video_format_desc& format_desc, const core::channel_info& channel_info, int port_index) override\n    {\n        return consumer_->initialize(format_desc, channel_info, port_index);\n    }\n    std::future<bool>    call(const std::vector<std::wstring>& params) override { return consumer_->call(params); }\n    std::wstring         print() const override { return consumer_->print(); }\n    std::wstring         name() const override { return consumer_->name(); }\n    bool                 has_synchronization_clock() const override { return consumer_->has_synchronization_clock(); }\n    int                  index() const override { return consumer_->index(); }\n    core::monitor::state state() const override { return consumer_->state(); }\n};\n\nclass print_consumer_proxy : public frame_consumer\n{\n    std::shared_ptr<frame_consumer> consumer_;\n\n  public:\n    print_consumer_proxy(spl::shared_ptr<frame_consumer>&& consumer)\n        : consumer_(std::move(consumer))\n    {\n    }\n\n    ~print_consumer_proxy()\n    {\n        auto str = consumer_->print();\n        CASPAR_LOG(debug) << str << L\" Uninitializing.\";\n        consumer_.reset();\n        CASPAR_LOG(info) << str << L\" Uninitialized.\";\n    }\n\n    std::future<bool> send(const core::video_field field, const_frame frame) override\n    {\n        return consumer_->send(field, std::move(frame));\n    }\n    void\n    initialize(const video_format_desc& format_desc, const core::channel_info& channel_info, int port_index) override\n    {\n        consumer_->initialize(format_desc, channel_info, port_index);\n        CASPAR_LOG(info) << consumer_->print() << L\" Initialized.\";\n    }\n    std::future<bool>    call(const std::vector<std::wstring>& params) override { return consumer_->call(params); }\n    std::wstring         print() const override { return consumer_->print(); }\n    std::wstring         name() const override { return consumer_->name(); }\n    bool                 has_synchronization_clock() const override { return consumer_->has_synchronization_clock(); }\n    int                  index() const override { return consumer_->index(); }\n    core::monitor::state state() const override { return consumer_->state(); }\n};\n\nframe_consumer_registry::frame_consumer_registry() {}\n\nvoid frame_consumer_registry::register_consumer_factory(const std::wstring& name, const consumer_factory_t& factory)\n{\n    consumer_factories_.push_back(factory);\n}\n\nvoid frame_consumer_registry::register_preconfigured_consumer_factory(const std::wstring& element_name,\n                                                                      const preconfigured_consumer_factory_t& factory)\n{\n    preconfigured_consumer_factories_.insert(std::make_pair(element_name, factory));\n}\n\nspl::shared_ptr<core::frame_consumer>\nframe_consumer_registry::create_consumer(const std::vector<std::wstring>&                         params,\n                                         const core::video_format_repository&                     format_repository,\n                                         const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                         const core::channel_info&                                channel_info) const\n{\n    if (params.empty())\n        CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(\"params cannot be empty\"));\n\n    auto  consumer           = frame_consumer::empty();\n    auto& consumer_factories = consumer_factories_;\n    if (!std::any_of(\n            consumer_factories.begin(), consumer_factories.end(), [&](const consumer_factory_t& factory) -> bool {\n                try {\n                    consumer = factory(params, format_repository, channels, channel_info);\n                } catch (...) {\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n                }\n                return consumer != frame_consumer::empty();\n            })) {\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(\"No match found for supplied commands. Check syntax.\"));\n    }\n\n    return spl::make_shared<destroy_consumer_proxy>(spl::make_shared<print_consumer_proxy>(std::move(consumer)));\n}\n\nspl::shared_ptr<frame_consumer>\nframe_consumer_registry::create_consumer(const std::wstring&                                      element_name,\n                                         const boost::property_tree::wptree&                      element,\n                                         const core::video_format_repository&                     format_repository,\n                                         const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                         const core::channel_info&                                channel_info) const\n{\n    auto& preconfigured_consumer_factories = preconfigured_consumer_factories_;\n    auto  found                            = preconfigured_consumer_factories.find(element_name);\n\n    if (found == preconfigured_consumer_factories.end())\n        CASPAR_THROW_EXCEPTION(user_error()\n                               << msg_info(L\"No consumer factory registered for element name \" + element_name));\n\n    return spl::make_shared<destroy_consumer_proxy>(\n        spl::make_shared<print_consumer_proxy>(found->second(element, format_repository, channels, channel_info)));\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/consumer/frame_consumer_registry.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n#include \"channel_info.h\"\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/video_format.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <functional>\n#include <future>\n#include <map>\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nvoid destroy_consumers_synchronously();\n\nusing consumer_factory_t =\n    std::function<spl::shared_ptr<frame_consumer>(const std::vector<std::wstring>&     params,\n                                                  const core::video_format_repository& format_repository,\n                                                  const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                  const core::channel_info& channel_info)>;\nusing preconfigured_consumer_factory_t =\n    std::function<spl::shared_ptr<frame_consumer>(const boost::property_tree::wptree&  element,\n                                                  const core::video_format_repository& format_repository,\n                                                  const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                  const core::channel_info& channel_info)>;\n\nclass frame_consumer_registry\n{\n  public:\n    frame_consumer_registry();\n    void register_consumer_factory(const std::wstring& name, const consumer_factory_t& factory);\n    void register_preconfigured_consumer_factory(const std::wstring&                     element_name,\n                                                 const preconfigured_consumer_factory_t& factory);\n    spl::shared_ptr<frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                    const core::video_format_repository& format_repository,\n                                                    const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                    const core::channel_info& channel_info) const;\n    spl::shared_ptr<frame_consumer> create_consumer(const std::wstring&                  element_name,\n                                                    const boost::property_tree::wptree&  element,\n                                                    const core::video_format_repository& format_repository,\n                                                    const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                    const core::channel_info& channel_info) const;\n\n  private:\n    std::vector<consumer_factory_t>                          consumer_factories_;\n    std::map<std::wstring, preconfigured_consumer_factory_t> preconfigured_consumer_factories_;\n\n    frame_consumer_registry(const frame_consumer_registry&)            = delete;\n    frame_consumer_registry& operator=(const frame_consumer_registry&) = delete;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/consumer/output.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"output.h\"\n\n#include \"channel_info.h\"\n#include \"frame_consumer.h\"\n\n#include \"../frame/frame.h\"\n#include \"../frame/pixel_format.h\"\n\n#include <common/bit_depth.h>\n#include <common/diagnostics/graph.h>\n#include <common/except.h>\n#include <common/memory.h>\n\n#include <chrono>\n#include <map>\n#include <optional>\n#include <thread>\n#include <utility>\n\nnamespace caspar { namespace core {\n\nusing time_point_t = decltype(std::chrono::high_resolution_clock::now());\n\nstruct output::impl\n{\n    monitor::state                      state_;\n    spl::shared_ptr<diagnostics::graph> graph_;\n    const channel_info                  channel_info_;\n    video_format_desc                   format_desc_;\n\n    std::mutex                                     consumers_mutex_;\n    std::map<int, spl::shared_ptr<frame_consumer>> consumers_;\n\n    std::optional<time_point_t> time_;\n\n  public:\n    impl(const spl::shared_ptr<diagnostics::graph>& graph,\n         const video_format_desc&                   format_desc,\n         const core::channel_info&                  channel_info)\n        : graph_(graph)\n        , channel_info_(channel_info)\n        , format_desc_(format_desc)\n    {\n    }\n\n    void add(int index, spl::shared_ptr<frame_consumer> consumer)\n    {\n        remove(index);\n\n        consumer->initialize(format_desc_, channel_info_, index);\n\n        std::lock_guard<std::mutex> lock(consumers_mutex_);\n        consumers_.emplace(index, std::move(consumer));\n    }\n\n    void add(const spl::shared_ptr<frame_consumer>& consumer) { add(consumer->index(), consumer); }\n\n    bool remove(int index)\n    {\n        std::lock_guard<std::mutex> lock(consumers_mutex_);\n        auto                        count = consumers_.erase(index);\n        return count > 0;\n    }\n\n    bool remove(const spl::shared_ptr<frame_consumer>& consumer) { return remove(consumer->index()); }\n\n    std::future<bool> call(int index, const std::vector<std::wstring>& params)\n    {\n        std::lock_guard<std::mutex> lock(consumers_mutex_);\n        auto                        it = consumers_.find(index);\n        if (it != consumers_.end()) {\n            try {\n                return it->second->call(params);\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        } else {\n            CASPAR_LOG(warning) << print() << L\" No consumer found for index \" << index << L\".\";\n        }\n        return caspar::make_ready_future(false);\n    }\n\n    size_t consumer_count()\n    {\n        std::lock_guard<std::mutex> lock(consumers_mutex_);\n        return consumers_.size();\n    }\n\n    void operator()(const const_frame&             input_frame1,\n                    const const_frame&             input_frame2,\n                    const core::video_format_desc& format_desc)\n    {\n        auto time = std::move(time_);\n\n        if (format_desc_ != format_desc) {\n            std::lock_guard<std::mutex> lock(consumers_mutex_);\n            for (auto it = consumers_.begin(); it != consumers_.end();) {\n                try {\n                    it->second->initialize(format_desc, channel_info_, it->first);\n                    ++it;\n                } catch (...) {\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n                    it = consumers_.erase(it);\n                }\n            }\n            format_desc_ = format_desc;\n            time_        = {};\n            return;\n        }\n\n        // If no frame is provided, this should only happen when the channel has no consumers.\n        // Take a shortcut and perform the sleep to let the channel tick correctly.\n        if (!input_frame1) {\n            if (!time) {\n                time = std::chrono::high_resolution_clock::now();\n            } else {\n                std::this_thread::sleep_until(*time);\n            }\n            time_ = *time + std::chrono::microseconds(static_cast<int>(1e6 / format_desc_.hz));\n            return;\n        }\n\n        const auto bytesPerComponent1 =\n            input_frame1.pixel_format_desc().planes.at(0).depth == common::bit_depth::bit8 ? 1 : 2;\n        if (input_frame1.size() != format_desc_.size * bytesPerComponent1) {\n            CASPAR_LOG(warning) << print() << L\" Invalid input frame size.\";\n            return;\n        }\n\n        if (input_frame2) {\n            const auto bytesPerComponent2 =\n                input_frame2.pixel_format_desc().planes.at(0).depth == common::bit_depth::bit8 ? 1 : 2;\n\n            if (input_frame2.size() != format_desc_.size * bytesPerComponent2) {\n                CASPAR_LOG(warning) << print() << L\" Invalid input frame size.\";\n                return;\n            }\n        }\n\n        decltype(consumers_) consumers;\n        {\n            std::lock_guard<std::mutex> lock(consumers_mutex_);\n            consumers = consumers_;\n        }\n\n        auto do_send = [this, &consumers](core::video_field field, const core::const_frame& frame) {\n            std::map<int, std::future<bool>> futures;\n\n            for (auto it = consumers.begin(); it != consumers.end();) {\n                try {\n                    futures.emplace(it->first, it->second->send(field, frame));\n                    ++it;\n                } catch (...) {\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n                    auto index = it->first;\n                    it         = consumers.erase(it);\n\n                    std::lock_guard<std::mutex> lock(consumers_mutex_);\n                    consumers_.erase(index);\n                }\n            }\n\n            for (auto& p : futures) {\n                try {\n                    if (!p.second.get()) {\n                        consumers.erase(p.first);\n\n                        std::lock_guard<std::mutex> lock(consumers_mutex_);\n                        consumers_.erase(p.first);\n                    }\n                } catch (...) {\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n                    consumers.erase(p.first);\n\n                    std::lock_guard<std::mutex> lock(consumers_mutex_);\n                    consumers_.erase(p.first);\n                }\n            }\n        };\n\n        if (format_desc_.field_count == 2) {\n            do_send(core::video_field::a, input_frame1);\n            do_send(core::video_field::b, input_frame2);\n        } else {\n            do_send(core::video_field::progressive, input_frame1);\n        }\n\n        monitor::state state;\n        for (auto& p : consumers) {\n            state[\"port\"][p.first]             = p.second->state();\n            state[\"port\"][p.first][\"consumer\"] = p.second->name();\n        }\n        state_ = std::move(state);\n\n        const auto needs_sync = std::all_of(\n            consumers.begin(), consumers.end(), [](auto& p) { return !p.second->has_synchronization_clock(); });\n\n        if (needs_sync) {\n            if (!time) {\n                time = std::chrono::high_resolution_clock::now();\n            } else {\n                std::this_thread::sleep_until(*time);\n            }\n            time_ = *time + std::chrono::microseconds(static_cast<int>(1e6 / format_desc_.hz));\n        } else {\n            time_.reset();\n        }\n    }\n\n    std::wstring print() const { return L\"output[\" + std::to_wstring(channel_info_.index) + L\"]\"; }\n};\n\noutput::output(const spl::shared_ptr<diagnostics::graph>& graph,\n               const video_format_desc&                   format_desc,\n               const core::channel_info&                  channel_info)\n    : impl_(new impl(graph, format_desc, channel_info))\n{\n}\noutput::~output() {}\nvoid output::add(int index, const spl::shared_ptr<frame_consumer>& consumer) { impl_->add(index, consumer); }\nvoid output::add(const spl::shared_ptr<frame_consumer>& consumer) { impl_->add(consumer); }\nbool output::remove(int index) { return impl_->remove(index); }\nbool output::remove(const spl::shared_ptr<frame_consumer>& consumer) { return impl_->remove(consumer); }\nstd::future<bool> output::call(int index, const std::vector<std::wstring>& params)\n{\n    return impl_->call(index, params);\n}\nsize_t output::consumer_count() const { return impl_->consumer_count(); }\nvoid   output::operator()(const const_frame& frame, const const_frame& frame2, const video_format_desc& format_desc)\n{\n    return (*impl_)(frame, frame2, format_desc);\n}\ncore::monitor::state output::state() const { return impl_->state_; }\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/consumer/output.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n\n#include <common/memory.h>\n#include <core/video_format.h>\n\n#include <memory>\n\nnamespace caspar::diagnostics {\nclass graph;\n}\n\nnamespace caspar { namespace core {\n\nclass output final\n{\n  public:\n    explicit output(const spl::shared_ptr<diagnostics::graph>& graph,\n                    const video_format_desc&                   format_desc,\n                    const core::channel_info&                  channel_info);\n\n    output(const output&)            = delete;\n    output& operator=(const output&) = delete;\n    ~output();\n\n    // Send a frame to the output. If running an interlaced channel, two frames will be provided\n    void operator()(const const_frame& frame, const const_frame& frame2, const video_format_desc& format_desc);\n\n    void add(const spl::shared_ptr<frame_consumer>& consumer);\n    void add(int index, const spl::shared_ptr<frame_consumer>& consumer);\n    bool remove(const spl::shared_ptr<frame_consumer>& consumer);\n    bool remove(int index);\n\n    std::future<bool> call(int index, const std::vector<std::wstring>& params);\n\n    size_t consumer_count() const;\n\n    core::monitor::state state() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/diagnostics/call_context.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../StdAfx.h\"\n\n#include \"call_context.h\"\n\nnamespace caspar { namespace core { namespace diagnostics {\n\nthread_local call_context context;\n\ncall_context& call_context::for_thread() { return context; }\n\nstd::wstring call_context::to_string() const\n{\n    if (video_channel == -1)\n        return L\"[]\";\n    if (layer == -1)\n        return L\"[ch=\" + std::to_wstring(video_channel) + L\"]\";\n    return L\"[ch=\" + std::to_wstring(video_channel) + L\"; layer=\" + std::to_wstring(layer) + L\"]\";\n}\n\n}}} // namespace caspar::core::diagnostics\n"
  },
  {
    "path": "src/core/diagnostics/call_context.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <string>\n\nnamespace caspar { namespace core { namespace diagnostics {\n\nstruct call_context\n{\n    int video_channel = -1;\n    int layer         = -1;\n\n    static call_context& for_thread();\n    std::wstring         to_string() const;\n};\n\nclass scoped_call_context\n{\n    call_context saved_;\n\n    scoped_call_context(const scoped_call_context&)            = delete;\n    scoped_call_context& operator=(const scoped_call_context&) = delete;\n\n  public:\n    scoped_call_context() { saved_ = call_context::for_thread(); }\n    ~scoped_call_context() { call_context::for_thread() = saved_; }\n};\n\n}}} // namespace caspar::core::diagnostics\n"
  },
  {
    "path": "src/core/diagnostics/osd_graph.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"osd_graph.h\"\n\n#include \"call_context.h\"\n\n#include <common/executor.h>\n#include <common/timer.h>\n\n#include <SFML/Graphics.hpp>\n\n#include <boost/circular_buffer.hpp>\n\n#include <tbb/concurrent_unordered_map.h>\n\n#include <GL/glew.h>\n\n#include <atomic>\n#include <cstdio>\n#include <filesystem>\n#include <list>\n#include <memory>\n#include <mutex>\n#include <optional>\n#include <thread>\n\nnamespace fs = std::filesystem;\n\nnamespace caspar { namespace core { namespace diagnostics { namespace osd {\n\n#if SFML_VERSION_MAJOR >= 3\n\nvoid register_sink() {}\nvoid show_graphs(bool value) {}\nvoid shutdown() {}\n\n#else\n\nstatic const int PREFERRED_VERTICAL_GRAPHS = 8;\nstatic const int RENDERING_WIDTH           = 1024;\nstatic const int RENDERING_HEIGHT          = RENDERING_WIDTH / PREFERRED_VERTICAL_GRAPHS;\n\nsf::Color get_sfml_color(int color)\n{\n    auto c = caspar::diagnostics::color(color);\n\n    return {static_cast<sf::Uint8>(color >> 24 & 255),\n            static_cast<sf::Uint8>(color >> 16 & 255),\n            static_cast<sf::Uint8>(color >> 8 & 255),\n            static_cast<sf::Uint8>(color >> 0 & 255)};\n}\n\nauto& get_default_font()\n{\n    static sf::Font DEFAULT_FONT = []() {\n        fs::path path{DIAG_FONT_PATH};\n#ifdef __linux__\n        if (!fs::exists(path)) {\n            auto cmd = \"fc-match --format=%{file} \" + path.string();\n            if (auto pipe = popen(cmd.data(), \"r\")) {\n                char buf[128];\n                path.clear();\n                while (fgets(buf, sizeof(buf), pipe))\n                    path += buf;\n            }\n        }\n#endif\n        sf::Font font;\n        if (!font.loadFromFile(path.string()))\n            CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(DIAG_FONT_PATH \" not found\"));\n        return font;\n    }();\n\n    return DEFAULT_FONT;\n}\n\nstruct drawable\n    : public sf::Drawable\n    , public sf::Transformable\n{\n    virtual ~drawable() {}\n    virtual void render(sf::RenderTarget& target, sf::RenderStates states) = 0;\n\n    void draw(sf::RenderTarget& target, sf::RenderStates states) const override\n    {\n        states.transform *= getTransform();\n        const_cast<drawable*>(this)->render(target, states);\n    }\n};\n\nclass context : public drawable\n{\n    std::unique_ptr<sf::RenderWindow> window_;\n    sf::View                          view_;\n\n    std::list<std::weak_ptr<drawable>> drawables_;\n    caspar::timer                      display_time_;\n    bool                               calculate_view_  = true;\n    int                                scroll_position_ = 0;\n    bool                               dragging_        = false;\n    int                                last_mouse_y_    = 0;\n\n    executor executor_{L\"diagnostics\"};\n\n  public:\n    static void register_drawable(const std::shared_ptr<drawable>& drawable)\n    {\n        if (!drawable)\n            return;\n\n        get_instance()->executor_.begin_invoke([=] { get_instance()->do_register_drawable(drawable); });\n    }\n\n    static void show(bool value)\n    {\n        get_instance()->executor_.begin_invoke([=] { get_instance()->do_show(value); });\n    }\n\n    static void shutdown() { get_instance().reset(); }\n\n  private:\n    context() {}\n\n    void do_show(bool value)\n    {\n        if (value) {\n            if (!window_) {\n                window_.reset(\n                    new sf::RenderWindow(sf::VideoMode(RENDERING_WIDTH, RENDERING_WIDTH), \"CasparCG Diagnostics\"));\n                window_->setPosition(sf::Vector2i(0, 0));\n                window_->setActive();\n                window_->setVerticalSyncEnabled(true);\n                calculate_view_ = true;\n                glEnable(GL_BLEND);\n                glEnable(GL_LINE_SMOOTH);\n                glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\n                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\n                tick();\n            }\n        } else\n            window_.reset();\n    }\n\n    void tick()\n    {\n        if (!window_)\n            return;\n\n        sf::Event e;\n        while (window_->pollEvent(e)) {\n            switch (e.type) {\n                case sf::Event::Closed:\n                    window_.reset();\n                    return;\n                case sf::Event::Resized:\n                    calculate_view_ = true;\n                    break;\n                case sf::Event::MouseButtonPressed:\n                    dragging_     = true;\n                    last_mouse_y_ = e.mouseButton.y;\n                    break;\n                case sf::Event::MouseButtonReleased:\n                    dragging_ = false;\n                    break;\n                case sf::Event::MouseMoved:\n                    if (dragging_) {\n                        auto delta_y = e.mouseMove.y - last_mouse_y_;\n                        scroll_position_ += delta_y;\n                        last_mouse_y_   = e.mouseMove.y;\n                        calculate_view_ = true;\n                    }\n\n                    break;\n                case sf::Event::MouseWheelMoved:\n                    scroll_position_ += e.mouseWheel.delta * 15;\n                    calculate_view_ = true;\n                    break;\n                default:\n                    break;\n            }\n        }\n\n        window_->clear();\n\n        if (calculate_view_) {\n            int content_height      = static_cast<int>(RENDERING_HEIGHT * drawables_.size());\n            int window_height       = static_cast<int>(window_->getSize().y);\n            int not_visible         = std::max(0, content_height - window_height);\n            int min_scroll_position = -not_visible;\n            int max_scroll_position = 0;\n\n            scroll_position_ = std::min(max_scroll_position, std::max(min_scroll_position, scroll_position_));\n            view_.setViewport(sf::FloatRect(0, 0, 1.0, 1.0));\n            view_.setSize(RENDERING_WIDTH, window_height);\n            view_.setCenter(RENDERING_WIDTH / 2, window_height / 2 - scroll_position_);\n            window_->setView(view_);\n\n            calculate_view_ = false;\n        }\n\n        CASPAR_LOG(trace) << \"osd_graph::tick()\";\n        window_->draw(*this);\n        window_->display();\n\n        display_time_.restart();\n        if (executor_.is_running()) {\n            executor_.begin_invoke([this] { tick(); });\n        }\n\n        std::this_thread::sleep_for(std::chrono::milliseconds(40));\n    }\n\n    void render(sf::RenderTarget& target, sf::RenderStates states) override\n    {\n        int n = 0;\n\n        for (auto it = drawables_.begin(); it != drawables_.end(); ++n) {\n            auto drawable = it->lock();\n            if (drawable) {\n                float target_y = n * RENDERING_HEIGHT;\n                drawable->setPosition(0.0f, target_y);\n                target.draw(*drawable, states);\n                ++it;\n            } else\n                it = drawables_.erase(it);\n        }\n    }\n\n    void do_register_drawable(const std::shared_ptr<drawable>& drawable)\n    {\n        drawables_.push_back(drawable);\n        auto it = drawables_.begin();\n        while (it != drawables_.end()) {\n            if (it->lock())\n                ++it;\n            else\n                it = drawables_.erase(it);\n        }\n    }\n\n    static std::unique_ptr<context>& get_instance()\n    {\n        static auto impl = std::unique_ptr<context>(new context);\n        return impl;\n    }\n};\n\nclass line : public drawable\n{\n    size_t                                                 res_{1024};\n    boost::circular_buffer<sf::Vertex>                     line_data_{res_};\n    boost::circular_buffer<std::optional<sf::VertexArray>> line_tags_{res_};\n\n    std::atomic<float> tick_data_;\n    std::atomic<bool>  tick_tag_;\n    std::atomic<int>   color_;\n\n    double x_delta_ = 1.0 / (static_cast<double>(res_) - 1.0);\n\n  public:\n    line()\n        : tick_data_(-1.0f)\n        , tick_tag_(false)\n        , color_(0xFFFFFFFF)\n    {\n    }\n\n    line(const line& other)\n        : res_(other.res_)\n        , line_data_(other.line_data_)\n        , line_tags_(other.line_tags_)\n        , tick_data_(other.tick_data_.load())\n        , tick_tag_(other.tick_tag_.load())\n        , color_(other.color_.load())\n        , x_delta_(other.x_delta_)\n    {\n    }\n\n    void set_value(float value) { tick_data_ = value; }\n\n    void set_tag() { tick_tag_ = true; }\n\n    void set_color(int color) { color_ = color; }\n\n    int get_color() { return color_; }\n\n    void render(sf::RenderTarget& target, sf::RenderStates states) override\n    {\n        /*states.transform.translate(x_pos_, 0.f);\n\n        if (line_data_.size() == res_)\n            x_pos_ = -get_insertion_xcoord() + 1.0 - x_delta_; // Otherwise the graph will drift because of floating\n        point precision else x_pos_ -= x_delta_;*/\n\n        for (auto& vertex : line_data_)\n            vertex.position.x -= x_delta_;\n\n        for (auto& tag : line_tags_) {\n            if (tag) {\n                (*tag)[0].position.x -= x_delta_;\n                (*tag)[1].position.x -= x_delta_;\n            }\n        }\n\n        auto color = get_sfml_color(color_);\n        color.a    = 255 * 0.8;\n        line_data_.push_back(sf::Vertex(\n            sf::Vector2f(get_insertion_xcoord(), std::max(0.1f, std::min(0.9f, (1.0f - tick_data_) * 0.8f + 0.1f))),\n            color));\n\n        if (tick_tag_) {\n            sf::VertexArray vertical_dash(sf::LinesStrip);\n            vertical_dash.append(sf::Vertex(sf::Vector2f(get_insertion_xcoord() - x_delta_, 0.f), color));\n            vertical_dash.append(sf::Vertex(sf::Vector2f(get_insertion_xcoord() - x_delta_, 1.f), color));\n            line_tags_.push_back(vertical_dash);\n        } else\n            line_tags_.push_back({});\n\n        tick_tag_ = false;\n\n        if (tick_data_ > -0.5) {\n            auto array_one = line_data_.array_one();\n            auto array_two = line_data_.array_two();\n            // since boost::circular_buffer guarantees two contiguous views of the buffer we can provide raw access to\n            // SFML, which can use glDrawArrays.\n            target.draw(array_one.first, static_cast<unsigned int>(array_one.second), sf::LinesStrip, states);\n            target.draw(array_two.first, static_cast<unsigned int>(array_two.second), sf::LinesStrip, states);\n\n            if (array_one.second > 0 && array_two.second > 0) {\n                // Connect the gap between the arrays\n                sf::VertexArray connecting_line(sf::LinesStrip);\n                connecting_line.append(*(array_one.first + array_one.second - 1));\n                connecting_line.append(*array_two.first);\n                target.draw(connecting_line, states);\n            }\n        } else {\n            glEnable(GL_LINE_STIPPLE);\n            glLineStipple(3, 0xAAAA);\n\n            for (size_t n = 0; n < line_tags_.size(); ++n) {\n                if (line_tags_[n]) {\n                    target.draw(*line_tags_[n], states);\n                }\n            }\n\n            glDisable(GL_LINE_STIPPLE);\n        }\n    }\n\n  private:\n    double get_insertion_xcoord() const { return line_data_.empty() ? 1.0 : line_data_.back().position.x + x_delta_; }\n};\n\nstruct graph\n    : public drawable\n    , public caspar::diagnostics::spi::graph_sink\n    , public std::enable_shared_from_this<graph>\n{\n    call_context                                     context_ = call_context::for_thread();\n    tbb::concurrent_unordered_map<std::string, line> lines_;\n\n    std::mutex   mutex_;\n    std::wstring text_;\n    bool         auto_reset_ = false;\n\n    graph() {}\n\n    void activate() override { context::register_drawable(shared_from_this()); }\n\n    void set_text(const std::wstring& value) override\n    {\n        auto                        temp = value;\n        std::lock_guard<std::mutex> lock(mutex_);\n        text_ = std::move(temp);\n    }\n\n    void set_value(const std::string& name, double value) override\n    {\n        lines_[name].set_value(static_cast<float>(value));\n    }\n\n    void set_tag(caspar::diagnostics::tag_severity /*severity*/, const std::string& name) override\n    {\n        lines_[name].set_tag();\n    }\n\n    void set_color(const std::string& name, int color) override { lines_[name].set_color(color); }\n\n    void auto_reset() override\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n        auto_reset_ = true;\n    }\n\n  private:\n    void render(sf::RenderTarget& target, sf::RenderStates states) override\n    {\n        const size_t text_size   = 15;\n        const size_t text_margin = 2;\n        const size_t text_offset = (text_size + text_margin * 2) * 2;\n\n        std::wstring text_str;\n        bool         auto_reset;\n\n        {\n            std::lock_guard<std::mutex> lock(mutex_);\n            text_str   = text_;\n            auto_reset = auto_reset_;\n        }\n\n        sf::Text text(text_str.c_str(), get_default_font(), text_size);\n        text.setStyle(sf::Text::Italic);\n        text.move(text_margin, text_margin);\n\n        target.draw(text, states);\n\n        if (context_.video_channel != -1) {\n            auto ctx_str = std::to_string(context_.video_channel);\n\n            if (context_.layer != -1)\n                ctx_str += \"-\" + std::to_string(context_.layer);\n\n            sf::Text context_text(ctx_str, get_default_font(), text_size);\n            context_text.setStyle(sf::Text::Italic);\n            context_text.move(RENDERING_WIDTH - text_margin - 5 - context_text.getLocalBounds().width, text_margin);\n\n            target.draw(context_text, states);\n        }\n\n        float x_offset = text_margin;\n\n        for (auto it = lines_.begin(); it != lines_.end(); ++it) {\n            sf::Text line_text(it->first, get_default_font(), text_size);\n            line_text.setPosition(x_offset, text_margin + text_offset / 2);\n            line_text.setColor(get_sfml_color(it->second.get_color()));\n            target.draw(line_text, states);\n            x_offset += line_text.getLocalBounds().width + text_margin * 2;\n        }\n\n        static const auto rect = []() {\n            sf::RectangleShape r(sf::Vector2f(RENDERING_WIDTH, RENDERING_HEIGHT - 2));\n            r.setFillColor(sf::Color(255, 255, 255, 51));\n            r.setOutlineThickness(0.00f);\n            r.move(0, 1);\n            return r;\n        }();\n        target.draw(rect, states);\n\n        states.transform.translate(0, text_offset)\n            .scale(RENDERING_WIDTH,\n                   RENDERING_HEIGHT *\n                       (static_cast<float>(RENDERING_HEIGHT - text_offset) / static_cast<float>(RENDERING_HEIGHT)));\n\n        static const sf::Color       guide_color(255, 255, 255, 127);\n        static const sf::VertexArray middle_guide = []() {\n            sf::VertexArray result(sf::LinesStrip);\n            result.append(sf::Vertex(sf::Vector2f(0.0f, 0.5f), guide_color));\n            result.append(sf::Vertex(sf::Vector2f(1.0f, 0.5f), guide_color));\n            return result;\n        }();\n        static const sf::VertexArray bottom_guide = []() {\n            sf::VertexArray result(sf::LinesStrip);\n            result.append(sf::Vertex(sf::Vector2f(0.0f, 0.9f), guide_color));\n            result.append(sf::Vertex(sf::Vector2f(1.0f, 0.9f), guide_color));\n            return result;\n        }();\n        static const sf::VertexArray top_guide = []() {\n            sf::VertexArray result(sf::LinesStrip);\n            result.append(sf::Vertex(sf::Vector2f(0.0f, 0.1f), guide_color));\n            result.append(sf::Vertex(sf::Vector2f(1.0f, 0.1f), guide_color));\n            return result;\n        }();\n\n        glEnable(GL_LINE_STIPPLE);\n        glLineStipple(3, 0xAAAA);\n\n        target.draw(middle_guide, states);\n        target.draw(bottom_guide, states);\n        target.draw(top_guide, states);\n\n        glDisable(GL_LINE_STIPPLE);\n\n        for (auto it = lines_.begin(); it != lines_.end(); ++it) {\n            target.draw(it->second, states);\n            if (auto_reset)\n                it->second.set_value(0.0f);\n        }\n    }\n};\n\nvoid register_sink()\n{\n    caspar::diagnostics::spi::register_sink_factory([] { return spl::make_shared<graph>(); });\n}\n\nvoid show_graphs(bool value) { context::show(value); }\n\nvoid shutdown() { context::shutdown(); }\n\n#endif\n\n}}}} // namespace caspar::core::diagnostics::osd\n"
  },
  {
    "path": "src/core/diagnostics/osd_graph.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\nnamespace caspar { namespace core { namespace diagnostics { namespace osd {\n\nvoid register_sink();\nvoid show_graphs(bool value);\nvoid shutdown();\n\n}}}} // namespace caspar::core::diagnostics::osd\n"
  },
  {
    "path": "src/core/frame/draw_frame.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"draw_frame.h\"\n\n#include \"frame.h\"\n#include \"frame_transform.h\"\n#include \"frame_visitor.h\"\n\n#include <boost/variant.hpp>\n\nnamespace caspar { namespace core {\n\nusing frame_t = boost::variant<boost::blank, const_frame, std::vector<draw_frame>>;\n\nstruct draw_frame::impl\n{\n    frame_t         frame_;\n    frame_transform transform_;\n\n  public:\n    impl() {}\n\n    impl(frame_t frame)\n        : frame_(std::move(frame))\n    {\n    }\n\n    void accept(frame_visitor& visitor) const\n    {\n        struct accept_visitor : public boost::static_visitor<void>\n        {\n            frame_visitor& visitor;\n\n            accept_visitor(frame_visitor& visitor)\n                : visitor(visitor)\n            {\n            }\n\n            void operator()(boost::blank /*unused*/) const {}\n\n            void operator()(const const_frame& frame) const { visitor.visit(frame); }\n\n            void operator()(const std::vector<draw_frame>& frames) const\n            {\n                for (auto& frame : frames) {\n                    frame.accept(visitor);\n                }\n            }\n        };\n        visitor.push(transform_);\n        boost::apply_visitor(accept_visitor{visitor}, frame_);\n        visitor.pop();\n    }\n\n    bool operator==(const impl& other) const { return frame_ == other.frame_ && transform_ == other.transform_; }\n};\n\ndraw_frame::draw_frame()\n    : impl_(new impl())\n{\n}\ndraw_frame::draw_frame(const draw_frame& other)\n    : impl_(new impl())\n{\n    impl_->frame_     = other.impl_->frame_;\n    impl_->transform_ = other.impl_->transform_;\n}\n\ndraw_frame::draw_frame(draw_frame&& other)\n    : impl_(std::move(other.impl_))\n{\n}\ndraw_frame::draw_frame(const_frame frame)\n    : impl_(new impl(std::move(frame)))\n{\n}\ndraw_frame::draw_frame(mutable_frame&& frame)\n    : impl_(new impl(std::move(frame)))\n{\n}\ndraw_frame::draw_frame(std::vector<draw_frame> frames)\n    : impl_(new impl(std::move(frames)))\n{\n}\ndraw_frame::~draw_frame() {}\ndraw_frame& draw_frame::operator=(draw_frame other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\nvoid                   draw_frame::swap(draw_frame& other) { impl_.swap(other.impl_); }\nconst frame_transform& draw_frame::transform() const { return impl_->transform_; }\nframe_transform&       draw_frame::transform() { return impl_->transform_; }\nvoid                   draw_frame::accept(frame_visitor& visitor) const { impl_->accept(visitor); }\nbool                   draw_frame::operator==(const draw_frame& other) const { return impl_ && *impl_ == *other.impl_; }\nbool                   draw_frame::operator!=(const draw_frame& other) const { return !(*this == other); }\n\ndraw_frame draw_frame::over(draw_frame frame1, draw_frame frame2)\n{\n    if (!frame1 && !frame2) {\n        return draw_frame{};\n    }\n\n    std::vector<draw_frame> frames;\n    frames.push_back(std::move(frame1));\n    frames.push_back(std::move(frame2));\n    return draw_frame(std::move(frames));\n}\n\ndraw_frame draw_frame::mask(draw_frame fill, draw_frame key)\n{\n    if (!fill || !key) {\n        return draw_frame{};\n    }\n\n    std::vector<draw_frame> frames;\n    key.transform().image_transform.is_key = true;\n    frames.push_back(std::move(key));\n    frames.push_back(std::move(fill));\n    return draw_frame(std::move(frames));\n}\n\ndraw_frame draw_frame::push(draw_frame frame)\n{\n    std::vector<draw_frame> frames;\n    frames.push_back(std::move(frame));\n    return draw_frame(std::move(frames));\n}\n\ndraw_frame draw_frame::push(draw_frame frame, const frame_transform& transform)\n{\n    std::vector<draw_frame> frames;\n    frames.push_back(std::move(frame));\n    auto result        = draw_frame(std::move(frames));\n    result.transform() = std::move(transform);\n    return result;\n}\n\ndraw_frame draw_frame::pop(const draw_frame& frame)\n{\n    draw_frame result;\n    result.impl_->frame_ = frame.impl_->frame_;\n    return result;\n}\n\ndraw_frame draw_frame::still(draw_frame frame)\n{\n    frame.transform().audio_transform.volume           = 0.0;\n    frame.transform().audio_transform.immediate_volume = true;\n    return frame;\n}\n\ndraw_frame draw_frame::empty() { return draw_frame(std::vector<draw_frame>{}); }\n\ndraw_frame::operator bool() const { return impl_ && impl_->frame_.which() != 0; }\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/draw_frame.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#pragma once\n\n#include <memory>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nclass draw_frame final\n{\n  public:\n    static draw_frame over(draw_frame frame1, draw_frame frame2);\n    static draw_frame mask(draw_frame fill, draw_frame key);\n    static draw_frame still(draw_frame frame);\n    static draw_frame push(draw_frame frame);\n    static draw_frame push(draw_frame frame, const struct frame_transform& transform);\n    static draw_frame pop(const draw_frame& frame);\n    static draw_frame empty();\n\n    draw_frame();\n    draw_frame(const draw_frame& other);\n    draw_frame(draw_frame&& other);\n    draw_frame(class const_frame frame);\n    draw_frame(class mutable_frame&& frame);\n    draw_frame(std::vector<draw_frame> frames);\n\n    ~draw_frame();\n\n    draw_frame& operator=(draw_frame other);\n\n    void swap(draw_frame& other);\n\n    void accept(class frame_visitor& visitor) const;\n\n    bool operator==(const draw_frame& other) const;\n    bool operator!=(const draw_frame& other) const;\n\n    const struct frame_transform& transform() const;\n    struct frame_transform&       transform();\n\n    explicit operator bool() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/frame.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"frame.h\"\n\n#include \"geometry.h\"\n#include \"pixel_format.h\"\n\n#include <common/array.h>\n#include <common/except.h>\n\n#include <cstdint>\n#include <functional>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nstruct mutable_frame::impl\n{\n    std::vector<array<std::uint8_t>> image_data_;\n    array<std::int32_t>              audio_data_;\n    const core::pixel_format_desc    desc_;\n    const void*                      tag_;\n    frame_geometry                   geometry_ = frame_geometry::get_default();\n    mutable_frame::commit_t          commit_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n    impl(const void*                      tag,\n         std::vector<array<std::uint8_t>> image_data,\n         array<std::int32_t>              audio_data,\n         const core::pixel_format_desc&   desc,\n         commit_t                         commit)\n        : image_data_(std::move(image_data))\n        , audio_data_(std::move(audio_data))\n        , desc_(desc)\n        , tag_(tag)\n        , commit_(std::move(commit))\n    {\n    }\n};\n\nmutable_frame::mutable_frame(const void*                      tag,\n                             std::vector<array<std::uint8_t>> image_data,\n                             array<int32_t>                   audio_data,\n                             const core::pixel_format_desc&   desc,\n                             commit_t                         commit)\n    : impl_(new impl(tag, std::move(image_data), std::move(audio_data), desc, std::move(commit)))\n{\n}\nmutable_frame::mutable_frame(mutable_frame&& other) noexcept\n    : impl_(std::move(other.impl_))\n{\n}\nmutable_frame::~mutable_frame() {}\nmutable_frame& mutable_frame::operator=(mutable_frame&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\nvoid                           mutable_frame::swap(mutable_frame& other) { impl_.swap(other.impl_); }\nconst core::pixel_format_desc& mutable_frame::pixel_format_desc() const { return impl_->desc_; }\nconst array<std::uint8_t>& mutable_frame::image_data(std::size_t index) const { return impl_->image_data_.at(index); }\nconst array<std::int32_t>& mutable_frame::audio_data() const { return impl_->audio_data_; }\narray<std::uint8_t>&       mutable_frame::image_data(std::size_t index) { return impl_->image_data_.at(index); }\narray<std::int32_t>&       mutable_frame::audio_data() { return impl_->audio_data_; }\nstd::size_t                mutable_frame::width() const { return impl_->desc_.planes.at(0).width; }\nstd::size_t                mutable_frame::height() const { return impl_->desc_.planes.at(0).height; }\nconst void*                mutable_frame::stream_tag() const { return impl_->tag_; }\nconst frame_geometry&      mutable_frame::geometry() const { return impl_->geometry_; }\nframe_geometry&            mutable_frame::geometry() { return impl_->geometry_; }\n\nstruct const_frame::impl\n{\n    std::vector<array<const std::uint8_t>> image_data_;\n    array<const std::int32_t>              audio_data_;\n    core::pixel_format_desc                desc_ = core::pixel_format_desc(pixel_format::invalid);\n    const void*                            tag_;\n    frame_geometry                         geometry_ = frame_geometry::get_default();\n    std::any                               opaque_;\n    std::shared_ptr<core::texture>         texture_;\n\n    impl(const void*                            tag,\n         std::vector<array<const std::uint8_t>> image_data,\n         array<const std::int32_t>              audio_data,\n         const core::pixel_format_desc&         desc,\n         std::shared_ptr<core::texture>         texture)\n        : image_data_(std::move(image_data))\n        , audio_data_(std::move(audio_data))\n        , desc_(desc)\n        , tag_(tag)\n        , texture_(texture)\n    {\n        if (desc_.planes.size() != image_data_.size()) {\n            CASPAR_THROW_EXCEPTION(invalid_argument());\n        }\n    }\n\n    impl(mutable_frame&& other)\n        : image_data_(std::make_move_iterator(other.impl_->image_data_.begin()),\n                      std::make_move_iterator(other.impl_->image_data_.end()))\n        , audio_data_(std::move(other.impl_->audio_data_))\n        , desc_(std::move(other.impl_->desc_))\n        , tag_(other.stream_tag())\n        , texture_(nullptr)\n        , geometry_(std::move(other.impl_->geometry_))\n    {\n        if (desc_.planes.size() != image_data_.size() && !other.impl_->commit_) {\n            CASPAR_THROW_EXCEPTION(invalid_argument());\n        }\n        if (other.impl_->commit_) {\n            opaque_ = other.impl_->commit_(image_data_);\n        }\n    }\n\n    const array<const std::uint8_t>& image_data(std::size_t index) const { return image_data_.at(index); }\n\n    std::shared_ptr<core::texture> texture() { return texture_; }\n\n    std::size_t width() const { return desc_.planes.at(0).width; }\n\n    std::size_t height() const { return desc_.planes.at(0).height; }\n\n    std::size_t size() const { return desc_.planes.at(0).size; }\n};\n\nconst_frame::const_frame() {}\nconst_frame::const_frame(const void*                            tag,\n                         std::vector<array<const std::uint8_t>> image_data,\n                         array<const std::int32_t>              audio_data,\n                         const core::pixel_format_desc&         desc,\n                         std::shared_ptr<core::texture>         texture)\n    : impl_(new impl(tag, std::move(image_data), std::move(audio_data), desc, texture))\n{\n}\nconst_frame::const_frame(mutable_frame&& other)\n    : impl_(new impl(std::move(other)))\n{\n}\nconst_frame::const_frame(const const_frame& other)\n    : impl_(other.impl_)\n{\n}\nconst_frame::~const_frame() {}\nconst_frame& const_frame::operator=(const const_frame& other)\n{\n    impl_ = other.impl_;\n    return *this;\n}\nbool                     const_frame::operator==(const const_frame& other) const { return impl_ == other.impl_; }\nbool                     const_frame::operator!=(const const_frame& other) const { return !(*this == other); }\nbool                     const_frame::operator<(const const_frame& other) const { return impl_ < other.impl_; }\nbool                     const_frame::operator>(const const_frame& other) const { return impl_ > other.impl_; }\nconst pixel_format_desc& const_frame::pixel_format_desc() const { return impl_->desc_; }\nconst array<const std::uint8_t>& const_frame::image_data(std::size_t index) const { return impl_->image_data(index); }\nconst array<const std::int32_t>& const_frame::audio_data() const { return impl_->audio_data_; }\nstd::shared_ptr<core::texture>   const_frame::texture() const { return impl_->texture(); }\nstd::size_t                      const_frame::width() const { return impl_->width(); }\nstd::size_t                      const_frame::height() const { return impl_->height(); }\nstd::size_t                      const_frame::size() const { return impl_->size(); }\nconst void*                      const_frame::stream_tag() const { return impl_->tag_; }\nconst_frame                      const_frame::with_tag(const void* new_tag) const\n{\n    if (!impl_) {\n        return const_frame();\n    }\n\n    std::vector<array<const std::uint8_t>> image_data_copy = impl_->image_data_;\n    auto                                   new_frame =\n        const_frame(new_tag, std::move(image_data_copy), impl_->audio_data_, impl_->desc_, impl_->texture_);\n\n    new_frame.impl_->geometry_ = impl_->geometry_;\n    if (impl_->opaque_.has_value()) {\n        new_frame.impl_->opaque_ = impl_->opaque_;\n    }\n\n    return new_frame;\n}\nconst frame_geometry& const_frame::geometry() const { return impl_->geometry_; }\nconst std::any&       const_frame::opaque() const { return impl_->opaque_; }\nconst_frame::operator bool() const { return impl_ != nullptr && impl_->desc_.format != core::pixel_format::invalid; }\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/frame.h",
    "content": "#pragma once\n\n#include <common/array.h>\n\n#include <any>\n#include <cstddef>\n#include <cstdint>\n#include <functional>\n#include <memory>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nclass texture\n{\n  public:\n    virtual ~texture() {}\n    virtual void bind(int index) = 0;\n    virtual void unbind()        = 0;\n};\n\nclass mutable_frame final\n{\n    friend class const_frame;\n\n  public:\n    using commit_t = std::function<std::any(std::vector<array<const std::uint8_t>>)>;\n\n    explicit mutable_frame(const void*                      tag,\n                           std::vector<array<std::uint8_t>> image_data,\n                           array<std::int32_t>              audio_data,\n                           const struct pixel_format_desc&  desc,\n                           commit_t                         commit = nullptr);\n    mutable_frame(const mutable_frame&) = delete;\n    mutable_frame(mutable_frame&& other) noexcept;\n\n    ~mutable_frame();\n\n    mutable_frame& operator=(const mutable_frame&) = delete;\n    mutable_frame& operator=(mutable_frame&& other);\n\n    void swap(mutable_frame& other);\n\n    const struct pixel_format_desc& pixel_format_desc() const;\n\n    array<std::uint8_t>&       image_data(std::size_t index);\n    const array<std::uint8_t>& image_data(std::size_t index) const;\n\n    array<std::int32_t>&       audio_data();\n    const array<std::int32_t>& audio_data() const;\n\n    std::size_t width() const;\n\n    std::size_t height() const;\n\n    const void* stream_tag() const;\n\n    class frame_geometry&       geometry();\n    const class frame_geometry& geometry() const;\n\n  private:\n    struct impl;\n    std::unique_ptr<impl> impl_;\n};\n\nclass const_frame final\n{\n  public:\n    const_frame();\n    explicit const_frame(const void*                            tag,\n                         std::vector<array<const std::uint8_t>> image_data,\n                         array<const std::int32_t>              audio_data,\n                         const struct pixel_format_desc&        desc,\n                         std::shared_ptr<core::texture>         texture = nullptr);\n    const_frame(const const_frame& other);\n    const_frame(mutable_frame&& other);\n\n    ~const_frame();\n\n    const_frame& operator=(const const_frame& other);\n\n    const struct pixel_format_desc& pixel_format_desc() const;\n\n    const array<const std::uint8_t>& image_data(std::size_t index) const;\n\n    const array<const std::int32_t>& audio_data() const;\n\n    std::shared_ptr<core::texture> texture() const;\n\n    std::size_t width() const;\n\n    std::size_t height() const;\n\n    std::size_t size() const;\n\n    const void* stream_tag() const;\n    const_frame with_tag(const void* new_tag) const;\n\n    const std::any& opaque() const;\n\n    const class frame_geometry& geometry() const;\n\n    bool operator==(const const_frame& other) const;\n    bool operator!=(const const_frame& other) const;\n    bool operator<(const const_frame& other) const;\n    bool operator>(const const_frame& other) const;\n\n    explicit operator bool() const;\n\n  private:\n    struct impl;\n    std::shared_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/frame_factory.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n\n#ifdef WIN32\n#include <core/frame/pixel_format.h>\n#include <memory>\nnamespace caspar::accelerator::d3d {\nclass d3d_texture2d;\n}\n#endif\n\nnamespace caspar { namespace core {\n\nclass frame_factory\n{\n  public:\n    frame_factory()                                = default;\n    frame_factory& operator=(const frame_factory&) = delete;\n    virtual ~frame_factory()                       = default;\n\n    frame_factory(const frame_factory&) = delete;\n\n    virtual class mutable_frame create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc) = 0;\n    virtual class mutable_frame\n    create_frame(const void* video_stream_tag, const struct pixel_format_desc& desc, common::bit_depth depth) = 0;\n\n#ifdef WIN32\n    virtual class const_frame import_d3d_texture(const void* video_stream_tag,\n                                                 const std::shared_ptr<accelerator::d3d::d3d_texture2d>& d3d_texture,\n                                                 core::pixel_format                                      format,\n                                                 common::bit_depth                                       depth) = 0;\n#endif\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/frame_transform.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"frame_transform.h\"\n\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/range/algorithm/equal.hpp>\n\n#include <cmath>\n#include <utility>\n\nnamespace caspar { namespace core {\n\ndouble do_tween(double time, double source, double dest, double duration, const tweener& tween)\n{\n    return tween(time, source, dest - source, duration);\n}\n\ntemplate <typename Rect>\nvoid do_tween_rectangle(const Rect&    source,\n                        const Rect&    dest,\n                        Rect&          out,\n                        double         time,\n                        double         duration,\n                        const tweener& tweener)\n{\n    out.ul[0] = do_tween(time, source.ul[0], dest.ul[0], duration, tweener);\n    out.ul[1] = do_tween(time, source.ul[1], dest.ul[1], duration, tweener);\n    out.lr[0] = do_tween(time, source.lr[0], dest.lr[0], duration, tweener);\n    out.lr[1] = do_tween(time, source.lr[1], dest.lr[1], duration, tweener);\n}\n\nvoid do_tween_corners(const corners& source,\n                      const corners& dest,\n                      corners&       out,\n                      double         time,\n                      double         duration,\n                      const tweener& tweener)\n{\n    do_tween_rectangle(source, dest, out, time, duration, tweener);\n\n    out.ur[0] = do_tween(time, source.ur[0], dest.ur[0], duration, tweener);\n    out.ur[1] = do_tween(time, source.ur[1], dest.ur[1], duration, tweener);\n    out.ll[0] = do_tween(time, source.ll[0], dest.ll[0], duration, tweener);\n    out.ll[1] = do_tween(time, source.ll[1], dest.ll[1], duration, tweener);\n}\n\nimage_transform image_transform::tween(double                 time,\n                                       const image_transform& source,\n                                       const image_transform& dest,\n                                       double                 duration,\n                                       const tweener&         tween)\n{\n    image_transform result;\n\n    result.brightness          = do_tween(time, source.brightness, dest.brightness, duration, tween);\n    result.contrast            = do_tween(time, source.contrast, dest.contrast, duration, tween);\n    result.saturation          = do_tween(time, source.saturation, dest.saturation, duration, tween);\n    result.opacity             = do_tween(time, source.opacity, dest.opacity, duration, tween);\n    result.anchor[0]           = do_tween(time, source.anchor[0], dest.anchor[0], duration, tween);\n    result.anchor[1]           = do_tween(time, source.anchor[1], dest.anchor[1], duration, tween);\n    result.fill_translation[0] = do_tween(time, source.fill_translation[0], dest.fill_translation[0], duration, tween);\n    result.fill_translation[1] = do_tween(time, source.fill_translation[1], dest.fill_translation[1], duration, tween);\n    result.fill_scale[0]       = do_tween(time, source.fill_scale[0], dest.fill_scale[0], duration, tween);\n    result.fill_scale[1]       = do_tween(time, source.fill_scale[1], dest.fill_scale[1], duration, tween);\n    result.clip_translation[0] = do_tween(time, source.clip_translation[0], dest.clip_translation[0], duration, tween);\n    result.clip_translation[1] = do_tween(time, source.clip_translation[1], dest.clip_translation[1], duration, tween);\n    result.clip_scale[0]       = do_tween(time, source.clip_scale[0], dest.clip_scale[0], duration, tween);\n    result.clip_scale[1]       = do_tween(time, source.clip_scale[1], dest.clip_scale[1], duration, tween);\n    result.angle               = do_tween(time, source.angle, dest.angle, duration, tween);\n    result.levels.max_input    = do_tween(time, source.levels.max_input, dest.levels.max_input, duration, tween);\n    result.levels.min_input    = do_tween(time, source.levels.min_input, dest.levels.min_input, duration, tween);\n    result.levels.max_output   = do_tween(time, source.levels.max_output, dest.levels.max_output, duration, tween);\n    result.levels.min_output   = do_tween(time, source.levels.min_output, dest.levels.min_output, duration, tween);\n    result.levels.gamma        = do_tween(time, source.levels.gamma, dest.levels.gamma, duration, tween);\n    result.chroma.target_hue   = do_tween(time, source.chroma.target_hue, dest.chroma.target_hue, duration, tween);\n    result.chroma.hue_width    = do_tween(time, source.chroma.hue_width, dest.chroma.hue_width, duration, tween);\n    result.chroma.min_saturation =\n        do_tween(time, source.chroma.min_saturation, dest.chroma.min_saturation, duration, tween);\n    result.chroma.min_brightness =\n        do_tween(time, source.chroma.min_brightness, dest.chroma.min_brightness, duration, tween);\n    result.chroma.softness = do_tween(time, source.chroma.softness, dest.chroma.softness, duration, tween);\n    result.chroma.spill_suppress =\n        do_tween(time, source.chroma.spill_suppress, dest.chroma.spill_suppress, duration, tween);\n    result.chroma.spill_suppress_saturation =\n        do_tween(time, source.chroma.spill_suppress_saturation, dest.chroma.spill_suppress_saturation, duration, tween);\n    result.chroma.enable    = dest.chroma.enable;\n    result.chroma.show_mask = dest.chroma.show_mask;\n    result.is_key           = source.is_key || dest.is_key;\n    result.invert           = source.invert || dest.invert;\n    result.is_mix           = source.is_mix || dest.is_mix;\n    result.blend_mode       = std::max(source.blend_mode, dest.blend_mode);\n    result.layer_depth      = dest.layer_depth;\n\n    do_tween_rectangle(source.crop, dest.crop, result.crop, time, duration, tween);\n    do_tween_corners(source.perspective, dest.perspective, result.perspective, time, duration, tween);\n\n    return result;\n}\n\nbool eq(double lhs, double rhs) { return std::abs(lhs - rhs) < 5e-8; }\n\nbool operator==(const corners& lhs, const corners& rhs)\n{\n    return boost::range::equal(lhs.ul, rhs.ul, eq) && boost::range::equal(lhs.ur, rhs.ur, eq) &&\n           boost::range::equal(lhs.lr, rhs.lr, eq) && boost::range::equal(lhs.ll, rhs.ll, eq);\n}\n\nbool operator==(const rectangle& lhs, const rectangle& rhs)\n{\n    return boost::range::equal(lhs.ul, rhs.ul, eq) && boost::range::equal(lhs.lr, rhs.lr, eq);\n}\n\nbool operator==(const image_transform& lhs, const image_transform& rhs)\n{\n    return eq(lhs.opacity, rhs.opacity) && eq(lhs.contrast, rhs.contrast) && eq(lhs.brightness, rhs.brightness) &&\n               eq(lhs.saturation, rhs.saturation) && boost::range::equal(lhs.anchor, rhs.anchor, eq) &&\n               boost::range::equal(lhs.fill_translation, rhs.fill_translation, eq) &&\n               boost::range::equal(lhs.fill_scale, rhs.fill_scale, eq) &&\n               boost::range::equal(lhs.clip_translation, rhs.clip_translation, eq) &&\n               boost::range::equal(lhs.clip_scale, rhs.clip_scale, eq) && eq(lhs.angle, rhs.angle) &&\n               lhs.is_key == rhs.is_key && lhs.invert == rhs.invert && lhs.is_mix == rhs.is_mix &&\n               lhs.blend_mode == rhs.blend_mode && lhs.layer_depth == rhs.layer_depth &&\n               lhs.chroma.enable == rhs.chroma.enable && lhs.chroma.show_mask == rhs.chroma.show_mask &&\n               eq(lhs.chroma.target_hue, rhs.chroma.target_hue) && eq(lhs.chroma.hue_width, rhs.chroma.hue_width) &&\n               eq(lhs.chroma.min_saturation, rhs.chroma.min_saturation) &&\n               eq(lhs.chroma.min_brightness, rhs.chroma.min_brightness) &&\n               eq(lhs.chroma.softness, rhs.chroma.softness) &&\n               eq(lhs.chroma.spill_suppress, rhs.chroma.spill_suppress) &&\n               eq(lhs.chroma.spill_suppress_saturation, rhs.chroma.spill_suppress_saturation) && lhs.crop == rhs.crop &&\n               lhs.perspective == rhs.perspective ||\n           lhs.enable_geometry_modifiers == rhs.enable_geometry_modifiers;\n}\n\nbool operator!=(const image_transform& lhs, const image_transform& rhs) { return !(lhs == rhs); }\n\n// audio_transform\n\naudio_transform& audio_transform::operator*=(const audio_transform& other)\n{\n    volume *= other.volume;\n    return *this;\n}\n\naudio_transform audio_transform::operator*(const audio_transform& other) const\n{\n    return audio_transform(*this) *= other;\n}\n\naudio_transform audio_transform::tween(double                 time,\n                                       const audio_transform& source,\n                                       const audio_transform& dest,\n                                       double                 duration,\n                                       const tweener&         tween)\n{\n    audio_transform result;\n    result.volume = do_tween(time, source.volume, dest.volume, duration, tween);\n\n    return result;\n}\n\nbool operator==(const audio_transform& lhs, const audio_transform& rhs) { return eq(lhs.volume, rhs.volume); }\n\nbool operator!=(const audio_transform& lhs, const audio_transform& rhs) { return !(lhs == rhs); }\n\n// frame_transform\nframe_transform::frame_transform() = default;\n\nframe_transform frame_transform::tween(double                 time,\n                                       const frame_transform& source,\n                                       const frame_transform& dest,\n                                       double                 duration,\n                                       const tweener&         tween)\n{\n    frame_transform result;\n    result.image_transform =\n        image_transform::tween(time, source.image_transform, dest.image_transform, duration, tween);\n    result.audio_transform =\n        audio_transform::tween(time, source.audio_transform, dest.audio_transform, duration, tween);\n    return result;\n}\n\nbool operator==(const frame_transform& lhs, const frame_transform& rhs)\n{\n    return lhs.image_transform == rhs.image_transform && lhs.audio_transform == rhs.audio_transform;\n}\n\nbool operator!=(const frame_transform& lhs, const frame_transform& rhs) { return !(lhs == rhs); }\n\ntweened_transform::tweened_transform(const frame_transform& source,\n                                     const frame_transform& dest,\n                                     int                    duration,\n                                     tweener                tween)\n    : source_(source)\n    , dest_(dest)\n    , duration_(duration)\n    , tweener_(std::move(tween))\n{\n}\n\nconst frame_transform& tweened_transform::dest() const { return dest_; }\n\nframe_transform tweened_transform::fetch()\n{\n    return time_ == duration_\n               ? dest_\n               : frame_transform::tween(\n                     static_cast<double>(time_), source_, dest_, static_cast<double>(duration_), tweener_);\n}\n\nvoid tweened_transform::tick(int num) { time_ = std::min(time_ + num, duration_); }\n\nstd::optional<chroma::legacy_type> get_chroma_mode(const std::wstring& str)\n{\n    if (boost::iequals(str, L\"none\")) {\n        return chroma::legacy_type::none;\n    }\n    if (boost::iequals(str, L\"green\")) {\n        return chroma::legacy_type::green;\n    }\n    if (boost::iequals(str, L\"blue\")) {\n        return chroma::legacy_type::blue;\n    } else {\n        return {};\n    }\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/frame_transform.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/tweener.h>\n\n#include <core/mixer/image/blend_modes.h>\n\n#include <array>\n#include <optional>\n\nnamespace caspar { namespace core {\n\nstruct chroma\n{\n    enum class legacy_type\n    {\n        none,\n        green,\n        blue\n    };\n\n    bool   enable                    = false;\n    bool   show_mask                 = false;\n    double target_hue                = 0.0;\n    double hue_width                 = 0.0;\n    double min_saturation            = 0.0;\n    double min_brightness            = 0.0;\n    double softness                  = 0.0;\n    double spill_suppress            = 0.0;\n    double spill_suppress_saturation = 1.0;\n};\n\nstruct levels final\n{\n    double min_input  = 0.0;\n    double max_input  = 1.0;\n    double gamma      = 1.0;\n    double min_output = 0.0;\n    double max_output = 1.0;\n};\n\nstruct corners final\n{\n    std::array<double, 2> ul = {0.0, 0.0};\n    std::array<double, 2> ur = {1.0, 0.0};\n    std::array<double, 2> lr = {1.0, 1.0};\n    std::array<double, 2> ll = {0.0, 1.0};\n};\n\nstruct rectangle final\n{\n    std::array<double, 2> ul = {0.0, 0.0};\n    std::array<double, 2> lr = {1.0, 1.0};\n};\n\nstruct image_transform final\n{\n    double opacity    = 1.0;\n    double contrast   = 1.0;\n    double brightness = 1.0;\n    double saturation = 1.0;\n\n    /**\n     * This enables the clip/crop/perspective fields.\n     * It is often desirable to have this disabled, to avoid cropping/clipping unnecessarily\n     */\n    bool enable_geometry_modifiers = false;\n\n    std::array<double, 2> anchor           = {0.0, 0.0};\n    std::array<double, 2> fill_translation = {0.0, 0.0};\n    std::array<double, 2> fill_scale       = {1.0, 1.0};\n    std::array<double, 2> clip_translation = {0.0, 0.0};\n    std::array<double, 2> clip_scale       = {1.0, 1.0};\n    double                angle            = 0.0;\n    rectangle             crop;\n    corners               perspective;\n    core::levels          levels;\n    core::chroma          chroma;\n\n    bool             is_key      = false;\n    bool             invert      = false;\n    bool             is_mix      = false;\n    core::blend_mode blend_mode  = blend_mode::normal;\n    int              layer_depth = 0;\n\n    static image_transform tween(double                 time,\n                                 const image_transform& source,\n                                 const image_transform& dest,\n                                 double                 duration,\n                                 const tweener&         tween);\n};\n\nbool operator==(const image_transform& lhs, const image_transform& rhs);\nbool operator!=(const image_transform& lhs, const image_transform& rhs);\n\nstruct audio_transform final\n{\n    double volume           = 1.0;\n    bool   immediate_volume = false; // When false, intra-frame samples are ramped from previous volume in audio mixer\n\n    audio_transform& operator*=(const audio_transform& other);\n    audio_transform  operator*(const audio_transform& other) const;\n\n    static audio_transform tween(double                 time,\n                                 const audio_transform& source,\n                                 const audio_transform& dest,\n                                 double                 duration,\n                                 const tweener&         tween);\n};\n\nbool operator==(const audio_transform& lhs, const audio_transform& rhs);\nbool operator!=(const audio_transform& lhs, const audio_transform& rhs);\n\nstruct frame_transform final\n{\n  public:\n    frame_transform();\n\n    core::image_transform image_transform;\n    core::audio_transform audio_transform;\n\n    static frame_transform tween(double                 time,\n                                 const frame_transform& source,\n                                 const frame_transform& dest,\n                                 double                 duration,\n                                 const tweener&         tween);\n};\n\nbool operator==(const frame_transform& lhs, const frame_transform& rhs);\nbool operator!=(const frame_transform& lhs, const frame_transform& rhs);\n\nclass tweened_transform\n{\n    frame_transform source_;\n    frame_transform dest_;\n    int             duration_ = 0;\n    int             time_     = 0;\n    tweener         tweener_;\n\n  public:\n    tweened_transform() = default;\n\n    tweened_transform(const frame_transform& source, const frame_transform& dest, int duration, tweener tween);\n\n    const frame_transform& dest() const;\n\n    frame_transform fetch();\n    void            tick(int num);\n};\n\nstd::optional<chroma::legacy_type> get_chroma_mode(const std::wstring& str);\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/frame_visitor.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\nnamespace caspar { namespace core {\n\nclass frame_visitor\n{\n  public:\n    frame_visitor()                     = default;\n    frame_visitor(const frame_visitor&) = delete;\n    virtual ~frame_visitor()            = default;\n\n    frame_visitor& operator=(const frame_visitor&) = delete;\n\n    virtual void push(const struct frame_transform& transform) = 0;\n    virtual void visit(const class const_frame& frame)         = 0;\n    virtual void pop()                                         = 0;\n};\n\n}} // namespace caspar::core"
  },
  {
    "path": "src/core/frame/geometry.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas P Andersson, niklas.p.andersson@svt.se\n */\n#include \"geometry.h\"\n\n#include <common/except.h>\n\nnamespace caspar { namespace core {\n\nframe_geometry::coord::coord(double vertex_x, double vertex_y, double texture_x, double texture_y)\n    : vertex_x(vertex_x)\n    , vertex_y(vertex_y)\n    , texture_x(texture_x)\n    , texture_y(texture_y)\n{\n}\n\nbool frame_geometry::coord::operator==(const frame_geometry::coord& other) const\n{\n    return vertex_x == other.vertex_x && vertex_y == other.vertex_y && texture_x == other.texture_x &&\n           texture_y == other.texture_y && texture_r == other.texture_r && texture_q == other.texture_q;\n}\n\nstruct frame_geometry::impl\n{\n    impl(frame_geometry::geometry_type type, frame_geometry::scale_mode mode, std::vector<coord> data)\n        : type_{type}\n        , mode_{mode}\n    {\n        if (type == geometry_type::quad && data.size() != 4)\n            CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(\"The number of coordinates needs to be 4\"));\n\n        data_ = std::move(data);\n    }\n\n    frame_geometry::geometry_type type_;\n    frame_geometry::scale_mode    mode_;\n    std::vector<coord>            data_;\n};\n\nframe_geometry::frame_geometry(geometry_type type, scale_mode mode, std::vector<coord> data)\n    : impl_{new impl{type, mode, std::move(data)}}\n{\n}\n\nframe_geometry::geometry_type             frame_geometry::type() const { return impl_->type_; }\nframe_geometry::scale_mode                frame_geometry::mode() const { return impl_->mode_; }\nconst std::vector<frame_geometry::coord>& frame_geometry::data() const { return impl_->data_; }\n\nconst frame_geometry frame_geometry::get_default(scale_mode mode)\n{\n    std::vector<frame_geometry::coord> data{\n        //    vertex    texture\n        {0.0, 0.0, 0.0, 0.0}, // upper left\n        {1.0, 0.0, 1.0, 0.0}, // upper right\n        {1.0, 1.0, 1.0, 1.0}, // lower right\n        {0.0, 1.0, 0.0, 1.0}  // lower left\n    };\n    return frame_geometry{frame_geometry::geometry_type::quad, mode, std::move(data)};\n}\nconst frame_geometry frame_geometry::get_default_vflip(scale_mode mode)\n{\n    std::vector<frame_geometry::coord> data{\n        //    vertex    texture\n        {0.0, 0.0, 0.0, 1.0}, // upper left\n        {1.0, 0.0, 1.0, 1.0}, // upper right\n        {1.0, 1.0, 1.0, 0.0}, // lower right\n        {0.0, 1.0, 0.0, 0.0}  // lower left\n    };\n    return frame_geometry{frame_geometry::geometry_type::quad, mode, std::move(data)};\n}\n\nframe_geometry::scale_mode scale_mode_from_string(const std::wstring& str)\n{\n    auto str2 = boost::to_lower_copy(str);\n    if (str2 == L\"fit\") {\n        return frame_geometry::scale_mode::fit;\n    } else if (str2 == L\"fill\") {\n        return frame_geometry::scale_mode::fill;\n    } else if (str2 == L\"original\") {\n        return frame_geometry::scale_mode::original;\n    } else if (str2 == L\"hfill\") {\n        return frame_geometry::scale_mode::hfill;\n    } else if (str2 == L\"vfill\") {\n        return frame_geometry::scale_mode::vfill;\n    } else {\n        return frame_geometry::scale_mode::stretch;\n    }\n}\n\nstd::wstring scale_mode_to_string(frame_geometry::scale_mode mode)\n{\n    switch (mode) {\n        case frame_geometry::scale_mode::fit:\n            return L\"FIT\";\n        case frame_geometry::scale_mode::fill:\n            return L\"FILL\";\n        case frame_geometry::scale_mode::original:\n            return L\"ORIGINAL\";\n        case frame_geometry::scale_mode::hfill:\n            return L\"HFILL\";\n        case frame_geometry::scale_mode::vfill:\n            return L\"VFILL\";\n        default:\n            return L\"STRETCH\";\n    }\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/geometry.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas P Andersson, niklas.p.andersson@svt.se\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include <vector>\n\nnamespace caspar { namespace core {\n\nclass frame_geometry\n{\n  public:\n    enum class geometry_type\n    {\n        quad\n    };\n\n    enum class scale_mode\n    {\n        stretch, // default\n        fit,\n        fill,\n        original,\n        hfill,\n        vfill,\n    };\n\n    struct coord\n    {\n        double vertex_x  = 0.0;\n        double vertex_y  = 0.0;\n        double texture_x = 0.0;\n        double texture_y = 0.0;\n        double texture_r = 0.0;\n        double texture_q = 1.0;\n\n        coord() = default;\n        coord(double vertex_x, double vertex_y, double texture_x, double texture_y);\n\n        bool operator==(const coord& other) const;\n    };\n\n    frame_geometry(geometry_type type, scale_mode, std::vector<coord> data);\n\n    geometry_type             type() const;\n    scale_mode                mode() const;\n    const std::vector<coord>& data() const;\n\n    static const frame_geometry get_default(scale_mode = scale_mode::stretch);\n    static const frame_geometry get_default_vflip(scale_mode = scale_mode::stretch);\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\nframe_geometry::scale_mode scale_mode_from_string(const std::wstring&);\nstd::wstring               scale_mode_to_string(frame_geometry::scale_mode);\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/frame/pixel_format.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <vector>\n\n#include <common/bit_depth.h>\n\nnamespace caspar { namespace core {\n\nenum class pixel_format\n{\n    gray = 0,\n    bgra,\n    rgba,\n    argb,\n    abgr,\n    ycbcr,\n    ycbcra,\n    luma,\n    bgr,\n    rgb,\n    uyvy,\n    gbrp,  // planar\n    gbrap, // planar\n    count,\n    invalid,\n};\n\nenum class color_space\n{\n    bt601,\n    bt709,\n    bt2020,\n};\n\nstruct pixel_format_desc final\n{\n    struct plane\n    {\n        int               linesize = 0;\n        int               width    = 0;\n        int               height   = 0;\n        int               size     = 0;\n        int               stride   = 0;\n        common::bit_depth depth    = common::bit_depth::bit8;\n\n        plane() = default;\n\n        plane(int width, int height, int stride, common::bit_depth depth = common::bit_depth::bit8)\n            : linesize(width * stride * (depth == common::bit_depth::bit8 ? 1 : 2))\n            , width(width)\n            , height(height)\n            , size(width * height * stride * (depth == common::bit_depth::bit8 ? 1 : 2))\n            , stride(stride)\n            , depth(depth)\n        {\n        }\n    };\n\n    pixel_format_desc() = default;\n\n    explicit pixel_format_desc(pixel_format format, core::color_space color_space = core::color_space::bt709)\n        : format(format)\n        , color_space(color_space)\n    {\n    }\n\n    pixel_format       format            = pixel_format::invalid;\n    bool               is_straight_alpha = false;\n    std::vector<plane> planes;\n    core::color_space  color_space = core::color_space::bt709;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/fwd.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#pragma once\n\nnamespace caspar::accelerator {\nclass accelerator;\n}\nnamespace caspar::accelerator::ogl {\nclass device;\n}\n\nnamespace caspar::core {\nclass stage;\nclass mixer;\nclass output;\nclass image_mixer;\nstruct video_format_desc;\nclass frame_factory;\nclass frame_producer;\nclass frame_consumer;\nclass draw_frame;\nclass mutable_frame;\nclass const_frame;\nclass video_channel;\nstruct pixel_format_desc;\nstruct frame_transform;\nstruct frame_producer_dependencies;\nstruct module_dependencies;\nclass cg_producer_registry;\nclass frame_producer_registry;\nclass frame_consumer_registry;\nclass video_format_repository;\nstruct channel_info;\n} // namespace caspar::core\n"
  },
  {
    "path": "src/core/mixer/audio/audio_mixer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../StdAfx.h\"\n\n#include \"audio_mixer.h\"\n\n#include <core/frame/frame.h>\n#include <core/frame/frame_transform.h>\n#include <core/monitor/monitor.h>\n\n#include <common/diagnostics/graph.h>\n\n#include <boost/container/flat_map.hpp>\n#include <boost/range/algorithm.hpp>\n\n#include <atomic>\n#include <map>\n#include <stack>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nusing namespace boost::container;\n\nstruct audio_item\n{\n    const void*          tag = nullptr;\n    audio_transform      transform;\n    array<const int32_t> samples;\n};\n\nusing audio_buffer_ps = std::vector<double>;\n\nstruct audio_mixer::impl\n{\n    monitor::state                              state_;\n    std::stack<core::audio_transform>           transform_stack_;\n    std::vector<audio_item>                     items_;\n    std::map<const void*, std::vector<int32_t>> audio_streams_;    // For audio cadence handling\n    std::map<const void*, double>               previous_volumes_; // For audio transitions\n    video_format_desc                           format_desc_;\n    std::atomic<float>                          master_volume_{1.0f};\n    spl::shared_ptr<diagnostics::graph>         graph_;\n    size_t                                      max_expected_cadence_samples_{0};\n    size_t                                      max_buffer_size_{0};\n    bool                                        has_variable_cadence_{false};\n    std::vector<int32_t>                        silence_buffer_;\n    int                                         channels_{0};\n\n    impl(spl::shared_ptr<diagnostics::graph> graph)\n        : graph_(std::move(graph))\n    {\n        graph_->set_color(\"volume\", diagnostics::color(1.0f, 0.8f, 0.1f));\n        graph_->set_color(\"audio-clipping\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"audio-buffer-overflow\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        transform_stack_.push(core::audio_transform());\n    }\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n    void push(const frame_transform& transform)\n    {\n        transform_stack_.push(transform_stack_.top() * transform.audio_transform);\n    }\n\n    void visit(const const_frame& frame)\n    {\n        if (transform_stack_.top().volume < 0.002 || !frame.audio_data())\n            return;\n\n        items_.push_back(std::move(audio_item{frame.stream_tag(), transform_stack_.top(), frame.audio_data()}));\n    }\n\n    void pop() { transform_stack_.pop(); }\n\n    void set_master_volume(float volume) { master_volume_ = volume; }\n\n    float get_master_volume() { return master_volume_; }\n\n    array<const int32_t> mix(const video_format_desc& format_desc, int nb_samples)\n    {\n        if (format_desc_ != format_desc) {\n            audio_streams_.clear();\n            previous_volumes_.clear();\n\n            format_desc_ = format_desc;\n            channels_    = format_desc.audio_channels;\n\n            // Calculate these values only when format changes\n            max_expected_cadence_samples_ = 0;\n            if (!format_desc.audio_cadence.empty()) {\n                max_expected_cadence_samples_ =\n                    *std::max_element(format_desc.audio_cadence.begin(), format_desc.audio_cadence.end());\n            }\n\n            // Pre-calculate max buffer size based on max cadence (2 frames worth)\n            max_buffer_size_ = channels_;\n            if (max_expected_cadence_samples_ > 0) {\n                max_buffer_size_ *= 2 * max_expected_cadence_samples_;\n            } else {\n                max_buffer_size_ *= 4000; // Fallback: 2 frames × ~2000 samples\n            }\n\n            has_variable_cadence_ = format_desc.audio_cadence.size() > 1;\n\n            if (has_variable_cadence_) {\n                silence_buffer_.resize(channels_, 0);\n            } else {\n                silence_buffer_.clear();\n            }\n        }\n\n        auto items  = std::move(items_);\n        auto result = std::vector<int32_t>(size_t(nb_samples) * channels_, 0);\n        auto mixed  = std::vector<double>(size_t(nb_samples) * channels_, 0.0f);\n\n        std::map<const void*, std::vector<int32_t>> next_audio_streams;\n        std::map<const void*, double>               next_volumes;\n\n        for (auto& item : items) {\n            auto ptr       = item.samples.data();\n            auto item_size = item.samples.size();\n            auto dst_size  = result.size();\n\n            size_t         last_size = 0;\n            const int32_t* last_ptr  = nullptr;\n\n            if (has_variable_cadence_) {\n                auto audio_stream = audio_streams_.find(item.tag);\n                if (audio_stream != audio_streams_.end()) {\n                    last_size = audio_stream->second.size();\n                    last_ptr  = audio_stream->second.data();\n                } else if (nullptr != item.tag) {\n                    // Insert a sample of silence at startup\n                    // Covers the startup case where there may be a cadence mismatch\n                    // The sample of silence will be output before any valid audio data from the source\n                    last_size = channels_;\n                    last_ptr  = silence_buffer_.data();\n                }\n            }\n\n            // Get previous volume for this tag, defaulting to current volume\n            double previous_volume = item.transform.volume;\n            auto   prev_vol_it     = previous_volumes_.find(item.tag);\n            if (prev_vol_it != previous_volumes_.end()) {\n                previous_volume = prev_vol_it->second;\n            }\n\n            // Store current volume for next frame\n            next_volumes[item.tag] = item.transform.volume;\n\n            // Sample collection and volume application loop\n            for (auto n = 0; n < dst_size; ++n) {\n                double sample_value = 0.0;\n\n                if (last_ptr && n < last_size) {\n                    sample_value = static_cast<double>(last_ptr[n]);\n                } else if (n < last_size + item_size) {\n                    sample_value = static_cast<double>(ptr[n - last_size]);\n                } else {\n                    // If we run out of samples, hold the last sample value per channel\n                    int channel_pos = n % channels_;\n                    int offset      = int(item_size) - (channels_ - channel_pos);\n                    if (offset < 0) {\n                        offset = channel_pos;\n                    }\n                    sample_value = static_cast<double>(ptr[offset]);\n                }\n\n                double applied_volume = item.transform.volume;\n\n                // Apply sample-level volume ramping if not immediate volume and there's a volume change\n                if (!item.transform.immediate_volume && std::abs(item.transform.volume - previous_volume) > 0.001) {\n                    size_t sample_index  = n / channels_;\n                    size_t total_samples = dst_size / channels_;\n\n                    // Calculate linear interpolation position (0.0 to 1.0)\n                    double position = total_samples > 1\n                                          ? static_cast<double>(sample_index) / static_cast<double>(total_samples - 1)\n                                          : 1.0;\n                    position        = std::min(1.0, std::max(0.0, position)); // Clamp between 0 and 1\n\n                    // Linear interpolation between previous and current volume\n                    applied_volume = previous_volume + (item.transform.volume - previous_volume) * position;\n                }\n\n                mixed[n] += sample_value * applied_volume;\n            }\n\n            if (has_variable_cadence_ && item.tag) {\n                if (item_size + last_size > dst_size) {\n                    // Calculate remaining samples after mixing the current frame\n                    auto remaining_samples = item_size + last_size - dst_size;\n\n                    // Apply the most restrictive limit and log if needed\n                    if (remaining_samples > max_buffer_size_ || remaining_samples > item_size) {\n                        graph_->set_tag(diagnostics::tag_severity::WARNING, \"audio-buffer-overflow\");\n\n                        // Apply the most restrictive limit\n                        remaining_samples = (max_buffer_size_ < item_size) ? max_buffer_size_ : item_size;\n                    }\n\n                    std::vector<int32_t> buf(remaining_samples);\n                    // Calculate the correct offset in the source buffer\n                    size_t offset = (dst_size > last_size) ? (dst_size - last_size) : 0;\n                    if (offset < item_size) {\n                        std::memcpy(buf.data(), ptr + offset, remaining_samples * sizeof(int32_t));\n                        next_audio_streams[item.tag] = std::move(buf);\n                    } else {\n                        next_audio_streams[item.tag] = std::vector<int32_t>();\n                    }\n                } else {\n                    next_audio_streams[item.tag] = std::vector<int32_t>();\n                }\n            }\n        }\n\n        previous_volumes_ = std::move(next_volumes);\n        audio_streams_    = std::move(next_audio_streams);\n\n        auto master_volume = master_volume_.load();\n        for (auto n = 0; n < mixed.size(); ++n) {\n            auto sample = mixed[n] * master_volume;\n            if (sample > std::numeric_limits<int32_t>::max()) {\n                result[n] = std::numeric_limits<int32_t>::max();\n            } else if (sample < std::numeric_limits<int32_t>::min()) {\n                result[n] = std::numeric_limits<int32_t>::min();\n            } else {\n                result[n] = static_cast<int32_t>(sample);\n            }\n        }\n\n        auto max = std::vector<int32_t>(channels_, std::numeric_limits<int32_t>::min());\n        for (size_t n = 0; n < result.size(); n += channels_) {\n            for (int ch = 0; ch < channels_; ++ch) {\n                max[ch] = std::max(max[ch], std::abs(result[n + ch]));\n            }\n        }\n\n        if (boost::range::count_if(max, [](auto val) { return val >= std::numeric_limits<int32_t>::max(); }) > 0) {\n            graph_->set_tag(diagnostics::tag_severity::WARNING, \"audio-clipping\");\n        }\n\n        state_[\"volume\"] = std::move(max);\n\n        graph_->set_value(\"volume\",\n                          static_cast<double>(*boost::max_element(max)) / std::numeric_limits<int32_t>::max());\n\n        return std::move(result);\n    }\n};\n\naudio_mixer::audio_mixer(spl::shared_ptr<diagnostics::graph> graph)\n    : impl_(new impl(std::move(graph)))\n{\n}\nvoid                 audio_mixer::push(const frame_transform& transform) { impl_->push(transform); }\nvoid                 audio_mixer::visit(const const_frame& frame) { impl_->visit(frame); }\nvoid                 audio_mixer::pop() { impl_->pop(); }\nvoid                 audio_mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }\nfloat                audio_mixer::get_master_volume() { return impl_->get_master_volume(); }\narray<const int32_t> audio_mixer::operator()(const video_format_desc& format_desc, int nb_samples)\n{\n    return impl_->mix(format_desc, nb_samples);\n}\ncore::monitor::state audio_mixer::state() const { return impl_->state_; }\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/mixer/audio/audio_mixer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/array.h>\n#include <common/memory.h>\n\n#include <core/frame/frame_visitor.h>\n#include <core/monitor/monitor.h>\n#include <core/video_format.h>\n\n#include <cstdint>\n\nnamespace caspar::diagnostics {\nclass graph;\n}\n\nnamespace caspar { namespace core {\n\nclass audio_mixer final : public frame_visitor\n{\n    audio_mixer(const audio_mixer&);\n    audio_mixer& operator=(const audio_mixer&);\n\n  public:\n    audio_mixer(spl::shared_ptr<::caspar::diagnostics::graph> graph);\n\n    array<const int32_t> operator()(const struct video_format_desc& format_desc, int nb_samples);\n    void                 set_master_volume(float volume);\n    float                get_master_volume();\n    core::monitor::state state() const;\n\n    void push(const struct frame_transform& transform) override;\n    void visit(const class const_frame& frame) override;\n    void pop() override;\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/mixer/audio/audio_util.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <algorithm>\n#include <cstdint>\n#include <vector>\n\nnamespace caspar { namespace core {\n\ntemplate <typename T>\nstd::vector<int8_t> audio_32_to_24(const T& audio_data)\n{\n    auto size    = std::distance(std::begin(audio_data), std::end(audio_data));\n    auto input8  = reinterpret_cast<const int8_t*>(&(*std::begin(audio_data)));\n    auto output8 = std::vector<int8_t>();\n\n    output8.reserve(size * 3);\n    for (int n = 0; n < size; ++n) {\n        output8.push_back(input8[n * 4 + 1]);\n        output8.push_back(input8[n * 4 + 2]);\n        output8.push_back(input8[n * 4 + 3]);\n    }\n\n    return output8;\n}\n\ntemplate <typename T>\nstd::vector<int16_t> audio_32_to_16(const T& audio_data)\n{\n    auto size     = std::distance(std::begin(audio_data), std::end(audio_data));\n    auto input32  = &(*std::begin(audio_data));\n    auto output16 = std::vector<int16_t>();\n\n    output16.reserve(size);\n    for (int n = 0; n < size; ++n)\n        output16.push_back((input32[n] >> 16) & 0xFFFF);\n\n    return output16;\n}\n\n}} // namespace caspar::core"
  },
  {
    "path": "src/core/mixer/image/blend_modes.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../StdAfx.h\"\n\n#include \"blend_modes.h\"\n\n#include <boost/algorithm/string.hpp>\n\nnamespace caspar { namespace core {\n\nblend_mode get_blend_mode(const std::wstring& str)\n{\n    if (boost::iequals(str, L\"normal\"))\n        return blend_mode::normal;\n    if (boost::iequals(str, L\"lighten\"))\n        return blend_mode::lighten;\n    if (boost::iequals(str, L\"darken\"))\n        return blend_mode::darken;\n    if (boost::iequals(str, L\"multiply\"))\n        return blend_mode::multiply;\n    if (boost::iequals(str, L\"average\"))\n        return blend_mode::average;\n    if (boost::iequals(str, L\"add\"))\n        return blend_mode::add;\n    if (boost::iequals(str, L\"subtract\"))\n        return blend_mode::subtract;\n    if (boost::iequals(str, L\"difference\"))\n        return blend_mode::difference;\n    if (boost::iequals(str, L\"negation\"))\n        return blend_mode::negation;\n    if (boost::iequals(str, L\"exclusion\"))\n        return blend_mode::exclusion;\n    if (boost::iequals(str, L\"screen\"))\n        return blend_mode::screen;\n    if (boost::iequals(str, L\"overlay\"))\n        return blend_mode::overlay;\n    if (boost::iequals(str, L\"soft_light\"))\n        return blend_mode::soft_light;\n    if (boost::iequals(str, L\"hard_light\"))\n        return blend_mode::hard_light;\n    if (boost::iequals(str, L\"color_dodge\"))\n        return blend_mode::color_dodge;\n    if (boost::iequals(str, L\"color_burn\"))\n        return blend_mode::color_burn;\n    if (boost::iequals(str, L\"linear_dodge\"))\n        return blend_mode::linear_dodge;\n    if (boost::iequals(str, L\"linear_burn\"))\n        return blend_mode::linear_burn;\n    if (boost::iequals(str, L\"linear_light\"))\n        return blend_mode::linear_light;\n    if (boost::iequals(str, L\"vivid_light\"))\n        return blend_mode::vivid_light;\n    if (boost::iequals(str, L\"pin_light\"))\n        return blend_mode::pin_light;\n    if (boost::iequals(str, L\"hard_mix\"))\n        return blend_mode::hard_mix;\n    if (boost::iequals(str, L\"reflect\"))\n        return blend_mode::reflect;\n    if (boost::iequals(str, L\"glow\"))\n        return blend_mode::glow;\n    if (boost::iequals(str, L\"phoenix\"))\n        return blend_mode::phoenix;\n    if (boost::iequals(str, L\"contrast\"))\n        return blend_mode::contrast;\n    if (boost::iequals(str, L\"saturation\"))\n        return blend_mode::saturation;\n    if (boost::iequals(str, L\"color\"))\n        return blend_mode::color;\n    if (boost::iequals(str, L\"luminosity\"))\n        return blend_mode::luminosity;\n\n    return blend_mode::normal;\n}\n\nstd::wstring get_blend_mode(blend_mode mode)\n{\n    switch (mode) {\n        case blend_mode::normal:\n            return L\"normal\";\n        case blend_mode::lighten:\n            return L\"lighten\";\n        case blend_mode::darken:\n            return L\"darken\";\n        case blend_mode::multiply:\n            return L\"multiply\";\n        case blend_mode::average:\n            return L\"average\";\n        case blend_mode::add:\n            return L\"add\";\n        case blend_mode::subtract:\n            return L\"subtract\";\n        case blend_mode::difference:\n            return L\"difference\";\n        case blend_mode::negation:\n            return L\"negation\";\n        case blend_mode::exclusion:\n            return L\"exclusion\";\n        case blend_mode::screen:\n            return L\"screen\";\n        case blend_mode::overlay:\n            return L\"overlay\";\n        case blend_mode::soft_light:\n            return L\"soft_light\";\n        case blend_mode::hard_light:\n            return L\"hard_light\";\n        case blend_mode::color_dodge:\n            return L\"color_dodge\";\n        case blend_mode::color_burn:\n            return L\"color_burn\";\n        case blend_mode::linear_dodge:\n            return L\"linear_dodge\";\n        case blend_mode::linear_burn:\n            return L\"linear_burn\";\n        case blend_mode::linear_light:\n            return L\"linear_light\";\n        case blend_mode::vivid_light:\n            return L\"vivid_light\";\n        case blend_mode::pin_light:\n            return L\"pin_light\";\n        case blend_mode::hard_mix:\n            return L\"hard_mix\";\n        case blend_mode::reflect:\n            return L\"reflect\";\n        case blend_mode::glow:\n            return L\"glow\";\n        case blend_mode::phoenix:\n            return L\"phoenix\";\n        case blend_mode::contrast:\n            return L\"contrast\";\n        case blend_mode::saturation:\n            return L\"saturation\";\n        case blend_mode::color:\n            return L\"color\";\n        case blend_mode::luminosity:\n            return L\"luminosity\";\n        default:\n            return L\"normal\";\n    }\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/mixer/image/blend_modes.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <string>\n\nnamespace caspar { namespace core {\n\nenum class blend_mode\n{\n    normal = 0,\n    lighten,\n    darken,\n    multiply,\n    average,\n    add,\n    subtract,\n    difference,\n    negation,\n    exclusion,\n    screen,\n    overlay,\n    soft_light,\n    hard_light,\n    color_dodge,\n    color_burn,\n    linear_dodge,\n    linear_burn,\n    linear_light,\n    vivid_light,\n    pin_light,\n    hard_mix,\n    reflect,\n    glow,\n    phoenix,\n    contrast,\n    saturation,\n    color,\n    luminosity,\n    mix,\n    blend_mode_count\n};\n\nblend_mode   get_blend_mode(const std::wstring& str);\nstd::wstring get_blend_mode(blend_mode mode);\n\n}} // namespace caspar::core"
  },
  {
    "path": "src/core/mixer/image/image_mixer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/frame_visitor.h>\n#include <core/frame/pixel_format.h>\n\n#include <cstdint>\n#include <future>\n\nnamespace caspar { namespace core {\n\nclass image_mixer\n    : public frame_visitor\n    , public frame_factory\n{\n    image_mixer(const image_mixer&);\n    image_mixer& operator=(const image_mixer&);\n\n  public:\n    image_mixer() {}\n    virtual ~image_mixer() {}\n\n    void push(const struct frame_transform& frame) override = 0;\n    void visit(const class const_frame& frame) override     = 0;\n    void pop() override                                     = 0;\n\n    virtual void update_aspect_ratio(double aspect_ratio) = 0;\n\n    virtual std::future<std::tuple<array<const std::uint8_t>, std::shared_ptr<texture>>>\n    render(const struct video_format_desc& format_desc) = 0;\n\n    class mutable_frame create_frame(const void* tag, const struct pixel_format_desc& desc) override = 0;\n    class mutable_frame create_frame(const void*                     video_stream_tag,\n                                     const struct pixel_format_desc& desc,\n                                     common::bit_depth               depth) override                               = 0;\n\n#ifdef WIN32\n    class const_frame import_d3d_texture(const void*                                             tag,\n                                         const std::shared_ptr<accelerator::d3d::d3d_texture2d>& d3d_texture,\n                                         core::pixel_format                                      format,\n                                         common::bit_depth                                       depth) override = 0;\n#endif\n\n    virtual common::bit_depth depth() const = 0;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/mixer/mixer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"mixer.h\"\n\n#include \"../frame/frame.h\"\n\n#include \"audio/audio_mixer.h\"\n#include \"image/image_mixer.h\"\n\n#include <common/diagnostics/graph.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/pixel_format.h>\n#include <core/video_format.h>\n\n#include <queue>\n#include <unordered_map>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nstruct mixer::impl\n{\n    monitor::state                       state_;\n    int                                  channel_index_;\n    spl::shared_ptr<diagnostics::graph>  graph_;\n    audio_mixer                          audio_mixer_{graph_};\n    spl::shared_ptr<image_mixer>         image_mixer_;\n    std::queue<std::future<const_frame>> buffer_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n    impl(int channel_index, spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer)\n        : channel_index_(channel_index)\n        , graph_(std::move(graph))\n        , image_mixer_(std::move(image_mixer))\n    {\n    }\n\n    const_frame operator()(std::vector<draw_frame> frames, const video_format_desc& format_desc, int nb_samples)\n    {\n        image_mixer_->update_aspect_ratio(static_cast<double>(format_desc.square_width) /\n                                          static_cast<double>(format_desc.square_height));\n\n        for (auto& frame : frames) {\n            frame.accept(audio_mixer_);\n            frame.transform().image_transform.layer_depth = 1;\n            frame.accept(*image_mixer_);\n        }\n\n        auto result = image_mixer_->render(format_desc);\n        auto audio  = audio_mixer_(format_desc, nb_samples);\n\n        state_[\"audio\"] = audio_mixer_.state();\n\n        auto depth = image_mixer_->depth();\n\n        buffer_.push(std::async(\n            std::launch::deferred,\n            [result = std::move(result),\n             audio  = std::move(audio),\n             graph  = graph_,\n             depth,\n             format_desc,\n             tag = this]() mutable {\n                auto desc = pixel_format_desc(pixel_format::bgra);\n                desc.planes.push_back(pixel_format_desc::plane(format_desc.width, format_desc.height, 4, depth));\n                std::vector<array<const uint8_t>> image_data;\n                auto                              tuple = std::move(result.get());\n                image_data.emplace_back(std::move(std::get<0>(tuple)));\n                return const_frame(tag, std::move(image_data), std::move(audio), desc, std::move(std::get<1>(tuple)));\n            }));\n\n        if (buffer_.size() <= format_desc.field_count) {\n            return const_frame{};\n        }\n\n        auto frame = std::move(buffer_.front().get());\n        buffer_.pop();\n        return frame;\n    }\n\n    void set_master_volume(float volume) { audio_mixer_.set_master_volume(volume); }\n\n    float get_master_volume() { return audio_mixer_.get_master_volume(); }\n};\n\nmixer::mixer(int channel_index, spl::shared_ptr<diagnostics::graph> graph, spl::shared_ptr<image_mixer> image_mixer)\n    : impl_(new impl(channel_index, std::move(graph), std::move(image_mixer)))\n{\n}\nvoid        mixer::set_master_volume(float volume) { impl_->set_master_volume(volume); }\nfloat       mixer::get_master_volume() { return impl_->get_master_volume(); }\nconst_frame mixer::operator()(std::vector<draw_frame> frames, const video_format_desc& format_desc, int nb_samples)\n{\n    return (*impl_)(std::move(frames), format_desc, nb_samples);\n}\nmutable_frame mixer::create_frame(const void* tag, const pixel_format_desc& desc)\n{\n    return impl_->image_mixer_->create_frame(tag, desc);\n}\ncore::monitor::state mixer::state() const { return impl_->state_; }\n\ncommon::bit_depth mixer::depth() const { return impl_->image_mixer_->depth(); }\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/mixer/mixer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/fwd.h>\n#include <core/monitor/monitor.h>\n\nnamespace caspar::diagnostics {\nclass graph;\n}\n\nnamespace caspar { namespace core {\n\nclass mixer final\n{\n    mixer(const mixer&);\n    mixer& operator=(const mixer&);\n\n  public:\n    explicit mixer(int                                         channel_index,\n                   spl::shared_ptr<caspar::diagnostics::graph> graph,\n                   spl::shared_ptr<image_mixer>                image_mixer);\n\n    const_frame operator()(std::vector<draw_frame> frames, const video_format_desc& format_desc, int nb_samples);\n\n    void  set_master_volume(float volume);\n    float get_master_volume();\n\n    mutable_frame create_frame(const void* tag, const pixel_format_desc& desc);\n\n    core::monitor::state state() const;\n\n    common::bit_depth depth() const;\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/module_dependencies.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include \"consumer/frame_consumer_registry.h\"\n#include \"producer/cg_proxy.h\"\n#include \"producer/frame_producer_registry.h\"\n\nnamespace caspar::protocol::amcp {\nclass amcp_command_repository_wrapper;\n}\n\nnamespace caspar::core {\n\nstruct module_dependencies\n{\n    const spl::shared_ptr<cg_producer_registry>                            cg_registry;\n    const spl::shared_ptr<frame_producer_registry>                         producer_registry;\n    const spl::shared_ptr<frame_consumer_registry>                         consumer_registry;\n    const std::shared_ptr<protocol::amcp::amcp_command_repository_wrapper> command_repository;\n\n    module_dependencies(const spl::shared_ptr<cg_producer_registry>&                            cg_registry,\n                        const spl::shared_ptr<frame_producer_registry>&                         producer_registry,\n                        const spl::shared_ptr<frame_consumer_registry>&                         consumer_registry,\n                        const std::shared_ptr<protocol::amcp::amcp_command_repository_wrapper>& command_repository)\n        : cg_registry(cg_registry)\n        , producer_registry(producer_registry)\n        , consumer_registry(consumer_registry)\n        , command_repository(command_repository)\n    {\n    }\n};\n\n} // namespace caspar::core\n"
  },
  {
    "path": "src/core/monitor/monitor.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#pragma once\n\n#include <boost/lexical_cast.hpp>\n#include <boost/variant.hpp>\n\n#include <cstdint>\n#include <string>\n#include <vector>\n\n#include <boost/container/flat_map.hpp>\n#include <boost/container/small_vector.hpp>\n\nnamespace caspar { namespace core { namespace monitor {\n\nusing data_t = boost::\n    variant<bool, std::int32_t, std::int64_t, std::uint32_t, std::uint64_t, float, double, std::string, std::wstring>;\nusing vector_t   = boost::container::small_vector<data_t, 2>;\nusing data_map_t = boost::container::flat_map<std::string, vector_t>;\n\nclass state\n{\n    data_map_t data_;\n\n    class state_proxy\n    {\n        std::string key_;\n        data_map_t& data_;\n\n      public:\n        state_proxy(const std::string& key, data_map_t& data)\n            : key_(key)\n            , data_(data)\n        {\n        }\n\n        state_proxy& operator=(data_t data)\n        {\n            data_[key_] = {std::move(data)};\n            return *this;\n        }\n\n        state_proxy& operator=(vector_t data)\n        {\n            data_[key_] = std::move(data);\n            return *this;\n        }\n\n        template <typename T>\n        state_proxy operator[](const T& key)\n        {\n            return state_proxy(key_ + \"/\" + boost::lexical_cast<std::string>(key), data_);\n        }\n\n        template <typename T>\n        state_proxy& operator=(const std::vector<T>& data)\n        {\n            data_[key_] = vector_t(data.begin(), data.end());\n            return *this;\n        }\n\n        state_proxy& operator=(std::initializer_list<data_t> data)\n        {\n            data_[key_] = vector_t(std::move(data));\n            return *this;\n        }\n\n        state_proxy& operator=(const state& other)\n        {\n            for (auto& p : other) {\n                data_[key_ + \"/\" + p.first] = std::move(p.second);\n            }\n            return *this;\n        }\n    };\n\n  public:\n    state() = default;\n    state(const state& other)\n        : data_(other.data_)\n    {\n    }\n    state(data_map_t data)\n        : data_(std::move(data))\n    {\n    }\n    state& operator=(const state& other)\n    {\n        data_ = other.data_;\n        return *this;\n    }\n\n    template <typename T>\n    state_proxy operator[](const T& key)\n    {\n        return state_proxy(boost::lexical_cast<std::string>(key), data_);\n    }\n\n    data_map_t::const_iterator begin() const { return data_.begin(); }\n\n    data_map_t::const_iterator end() const { return data_.end(); }\n};\n\n}}} // namespace caspar::core::monitor\n"
  },
  {
    "path": "src/core/producer/cg_proxy.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../StdAfx.h\"\n\n#include \"cg_proxy.h\"\n\n#include \"../diagnostics/call_context.h\"\n#include \"../video_channel.h\"\n#include \"frame_producer.h\"\n#include \"stage.h\"\n\n#include <common/env.h>\n#include <common/os/filesystem.h>\n#include <common/param.h>\n\n#include <boost/filesystem.hpp>\n\n#include <future>\n#include <map>\n#include <optional>\n\nnamespace caspar { namespace core {\n\nconst spl::shared_ptr<cg_proxy>& cg_proxy::empty()\n{\n    class empty_proxy : public cg_proxy\n    {\n        void         add(int, const std::wstring&, bool, const std::wstring&, const std::wstring&) override {}\n        void         remove(int) override {}\n        void         play(int) override {}\n        void         stop(int) override {}\n        void         next(int) override {}\n        void         update(int, const std::wstring&) override {}\n        std::wstring invoke(int, const std::wstring&) override { return L\"\"; }\n    };\n\n    static spl::shared_ptr<cg_proxy> instance = spl::make_shared<empty_proxy>();\n    return instance;\n}\n\nstruct cg_producer_registry::impl\n{\n  private:\n    struct record\n    {\n        std::wstring        name;\n        cg_proxy_factory    proxy_factory;\n        cg_producer_factory producer_factory;\n        bool                reusable_producer_instance;\n    };\n\n    mutable std::mutex             mutex_;\n    std::map<std::wstring, record> records_by_extension_;\n\n  public:\n    void register_cg_producer(std::wstring           cg_producer_name,\n                              std::set<std::wstring> file_extensions,\n                              cg_proxy_factory       proxy_factory,\n                              cg_producer_factory    producer_factory,\n                              bool                   reusable_producer_instance)\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        record rec{std::move(cg_producer_name),\n                   std::move(proxy_factory),\n                   std::move(producer_factory),\n                   reusable_producer_instance};\n\n        for (auto& extension : file_extensions) {\n            records_by_extension_.insert(std::make_pair(extension, rec));\n        }\n    }\n\n    spl::shared_ptr<frame_producer> create_producer(const frame_producer_dependencies& dependencies,\n                                                    const std::wstring&                filename) const\n    {\n        auto found = find_record(filename);\n\n        if (!found)\n            return frame_producer::empty();\n\n        return found->producer_factory(dependencies, filename);\n    }\n\n    spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<frame_producer>& producer) const\n    {\n        auto producer_name = producer->name();\n\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        for (auto& elem : records_by_extension_) {\n            if (elem.second.name == producer_name)\n                return elem.second.proxy_factory(producer);\n        }\n\n        return cg_proxy::empty();\n    }\n\n    spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<video_channel>& video_channel, int render_layer) const\n    {\n        auto producer = spl::make_shared_ptr(video_channel->stage()->foreground(render_layer).get());\n\n        return get_proxy(producer);\n    }\n\n    spl::shared_ptr<cg_proxy> get_or_create_proxy(const spl::shared_ptr<video_channel>& video_channel,\n                                                  const frame_producer_dependencies&    dependencies,\n                                                  int                                   render_layer,\n                                                  const std::wstring&                   filename) const\n    {\n        using namespace boost::filesystem;\n\n        auto found = find_record(filename);\n\n        if (!found)\n            return cg_proxy::empty();\n\n        auto producer              = spl::make_shared_ptr(video_channel->stage()->foreground(render_layer).get());\n        auto current_producer_name = producer->name();\n        bool create_new            = current_producer_name != found->name || !found->reusable_producer_instance;\n\n        if (create_new) {\n            diagnostics::scoped_call_context save;\n            diagnostics::call_context::for_thread().video_channel = video_channel->index();\n            diagnostics::call_context::for_thread().layer         = render_layer;\n\n            producer = found->producer_factory(dependencies, filename);\n            if (producer == core::frame_producer::empty())\n                return cg_proxy::empty();\n\n            video_channel->stage()->load(render_layer, producer);\n            video_channel->stage()->play(render_layer);\n        }\n\n        return found->proxy_factory(producer);\n    }\n\n    bool is_cg_extension(const std::wstring& extension) const\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        return records_by_extension_.find(extension) != records_by_extension_.end();\n    }\n\n    std::wstring get_cg_producer_name(const std::wstring& filename) const\n    {\n        auto record = find_record(filename);\n\n        if (!record)\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(filename + L\" is not a cg template.\"));\n\n        return record->name;\n    }\n\n  private:\n    std::optional<record> find_record(const std::wstring& filename) const\n    {\n        using namespace boost::filesystem;\n\n        auto basepath = path(env::template_folder()) / path(filename);\n\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        for (auto& rec : records_by_extension_) {\n            auto p = path(basepath.wstring() + rec.first);\n\n            if (find_case_insensitive(p.wstring()))\n                return rec.second;\n        }\n\n        auto protocol = caspar::protocol_split(filename).first;\n        if (!protocol.empty()) {\n            auto ext = path(filename).extension().wstring();\n\n            for (auto& rec : records_by_extension_) {\n                if (rec.first == ext)\n                    return rec.second;\n            }\n        }\n\n        // TODO (fix): This is a hack to allow query params.\n        for (auto& rec : records_by_extension_) {\n            if (rec.first == L\".html\")\n                return rec.second;\n        }\n\n        return {};\n    }\n};\n\ncg_producer_registry::cg_producer_registry()\n    : impl_(new impl)\n{\n}\n\nvoid cg_producer_registry::register_cg_producer(std::wstring           cg_producer_name,\n                                                std::set<std::wstring> file_extensions,\n                                                cg_proxy_factory       proxy_factory,\n                                                cg_producer_factory    producer_factory,\n                                                bool                   reusable_producer_instance)\n{\n    impl_->register_cg_producer(std::move(cg_producer_name),\n                                std::move(file_extensions),\n                                std::move(proxy_factory),\n                                std::move(producer_factory),\n                                reusable_producer_instance);\n}\n\nspl::shared_ptr<frame_producer> cg_producer_registry::create_producer(const frame_producer_dependencies& dependencies,\n                                                                      const std::wstring&                filename) const\n{\n    return impl_->create_producer(dependencies, filename);\n}\n\nspl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(const spl::shared_ptr<frame_producer>& producer) const\n{\n    return impl_->get_proxy(producer);\n}\n\nspl::shared_ptr<cg_proxy> cg_producer_registry::get_proxy(const spl::shared_ptr<video_channel>& video_channel,\n                                                          int                                   render_layer) const\n{\n    return impl_->get_proxy(video_channel, render_layer);\n}\n\nspl::shared_ptr<cg_proxy> cg_producer_registry::get_or_create_proxy(const spl::shared_ptr<video_channel>& video_channel,\n                                                                    const frame_producer_dependencies&    dependencies,\n                                                                    int                                   render_layer,\n                                                                    const std::wstring& filename) const\n{\n    return impl_->get_or_create_proxy(video_channel, dependencies, render_layer, filename);\n}\n\nbool cg_producer_registry::is_cg_extension(const std::wstring& extension) const\n{\n    return impl_->is_cg_extension(extension);\n}\n\nstd::wstring cg_producer_registry::get_cg_producer_name(const std::wstring& filename) const\n{\n    return impl_->get_cg_producer_name(filename);\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/cg_proxy.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"frame_producer.h\"\n\n#include <common/memory.h>\n\n#include <functional>\n#include <set>\n#include <string>\n\nnamespace caspar { namespace core {\n\nclass cg_proxy\n{\n  public:\n    static const unsigned int DEFAULT_LAYER = 9999;\n\n    virtual ~cg_proxy() {}\n\n    virtual void         add(int                 layer,\n                             const std::wstring& template_name,\n                             bool                play_on_load,\n                             const std::wstring& start_from_label = L\"\",\n                             const std::wstring& data             = L\"\")          = 0;\n    virtual void         remove(int layer)                            = 0;\n    virtual void         play(int layer)                              = 0;\n    virtual void         stop(int layer)                              = 0;\n    virtual void         next(int layer)                              = 0;\n    virtual void         update(int layer, const std::wstring& data)  = 0;\n    virtual std::wstring invoke(int layer, const std::wstring& label) = 0;\n\n    static const spl::shared_ptr<cg_proxy>& empty();\n};\n\nusing cg_proxy_factory = std::function<spl::shared_ptr<cg_proxy>(const spl::shared_ptr<frame_producer>& producer)>;\nusing cg_producer_factory =\n    std::function<spl::shared_ptr<frame_producer>(const frame_producer_dependencies& dependencies,\n                                                  const std::wstring&                filename)>;\n\nclass cg_producer_registry\n{\n  public:\n    cg_producer_registry();\n\n    void register_cg_producer(std::wstring           cg_producer_name,\n                              std::set<std::wstring> file_extensions,\n                              cg_proxy_factory       proxy_factory,\n                              cg_producer_factory    producer_factory,\n                              bool                   reusable_producer_instance);\n\n    spl::shared_ptr<frame_producer> create_producer(const frame_producer_dependencies& dependencies,\n                                                    const std::wstring&                filename) const;\n\n    spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<frame_producer>& producer) const;\n    spl::shared_ptr<cg_proxy> get_proxy(const spl::shared_ptr<video_channel>& video_channel, int render_layer) const;\n    spl::shared_ptr<cg_proxy> get_or_create_proxy(const spl::shared_ptr<video_channel>& video_channel,\n                                                  const frame_producer_dependencies&    dependencies,\n                                                  int                                   render_layer,\n                                                  const std::wstring&                   filename) const;\n\n    bool         is_cg_extension(const std::wstring& extension) const;\n    std::wstring get_cg_producer_name(const std::wstring& filename) const;\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n\n    cg_producer_registry(const cg_producer_registry&)            = delete;\n    cg_producer_registry& operator=(const cg_producer_registry&) = delete;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/color/color_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../StdAfx.h\"\n\n#include \"color_producer.h\"\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/pixel_format.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <common/array.h>\n#include <common/except.h>\n#include <common/scope_exit.h>\n\n#include <boost/algorithm/string.hpp>\n\n#include <sstream>\n\nnamespace caspar { namespace core {\n\ndraw_frame\ncreate_color_frame(void* tag, const spl::shared_ptr<frame_factory>& frame_factory, const std::vector<uint32_t>& values)\n{\n    core::pixel_format_desc desc(pixel_format::bgra);\n    desc.planes.push_back(core::pixel_format_desc::plane(static_cast<int>(values.size()), 1, 4));\n    auto frame = frame_factory->create_frame(tag, desc);\n\n    for (int i = 0; i < values.size(); ++i)\n        *reinterpret_cast<uint32_t*>(frame.image_data(0).begin() + i * 4) = values.at(i);\n\n    return core::draw_frame(std::move(frame));\n}\n\ndraw_frame create_color_frame(void* tag, const spl::shared_ptr<frame_factory>& frame_factory, uint32_t value)\n{\n    std::vector<uint32_t> values = {value};\n\n    return create_color_frame(tag, frame_factory, values);\n}\n\ndraw_frame create_color_frame(void*                                 tag,\n                              const spl::shared_ptr<frame_factory>& frame_factory,\n                              const std::vector<std::wstring>&      strs)\n{\n    std::vector<uint32_t> values(strs.size());\n\n    for (int i = 0; i < values.size(); ++i) {\n        if (!try_get_color(strs.at(i), values.at(i)))\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid color: \" + strs.at(i)));\n    }\n\n    return create_color_frame(tag, frame_factory, values);\n}\n\nclass color_producer : public frame_producer\n{\n    monitor::state state_;\n\n    const std::wstring color_str_;\n    draw_frame         frame_;\n\n  public:\n    color_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, uint32_t value)\n        : frame_(create_color_frame(this, frame_factory, value))\n    {\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    color_producer(const spl::shared_ptr<core::frame_factory>& frame_factory, const std::vector<std::wstring>& colors)\n        : color_str_(boost::join(colors, L\", \"))\n        , frame_(create_color_frame(this, frame_factory, colors))\n    {\n        state_[\"color\"] = color_str_;\n\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    // frame_producer\n\n    draw_frame receive_impl(const core::video_field field, int nb_samples) override { return frame_; }\n\n    std::wstring print() const override { return L\"color[\" + color_str_ + L\"]\"; }\n\n    std::wstring name() const override { return L\"color\"; }\n\n    core::monitor::state state() const override { return state_; }\n\n    bool is_ready() override { return true; }\n};\n\nstd::wstring get_hex_color(const std::wstring& str)\n{\n    if (str.size() == 0)\n        return str;\n\n    if (str.at(0) == '#')\n        return str.length() == 7 ? L\"#FF\" + str.substr(1) : str;\n\n    std::wstring col_str = boost::to_upper_copy(str);\n\n    if (col_str == L\"EMPTY\")\n        return L\"#00000000\";\n\n    if (col_str == L\"BLACK\")\n        return L\"#FF000000\";\n\n    if (col_str == L\"WHITE\")\n        return L\"#FFFFFFFF\";\n\n    if (col_str == L\"RED\")\n        return L\"#FFFF0000\";\n\n    if (col_str == L\"GREEN\")\n        return L\"#FF00FF00\";\n\n    if (col_str == L\"BLUE\")\n        return L\"#FF0000FF\";\n\n    if (col_str == L\"ORANGE\")\n        return L\"#FFFFA500\";\n\n    if (col_str == L\"YELLOW\")\n        return L\"#FFFFFF00\";\n\n    if (col_str == L\"BROWN\")\n        return L\"#FFA52A2A\";\n\n    if (col_str == L\"GRAY\")\n        return L\"#FF808080\";\n\n    if (col_str == L\"TEAL\")\n        return L\"#FF008080\";\n\n    return str;\n}\n\nbool try_get_color(const std::wstring& str, uint32_t& value)\n{\n    auto color_str = get_hex_color(str);\n    if (color_str.length() != 9 || color_str[0] != '#')\n        return false;\n\n    std::wstringstream ss(color_str.substr(1));\n    if (!(ss >> std::hex >> value) || !ss.eof())\n        return false;\n\n    return true;\n}\nspl::shared_ptr<frame_producer> create_color_producer(const spl::shared_ptr<frame_factory>& frame_factory,\n                                                      uint32_t                              value)\n{\n    return spl::make_shared<color_producer>(frame_factory, value);\n}\n\nspl::shared_ptr<frame_producer> create_color_producer(const spl::shared_ptr<frame_factory>& frame_factory,\n                                                      const std::vector<std::wstring>&      params)\n{\n    if (params.size() < 1)\n        return core::frame_producer::empty();\n\n    uint32_t value = 0;\n    if (!try_get_color(params.at(0), value))\n        return core::frame_producer::empty();\n\n    std::vector<std::wstring> colors;\n\n    for (auto& param : params) {\n        if (try_get_color(param, value)) {\n            colors.push_back(param);\n        } else {\n            // Stop after something not a colour, as that probably means the transition definition\n            break;\n        }\n    }\n\n    return spl::make_shared<color_producer>(frame_factory, colors);\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/color/color_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <cstdint>\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nbool try_get_color(const std::wstring& str, uint32_t& value);\n\nspl::shared_ptr<frame_producer> create_color_producer(const spl::shared_ptr<frame_factory>& frame_factory,\n                                                      uint32_t                              value);\nspl::shared_ptr<frame_producer> create_color_producer(const spl::shared_ptr<frame_factory>& frame_factory,\n                                                      const std::vector<std::wstring>&      params);\ndraw_frame create_color_frame(void* tag, const spl::shared_ptr<frame_factory>& frame_factory, uint32_t value);\ndraw_frame\ncreate_color_frame(void* tag, const spl::shared_ptr<frame_factory>& frame_factory, const std::wstring& color);\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/frame_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"cg_proxy.h\"\n#include \"frame_producer.h\"\n\n#include <common/except.h>\n#include <common/future.h>\n#include <common/memory.h>\n\n#include <boost/algorithm/string/predicate.hpp>\n\nnamespace caspar { namespace core {\n\nframe_producer_dependencies::frame_producer_dependencies(\n    const spl::shared_ptr<core::frame_factory>&           frame_factory,\n    const std::vector<spl::shared_ptr<video_channel>>&    channels,\n    const video_format_repository&                        format_repository,\n    const video_format_desc&                              format_desc,\n    const spl::shared_ptr<const frame_producer_registry>& producer_registry,\n    const spl::shared_ptr<const cg_producer_registry>&    cg_registry)\n    : frame_factory(frame_factory)\n    , channels(channels)\n    , format_repository(format_repository)\n    , format_desc(format_desc)\n    , producer_registry(producer_registry)\n    , cg_registry(cg_registry)\n{\n}\n\nconst spl::shared_ptr<frame_producer>& frame_producer::empty()\n{\n    class empty_frame_producer : public frame_producer\n    {\n      public:\n        empty_frame_producer() {}\n\n        draw_frame   receive_impl(const core::video_field field, int nb_samples) override { return draw_frame{}; }\n        uint32_t     nb_frames() const override { return 0; }\n        std::wstring print() const override { return L\"empty\"; }\n        std::wstring name() const override { return L\"empty\"; }\n        uint32_t     frame_number() const override { return 0; }\n        std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n        {\n            CASPAR_LOG(warning) << L\" Cannot call on empty frame_producer\";\n            return make_ready_future(std::wstring());\n        }\n        draw_frame           last_frame(const core::video_field field) override { return draw_frame{}; }\n        draw_frame           first_frame(const core::video_field field) override { return draw_frame{}; }\n        core::monitor::state state() const override\n        {\n            static const monitor::state empty;\n            return empty;\n        }\n\n        bool is_ready() override { return true; }\n    };\n\n    static spl::shared_ptr<frame_producer> producer = spl::make_shared<empty_frame_producer>();\n    return producer;\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/frame_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n\n#include <common/except.h>\n#include <common/memory.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/video_format.h>\n\n#include <cstdint>\n#include <functional>\n#include <future>\n#include <optional>\n#include <string>\n#include <type_traits>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nclass frame_producer\n{\n    frame_producer(const frame_producer&);\n    frame_producer& operator=(const frame_producer&);\n\n    uint32_t         frame_number_ = 0;\n    core::draw_frame last_frame_;\n    core::draw_frame first_frame_;\n    bool             is_ready_ = false;\n\n  public:\n    static const spl::shared_ptr<frame_producer>& empty();\n\n    frame_producer()          = default;\n    virtual ~frame_producer() = default;\n\n    draw_frame receive(const video_field field, int nb_samples)\n    {\n        if (frame_number_ == 0 && first_frame_) {\n            frame_number_ += 1;\n            return first_frame_;\n        }\n\n        auto frame = receive_impl(field, nb_samples);\n\n        if (frame) {\n            frame_number_ += 1;\n            last_frame_ = frame;\n\n            if (!first_frame_) {\n                first_frame_ = frame;\n            }\n        }\n\n        return frame;\n    }\n\n    virtual draw_frame receive_impl(const video_field field, int nb_samples) = 0;\n\n    virtual std::future<std::wstring> call(const std::vector<std::wstring>& params)\n    {\n        CASPAR_THROW_EXCEPTION(not_implemented());\n    }\n\n    virtual core::monitor::state state() const = 0;\n    virtual std::wstring         print() const = 0;\n    virtual std::wstring         name() const  = 0;\n    virtual uint32_t             frame_number() const { return frame_number_; }\n    virtual uint32_t             nb_frames() const { return std::numeric_limits<uint32_t>::max(); }\n    virtual draw_frame           last_frame(const video_field field)\n    {\n        if (!last_frame_) {\n            last_frame_ = receive_impl(field, 0);\n        }\n        return core::draw_frame::still(last_frame_);\n    }\n    virtual draw_frame first_frame(const video_field field)\n    {\n        if (!first_frame_) {\n            first_frame_ = receive_impl(field, 0);\n        }\n        return core::draw_frame::still(first_frame_);\n    }\n    virtual void                            leading_producer(const spl::shared_ptr<frame_producer>&) {}\n    virtual spl::shared_ptr<frame_producer> following_producer() const { return core::frame_producer::empty(); }\n    virtual std::optional<int64_t>          auto_play_delta() const { return {}; }\n\n    /**\n     * Some producers take a couple of frames before they produce frames.\n     * While this returns false, the previous producer will be left running for a limited number of frames.\n     */\n    virtual bool is_ready() = 0;\n};\n\nclass const_producer : public core::frame_producer\n{\n    const core::draw_frame frame1_;\n    const core::draw_frame frame2_;\n\n  public:\n    const_producer(core::draw_frame frame1, core::draw_frame frame2)\n        : frame1_(std::move(frame1))\n        , frame2_(std::move(frame2))\n    {\n    }\n\n    // frame_producer\n\n    core::draw_frame last_frame(const core::video_field field) override\n    {\n        if (field == core::video_field::b)\n            return frame2_;\n        else\n            return frame1_;\n    }\n\n    core::draw_frame first_frame(const core::video_field field) override { return last_frame(field); }\n\n    core::draw_frame receive_impl(const video_field field, int nb_samples) override { return last_frame(field); }\n\n    std::wstring name() const override { return L\"const_producer\"; }\n\n    std::wstring print() const override { return L\"const_producer\"; }\n\n    core::monitor::state state() const override\n    {\n        static const monitor::state empty;\n        return empty;\n    }\n\n    bool is_ready() override { return true; }\n};\n\nclass frame_producer_registry;\n\nstruct frame_producer_dependencies\n{\n    spl::shared_ptr<core::frame_factory>           frame_factory;\n    std::vector<spl::shared_ptr<video_channel>>    channels;\n    video_format_repository                        format_repository;\n    video_format_desc                              format_desc;\n    spl::shared_ptr<const frame_producer_registry> producer_registry;\n    spl::shared_ptr<const cg_producer_registry>    cg_registry;\n\n    frame_producer_dependencies(const spl::shared_ptr<core::frame_factory>&           frame_factory,\n                                const std::vector<spl::shared_ptr<video_channel>>&    channels,\n                                const video_format_repository&                        format_repository,\n                                const video_format_desc&                              format_desc,\n                                const spl::shared_ptr<const frame_producer_registry>& producer_registry,\n                                const spl::shared_ptr<const cg_producer_registry>&    cg_registry);\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/frame_producer_registry.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"../StdAfx.h\"\n\n#include \"cg_proxy.h\"\n#include \"frame_producer.h\"\n#include \"frame_producer_registry.h\"\n\n#include \"color/color_producer.h\"\n#include \"route/route_producer.h\"\n#include \"separated/separated_producer.h\"\n\n#include <boost/algorithm/string/predicate.hpp>\n\nnamespace caspar { namespace core {\n\nframe_producer_registry::frame_producer_registry() {}\n\nvoid frame_producer_registry::register_producer_factory(std::wstring name, const producer_factory_t& factory)\n{\n    producer_factories_.push_back(factory);\n}\n\nstd::shared_ptr<executor>& producer_destroyer()\n{\n    static auto destroyer = [] {\n        auto result = std::make_shared<executor>(L\"Producer destroyer\");\n        result->set_capacity(std::numeric_limits<unsigned int>::max());\n        return result;\n    }();\n\n    return destroyer;\n}\n\nstd::atomic<bool>& destroy_producers_in_separate_thread()\n{\n    static std::atomic<bool> state;\n\n    return state;\n}\n\nvoid destroy_producers_synchronously()\n{\n    destroy_producers_in_separate_thread() = false;\n    // Join destroyer, executing rest of producers in queue synchronously.\n    producer_destroyer().reset();\n}\n\nclass destroy_producer_proxy : public frame_producer\n{\n    std::shared_ptr<frame_producer> producer_;\n\n  public:\n    destroy_producer_proxy(spl::shared_ptr<frame_producer>&& producer)\n        : producer_(std::move(producer))\n    {\n        destroy_producers_in_separate_thread() = true;\n    }\n\n    virtual ~destroy_producer_proxy()\n    {\n        if (producer_ == core::frame_producer::empty() || !destroy_producers_in_separate_thread())\n            return;\n\n        auto destroyer = producer_destroyer();\n\n        if (!destroyer)\n            return;\n\n        CASPAR_VERIFY(destroyer->size() < 8);\n\n        auto producer = new spl::shared_ptr<frame_producer>(std::move(producer_));\n\n        destroyer->begin_invoke([=] {\n            std::unique_ptr<spl::shared_ptr<frame_producer>> pointer_guard(producer);\n            auto                                             str = (*producer)->print();\n            try {\n                if (producer->use_count() != 1)\n                    CASPAR_LOG(debug) << str << L\" Not destroyed on asynchronous destruction thread: \"\n                                      << producer->use_count();\n                else\n                    CASPAR_LOG(debug) << str << L\" Destroying on asynchronous destruction thread.\";\n            } catch (...) {\n            }\n\n            try {\n                pointer_guard.reset();\n                CASPAR_LOG(info) << str << L\" Destroyed.\";\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        });\n    }\n\n    draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        return producer_->receive(field, nb_samples);\n    }\n    std::wstring              print() const override { return producer_->print(); }\n    std::wstring              name() const override { return producer_->name(); }\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override { return producer_->call(params); }\n    void                      leading_producer(const spl::shared_ptr<frame_producer>& producer) override\n    {\n        return producer_->leading_producer(producer);\n    }\n    uint32_t             frame_number() const override { return producer_->frame_number(); }\n    uint32_t             nb_frames() const override { return producer_->nb_frames(); }\n    draw_frame           last_frame(const core::video_field field) override { return producer_->last_frame(field); }\n    draw_frame           first_frame(const core::video_field field) override { return producer_->first_frame(field); }\n    core::monitor::state state() const override { return producer_->state(); }\n    bool                 is_ready() override { return producer_->is_ready(); }\n};\n\nspl::shared_ptr<core::frame_producer> do_create_producer(const frame_producer_dependencies&     dependencies,\n                                                         const std::vector<std::wstring>&       params,\n                                                         const std::vector<producer_factory_t>& factories,\n                                                         bool                                   throw_on_fail = false)\n{\n    if (params.empty()) {\n        CASPAR_THROW_EXCEPTION(invalid_argument() << msg_info(\"params cannot be empty\"));\n    }\n\n    auto producer = create_color_producer(dependencies.frame_factory, params);\n    if (producer != frame_producer::empty()) {\n        return producer;\n    }\n\n    producer = create_route_producer(dependencies, params);\n    if (producer != frame_producer::empty()) {\n        return producer;\n    }\n\n    if (std::any_of(factories.begin(), factories.end(), [&](const producer_factory_t& factory) -> bool {\n            try {\n                producer = factory(dependencies, params);\n            } catch (user_error&) {\n                throw;\n            } catch (...) {\n                if (throw_on_fail)\n                    throw;\n                else\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n            return producer != frame_producer::empty();\n        })) {\n        return producer;\n    }\n    return frame_producer::empty();\n}\n\nspl::shared_ptr<core::frame_producer>\nframe_producer_registry::create_producer(const frame_producer_dependencies& dependencies,\n                                         const std::vector<std::wstring>&   params) const\n{\n    auto& producer_factories = producer_factories_;\n    auto  producer           = do_create_producer(dependencies, params, producer_factories);\n    auto  key_producer       = frame_producer::empty();\n\n    if (!params.empty() && !boost::contains(params.at(0), L\"://\")) {\n        try // to find a key file.\n        {\n            auto params_copy = params;\n            params_copy[0] += L\"_A\";\n            key_producer = do_create_producer(dependencies, params_copy, producer_factories);\n            if (key_producer == frame_producer::empty()) {\n                params_copy[0] += L\"LPHA\";\n                key_producer = do_create_producer(dependencies, params_copy, producer_factories);\n            }\n        } catch (...) {\n        }\n    }\n\n    if (producer != frame_producer::empty() && key_producer != frame_producer::empty())\n        return create_separated_producer(producer, key_producer);\n\n    if (producer == frame_producer::empty()) {\n        std::wstring str;\n        for (auto& param : params)\n            str += param + L\" \";\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(\"No match found for supplied commands. Check syntax.\")\n                                                << arg_value_info(u8(str)));\n    }\n\n    // Skip destroy_producer_proxy for route_producer, as it needs to be able to perform this cast\n    // This isn't a nice approach, but it keeps it simple and ensures every other producer has the\n    // destroy_producer_proxy wrapping\n    if (spl::instance_of<core::route_control>(producer)) {\n        return std::move(producer);\n    }\n\n    return spl::make_shared<destroy_producer_proxy>(std::move(producer));\n}\n\nspl::shared_ptr<core::frame_producer>\nframe_producer_registry::create_producer(const frame_producer_dependencies& dependencies,\n                                         const std::wstring&                params) const\n{\n    std::wstringstream        iss(params);\n    std::vector<std::wstring> tokens;\n    using iterator = std::istream_iterator<std::wstring, wchar_t, std::char_traits<wchar_t>>;\n    std::copy(iterator(iss), iterator(), std::back_inserter(tokens));\n    return create_producer(dependencies, tokens);\n}\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/frame_producer_registry.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n\n#include <common/except.h>\n#include <common/memory.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/video_format.h>\n\n#include <cstdint>\n#include <functional>\n#include <future>\n#include <optional>\n#include <string>\n#include <type_traits>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nusing producer_factory_t = std::function<spl::shared_ptr<core::frame_producer>(const frame_producer_dependencies&,\n                                                                               const std::vector<std::wstring>&)>;\n\nclass frame_producer_registry\n{\n  public:\n    frame_producer_registry();\n    void register_producer_factory(std::wstring name, const producer_factory_t& factoryr); // Not thread-safe.\n    spl::shared_ptr<core::frame_producer> create_producer(const frame_producer_dependencies&,\n                                                          const std::vector<std::wstring>& params) const;\n    spl::shared_ptr<core::frame_producer> create_producer(const frame_producer_dependencies&,\n                                                          const std::wstring& params) const;\n\n  private:\n    std::vector<producer_factory_t> producer_factories_;\n\n    frame_producer_registry(const frame_producer_registry&)            = delete;\n    frame_producer_registry& operator=(const frame_producer_registry&) = delete;\n};\n\nvoid destroy_producers_synchronously();\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/layer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"layer.h\"\n\n#include \"frame_producer.h\"\n\n#include \"../frame/draw_frame.h\"\n#include \"../video_format.h\"\n\nnamespace caspar { namespace core {\n\nstruct layer::impl\n{\n    monitor::state                state_;\n    const core::video_format_desc format_desc_;\n\n    spl::shared_ptr<frame_producer> foreground_ = frame_producer::empty();\n    spl::shared_ptr<frame_producer> background_ = frame_producer::empty();\n\n    bool auto_play_ = false;\n    bool paused_    = false;\n\n  public:\n    impl(const core::video_format_desc format_desc)\n        : format_desc_(format_desc)\n    {\n    }\n\n    void pause() { paused_ = true; }\n\n    void resume() { paused_ = false; }\n\n    void load(spl::shared_ptr<frame_producer> producer, bool preview_producer, bool auto_play)\n    {\n        background_ = std::move(producer);\n        auto_play_  = auto_play;\n\n        if (auto_play_ && foreground_ == frame_producer::empty()) {\n            play();\n        } else if (preview_producer) {\n            preview(true);\n        }\n    }\n\n    void preview(bool force)\n    {\n        if (force || background_ != frame_producer::empty()) {\n            play();\n            paused_ = true;\n        }\n    }\n\n    void play()\n    {\n        if (background_ != frame_producer::empty()) {\n            if (!paused_) {\n                background_->leading_producer(foreground_);\n            } else {\n                if (format_desc_.field_count == 2) {\n                    auto frame1 = foreground_->last_frame(core::video_field::a);\n                    auto frame2 = foreground_->last_frame(core::video_field::b);\n                    background_->leading_producer(\n                        spl::make_shared<core::const_producer>(std::move(frame1), std::move(frame2)));\n                } else {\n                    auto frame = foreground_->last_frame(core::video_field::progressive);\n                    background_->leading_producer(spl::make_shared<core::const_producer>(frame, frame));\n                }\n            }\n\n            foreground_ = std::move(background_);\n            background_ = frame_producer::empty();\n\n            auto_play_ = false;\n        }\n\n        paused_ = false;\n    }\n\n    void stop()\n    {\n        foreground_ = frame_producer::empty();\n        auto_play_  = false;\n    }\n\n    draw_frame receive(const video_field field, int nb_samples)\n    {\n        try {\n            if (foreground_->following_producer() != core::frame_producer::empty() && field != video_field::b) {\n                foreground_ = foreground_->following_producer();\n            }\n\n            int64_t frames_left = 0;\n            if (auto_play_) {\n                auto auto_play_delta = background_->auto_play_delta();\n                if (auto_play_delta) {\n                    auto time     = static_cast<std::int64_t>(foreground_->frame_number());\n                    auto duration = static_cast<std::int64_t>(foreground_->nb_frames());\n                    frames_left   = duration - time - *auto_play_delta;\n                    if (frames_left < 1 && field != video_field::b) {\n                        play();\n                    }\n                }\n            }\n\n            auto frame = paused_ ? core::draw_frame{} : foreground_->receive(field, nb_samples);\n            if (!frame) {\n                frame = foreground_->last_frame(field);\n            }\n\n            state_                           = {};\n            state_[\"foreground\"]             = foreground_->state();\n            state_[\"foreground\"][\"producer\"] = foreground_->name();\n            state_[\"foreground\"][\"paused\"]   = paused_;\n\n            if (frames_left > 0) {\n                state_[\"foreground\"][\"frames_left\"] = frames_left;\n            }\n\n            state_[\"background\"]             = background_->state();\n            state_[\"background\"][\"producer\"] = background_->name();\n\n            return frame;\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n            stop();\n            return draw_frame{};\n        }\n    }\n\n    draw_frame receive_background(const video_field field, int nb_samples)\n    {\n        try {\n            return background_->first_frame(field);\n\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n            background_ = frame_producer::empty();\n            return draw_frame{};\n        }\n    }\n};\n\nlayer::layer(const core::video_format_desc format_desc)\n    : impl_(new impl(format_desc))\n{\n}\nlayer::layer(layer&& other)\n    : impl_(std::move(other.impl_))\n{\n}\nlayer& layer::operator=(layer&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\nvoid layer::swap(layer& other) { impl_.swap(other.impl_); }\nvoid layer::load(spl::shared_ptr<frame_producer> frame_producer, bool preview, bool auto_play)\n{\n    return impl_->load(std::move(frame_producer), preview, auto_play);\n}\nvoid       layer::play() { impl_->play(); }\nvoid       layer::preview() { impl_->preview(false); }\nvoid       layer::pause() { impl_->pause(); }\nvoid       layer::resume() { impl_->resume(); }\nvoid       layer::stop() { impl_->stop(); }\ndraw_frame layer::receive(const video_field field, int nb_samples) { return impl_->receive(field, nb_samples); }\ndraw_frame layer::receive_background(const video_field field, int nb_samples)\n{\n    return impl_->receive_background(field, nb_samples);\n}\nspl::shared_ptr<frame_producer> layer::foreground() const { return impl_->foreground_; }\nspl::shared_ptr<frame_producer> layer::background() const { return impl_->background_; }\nbool                            layer::has_background() const { return impl_->background_ != frame_producer::empty(); }\ncore::monitor::state            layer::state() const { return impl_->state_; }\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/layer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"frame_producer.h\"\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n\n#include <common/memory.h>\n\nnamespace caspar { namespace core {\n\nclass layer final\n{\n    layer(const layer&);\n    layer& operator=(const layer&);\n\n  public:\n    explicit layer(const core::video_format_desc format_desc);\n    layer(layer&& other);\n\n    layer& operator=(layer&& other);\n\n    void swap(layer& other);\n\n    void load(spl::shared_ptr<frame_producer> producer, bool preview, bool auto_play = false);\n    void play();\n    void preview();\n    void pause();\n    void resume();\n    void stop();\n\n    draw_frame receive(const video_field field, int nb_samples);\n    draw_frame receive_background(const video_field field, int nb_samples);\n\n    core::monitor::state state() const;\n\n    spl::shared_ptr<frame_producer> foreground() const;\n    spl::shared_ptr<frame_producer> background() const;\n    bool                            has_background() const;\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/route/route_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"route_producer.h\"\n\n#include <common/diagnostics/graph.h>\n#include <common/param.h>\n#include <common/timer.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/frame_visitor.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n#include <core/video_channel.h>\n\n#include <boost/regex.hpp>\n#include <boost/signals2.hpp>\n\n#include <tbb/concurrent_queue.h>\n\n#include <optional>\n#include <stack>\n#include <unordered_map>\n#include <unordered_set>\n\nnamespace caspar { namespace core {\n\nclass fix_stream_tag : public frame_visitor\n{\n    const void*                                                     route_producer_ptr_;\n    std::stack<std::pair<frame_transform, std::vector<draw_frame>>> frames_stack_;\n    std::optional<const_frame>                                      upd_frame_;\n\n    fix_stream_tag(const fix_stream_tag&);\n    fix_stream_tag& operator=(const fix_stream_tag&);\n\n  public:\n    fix_stream_tag(void* stream_tag)\n        : route_producer_ptr_(stream_tag)\n    {\n        frames_stack_ = std::stack<std::pair<frame_transform, std::vector<draw_frame>>>();\n        frames_stack_.emplace(frame_transform{}, std::vector<draw_frame>());\n    }\n\n    void push(const frame_transform& transform) { frames_stack_.emplace(transform, std::vector<core::draw_frame>()); }\n\n    void visit(const const_frame& frame)\n    {\n        // Get original tag from the frame\n        const void* source_tag = frame.stream_tag();\n\n        // Calculate a unique but stable tag for this source\n        // This calculation will always produce the same result for the same inputs\n        intptr_t base_addr   = reinterpret_cast<intptr_t>(route_producer_ptr_);\n        intptr_t source_addr = reinterpret_cast<intptr_t>(source_tag);\n        // Use XOR to create a unique value that combines route producer and source identities\n        intptr_t    unique_value = base_addr ^ source_addr ^ 0xDEADBEEF; // Constant helps avoid collisions\n        const void* unique_tag   = reinterpret_cast<const void*>(unique_value);\n\n        // Apply the tag to the frame\n        upd_frame_ = frame.with_tag(unique_tag);\n    }\n\n    void pop()\n    {\n        auto popped = frames_stack_.top();\n        frames_stack_.pop();\n\n        if (upd_frame_ != std::nullopt) {\n            auto new_frame        = draw_frame(std::move(*upd_frame_));\n            upd_frame_            = std::nullopt;\n            new_frame.transform() = popped.first;\n            frames_stack_.top().second.push_back(std::move(new_frame));\n        } else {\n            auto new_frame        = draw_frame(std::move(popped.second));\n            new_frame.transform() = popped.first;\n            frames_stack_.top().second.push_back(new_frame);\n        }\n    }\n\n    draw_frame operator()(draw_frame frame)\n    {\n        frame.accept(*this);\n\n        auto popped = frames_stack_.top();\n        frames_stack_.pop();\n        draw_frame result = draw_frame(std::move(popped.second));\n\n        frames_stack_ = std::stack<std::pair<frame_transform, std::vector<draw_frame>>>();\n        frames_stack_.emplace(frame_transform{}, std::vector<draw_frame>());\n        return result;\n    }\n};\n\nclass route_producer\n    : public frame_producer\n    , public route_control\n    , public std::enable_shared_from_this<route_producer>\n{\n    spl::shared_ptr<diagnostics::graph> graph_;\n\n    tbb::concurrent_bounded_queue<std::pair<core::draw_frame, core::draw_frame>> buffer_;\n\n    caspar::timer produce_timer_;\n    caspar::timer consume_timer_;\n\n    std::shared_ptr<route>  route_;\n    const video_format_desc format_desc_;\n\n    std::optional<std::pair<core::draw_frame, core::draw_frame>> frame_;\n    int                                                          source_channel_;\n    int                                                          source_layer_;\n    fix_stream_tag                                               tag_fix_;\n    core::video_format_desc                                      source_format_;\n    bool                                                         is_cross_channel_ = false;\n\n    boost::signals2::scoped_connection connection_;\n\n    int get_source_channel() const override { return source_channel_; }\n    int get_source_layer() const override { return source_layer_; }\n\n    // set the buffer depth to 2 for cross-channel routes, 1 otherwise\n    void set_cross_channel(bool cross) override\n    {\n        is_cross_channel_ = cross;\n        if (cross) {\n            buffer_.set_capacity(2);\n            source_format_ = route_->format_desc;\n        } else {\n            buffer_.set_capacity(1);\n            source_format_ = core::video_format_desc();\n        }\n    }\n\n  public:\n    route_producer(std::shared_ptr<route> route,\n                   video_format_desc      format_desc,\n                   int                    buffer,\n                   int                    source_channel,\n                   int                    source_layer)\n        : route_(route)\n        , format_desc_(format_desc)\n        , source_channel_(source_channel)\n        , source_layer_(source_layer)\n        , tag_fix_(this)\n    {\n        graph_ = spl::make_shared<diagnostics::graph>();\n        buffer_.set_capacity(buffer > 0 ? buffer : 1);\n\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        graph_->set_color(\"produce-time\", caspar::diagnostics::color(0.0f, 1.0f, 0.0f));\n        graph_->set_color(\"consume-time\", caspar::diagnostics::color(1.0f, 0.4f, 0.0f, 0.8f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        CASPAR_LOG(debug) << print() << L\" Initialized\";\n    }\n\n    void connect_slot()\n    {\n        auto weak_self = weak_from_this();\n        connection_ =\n            route_->signal.connect([weak_self](const core::draw_frame& frame1, const core::draw_frame& frame2) {\n                if (auto self = weak_self.lock()) {\n                    auto frame1b = frame1;\n                    if (!frame1b) {\n                        // We got a frame, so ensure it is a real frame (otherwise the layer gets confused)\n                        frame1b = core::draw_frame::push(frame1);\n                    }\n\n                    // Update the tag in the frame to allow the audio mixer to distinguish between the source frame and\n                    // the routed frame\n                    frame1b = self->tag_fix_(frame1b);\n\n                    auto frame2b = frame2;\n                    if (!frame2b) {\n                        // Ensure that any interlaced channel will repeat frames instead of showing black.\n                        frame2b = frame1b;\n                    } else {\n                        // For interlaced formats, ensure field B gets the proper tag as well\n                        frame2b = self->tag_fix_(frame2b);\n                    }\n\n                    if (!self->buffer_.try_push(std::make_pair(frame1b, frame2b))) {\n                        self->graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n                    }\n                    self->graph_->set_value(\"produce-time\",\n                                            self->produce_timer_.elapsed() * self->route_->format_desc.fps * 0.5);\n                    self->produce_timer_.restart();\n                }\n            });\n    }\n\n    draw_frame last_frame(const core::video_field field) override\n    {\n        if (!frame_) {\n            std::pair<core::draw_frame, core::draw_frame> frame;\n            if (buffer_.try_pop(frame)) {\n                frame_ = frame;\n            }\n        }\n\n        if (!frame_) {\n            return core::draw_frame{};\n        }\n\n        if (field == core::video_field::b) {\n            return core::draw_frame::still(frame_->second);\n        } else {\n            return core::draw_frame::still(frame_->first);\n        }\n    }\n\n    core::video_field next_field_ = core::video_field::a;\n    draw_frame        receive_impl(core::video_field field, int nb_samples) override\n    {\n        // If going i -> p, alternate between the fields\n        // Note: this doesn't fix the audio if going 50i -> 25p\n        if (field == core::video_field::progressive && source_format_.field_count != 1 &&\n            format_desc_.fps >= source_format_.fps) {\n            field       = next_field_;\n            next_field_ = (next_field_ == core::video_field::a) ? core::video_field::b : core::video_field::a;\n        }\n\n        if (field == core::video_field::a || field == core::video_field::progressive) {\n            std::pair<core::draw_frame, core::draw_frame> frame;\n            if (!buffer_.try_pop(frame)) {\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"late-frame\");\n            } else {\n                frame_ = frame;\n            }\n        }\n\n        graph_->set_value(\"consume-time\", consume_timer_.elapsed() * route_->format_desc.fps * 0.5);\n        consume_timer_.restart();\n\n        if (!frame_) {\n            return core::draw_frame{};\n        }\n\n        if (field == core::video_field::b) {\n            return frame_->second;\n        } else {\n            return frame_->first;\n        }\n    }\n\n    bool is_ready() override { return true; }\n\n    std::wstring print() const override { return L\"route[\" + route_->name + L\"]\"; }\n\n    std::wstring name() const override { return L\"route\"; }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"route/channel\"] = source_channel_;\n\n        if (source_layer_ > -1) {\n            state[\"route/layer\"] = source_layer_;\n        }\n\n        return state;\n    }\n};\n\nspl::shared_ptr<core::frame_producer> create_route_producer(const core::frame_producer_dependencies& dependencies,\n                                                            const std::vector<std::wstring>&         params)\n{\n    static boost::wregex expr(L\"route://(?<CHANNEL>\\\\d+)(-(?<LAYER>\\\\d+))?\", boost::regex::icase);\n    boost::wsmatch       what;\n\n    if (params.empty() || !boost::regex_match(params.at(0), what, expr)) {\n        return core::frame_producer::empty();\n    }\n\n    auto channel = std::stoi(what[\"CHANNEL\"].str());\n    auto layer   = what[\"LAYER\"].matched ? std::stoi(what[\"LAYER\"].str()) : -1;\n\n    auto mode = core::route_mode::foreground;\n    if (layer >= 0) {\n        if (contains_param(L\"BACKGROUND\", params))\n            mode = core::route_mode::background;\n        else if (contains_param(L\"NEXT\", params))\n            mode = core::route_mode::next;\n    }\n\n    auto channel_it =\n        std::find_if(dependencies.channels.begin(),\n                     dependencies.channels.end(),\n                     [=](const spl::shared_ptr<core::video_channel>& ch) { return ch->index() == channel; });\n\n    if (channel_it == dependencies.channels.end()) {\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"No channel with id \" + std::to_wstring(channel)));\n    }\n\n    auto buffer = get_param(L\"BUFFER\", params, 0);\n    auto rp     = spl::make_shared<route_producer>(\n        (*channel_it)->route(layer, mode), dependencies.format_desc, buffer, channel, layer);\n    rp->connect_slot();\n    return rp;\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/route/route_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/producer/frame_producer.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nclass route_control\n{\n  public:\n    virtual ~route_control() {}\n\n    virtual int get_source_channel() const = 0;\n    virtual int get_source_layer() const   = 0;\n\n    virtual void set_cross_channel(bool cross) = 0;\n};\n\nspl::shared_ptr<core::frame_producer> create_route_producer(const core::frame_producer_dependencies& dependencies,\n                                                            const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/separated/separated_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../StdAfx.h\"\n\n#include \"separated_producer.h\"\n\n#include <common/scope_exit.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <future>\n\nnamespace caspar { namespace core {\n\nstruct frame_pair\n{\n    draw_frame field1;\n    draw_frame field2;\n\n    draw_frame get(video_field field)\n    {\n        if (field == video_field::b)\n            return field2;\n        else\n            return field1;\n    }\n\n    void set(video_field field, const draw_frame& frame)\n    {\n        if (field == video_field::b)\n            field2 = frame;\n        else\n            field1 = frame;\n    }\n};\n\nclass separated_producer : public frame_producer\n{\n    monitor::state state_;\n\n    spl::shared_ptr<frame_producer> fill_producer_;\n    spl::shared_ptr<frame_producer> key_producer_;\n    frame_pair                      fill_;\n    frame_pair                      key_;\n\n  public:\n    explicit separated_producer(const spl::shared_ptr<frame_producer>& fill, const spl::shared_ptr<frame_producer>& key)\n        : fill_producer_(fill)\n        , key_producer_(key)\n    {\n        CASPAR_LOG(debug) << print() << L\" Initialized\";\n    }\n\n    // frame_producer\n\n    draw_frame last_frame(const core::video_field field) override\n    {\n        return draw_frame::mask(fill_producer_->last_frame(field), key_producer_->last_frame(field));\n    }\n    draw_frame first_frame(const core::video_field field) override\n    {\n        return draw_frame::mask(fill_producer_->first_frame(field), key_producer_->first_frame(field));\n    }\n\n    draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        CASPAR_SCOPE_EXIT\n        {\n            state_          = fill_producer_->state();\n            state_[\"keyer\"] = key_producer_->state();\n        };\n\n        auto fill = fill_.get(field);\n        auto key  = key_.get(field);\n\n        if (!fill) {\n            fill = fill_producer_->receive(field, nb_samples);\n        }\n\n        if (!key) {\n            key = key_producer_->receive(field, nb_samples);\n        }\n\n        if (!fill || !key) {\n            fill_.set(field, fill);\n            key_.set(field, key);\n            return core::draw_frame{};\n        }\n\n        auto frame = draw_frame::mask(fill, key);\n\n        fill_.set(field, draw_frame{});\n        key_.set(field, draw_frame{});\n\n        return frame;\n    }\n\n    uint32_t frame_number() const override { return fill_producer_->frame_number(); }\n\n    uint32_t nb_frames() const override { return std::min(fill_producer_->nb_frames(), key_producer_->nb_frames()); }\n\n    std::wstring print() const override\n    {\n        return L\"separated[fill:\" + fill_producer_->print() + L\"|key[\" + key_producer_->print() + L\"]]\";\n    }\n\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        key_producer_->call(params);\n        return fill_producer_->call(params);\n    }\n\n    std::wstring name() const override { return L\"separated\"; }\n\n    core::monitor::state state() const override { return state_; }\n\n    bool is_ready() override { return key_producer_->is_ready() && fill_producer_->is_ready(); }\n};\n\nspl::shared_ptr<frame_producer> create_separated_producer(const spl::shared_ptr<frame_producer>& fill,\n                                                          const spl::shared_ptr<frame_producer>& key)\n{\n    return spl::make_shared<separated_producer>(fill, key);\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/separated/separated_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/memory.h>\n\nnamespace caspar { namespace core {\n\nspl::shared_ptr<class frame_producer> create_separated_producer(const spl::shared_ptr<class frame_producer>& fill,\n                                                                const spl::shared_ptr<class frame_producer>& key);\n\n}} // namespace caspar::core"
  },
  {
    "path": "src/core/producer/stage.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"stage.h\"\n\n#include \"layer.h\"\n\n#include \"../frame/draw_frame.h\"\n\n#include <common/diagnostics/graph.h>\n#include <common/executor.h>\n#include <common/future.h>\n\n#include <core/frame/frame_transform.h>\n#include <core/producer/route/route_producer.h>\n\n#include <boost/range/adaptors.hpp>\n\n#include <functional>\n#include <future>\n#include <map>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nstruct stage::impl : public std::enable_shared_from_this<impl>\n{\n    int                                 channel_index_;\n    spl::shared_ptr<diagnostics::graph> graph_;\n    monitor::state                      state_;\n    std::map<int, layer>                layers_;\n    std::map<int, tweened_transform>    tweens_;\n    std::set<int>                       routeSources;\n\n    mutable std::mutex      format_desc_mutex_;\n    core::video_format_desc format_desc_;\n\n    executor   executor_{L\"stage \" + std::to_wstring(channel_index_)};\n    std::mutex lock_;\n\n  private:\n    void orderSourceLayers(std::vector<std::pair<int, bool>>&        layerVec,\n                           const std::map<int, std::pair<int, int>>& routed_layers,\n                           int                                       l,\n                           int                                       depth)\n    {\n        if (0 == depth)\n            routeSources.clear();\n\n        if (std::find_if(layerVec.begin(), layerVec.end(), [l](std::pair<int, bool> p) { return p.first == l; }) !=\n            layerVec.end()) {\n            return;\n        }\n\n        auto routeIt = routed_layers.find(l);\n        if (routed_layers.end() == routeIt) {\n            layerVec.push_back(std::make_pair(l, true));\n            return;\n        }\n\n        std::pair<int, int> routeSrc(routeIt->second);\n        if (channel_index_ != routeSrc.first) {\n            layerVec.push_back(std::make_pair(l, true));\n            return;\n        }\n\n        // check for circular route setup - skip recursion if found\n        routeSources.emplace(routeSrc.second);\n        bool layerOK = true;\n        if (routeSources.find(l) == routeSources.end()) {\n            orderSourceLayers(layerVec, routed_layers, routeSrc.second, ++depth);\n        } else {\n            layerOK = false;\n        }\n\n        if (std::find_if(layerVec.begin(), layerVec.end(), [l](std::pair<int, bool> p) { return p.first == l; }) ==\n            layerVec.end()) {\n            layerVec.push_back(std::make_pair(l, layerOK));\n        }\n    }\n\n    layer& get_layer(int index)\n    {\n        auto it = layers_.find(index);\n        if (it == std::end(layers_)) {\n            it = layers_.emplace(index, layer(video_format_desc())).first;\n        }\n        return it->second;\n    }\n\n  public:\n    impl(int channel_index, spl::shared_ptr<diagnostics::graph> graph, const core::video_format_desc& format_desc)\n        : channel_index_(channel_index)\n        , graph_(std::move(graph))\n        , format_desc_(format_desc)\n    {\n    }\n\n    const stage_frames operator()(uint64_t                                     frame_number,\n                                  std::vector<int>&                            fetch_background,\n                                  std::function<void(int, const layer_frame&)> routesCb)\n    {\n        return executor_.invoke([=, this] {\n            std::map<int, layer_frame> frames;\n            stage_frames               result = {};\n\n            result.format_desc = video_format_desc();\n            result.nb_samples =\n                result.format_desc.audio_cadence[frame_number % result.format_desc.audio_cadence.size()];\n\n            auto is_interlaced = format_desc_.field_count == 2;\n            auto field1        = is_interlaced ? video_field::a : video_field::progressive;\n\n            try {\n                for (auto& t : tweens_)\n                    t.second.tick(1);\n\n                // build a map of layers that are sourced from route producers\n                std::map<int, std::pair<int, int>> routed_layers;\n                for (auto& p : layers_) {\n                    auto producer = std::move(p.second.foreground());\n                    if (0 == producer->name().compare(L\"route\")) {\n                        try {\n                            auto rc       = spl::dynamic_pointer_cast<core::route_control>(producer);\n                            auto srcChan  = rc->get_source_channel();\n                            auto srcLayer = rc->get_source_layer();\n                            routed_layers.emplace(p.first, std::make_pair(srcChan, srcLayer));\n                            rc->set_cross_channel(channel_index_ != srcChan);\n                        } catch (std::bad_cast) {\n                            CASPAR_LOG(error) << \"Failed to cast route producer\";\n                        }\n                    }\n                }\n\n                // sort layer order so that sources get pulled before routes\n                std::vector<std::pair<int, bool>> layerVec;\n                for (auto& p : layers_)\n                    orderSourceLayers(layerVec, routed_layers, p.first, 0);\n\n                // when running interlaced, both fields are be pulled at once.\n                // This will risk some stutter for freshly created producers, but it lets us tick at 25hz and avoids\n                // amcp changes starting on the second field\n\n                for (auto& l : layerVec) {\n                    auto p = layers_.find(l.first);\n                    if (p == layers_.end())\n                        continue;\n\n                    auto& layer = p->second;\n                    auto& tween = tweens_[p->first];\n\n                    auto has_background_route =\n                        std::find(fetch_background.begin(), fetch_background.end(), p->first) != fetch_background.end();\n\n                    layer_frame res = {};\n                    if (l.second) {\n                        res.foreground1 = draw_frame::push(layer.receive(field1, result.nb_samples), tween.fetch());\n                        res.foreground1.transform().image_transform.enable_geometry_modifiers = true;\n                    }\n\n                    res.has_background = layer.has_background();\n                    if (has_background_route)\n                        res.background1 = layer.receive_background(field1, result.nb_samples);\n\n                    if (is_interlaced) {\n                        res.is_interlaced = true;\n                        if (l.second) {\n                            res.foreground2 =\n                                draw_frame::push(layer.receive(video_field::b, result.nb_samples), tween.fetch());\n                            res.foreground2.transform().image_transform.enable_geometry_modifiers = true;\n                        }\n                        if (has_background_route)\n                            res.background2 = layer.receive_background(video_field::b, result.nb_samples);\n                    }\n\n                    frames[p->first] = res;\n\n                    // push received foreground frame to any configured route producer\n                    routesCb(p->first, res);\n                }\n\n                for (auto& p : frames) {\n                    result.frames.push_back(p.second.foreground1);\n                    if (is_interlaced)\n                        result.frames2.push_back(p.second.foreground2);\n                }\n\n                {\n                    // push stage_frames to support any channel routes that have been set\n                    layer_frame chan_lf   = {};\n                    chan_lf.is_interlaced = is_interlaced;\n                    chan_lf.foreground1   = wrap_layer_frames_for_route(result.frames);\n                    if (is_interlaced)\n                        chan_lf.foreground2 = wrap_layer_frames_for_route(result.frames2);\n\n                    routesCb(-1, chan_lf);\n                }\n\n                monitor::state state;\n                for (auto& p : layers_) {\n                    state[\"layer\"][p.first] = p.second.state();\n                }\n                state_ = std::move(state);\n            } catch (...) {\n                layers_.clear();\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n\n            return result;\n        });\n    }\n\n    core::draw_frame wrap_layer_frames_for_route(std::vector<core::draw_frame> frames)\n    {\n        // Note: this must not mutate the vector used for the layer\n        for (auto& frame : frames) {\n            // Tell the compositor that these are layers, matching what normal rendering does\n            frame.transform().image_transform.layer_depth = 1;\n        }\n        return core::draw_frame(frames);\n    }\n\n    std::future<void>\n    apply_transforms(const std::vector<std::tuple<int, stage::transform_func_t, unsigned int, tweener>>& transforms)\n    {\n        return executor_.begin_invoke([=, this] {\n            for (auto& transform : transforms) {\n                auto& tween = tweens_[std::get<0>(transform)];\n                auto  src   = tween.fetch();\n                auto  dst   = std::get<1>(transform)(tween.dest());\n                tweens_[std::get<0>(transform)] =\n                    tweened_transform(src, dst, std::get<2>(transform), std::get<3>(transform));\n            }\n        });\n    }\n\n    std::future<void> apply_transform(int                            index,\n                                      const stage::transform_func_t& transform,\n                                      unsigned int                   mix_duration,\n                                      const tweener&                 tween)\n    {\n        return executor_.begin_invoke([=, this] {\n            auto src       = tweens_[index].fetch();\n            auto dst       = transform(src);\n            tweens_[index] = tweened_transform(src, dst, mix_duration, tween);\n        });\n    }\n\n    std::future<void> clear_transforms(int index)\n    {\n        return executor_.begin_invoke([=, this] { tweens_.erase(index); });\n    }\n\n    std::future<void> clear_transforms()\n    {\n        return executor_.begin_invoke([=, this] { tweens_.clear(); });\n    }\n\n    std::future<frame_transform> get_current_transform(int index)\n    {\n        return executor_.begin_invoke([=, this] { return tweens_[index].fetch(); });\n    }\n\n    std::future<void> load(int index, const spl::shared_ptr<frame_producer>& producer, bool preview, bool auto_play)\n    {\n        return executor_.begin_invoke([=, this] { get_layer(index).load(producer, preview, auto_play); });\n    }\n\n    std::future<void> preview(int index)\n    {\n        return executor_.begin_invoke([=, this] { get_layer(index).preview(); });\n    }\n\n    std::future<void> pause(int index)\n    {\n        return executor_.begin_invoke([=, this] { get_layer(index).pause(); });\n    }\n\n    std::future<void> resume(int index)\n    {\n        return executor_.begin_invoke([=, this] { get_layer(index).resume(); });\n    }\n\n    std::future<void> play(int index)\n    {\n        return executor_.begin_invoke([=, this] { get_layer(index).play(); });\n    }\n\n    std::future<void> stop(int index)\n    {\n        return executor_.begin_invoke([=, this] { get_layer(index).stop(); });\n    }\n\n    std::future<void> clear(int index)\n    {\n        return executor_.begin_invoke([=, this] { layers_.erase(index); });\n    }\n\n    std::future<void> clear()\n    {\n        return executor_.begin_invoke([=, this] { layers_.clear(); });\n    }\n\n    std::future<void> swap_layers(const std::shared_ptr<stage>& other, bool swap_transforms)\n    {\n        auto other_impl = other->impl_;\n\n        if (other_impl.get() == this) {\n            return make_ready_future();\n        }\n\n        auto func = [=, this] {\n            auto layers       = layers_ | boost::adaptors::map_values;\n            auto other_layers = other_impl->layers_ | boost::adaptors::map_values;\n\n            std::swap(layers_, other_impl->layers_);\n\n            if (swap_transforms)\n                std::swap(tweens_, other_impl->tweens_);\n        };\n\n        return invoke_both(other, func);\n    }\n\n    std::future<void> swap_layer(int index, int other_index, bool swap_transforms)\n    {\n        return executor_.begin_invoke([=, this] {\n            std::swap(get_layer(index), get_layer(other_index));\n\n            if (swap_transforms)\n                std::swap(tweens_[index], tweens_[other_index]);\n        });\n    }\n\n    std::future<void> swap_layer(int index, int other_index, const std::shared_ptr<stage>& other, bool swap_transforms)\n    {\n        auto other_impl = other->impl_;\n\n        if (other_impl.get() == this)\n            return swap_layer(index, other_index, swap_transforms);\n        auto func = [=, this] {\n            auto& my_layer    = get_layer(index);\n            auto& other_layer = other_impl->get_layer(other_index);\n\n            std::swap(my_layer, other_layer);\n\n            if (swap_transforms) {\n                auto& my_tween    = tweens_[index];\n                auto& other_tween = other_impl->tweens_[other_index];\n                std::swap(my_tween, other_tween);\n            }\n        };\n\n        return invoke_both(other, func);\n    }\n\n    std::future<void> invoke_both(const std::shared_ptr<stage>& other, std::function<void()> func)\n    {\n        auto other_impl = other->impl_;\n\n        if (other_impl->channel_index_ < channel_index_) {\n            return other_impl->executor_.begin_invoke([=, this] { executor_.invoke(func); });\n        }\n\n        return executor_.begin_invoke([=, this] { other_impl->executor_.invoke(func); });\n    }\n\n    std::future<std::shared_ptr<frame_producer>> foreground(int index)\n    {\n        return executor_.begin_invoke(\n            [=, this]() -> std::shared_ptr<frame_producer> { return get_layer(index).foreground(); });\n    }\n\n    std::future<std::shared_ptr<frame_producer>> background(int index)\n    {\n        return executor_.begin_invoke(\n            [=, this]() -> std::shared_ptr<frame_producer> { return get_layer(index).background(); });\n    }\n\n    std::future<std::wstring> call(int index, const std::vector<std::wstring>& params)\n    {\n        return flatten(\n            executor_.begin_invoke([=, this] { return get_layer(index).foreground()->call(params).share(); }));\n    }\n    std::future<std::wstring> callbg(int index, const std::vector<std::wstring>& params)\n    {\n        return flatten(\n            executor_.begin_invoke([=, this] { return get_layer(index).background()->call(params).share(); }));\n    }\n\n    std::unique_lock<std::mutex> get_lock() { return std::move(std::unique_lock<std::mutex>(lock_)); }\n\n    core::video_format_desc video_format_desc() const\n    {\n        std::lock_guard<std::mutex> lock(format_desc_mutex_);\n        return format_desc_;\n    }\n\n    std::future<void> video_format_desc(const core::video_format_desc& format_desc)\n    {\n        return executor_.begin_invoke([=, this] {\n            {\n                std::lock_guard<std::mutex> lock(format_desc_mutex_);\n                format_desc_ = format_desc;\n            }\n\n            layers_.clear();\n        });\n    }\n};\n\nstage::stage(int channel_index, spl::shared_ptr<diagnostics::graph> graph, const core::video_format_desc& format_desc)\n    : impl_(new impl(channel_index, std::move(graph), format_desc))\n{\n}\nstd::future<std::wstring> stage::call(int index, const std::vector<std::wstring>& params)\n{\n    return impl_->call(index, params);\n}\nstd::future<std::wstring> stage::callbg(int index, const std::vector<std::wstring>& params)\n{\n    return impl_->callbg(index, params);\n}\nstd::future<void> stage::apply_transforms(const std::vector<stage::transform_tuple_t>& transforms)\n{\n    return impl_->apply_transforms(transforms);\n}\nstd::future<void> stage::apply_transform(int                                                                index,\n                                         const std::function<core::frame_transform(core::frame_transform)>& transform,\n                                         unsigned int   mix_duration,\n                                         const tweener& tween)\n{\n    return impl_->apply_transform(index, transform, mix_duration, tween);\n}\nstd::future<void>            stage::clear_transforms(int index) { return impl_->clear_transforms(index); }\nstd::future<void>            stage::clear_transforms() { return impl_->clear_transforms(); }\nstd::future<frame_transform> stage::get_current_transform(int index) { return impl_->get_current_transform(index); }\nstd::future<void> stage::load(int index, const spl::shared_ptr<frame_producer>& producer, bool preview, bool auto_play)\n{\n    return impl_->load(index, producer, preview, auto_play);\n}\nstd::future<void> stage::preview(int index) { return impl_->preview(index); }\nstd::future<void> stage::pause(int index) { return impl_->pause(index); }\nstd::future<void> stage::resume(int index) { return impl_->resume(index); }\nstd::future<void> stage::play(int index) { return impl_->play(index); }\nstd::future<void> stage::stop(int index) { return impl_->stop(index); }\nstd::future<void> stage::clear(int index) { return impl_->clear(index); }\nstd::future<void> stage::clear() { return impl_->clear(); }\nstd::future<void> stage::swap_layers(const std::shared_ptr<stage_base>& other, bool swap_transforms)\n{\n    const auto other2 = std::static_pointer_cast<stage>(other);\n    return impl_->swap_layers(other2, swap_transforms);\n}\nstd::future<void> stage::swap_layer(int index, int other_index, bool swap_transforms)\n{\n    return impl_->swap_layer(index, other_index, swap_transforms);\n}\nstd::future<void>\nstage::swap_layer(int index, int other_index, const std::shared_ptr<stage_base>& other, bool swap_transforms)\n{\n    const auto other2 = std::static_pointer_cast<stage>(other);\n    return impl_->swap_layer(index, other_index, other2, swap_transforms);\n}\nstd::future<std::shared_ptr<frame_producer>> stage::foreground(int index) { return impl_->foreground(index); }\nstd::future<std::shared_ptr<frame_producer>> stage::background(int index) { return impl_->background(index); }\nconst stage_frames                           stage::operator()(uint64_t                                     frame_number,\n                                     std::vector<int>&                            fetch_background,\n                                     std::function<void(int, const layer_frame&)> routesCb)\n{\n    return (*impl_)(frame_number, fetch_background, routesCb);\n}\ncore::monitor::state    stage::state() const { return impl_->state_; }\ncore::video_format_desc stage::video_format_desc() const { return impl_->video_format_desc(); }\nstd::future<void>       stage::video_format_desc(const core::video_format_desc& format_desc)\n{\n    return impl_->video_format_desc(format_desc);\n}\nstd::unique_lock<std::mutex> stage::get_lock() const { return impl_->get_lock(); }\nstd::future<void>            stage::execute(std::function<void()> func)\n{\n    func();\n    return make_ready_future();\n}\n\n// STAGE DELAYED (For batching operations)\nstage_delayed::stage_delayed(std::shared_ptr<stage>& st, int index)\n    : executor_{L\"batch stage \" + boost::lexical_cast<std::wstring>(index)}\n    , stage_(st)\n{\n    // Start the executor blocked on a future that will complete when we are ready for it to execute\n    executor_.begin_invoke([=, this]() -> void { waiter_.get_future().get(); });\n}\n\nstd::future<std::wstring> stage_delayed::call(int index, const std::vector<std::wstring>& params)\n{\n    return executor_.begin_invoke([=, this]() -> std::wstring { return stage_->call(index, params).get(); });\n}\nstd::future<std::wstring> stage_delayed::callbg(int index, const std::vector<std::wstring>& params)\n{\n    return executor_.begin_invoke([=, this]() -> std::wstring { return stage_->callbg(index, params).get(); });\n}\nstd::future<void> stage_delayed::apply_transforms(const std::vector<stage_delayed::transform_tuple_t>& transforms)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->apply_transforms(transforms).get(); });\n}\nstd::future<void>\nstage_delayed::apply_transform(int                                                                index,\n                               const std::function<core::frame_transform(core::frame_transform)>& transform,\n                               unsigned int                                                       mix_duration,\n                               const tweener&                                                     tween)\n{\n    return executor_.begin_invoke(\n        [=, this]() { return stage_->apply_transform(index, transform, mix_duration, tween).get(); });\n}\nstd::future<void> stage_delayed::clear_transforms(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->clear_transforms(index).get(); });\n}\nstd::future<void> stage_delayed::clear_transforms()\n{\n    return executor_.begin_invoke([=, this]() { return stage_->clear_transforms().get(); });\n}\nstd::future<frame_transform> stage_delayed::get_current_transform(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->get_current_transform(index).get(); });\n}\nstd::future<void>\nstage_delayed::load(int index, const spl::shared_ptr<frame_producer>& producer, bool preview, bool auto_play)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->load(index, producer, preview, auto_play).get(); });\n}\nstd::future<void> stage_delayed::preview(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->preview(index).get(); });\n}\nstd::future<void> stage_delayed::pause(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->pause(index).get(); });\n}\nstd::future<void> stage_delayed::resume(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->resume(index).get(); });\n}\nstd::future<void> stage_delayed::play(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->play(index).get(); });\n}\nstd::future<void> stage_delayed::stop(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->stop(index).get(); });\n}\nstd::future<void> stage_delayed::clear(int index)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->clear(index).get(); });\n}\nstd::future<void> stage_delayed::clear()\n{\n    return executor_.begin_invoke([=, this]() { return stage_->clear().get(); });\n}\nstd::future<void> stage_delayed::swap_layers(const std::shared_ptr<stage_base>& other, bool swap_transforms)\n{\n    const auto other2 = std::static_pointer_cast<stage_delayed>(other);\n    return executor_.begin_invoke([=, this]() { return stage_->swap_layers(other2->stage_, swap_transforms).get(); });\n}\nstd::future<void> stage_delayed::swap_layer(int index, int other_index, bool swap_transforms)\n{\n    return executor_.begin_invoke(\n        [=, this]() { return stage_->swap_layer(index, other_index, swap_transforms).get(); });\n}\nstd::future<void>\nstage_delayed::swap_layer(int index, int other_index, const std::shared_ptr<stage_base>& other, bool swap_transforms)\n{\n    const auto other2 = std::static_pointer_cast<stage_delayed>(other);\n\n    // Something so that we know to lock the channel\n    other2->executor_.begin_invoke([]() {});\n\n    return executor_.begin_invoke(\n        [=, this]() { return stage_->swap_layer(index, other_index, other2->stage_, swap_transforms).get(); });\n}\n\nstd::future<std::shared_ptr<frame_producer>> stage_delayed::foreground(int index)\n{\n    return executor_.begin_invoke(\n        [=, this]() -> std::shared_ptr<frame_producer> { return stage_->foreground(index).get(); });\n}\nstd::future<std::shared_ptr<frame_producer>> stage_delayed::background(int index)\n{\n    return executor_.begin_invoke(\n        [=, this]() -> std::shared_ptr<frame_producer> { return stage_->background(index).get(); });\n}\n\nstd::future<void> stage_delayed::execute(std::function<void()> func)\n{\n    return executor_.begin_invoke([=, this]() { return stage_->execute(func).get(); });\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/stage.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../fwd.h\"\n#include \"../monitor/monitor.h\"\n\n#include <common/executor.h>\n#include <common/memory.h>\n#include <common/tweener.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/video_format.h>\n\n#include <functional>\n#include <future>\n#include <map>\n#include <mutex>\n#include <tuple>\n#include <vector>\n\nnamespace caspar::diagnostics {\nclass graph;\n}\n\nnamespace caspar { namespace core {\n\nstruct layer_frame\n{\n    bool       is_interlaced;\n    draw_frame foreground1;\n    draw_frame background1;\n    draw_frame foreground2;\n    draw_frame background2;\n    bool       has_background;\n};\n\nstruct stage_frames\n{\n    core::video_format_desc format_desc;\n    int                     nb_samples;\n    std::vector<draw_frame> frames;\n    std::vector<draw_frame> frames2;\n};\n\n/**\n * Base class for the stage. Should be used when either stage or stage_delayed may be used\n */\nclass stage_base\n{\n  public:\n    using transform_func_t  = std::function<struct frame_transform(struct frame_transform)>;\n    using transform_tuple_t = std::tuple<int, transform_func_t, unsigned int, tweener>;\n\n    virtual ~stage_base() {}\n\n    // Methods\n    virtual std::future<void> apply_transforms(const std::vector<transform_tuple_t>& transforms) = 0;\n    virtual std::future<void>\n    apply_transform(int index, const transform_func_t& transform, unsigned int mix_duration, const tweener& tween) = 0;\n    virtual std::future<void>            clear_transforms(int index)                                               = 0;\n    virtual std::future<void>            clear_transforms()                                                        = 0;\n    virtual std::future<frame_transform> get_current_transform(int index)                                          = 0;\n    virtual std::future<void>\n    load(int index, const spl::shared_ptr<frame_producer>& producer, bool preview = false, bool auto_play = false) = 0;\n    virtual std::future<void>         preview(int index)                                                           = 0;\n    virtual std::future<void>         pause(int index)                                                             = 0;\n    virtual std::future<void>         resume(int index)                                                            = 0;\n    virtual std::future<void>         play(int index)                                                              = 0;\n    virtual std::future<void>         stop(int index)                                                              = 0;\n    virtual std::future<std::wstring> call(int index, const std::vector<std::wstring>& params)                     = 0;\n    virtual std::future<std::wstring> callbg(int index, const std::vector<std::wstring>& params)                   = 0;\n    virtual std::future<void>         clear(int index)                                                             = 0;\n    virtual std::future<void>         clear()                                                                      = 0;\n    virtual std::future<void>         swap_layers(const std::shared_ptr<stage_base>& other, bool swap_transforms)  = 0;\n    virtual std::future<void>         swap_layer(int index, int other_index, bool swap_transforms)                 = 0;\n    virtual std::future<void>\n    swap_layer(int index, int other_index, const std::shared_ptr<stage_base>& other, bool swap_transforms) = 0;\n\n    virtual std::future<void> execute(std::function<void()> k) = 0;\n\n    // Properties\n    virtual std::future<std::shared_ptr<frame_producer>> foreground(int index) = 0;\n    virtual std::future<std::shared_ptr<frame_producer>> background(int index) = 0;\n};\n\n/**\n * The normal stage implementation.\n */\nclass stage final : public stage_base\n{\n    stage(const stage&);\n    stage& operator=(const stage&);\n\n  public:\n    explicit stage(int                                         channel_index,\n                   spl::shared_ptr<caspar::diagnostics::graph> graph,\n                   const core::video_format_desc&              format_desc);\n\n    const stage_frames operator()(uint64_t                                     frame_number,\n                                  std::vector<int>&                            fetch_background,\n                                  std::function<void(int, const layer_frame&)> routesCb);\n\n    std::future<void>            apply_transforms(const std::vector<transform_tuple_t>& transforms) override;\n    std::future<void>            apply_transform(int                     index,\n                                                 const transform_func_t& transform,\n                                                 unsigned int            mix_duration,\n                                                 const tweener&          tween) override;\n    std::future<void>            clear_transforms(int index) override;\n    std::future<void>            clear_transforms() override;\n    std::future<frame_transform> get_current_transform(int index) override;\n    std::future<void>            load(int                                    index,\n                                      const spl::shared_ptr<frame_producer>& producer,\n                                      bool                                   preview   = false,\n                                      bool                                   auto_play = false) override;\n    std::future<void>            preview(int index) override;\n    std::future<void>            pause(int index) override;\n    std::future<void>            resume(int index) override;\n    std::future<void>            play(int index) override;\n    std::future<void>            stop(int index) override;\n    std::future<std::wstring>    call(int index, const std::vector<std::wstring>& params) override;\n    std::future<std::wstring>    callbg(int index, const std::vector<std::wstring>& params) override;\n    std::future<void>            clear(int index) override;\n    std::future<void>            clear() override;\n    std::future<void>            swap_layers(const std::shared_ptr<stage_base>& other, bool swap_transforms) override;\n    std::future<void>            swap_layer(int index, int other_index, bool swap_transforms) override;\n    std::future<void>\n    swap_layer(int index, int other_index, const std::shared_ptr<stage_base>& other, bool swap_transforms) override;\n\n    core::monitor::state state() const;\n\n    std::future<std::shared_ptr<frame_producer>> foreground(int index) override;\n    std::future<std::shared_ptr<frame_producer>> background(int index) override;\n\n    std::future<void>            execute(std::function<void()> k) override;\n    std::unique_lock<std::mutex> get_lock() const;\n\n    core::video_format_desc video_format_desc() const;\n    std::future<void>       video_format_desc(const core::video_format_desc& format_desc);\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\n/**\n * A stage wrapper, that queues up stage operations until release() is called.\n * This is useful for batching commands.\n */\nclass stage_delayed final : public stage_base\n{\n  public:\n    stage_delayed(std::shared_ptr<stage>& st, int index);\n\n    int64_t count_queued() const { return executor_.size(); }\n    void    release() { waiter_.set_value(); }\n    void    abort() { executor_.clear(); }\n    void    wait() { executor_.stop_and_wait(); }\n\n    std::future<void>            apply_transforms(const std::vector<transform_tuple_t>& transforms) override;\n    std::future<void>            apply_transform(int                     index,\n                                                 const transform_func_t& transform,\n                                                 unsigned int            mix_duration,\n                                                 const tweener&          tween) override;\n    std::future<void>            clear_transforms(int index) override;\n    std::future<void>            clear_transforms() override;\n    std::future<frame_transform> get_current_transform(int index) override;\n    std::future<void>            load(int                                    index,\n                                      const spl::shared_ptr<frame_producer>& producer,\n                                      bool                                   preview   = false,\n                                      bool                                   auto_play = false) override;\n    std::future<void>            preview(int index) override;\n    std::future<void>            pause(int index) override;\n    std::future<void>            resume(int index) override;\n    std::future<void>            play(int index) override;\n    std::future<void>            stop(int index) override;\n    std::future<std::wstring>    call(int index, const std::vector<std::wstring>& params) override;\n    std::future<std::wstring>    callbg(int index, const std::vector<std::wstring>& params) override;\n    std::future<void>            clear(int index) override;\n    std::future<void>            clear() override;\n    std::future<void>            swap_layers(const std::shared_ptr<stage_base>& other, bool swap_transforms) override;\n    std::future<void>            swap_layer(int index, int other_index, bool swap_transforms) override;\n    std::future<void>\n    swap_layer(int index, int other_index, const std::shared_ptr<stage_base>& other, bool swap_transforms) override;\n\n    // Properties\n\n    std::future<std::shared_ptr<frame_producer>> foreground(int index) override;\n    std::future<std::shared_ptr<frame_producer>> background(int index) override;\n\n    std::future<void>            execute(std::function<void()> k) override;\n    std::unique_lock<std::mutex> get_lock() const { return stage_->get_lock(); }\n\n  private:\n    std::promise<void>      waiter_;\n    std::shared_ptr<stage>& stage_;\n    executor                executor_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/transition/sting_producer.cpp",
    "content": "/*\n * Copyright (c) 2018 Norsk rikskringkasting AS\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"../../StdAfx.h\"\n\n#include \"sting_producer.h\"\n\n#include \"../../frame/draw_frame.h\"\n#include \"../../frame/frame_transform.h\"\n#include \"../../monitor/monitor.h\"\n#include \"../frame_producer.h\"\n#include \"../frame_producer_registry.h\"\n\n#include <common/scope_exit.h>\n\n#include <boost/algorithm/string/predicate.hpp>\n#include <future>\n#include <vector>\n\nnamespace caspar { namespace core {\n\nstruct frame_pair\n{\n    draw_frame field1;\n    draw_frame field2;\n\n    draw_frame get(video_field field)\n    {\n        if (field == video_field::b)\n            return field2;\n        else\n            return field1;\n    }\n\n    void set(video_field field, const draw_frame& frame)\n    {\n        if (field == video_field::b)\n            field2 = frame;\n        else\n            field1 = frame;\n    }\n};\n\nclass sting_producer : public frame_producer\n{\n    monitor::state  state_;\n    uint32_t        current_frame_ = 0;\n    caspar::tweener audio_tweener_{L\"linear\"};\n\n    frame_pair dst_;\n    frame_pair src_;\n    frame_pair mask_;\n    frame_pair overlay_;\n\n    const sting_info info_;\n    const bool       is_cut_mode_;\n\n    spl::shared_ptr<frame_producer> dst_producer_     = frame_producer::empty();\n    spl::shared_ptr<frame_producer> src_producer_     = frame_producer::empty();\n    spl::shared_ptr<frame_producer> mask_producer_    = frame_producer::empty();\n    spl::shared_ptr<frame_producer> overlay_producer_ = frame_producer::empty();\n\n  public:\n    sting_producer(const spl::shared_ptr<frame_producer>& dest,\n                   const sting_info&                      info,\n                   const spl::shared_ptr<frame_producer>& mask,\n                   const spl::shared_ptr<frame_producer>& overlay)\n        : info_(info)\n        , is_cut_mode_(boost::iequals(info.mask_filename, L\"empty\"))\n        , dst_producer_(dest)\n        , mask_producer_(mask)\n        , overlay_producer_(overlay)\n    {\n    }\n\n    // frame_producer\n\n    void leading_producer(const spl::shared_ptr<frame_producer>& producer) override { src_producer_ = producer; }\n\n    spl::shared_ptr<frame_producer> following_producer() const override\n    {\n        if (is_cut_mode_) {\n            uint32_t overlay_duration = 0;\n\n            if (overlay_producer_ != frame_producer::empty()) {\n                overlay_duration = overlay_producer_->nb_frames();\n                // Clamp ONLY infinite duration overlays to prevent infinite transitions\n                if (overlay_duration == UINT32_MAX) {\n                    overlay_duration = 0;\n                }\n            }\n\n            uint32_t transition_end = std::max(info_.trigger_point, overlay_duration);\n\n            if (current_frame_ >= transition_end) {\n                // CASPAR_LOG(debug) << L\"[sting] Cut mode transition complete at frame \" << current_frame_ << L\",\n                // returning dst_producer_\";\n                return dst_producer_;\n            }\n\n            return core::frame_producer::empty();\n        }\n\n        auto duration = target_duration();\n\n        if (info_.audio_fade_duration < UINT32_MAX) {\n            uint32_t audio_end = info_.audio_fade_start + info_.audio_fade_duration;\n            if (current_frame_ >= audio_end) {\n                return dst_producer_;\n            }\n        }\n\n        return duration && current_frame_ >= *duration ? dst_producer_ : core::frame_producer::empty();\n    }\n\n    std::optional<int64_t> auto_play_delta() const override\n    {\n        if (is_cut_mode_) {\n            uint32_t overlay_duration = 0;\n            if (overlay_producer_ != frame_producer::empty()) {\n                overlay_duration = overlay_producer_->nb_frames();\n                // Clamp ONLY infinite duration overlays to prevent infinite transitions\n                if (overlay_duration == UINT32_MAX) {\n                    overlay_duration = 0;\n                }\n            }\n\n            return static_cast<int64_t>(std::max(info_.trigger_point, overlay_duration));\n        }\n\n        auto duration = static_cast<int64_t>(mask_producer_->nb_frames());\n        if (duration > -1) {\n            return std::optional<int64_t>(duration);\n        }\n        return {};\n    }\n\n    std::optional<uint32_t> target_duration() const\n    {\n        if (is_cut_mode_) {\n            uint32_t overlay_duration = 0;\n            if (overlay_producer_ != frame_producer::empty()) {\n                overlay_duration = overlay_producer_->nb_frames();\n                // Clamp ONLY infinite duration overlays to prevent infinite transitions\n                if (overlay_duration == UINT32_MAX) {\n                    overlay_duration = 0;\n                }\n            }\n            return std::max(info_.trigger_point, overlay_duration);\n        }\n\n        // Sting mode logic\n        auto autoplay = auto_play_delta();\n        if (!autoplay) {\n            return {};\n        }\n\n        auto autoplay2 = static_cast<uint32_t>(*autoplay);\n\n        // If mask is infinite, rely on audio fade if specified\n        if (autoplay2 == UINT32_MAX) {\n            if (info_.audio_fade_duration < UINT32_MAX) {\n                return info_.audio_fade_start + info_.audio_fade_duration;\n            } else {\n                // Infinite mask and no audio fade: use a default duration (e.g., 10 seconds / 600 frames)\n                return 600;\n            }\n        }\n\n        // Finite mask: Use mask duration, potentially extended by audio fade\n        if (info_.audio_fade_duration < UINT32_MAX) {\n            return std::max(autoplay2, info_.audio_fade_duration + info_.audio_fade_start);\n        }\n        return autoplay2;\n    }\n\n    draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        auto duration = target_duration();\n\n        CASPAR_SCOPE_EXIT\n        {\n            state_                    = dst_producer_->state();\n            state_[\"transition/type\"] = is_cut_mode_ ? std::string(\"cut\") : std::string(\"sting\");\n\n            if (duration)\n                state_[\"transition/frame\"] = {static_cast<int>(current_frame_), static_cast<int>(*duration)};\n        };\n\n        if (duration && current_frame_ >= *duration) {\n            return dst_producer_->receive(field, nb_samples);\n        }\n\n        if (is_cut_mode_) {\n            uint32_t overlay_duration = 0;\n\n            if (overlay_producer_ != frame_producer::empty()) {\n                overlay_duration = overlay_producer_->nb_frames();\n                if (overlay_duration == 0 || overlay_duration == UINT32_MAX) {\n                    overlay_duration = 0;\n                }\n            }\n\n            auto src = src_.get(field);\n            if (!src) {\n                src = src_producer_->receive(field, nb_samples);\n                src_.set(field, src);\n                if (!src)\n                    src = src_producer_->last_frame(field);\n            }\n\n            auto dst = dst_.get(field);\n            if (!dst && current_frame_ >= info_.trigger_point) {\n                dst = dst_producer_->receive(field, nb_samples);\n                dst_.set(field, dst);\n                if (!dst)\n                    dst = dst_producer_->last_frame(field);\n            }\n\n            draw_frame result = (current_frame_ < info_.trigger_point ? src : dst);\n\n            double audio_delta = get_audio_delta();\n            if (src)\n                src.transform().audio_transform.volume = 1.0 - audio_delta;\n            if (dst)\n                dst.transform().audio_transform.volume = audio_delta;\n\n            bool has_overlay = overlay_producer_ != core::frame_producer::empty();\n            auto overlay     = overlay_.get(field);\n            if (has_overlay && !overlay) {\n                overlay = overlay_producer_->receive(field, nb_samples);\n                overlay_.set(field, overlay);\n                if (!overlay)\n                    overlay = overlay_producer_->last_frame(field);\n            }\n\n            src_.set(field, draw_frame{});\n            dst_.set(field, draw_frame{});\n            overlay_.set(field, draw_frame{});\n            current_frame_++;\n\n            if (overlay && result) {\n                return draw_frame::over(result, overlay);\n            }\n            return result;\n        }\n\n        auto src = src_.get(field);\n        if (!src) {\n            src = src_producer_->receive(field, nb_samples);\n            src_.set(field, src);\n            if (!src) {\n                src = src_producer_->last_frame(field);\n            }\n        }\n\n        bool started_dst = current_frame_ >= info_.trigger_point;\n        auto dst         = dst_.get(field);\n        if (!dst && started_dst) {\n            dst = dst_producer_->receive(field, nb_samples);\n            dst_.set(field, dst);\n            if (!dst) {\n                dst = dst_producer_->last_frame(field);\n            }\n\n            if (!dst) {\n                src_.set(field, draw_frame{});\n                return src;\n            }\n        }\n\n        auto mask = mask_.get(field);\n        if (!mask) {\n            mask = mask_producer_->receive(field, nb_samples);\n            mask_.set(field, mask);\n        }\n\n        bool expecting_overlay = overlay_producer_ != core::frame_producer::empty();\n        auto overlay           = overlay_.get(field);\n        if (expecting_overlay && !overlay) {\n            overlay = overlay_producer_->receive(field, nb_samples);\n            overlay_.set(field, overlay);\n        }\n\n        bool mask_and_overlay_valid = mask && (!expecting_overlay || overlay);\n        if (current_frame_ == 0 && !mask_and_overlay_valid) {\n            src_.set(field, draw_frame{});\n            return src;\n        }\n\n        if (!mask_and_overlay_valid) {\n            mask    = mask_producer_->last_frame(field);\n            overlay = overlay_producer_->last_frame(field);\n        }\n\n        auto res = compose(dst, src, mask, overlay);\n\n        dst_.set(field, draw_frame{});\n        src_.set(field, draw_frame{});\n\n        if (mask_and_overlay_valid) {\n            mask_.set(field, draw_frame{});\n            overlay_.set(field, draw_frame{});\n\n            current_frame_ += 1;\n        }\n\n        return res;\n    }\n\n    core::draw_frame first_frame(const core::video_field field) override { return dst_producer_->first_frame(field); }\n\n    uint32_t nb_frames() const override { return dst_producer_->nb_frames(); }\n\n    uint32_t frame_number() const override { return dst_producer_->frame_number(); }\n\n    std::wstring print() const override\n    {\n        return L\"transition[\" + src_producer_->print() + L\"=>\" + dst_producer_->print() + L\"]\";\n    }\n\n    std::wstring name() const override { return L\"transition\"; }\n\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        return dst_producer_->call(params);\n    }\n\n    double get_audio_delta() const\n    {\n        if (info_.audio_fade_duration < UINT32_MAX) {\n            if (current_frame_ < info_.audio_fade_start) {\n                return 0;\n            }\n\n            auto total_duration = target_duration();\n            if (!total_duration) {\n                return 0;\n            }\n\n            uint32_t frame_number = current_frame_ - info_.audio_fade_start;\n            uint32_t duration     = std::min(*total_duration - info_.audio_fade_start, info_.audio_fade_duration);\n            if (frame_number > duration) {\n                return 1.0;\n            }\n\n            return audio_tweener_(frame_number, 0.0, 1.0, static_cast<double>(duration));\n        }\n\n        auto duration = target_duration();\n        if (!duration) {\n            return 0;\n        }\n\n        return audio_tweener_(current_frame_, 0.0, 1.0, static_cast<double>(*duration));\n    }\n\n    draw_frame\n    compose(draw_frame dst_frame, draw_frame src_frame, draw_frame mask_frame, draw_frame overlay_frame) const\n    {\n        const double delta                           = get_audio_delta();\n        src_frame.transform().audio_transform.volume = 1.0 - delta;\n        dst_frame.transform().audio_transform.volume = delta;\n\n        draw_frame mask_frame2                         = mask_frame;\n        mask_frame.transform().image_transform.is_key  = true;\n        mask_frame2.transform().image_transform.is_key = true;\n        mask_frame2.transform().image_transform.invert = true;\n\n        std::vector<draw_frame> frames;\n        frames.push_back(std::move(mask_frame2));\n        frames.push_back(std::move(src_frame));\n        frames.push_back(std::move(mask_frame));\n        frames.push_back(std::move(dst_frame));\n        if (overlay_frame != draw_frame::empty())\n            frames.push_back(std::move(overlay_frame));\n\n        return draw_frame(std::move(frames));\n    }\n\n    monitor::state state() const override { return state_; }\n\n    bool is_ready() override { return dst_producer_->is_ready(); }\n};\n\nspl::shared_ptr<frame_producer> create_sting_producer(const frame_producer_dependencies&     dependencies,\n                                                      const spl::shared_ptr<frame_producer>& destination,\n                                                      sting_info&                            info)\n{\n    auto mask_producer = dependencies.producer_registry->create_producer(dependencies, info.mask_filename);\n\n    auto overlay_producer = frame_producer::empty();\n    if (!info.overlay_filename.empty()) {\n        overlay_producer = dependencies.producer_registry->create_producer(dependencies, info.overlay_filename);\n    }\n\n    return spl::make_shared<sting_producer>(destination, info, mask_producer, overlay_producer);\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/transition/sting_producer.h",
    "content": "/*\n * Copyright (c) 2018 Norsk rikskringkasting AS\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include \"../../fwd.h\"\n#include \"../../video_format.h\"\n\n#include <common/memory.h>\n\n#include <string>\n\nnamespace caspar { namespace core {\n\nstruct sting_info\n{\n    std::wstring mask_filename       = L\"\";\n    std::wstring overlay_filename    = L\"\";\n    uint32_t     trigger_point       = 0;\n    uint32_t     audio_fade_start    = 0;\n    uint32_t     audio_fade_duration = UINT32_MAX;\n};\n\nspl::shared_ptr<frame_producer> create_sting_producer(const frame_producer_dependencies&     dependencies,\n                                                      const spl::shared_ptr<frame_producer>& destination,\n                                                      sting_info&                            info);\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/transition/transition_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../../StdAfx.h\"\n\n#include \"transition_producer.h\"\n\n#include \"../../frame/draw_frame.h\"\n#include \"../../frame/frame_transform.h\"\n#include \"../../monitor/monitor.h\"\n#include \"../frame_producer.h\"\n\n#include <common/scope_exit.h>\n\n#include <future>\n#include <utility>\n\nnamespace caspar::core {\n\nclass transition_producer : public frame_producer\n{\n    monitor::state state_;\n    int            current_frame_ = 0;\n\n    const transition_info info_;\n\n    spl::shared_ptr<frame_producer> dst_producer_ = frame_producer::empty();\n    spl::shared_ptr<frame_producer> src_producer_ = frame_producer::empty();\n    bool                            dst_is_ready_ = false;\n\n  public:\n    transition_producer(const spl::shared_ptr<frame_producer>& dest, transition_info info)\n        : info_(std::move(info))\n        , dst_producer_(dest)\n    {\n        dst_is_ready_ = dst_producer_->is_ready();\n        update_state();\n    }\n\n    // frame_producer\n\n    void update_is_ready(const core::video_field field)\n    {\n        // Ensure a frame has been attempted\n        dst_producer_->first_frame(field);\n\n        dst_is_ready_ = dst_producer_->is_ready();\n    }\n\n    core::draw_frame last_frame(const core::video_field field) override\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        update_is_ready(field);\n\n        if (!dst_is_ready_) {\n            return src_producer_->last_frame(field);\n        }\n\n        auto src = src_producer_->last_frame(field);\n        auto dst = dst_producer_->last_frame(field);\n\n        if (dst && current_frame_ >= info_.duration) {\n            return dst;\n        } else {\n            return src;\n        }\n    }\n\n    core::draw_frame first_frame(const core::video_field field) override { return dst_producer_->first_frame(field); }\n\n    void leading_producer(const spl::shared_ptr<frame_producer>& producer) override { src_producer_ = producer; }\n\n    [[nodiscard]] spl::shared_ptr<frame_producer> following_producer() const override\n    {\n        return current_frame_ >= info_.duration && dst_is_ready_ ? dst_producer_ : core::frame_producer::empty();\n    }\n\n    [[nodiscard]] std::optional<int64_t> auto_play_delta() const override\n    {\n        // Return how many frames before the end to start the transition\n        // Must never return 0 to avoid duplicate fields in AUTO playback\n\n        int64_t delta;\n\n        switch (info_.type) {\n            case transition_type::cut:\n                // CUT: Need full duration to show all frames\n                delta = info_.duration;\n                break;\n\n            case transition_type::cutfade:\n                // CUTFADE: Source is removed on first frame\n                delta = 1;\n                break;\n\n            case transition_type::vfade:\n                // VFADE: Source fades out by midpoint\n                delta = static_cast<int64_t>(std::floor(info_.duration / 2.0));\n                break;\n\n            default:\n                // Standard transitions (MIX, PUSH, SLIDE, WIPE)\n                // Need full duration to complete properly and avoid duplicated fields\n                delta = info_.duration;\n                break;\n        }\n\n        // Ensure we never return less than 1\n        return std::max(delta, int64_t(1));\n    }\n\n    void update_state()\n    {\n        state_                        = dst_producer_->state();\n        state_[\"transition/producer\"] = dst_producer_->name();\n        state_[\"transition/frame\"]    = {current_frame_, info_.duration};\n        state_[\"transition/type\"]     = [&]() -> std::string {\n            switch (info_.type) {\n                case transition_type::mix:\n                    return \"mix\";\n                case transition_type::wipe:\n                    return \"wipe\";\n                case transition_type::slide:\n                    return \"slide\";\n                case transition_type::push:\n                    return \"push\";\n                case transition_type::cut:\n                    return \"cut\";\n                case transition_type::fadecut:\n                    return \"fadecut\";\n                case transition_type::cutfade:\n                    return \"cutfade\";\n                case transition_type::vfade:\n                    return \"vfade\";\n                default:\n                    return \"n/a\";\n            }\n        }();\n        state_[\"transition/direction\"] = [&]() -> std::string {\n            switch (info_.direction) {\n                case transition_direction::from_left:\n                    return \"from_left\";\n                case transition_direction::from_right:\n                    return \"from_right\";\n                case transition_direction::from_top:\n                    return \"from_top\";\n                case transition_direction::from_bottom:\n                    return \"from_bottom\";\n                default:\n                    return \"n/a\";\n            }\n        }();\n    }\n\n    draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        update_is_ready(field);\n\n        // If destination is not ready, always use source (don't start any transition)\n        if (!dst_is_ready_) {\n            return src_producer_->receive(field, nb_samples);\n        }\n\n        // If transition is complete, return destination\n        if (current_frame_ >= info_.duration) {\n            auto dst = dst_producer_->receive(field, nb_samples);\n            if (!dst)\n                dst = dst_producer_->last_frame(field);\n            return dst;\n        }\n\n        // For CUT transitions, handle based on duration\n        if (info_.type == transition_type::cut) {\n            if (current_frame_ >= info_.duration) {\n                // Cut now - return destination\n                auto dst = dst_producer_->receive(field, nb_samples);\n                if (!dst)\n                    dst = dst_producer_->last_frame(field);\n                current_frame_++; // Increment after processing\n                return dst;\n            } else {\n                // Not time to cut yet - return source\n                auto src = src_producer_->receive(field, nb_samples);\n                if (!src)\n                    src = src_producer_->last_frame(field);\n                current_frame_++; // Increment after processing\n                return src;\n            }\n        }\n\n        // Compose and progress the transition\n        auto result = compose(field, nb_samples);\n        current_frame_++;\n        return result;\n    }\n\n    [[nodiscard]] uint32_t nb_frames() const override { return dst_producer_->nb_frames(); }\n\n    [[nodiscard]] uint32_t frame_number() const override { return dst_producer_->frame_number(); }\n\n    [[nodiscard]] std::wstring print() const override\n    {\n        return L\"transition[\" + src_producer_->print() + L\"=>\" + dst_producer_->print() + L\"]\";\n    }\n\n    [[nodiscard]] std::wstring name() const override { return L\"transition\"; }\n\n    [[nodiscard]] std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        return dst_producer_->call(params);\n    }\n\n    [[nodiscard]] draw_frame compose(const core::video_field field, int nb_samples) const\n    {\n        // Helper lambdas to get wrapped frames\n        auto get_src_frame = [&]() {\n            auto f = src_producer_->receive(field, nb_samples);\n            if (!f)\n                f = src_producer_->last_frame(field);\n            return draw_frame::push(std::move(f));\n        };\n        auto get_dst_frame = [&]() {\n            auto f = dst_producer_->receive(field, nb_samples);\n            if (!f)\n                f = dst_producer_->last_frame(field);\n            return draw_frame::push(std::move(f));\n        };\n\n        if (info_.type == transition_type::cut) {\n            return get_dst_frame();\n        } else if (info_.type == transition_type::fadecut) {\n            // Only use source during transition\n            auto   src     = get_src_frame();\n            double delta   = info_.tweener(current_frame_, 0.0, 1.0, static_cast<double>(info_.duration - 1));\n            double opacity = info_.duration > 1 ? 1.0 - delta : 0.0;\n            src.transform().image_transform.opacity          = opacity;\n            src.transform().audio_transform.volume           = opacity;\n            src.transform().audio_transform.immediate_volume = current_frame_ == 0;\n            return src;\n        } else if (info_.type == transition_type::vfade) {\n            double delta            = info_.tweener(current_frame_, 0.0, 1.0, static_cast<double>(info_.duration - 1));\n            bool   is_even_duration = (info_.duration % 2 == 0);\n\n            if (is_even_duration) {\n                double half_step = 0.5 / (info_.duration - 1);\n                if (delta >= (0.5 - half_step) && delta < 0.5) {\n                    auto src                                = get_src_frame();\n                    src.transform().image_transform.opacity = 0.0;\n                    src.transform().audio_transform.volume  = 0.0;\n                    return src;\n                }\n                if (delta >= 0.5 && delta < (0.5 + half_step)) {\n                    auto dst                                         = get_dst_frame();\n                    dst.transform().image_transform.opacity          = 0.0;\n                    dst.transform().audio_transform.volume           = 0.0;\n                    dst.transform().audio_transform.immediate_volume = true;\n                    return dst;\n                }\n            }\n            if (!is_even_duration && delta == 0.5) {\n                auto dst                                         = get_dst_frame();\n                dst.transform().image_transform.opacity          = 0.0;\n                dst.transform().audio_transform.volume           = 0.0;\n                dst.transform().audio_transform.immediate_volume = true;\n                return dst;\n            } else if (delta < 0.5) {\n                auto   src                              = get_src_frame();\n                double fade_out                         = 1.0 - (delta * 2.0);\n                src.transform().image_transform.opacity = fade_out;\n                src.transform().audio_transform.volume  = fade_out;\n                return src;\n            } else {\n                auto   dst                                       = get_dst_frame();\n                double fade_in                                   = (delta - 0.5) * 2.0;\n                dst.transform().image_transform.opacity          = fade_in;\n                dst.transform().audio_transform.volume           = fade_in;\n                dst.transform().audio_transform.immediate_volume = is_even_duration\n                                                                       ? (delta < 0.5 + (1.0 / (info_.duration - 1)))\n                                                                       : (delta <= 0.5 + (1.0 / (info_.duration - 1)));\n                return dst;\n            }\n        }\n        // For all other transitions, we need both frames\n        auto         src_frame = get_src_frame();\n        auto         dst_frame = get_dst_frame();\n        const double delta     = info_.tweener(current_frame_, 0.0, 1.0, static_cast<double>(info_.duration - 1));\n\n        // Get horizontal or vertical direction based on transition direction\n        const bool is_horizontal =\n            info_.direction == transition_direction::from_left || info_.direction == transition_direction::from_right;\n        const double h_dir = info_.direction == transition_direction::from_left ? 1.0 : -1.0;\n        const double v_dir = info_.direction == transition_direction::from_top ? 1.0 : -1.0;\n\n        src_frame.transform().audio_transform.volume = 1.0 - delta;\n        dst_frame.transform().audio_transform.volume = delta;\n        if (info_.type == transition_type::cutfade) {\n            double mix;\n            if (current_frame_ == 0) {\n                mix = 0.0;\n            } else {\n                mix = static_cast<double>(current_frame_) / static_cast<double>(info_.duration - 1);\n            }\n            if (info_.duration <= 1) {\n                mix = 1.0;\n            }\n            dst_frame.transform().image_transform.opacity          = mix;\n            dst_frame.transform().audio_transform.volume           = mix;\n            dst_frame.transform().audio_transform.immediate_volume = current_frame_ == 0;\n            return dst_frame;\n        } else if (info_.type == transition_type::mix) {\n            dst_frame.transform().image_transform.opacity = delta;\n            dst_frame.transform().image_transform.is_mix  = true;\n            src_frame.transform().image_transform.opacity = 1.0 - delta;\n            src_frame.transform().image_transform.is_mix  = true;\n        } else if (info_.type == transition_type::slide) {\n            if (is_horizontal) {\n                dst_frame.transform().image_transform.fill_translation[0] = (-1.0 + delta) * h_dir;\n            } else {\n                dst_frame.transform().image_transform.fill_translation[1] = (-1.0 + delta) * v_dir;\n            }\n        } else if (info_.type == transition_type::push) {\n            if (is_horizontal) {\n                dst_frame.transform().image_transform.fill_translation[0] = (-1.0 + delta) * h_dir;\n                src_frame.transform().image_transform.fill_translation[0] = (0.0 + delta) * h_dir;\n            } else {\n                dst_frame.transform().image_transform.fill_translation[1] = (-1.0 + delta) * v_dir;\n                src_frame.transform().image_transform.fill_translation[1] = (0.0 + delta) * v_dir;\n            }\n        } else if (info_.type == transition_type::wipe) {\n            if (is_horizontal) {\n                if (info_.direction == transition_direction::from_right) {\n                    dst_frame.transform().image_transform.clip_scale[0] = delta;\n                } else {\n                    dst_frame.transform().image_transform.clip_translation[0] = (1.0 - delta);\n                }\n            } else {\n                if (info_.direction == transition_direction::from_bottom) {\n                    dst_frame.transform().image_transform.clip_scale[1] = delta;\n                } else {\n                    dst_frame.transform().image_transform.clip_translation[1] = (1.0 - delta);\n                }\n            }\n        }\n        return draw_frame::over(src_frame, dst_frame);\n    }\n\n    [[nodiscard]] core::monitor::state state() const override { return state_; }\n\n    bool is_ready() override { return dst_producer_->is_ready(); }\n};\n\nspl::shared_ptr<frame_producer> create_transition_producer(const spl::shared_ptr<frame_producer>& destination,\n                                                           const transition_info&                 info)\n{\n    return spl::make_shared<transition_producer>(destination, info);\n}\n\nbool try_match_transition(const std::wstring& message, transition_info& transitionInfo)\n{\n    // Using word boundaries to ensure we match complete transition names\n    static const boost::wregex expr(\n        LR\"(.*\\b(?<TRANSITION>VFADE|FADECUT|CUTFADE|CUT|PUSH|SLIDE|WIPE|MIX)\\b\\s+(?<DURATION>\\d+)\\s*(?<TWEEN>(LINEAR)|(EASE[^\\s]*))?\\s*(?<DIRECTION>FROMLEFT|FROMRIGHT|FROMTOP|FROMBOTTOM|LEFT|RIGHT|UP|DOWN)?.*)\");\n    boost::wsmatch what;\n    if (!boost::regex_match(message, what, expr)) {\n        return false;\n    }\n\n    transitionInfo.duration = std::stoi(what[\"DURATION\"].str());\n    if (transitionInfo.duration == 0) {\n        return false;\n    }\n\n    auto transition        = what[\"TRANSITION\"].str();\n    auto direction         = what[\"DIRECTION\"].matched ? what[\"DIRECTION\"].str() : L\"\";\n    auto tween             = what[\"TWEEN\"].matched ? what[\"TWEEN\"].str() : L\"\";\n    transitionInfo.tweener = tween;\n\n    if (transition == L\"CUT\")\n        transitionInfo.type = transition_type::cut;\n    else if (transition == L\"MIX\")\n        transitionInfo.type = transition_type::mix;\n    else if (transition == L\"PUSH\")\n        transitionInfo.type = transition_type::push;\n    else if (transition == L\"SLIDE\")\n        transitionInfo.type = transition_type::slide;\n    else if (transition == L\"WIPE\")\n        transitionInfo.type = transition_type::wipe;\n    else if (transition == L\"FADECUT\")\n        transitionInfo.type = transition_type::fadecut;\n    else if (transition == L\"CUTFADE\")\n        transitionInfo.type = transition_type::cutfade;\n    else if (transition == L\"VFADE\")\n        transitionInfo.type = transition_type::vfade;\n\n    if (direction == L\"FROMLEFT\" || direction == L\"RIGHT\")\n        transitionInfo.direction = transition_direction::from_left;\n    else if (direction == L\"FROMRIGHT\" || direction == L\"LEFT\")\n        transitionInfo.direction = transition_direction::from_right;\n    else if (direction == L\"FROMTOP\" || direction == L\"DOWN\")\n        transitionInfo.direction = transition_direction::from_top;\n    else if (direction == L\"FROMBOTTOM\" || direction == L\"UP\")\n        transitionInfo.direction = transition_direction::from_bottom;\n\n    return true;\n}\n\n} // namespace caspar::core\n"
  },
  {
    "path": "src/core/producer/transition/transition_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"../../fwd.h\"\n\n#include <common/memory.h>\n#include <common/tweener.h>\n\n#include <string>\n\nnamespace caspar { namespace core {\n\nenum class transition_type\n{\n    cut,\n    mix,\n    push,\n    slide,\n    wipe,\n    fadecut,\n    cutfade,\n    vfade,\n    count\n};\n\nenum class transition_direction\n{\n    from_left,\n    from_right,\n    from_top,\n    from_bottom,\n    count\n};\n\nstruct transition_info\n{\n    int                  duration  = 0;\n    transition_direction direction = transition_direction::from_left;\n    transition_type      type      = transition_type::cut;\n    caspar::tweener      tweener{L\"linear\"};\n};\n\nbool try_match_transition(const std::wstring& message, transition_info& transitionInfo);\n\nspl::shared_ptr<frame_producer> create_transition_producer(const spl::shared_ptr<frame_producer>& destination,\n                                                           const transition_info&                 info);\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/video_channel.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"StdAfx.h\"\n\n#include \"common/os/thread.h\"\n#include \"video_channel.h\"\n\n#include \"video_format.h\"\n\n#include \"consumer/channel_info.h\"\n#include \"consumer/output.h\"\n#include \"frame/draw_frame.h\"\n#include \"frame/frame.h\"\n#include \"frame/frame_factory.h\"\n#include \"mixer/mixer.h\"\n#include \"producer/stage.h\"\n\n#include <common/diagnostics/graph.h>\n#include <common/executor.h>\n#include <common/timer.h>\n\n#include <core/diagnostics/call_context.h>\n#include <core/mixer/image/image_mixer.h>\n\n#include <mutex>\n#include <string>\n#include <unordered_map>\n#include <utility>\n\nnamespace caspar { namespace core {\n\nbool operator<(const route_id& a, const route_id& b) { return a.mode + (a.index << 2) < b.mode + (b.index << 2); }\n\nstruct video_channel::impl final\n{\n    monitor::state state_;\n\n    const channel_info channel_info_;\n\n    const spl::shared_ptr<caspar::diagnostics::graph> graph_ = [](int index) {\n        core::diagnostics::scoped_call_context save;\n        core::diagnostics::call_context::for_thread().video_channel = index;\n        return spl::make_shared<caspar::diagnostics::graph>();\n    }(channel_info_.index);\n\n    caspar::core::output         output_;\n    spl::shared_ptr<image_mixer> image_mixer_;\n    caspar::core::mixer          mixer_;\n    std::shared_ptr<core::stage> stage_;\n\n    uint64_t frame_counter_ = 0;\n\n    std::function<void(core::monitor::state)> tick_;\n\n    std::map<route_id, std::weak_ptr<core::route>> routes_;\n    std::mutex                                     routes_mutex_;\n\n    std::atomic<bool> abort_request_{false};\n    std::thread       thread_;\n\n    std::function<void(int, const layer_frame&)> routesCb = [&](int layer, const layer_frame& layer_frame) {\n        std::lock_guard<std::mutex> lock(routes_mutex_);\n        for (auto& r : routes_) {\n            // if this layer is the source for this route, push the frame to the route producers\n            if (layer == r.first.index) {\n                auto route = r.second.lock();\n                if (!route)\n                    continue;\n\n                if (r.first.index == -1) {\n                    route->signal(layer_frame.foreground1, layer_frame.foreground2);\n                } else if (r.first.mode == route_mode::background ||\n                           (r.first.mode == route_mode::next && layer_frame.has_background)) {\n                    route->signal(draw_frame::pop(layer_frame.background1), draw_frame::pop(layer_frame.background2));\n                } else {\n                    route->signal(draw_frame::pop(layer_frame.foreground1), draw_frame::pop(layer_frame.foreground2));\n                }\n            }\n        }\n    };\n\n  public:\n    impl(int                                       index,\n         const core::video_format_desc&            format_desc,\n         color_space                               default_color_space,\n         std::unique_ptr<image_mixer>              image_mixer,\n         std::function<void(core::monitor::state)> tick)\n        : channel_info_(index, image_mixer->depth(), default_color_space)\n        , output_(graph_, format_desc, channel_info_)\n        , image_mixer_(std::move(image_mixer))\n        , mixer_(index, graph_, image_mixer_)\n        , stage_(std::make_shared<core::stage>(index, graph_, format_desc))\n        , tick_(std::move(tick))\n    {\n        graph_->set_color(\"produce-time\", caspar::diagnostics::color(0.0f, 1.0f, 0.0f));\n        graph_->set_color(\"mix-time\", caspar::diagnostics::color(1.0f, 0.0f, 0.9f, 0.8f));\n        graph_->set_color(\"consume-time\", caspar::diagnostics::color(1.0f, 0.4f, 0.0f, 0.8f));\n        graph_->set_color(\"frame-time\", caspar::diagnostics::color(1.0f, 0.4f, 0.4f, 0.8f));\n        graph_->set_color(\"osc-time\", caspar::diagnostics::color(0.3f, 0.4f, 0.0f, 0.8f));\n        graph_->set_text(print());\n        caspar::diagnostics::register_graph(graph_);\n\n        CASPAR_LOG(info) << print() << \" Successfully Initialized.\";\n\n        thread_ = std::thread([this] {\n            set_thread_realtime_priority();\n            set_thread_name(L\"channel-\" + std::to_wstring(channel_info_.index));\n\n            while (!abort_request_) {\n                try {\n                    graph_->set_text(print());\n\n                    frame_counter_ += 1;\n\n                    caspar::timer frame_timer;\n\n                    // Determine all layers that need a frame from the background producer\n                    std::vector<int> background_routes = {};\n                    {\n                        std::lock_guard<std::mutex> lock(routes_mutex_);\n\n                        for (auto& r : routes_) {\n                            // Ensure pointer is still valid\n                            if (!r.second.lock())\n                                continue;\n\n                            if (r.first.mode != route_mode::foreground) {\n                                background_routes.push_back(r.first.index);\n                            }\n                        }\n                    }\n\n                    // Produce\n                    caspar::timer produce_timer;\n                    auto          stage_frames = (*stage_)(frame_counter_, background_routes, routesCb);\n                    graph_->set_value(\"produce-time\", produce_timer.elapsed() * stage_frames.format_desc.hz * 0.5);\n\n                    // This is a little race prone, but at worst a new consumer will start with a frame of black\n                    bool has_consumers = output_.consumer_count() > 0;\n\n                    // Mix\n                    caspar::timer mix_timer;\n                    auto          mixed_frame =\n                        has_consumers ? mixer_(stage_frames.frames, stage_frames.format_desc, stage_frames.nb_samples)\n                                               : const_frame{};\n                    auto mixed_frame2 =\n                        has_consumers && stage_frames.format_desc.field_count == 2\n                            ? mixer_(stage_frames.frames2, stage_frames.format_desc, stage_frames.nb_samples)\n                            : const_frame{};\n                    graph_->set_value(\"mix-time\", mix_timer.elapsed() * stage_frames.format_desc.hz * 0.5);\n\n                    // Consume\n                    caspar::timer consume_timer;\n                    output_(mixed_frame, mixed_frame2, stage_frames.format_desc);\n                    graph_->set_value(\"consume-time\", consume_timer.elapsed() * stage_frames.format_desc.hz * 0.5);\n\n                    graph_->set_value(\"frame-time\", frame_timer.elapsed() * stage_frames.format_desc.hz * 0.5);\n\n                    monitor::state state = {};\n                    state[\"stage\"]       = stage_->state();\n                    state[\"mixer\"]       = mixer_.state();\n                    state[\"output\"]      = output_.state();\n                    state[\"framerate\"]   = {stage_frames.format_desc.framerate.numerator() *\n                                                stage_frames.format_desc.field_count,\n                                            stage_frames.format_desc.framerate.denominator()};\n                    state[\"format\"]      = stage_frames.format_desc.name;\n                    state_               = state;\n\n                    caspar::timer osc_timer;\n                    tick_(state_);\n                    graph_->set_value(\"osc-time\", osc_timer.elapsed() * stage_frames.format_desc.hz * 0.5);\n                } catch (...) {\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n                }\n            }\n        });\n    }\n\n    ~impl()\n    {\n        CASPAR_LOG(info) << print() << \" Uninitializing.\";\n        abort_request_ = true;\n        thread_.join();\n    }\n\n    std::shared_ptr<core::route> route(int index = -1, route_mode mode = route_mode::foreground)\n    {\n        std::lock_guard<std::mutex> lock(routes_mutex_);\n\n        route_id id = {};\n        id.index    = index;\n        id.mode     = mode;\n\n        auto route = routes_[id].lock();\n        if (!route) {\n            route              = std::make_shared<core::route>();\n            route->format_desc = stage_->video_format_desc(); // TODO this needs updating whenever the videomode changes\n            route->name        = std::to_wstring(channel_info_.index);\n            if (index != -1) {\n                route->name += L\"/\" + std::to_wstring(index);\n            }\n            if (mode == route_mode::background) {\n                route->name += L\"/background\";\n            } else if (mode == route_mode::next) {\n                route->name += L\"/next\";\n            }\n            routes_[id] = route;\n        }\n\n        return route;\n    }\n\n    std::wstring print() const\n    {\n        return L\"video_channel[\" + std::to_wstring(channel_info_.index) + L\"|\" + stage_->video_format_desc().name +\n               L\"]\";\n    }\n\n    int index() const { return channel_info_.index; }\n\n    channel_info get_consumer_channel_info() const { return channel_info_; }\n};\n\nvideo_channel::video_channel(int                                       index,\n                             const core::video_format_desc&            format_desc,\n                             color_space                               default_color_space,\n                             std::unique_ptr<image_mixer>              image_mixer,\n                             std::function<void(core::monitor::state)> tick)\n    : impl_(new impl(index, format_desc, default_color_space, std::move(image_mixer), std::move(tick)))\n{\n}\nvideo_channel::~video_channel() {}\nconst std::shared_ptr<core::stage>& video_channel::stage() const { return impl_->stage_; }\nstd::shared_ptr<core::stage>&       video_channel::stage() { return impl_->stage_; }\nconst mixer&                        video_channel::mixer() const { return impl_->mixer_; }\nmixer&                              video_channel::mixer() { return impl_->mixer_; }\nconst output&                       video_channel::output() const { return impl_->output_; }\noutput&                             video_channel::output() { return impl_->output_; }\nspl::shared_ptr<frame_factory>      video_channel::frame_factory() { return impl_->image_mixer_; }\nint                                 video_channel::index() const { return impl_->index(); }\nchannel_info         video_channel::get_consumer_channel_info() const { return impl_->get_consumer_channel_info(); };\ncore::monitor::state video_channel::state() const { return impl_->state_; }\n\nstd::shared_ptr<route> video_channel::route(int index, route_mode mode) { return impl_->route(index, mode); }\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/video_channel.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include \"fwd.h\"\n#include \"video_format.h\"\n\n#include \"frame/pixel_format.h\"\n\n#include \"monitor/monitor.h\"\n\n#include <common/memory.h>\n\n#include <boost/signals2.hpp>\n\n#include <functional>\n\nnamespace caspar { namespace core {\n\nenum route_mode\n{\n    foreground,\n    background,\n    next, // background if any, otherwise foreground\n};\n\nstruct route_id\n{\n    int        index;\n    route_mode mode;\n\n    bool const operator==(const route_id& o) { return index == o.index && mode == o.mode; }\n};\n\nstruct route\n{\n    route()             = default;\n    route(const route&) = delete;\n    route(route&&)      = default;\n\n    route& operator=(const route&) = delete;\n    route& operator=(route&&)      = default;\n\n    boost::signals2::signal<void(class draw_frame, class draw_frame)> signal;\n    video_format_desc                                                 format_desc;\n    std::wstring                                                      name;\n};\n\nclass video_channel final\n{\n    video_channel(const video_channel&);\n    video_channel& operator=(const video_channel&);\n\n  public:\n    explicit video_channel(int                                       index,\n                           const video_format_desc&                  format_desc,\n                           color_space                               default_color_space,\n                           std::unique_ptr<image_mixer>              image_mixer,\n                           std::function<void(core::monitor::state)> on_tick);\n    ~video_channel();\n\n    core::monitor::state state() const;\n\n    const std::shared_ptr<core::stage>& stage() const;\n    std::shared_ptr<core::stage>&       stage();\n    const core::mixer&                  mixer() const;\n    core::mixer&                        mixer();\n    const core::output&                 output() const;\n    core::output&                       output();\n\n    spl::shared_ptr<core::frame_factory> frame_factory();\n\n    int index() const;\n\n    [[nodiscard]] channel_info get_consumer_channel_info() const;\n\n    std::shared_ptr<core::route> route(int index = -1, route_mode mode = route_mode::foreground);\n\n  private:\n    struct impl;\n    spl::unique_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/video_format.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"StdAfx.h\"\n\n#include \"video_format.h\"\n\n#include <common/log.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/range/adaptors.hpp>\n#include <utility>\n\nnamespace caspar { namespace core {\n\nstruct video_format_repository::impl\n{\n  private:\n    std::map<std::wstring, video_format_desc> formats_;\n\n  public:\n    impl()\n        : formats_()\n    {\n        const std::vector<video_format_desc> default_formats = {\n            {video_format::pal, 2, 720, 576, 1024, 576, 25000, 1000, L\"PAL\", {1920 / 2}},\n            {video_format::ntsc,\n             2,\n             720,\n             486,\n             720,\n             540,\n             30000,\n             1001,\n             L\"NTSC\",\n             {801, 801, 801, 800, 801, 801, 801, 800, 801, 801}},\n            {video_format::x576p2500, 1, 720, 576, 1024, 576, 25000, 1000, L\"576p2500\", {1920}},\n            {video_format::x720p2398, 1, 1280, 720, 1280, 720, 24000, 1001, L\"720p2398\", {2002}},\n            {video_format::x720p2400, 1, 1280, 720, 1280, 720, 24000, 1000, L\"720p2400\", {2000}},\n            {video_format::x720p2500, 1, 1280, 720, 1280, 720, 25000, 1000, L\"720p2500\", {1920}},\n            {video_format::x720p2997,\n             1,\n             1280,\n             720,\n             1280,\n             720,\n             30000,\n             1001,\n             L\"720p2997\",\n             {1602, 1601, 1602, 1601, 1602}},\n            {video_format::x720p3000, 1, 1280, 720, 1280, 720, 30000, 1000, L\"720p3000\", {1600}},\n            {video_format::x720p5000, 1, 1280, 720, 1280, 720, 50000, 1000, L\"720p5000\", {960}},\n            {video_format::x720p5994, 1, 1280, 720, 1280, 720, 60000, 1001, L\"720p5994\", {801, 800, 801, 801, 801}},\n            {video_format::x720p6000, 1, 1280, 720, 1280, 720, 60000, 1000, L\"720p6000\", {800}},\n            {video_format::x1080i5000, 2, 1920, 1080, 1920, 1080, 25000, 1000, L\"1080i5000\", {1920 / 2}},\n            {video_format::x1080i5994,\n             2,\n             1920,\n             1080,\n             1920,\n             1080,\n             30000,\n             1001,\n             L\"1080i5994\",\n             {801, 801, 801, 800, 801, 801, 801, 800, 801, 801}},\n            {video_format::x1080i6000, 2, 1920, 1080, 1920, 1080, 30000, 1000, L\"1080i6000\", {1600 / 2}},\n            {video_format::x1080p2398, 1, 1920, 1080, 1920, 1080, 24000, 1001, L\"1080p2398\", {2002}},\n            {video_format::x1080p2400, 1, 1920, 1080, 1920, 1080, 24000, 1000, L\"1080p2400\", {2000}},\n            {video_format::x1080p2500, 1, 1920, 1080, 1920, 1080, 25000, 1000, L\"1080p2500\", {1920}},\n            {video_format::x1080p2997,\n             1,\n             1920,\n             1080,\n             1920,\n             1080,\n             30000,\n             1001,\n             L\"1080p2997\",\n             {1602, 1601, 1602, 1601, 1602}},\n            {video_format::x1080p3000, 1, 1920, 1080, 1920, 1080, 30000, 1000, L\"1080p3000\", {1600}},\n            {video_format::x1080p5000, 1, 1920, 1080, 1920, 1080, 50000, 1000, L\"1080p5000\", {960}},\n            {video_format::x1080p5994, 1, 1920, 1080, 1920, 1080, 60000, 1001, L\"1080p5994\", {801, 800, 801, 801, 801}},\n            {video_format::x1080p6000, 1, 1920, 1080, 1920, 1080, 60000, 1000, L\"1080p6000\", {800}},\n            {video_format::x1556p2398, 1, 2048, 1556, 2048, 1556, 24000, 1001, L\"1556p2398\", {2002}},\n            {video_format::x1556p2400, 1, 2048, 1556, 2048, 1556, 24000, 1000, L\"1556p2400\", {2000}},\n            {video_format::x1556p2500, 1, 2048, 1556, 2048, 1556, 25000, 1000, L\"1556p2500\", {1920}},\n            {video_format::x2160p2398, 1, 3840, 2160, 3840, 2160, 24000, 1001, L\"2160p2398\", {2002}},\n            {video_format::x2160p2400, 1, 3840, 2160, 3840, 2160, 24000, 1000, L\"2160p2400\", {2000}},\n            {video_format::x2160p2500, 1, 3840, 2160, 3840, 2160, 25000, 1000, L\"2160p2500\", {1920}},\n            {video_format::x2160p2997,\n             1,\n             3840,\n             2160,\n             3840,\n             2160,\n             30000,\n             1001,\n             L\"2160p2997\",\n             {1602, 1601, 1602, 1601, 1602}},\n            {video_format::x2160p3000, 1, 3840, 2160, 3840, 2160, 30000, 1000, L\"2160p3000\", {1600}},\n            {video_format::x2160p5000, 1, 3840, 2160, 3840, 2160, 50000, 1000, L\"2160p5000\", {960}},\n            {video_format::x2160p5994, 1, 3840, 2160, 3840, 2160, 60000, 1001, L\"2160p5994\", {801, 800, 801, 801, 801}},\n            {video_format::x2160p6000, 1, 3840, 2160, 3840, 2160, 60000, 1000, L\"2160p6000\", {800}},\n            {video_format::x4kDCIp2398, 1, 4096, 2160, 4096, 2160, 24000, 1001, L\"4kDCIp2398\", {2002}},\n            {video_format::x4kDCIp2400, 1, 4096, 2160, 4096, 2160, 24000, 1000, L\"4kDCIp2400\", {2000}},\n            {video_format::x4kDCIp2500, 1, 4096, 2160, 4096, 2160, 25000, 1000, L\"4kDCIp2500\", {1920}},\n            {video_format::x4kDCIp2997,\n             1,\n             4096,\n             2160,\n             4096,\n             2160,\n             30000,\n             1001,\n             L\"4kDCIp2997\",\n             {1602, 1601, 1602, 1601, 1602}},\n            {video_format::x4kDCIp3000, 1, 4096, 2160, 4096, 2160, 30000, 1000, L\"4kDCIp3000\", {1600}},\n            {video_format::x4kDCIp5000, 1, 4096, 2160, 4096, 2160, 50000, 1000, L\"4kDCIp5000\", {960}},\n            {video_format::x4kDCIp5994,\n             1,\n             4096,\n             2160,\n             4096,\n             2160,\n             60000,\n             1001,\n             L\"4kDCIp5994\",\n             {801, 800, 801, 801, 801}},\n            {video_format::x4kDCIp6000, 1, 4096, 2160, 4096, 2160, 60000, 1000, L\"4kDCIp6000\", {800}},\n        };\n\n        for (auto& f : default_formats)\n            formats_.insert({(boost::to_lower_copy(f.name)), f});\n    }\n\n    video_format_desc find(const std::wstring& name) const\n    {\n        const std::wstring lower = boost::to_lower_copy(name);\n\n        const auto res = formats_.find(lower);\n        if (res != formats_.end())\n            return res->second;\n\n        return invalid();\n    }\n\n    video_format_desc find_format(const video_format& id) const\n    {\n        for (auto& f : formats_) {\n            if (f.second.format == id)\n                return f.second;\n        }\n\n        return invalid();\n    }\n\n    void store(const video_format_desc& format)\n    {\n        const std::wstring lower = boost::to_lower_copy(format.name);\n        formats_.insert({lower, format});\n    }\n\n    std::size_t get_max_video_format_size() const\n    {\n        size_t max = 0;\n        for (auto& f : formats_) {\n            if (f.second.size > max)\n                max = f.second.size;\n        }\n\n        const size_t MaxBytesPerColor = 2;\n        return max * MaxBytesPerColor;\n    }\n};\n\nvideo_format_repository::video_format_repository()\n    : impl_(new impl())\n{\n}\nvideo_format_desc video_format_repository::invalid()\n{\n    return video_format_desc(video_format::invalid, 1, 0, 0, 0, 0, 1, 1, L\"invalid\", {1});\n};\nvideo_format_desc video_format_repository::find(const std::wstring& name) const { return impl_->find(name); }\nvideo_format_desc video_format_repository::find_format(const video_format& format) const\n{\n    return impl_->find_format(format);\n}\nvoid video_format_repository::store(const video_format_desc& format) { impl_->store(format); }\n\nstd::size_t video_format_repository::get_max_video_format_size() const { return impl_->get_max_video_format_size(); }\n\nvideo_format_desc::video_format_desc(const video_format     format,\n                                     const int              field_count,\n                                     const int              width,\n                                     const int              height,\n                                     const int              square_width,\n                                     const int              square_height,\n                                     const int              time_scale,\n                                     const int              duration,\n                                     const std::wstring     name,\n                                     const std::vector<int> audio_cadence)\n    : format(format)\n    , width(width)\n    , height(height)\n    , square_width(square_width)\n    , square_height(square_height)\n    , field_count(field_count)\n    , hz(static_cast<double>(time_scale) / static_cast<double>(duration))\n    , fps(hz * field_count)\n    , framerate(time_scale, duration)\n    , time_scale(time_scale)\n    , duration(duration)\n    , size(width * height * 4)\n    , name(std::move(name))\n    , audio_sample_rate(48000)\n    , audio_cadence(std::move(audio_cadence))\n{\n}\n\nvideo_format_desc::video_format_desc()\n    : format(video_format::invalid)\n{\n    *this = video_format_repository::invalid();\n}\n\nbool operator==(const video_format_desc& lhs, const video_format_desc& rhs)\n{\n    if (lhs.format == video_format::custom || rhs.format == video_format::custom) {\n        if (lhs.format != rhs.format) {\n            // If one is custom, and the other isnt, then they dont match\n            return false;\n        }\n\n        // TODO - expand on this\n        if (lhs.width != rhs.width || lhs.height != rhs.height || lhs.framerate != rhs.framerate) {\n            return false;\n        }\n\n        return true;\n    } else {\n        // If neither are custom, look just at the format\n        return lhs.format == rhs.format;\n    }\n}\n\nbool operator!=(const video_format_desc& lhs, const video_format_desc& rhs) { return !(lhs == rhs); }\n\nstd::wostream& operator<<(std::wostream& out, const video_format_desc& format_desc)\n{\n    out << format_desc.name.c_str();\n    return out;\n}\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/core/video_format.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <cstddef>\n#include <string>\n#include <vector>\n\n#include <common/memory.h>\n\n#include <boost/rational.hpp>\n\nnamespace caspar { namespace core {\n\nenum class video_field\n{\n    progressive,\n    a,\n    b,\n};\n\nenum class video_format\n{\n    pal,\n    ntsc,\n    x576p2500,\n    x720p2398,\n    x720p2400,\n    x720p2500,\n    x720p2997,\n    x720p3000,\n    x720p5000,\n    x720p5994,\n    x720p6000,\n    x1080i5000,\n    x1080i5994,\n    x1080i6000,\n    x1080p2398,\n    x1080p2400,\n    x1080p2500,\n    x1080p2997,\n    x1080p3000,\n    x1080p5000,\n    x1080p5994,\n    x1080p6000,\n    x1556p2398,\n    x1556p2400,\n    x1556p2500,\n    x2160p2398,\n    x2160p2400,\n    x2160p2500,\n    x2160p2997,\n    x2160p3000,\n    x2160p5000,\n    x2160p5994,\n    x2160p6000,\n    x4kDCIp2398,\n    x4kDCIp2400,\n    x4kDCIp2500,\n    x4kDCIp2997,\n    x4kDCIp3000,\n    x4kDCIp5000,\n    x4kDCIp5994,\n    x4kDCIp6000,\n    invalid,\n    custom,\n    count\n};\n\nstruct video_format_desc final\n{\n    video_format format{video_format::invalid};\n\n    int                  width;\n    int                  height;\n    int                  square_width;\n    int                  square_height;\n    int                  field_count;\n    double               hz;  // actual tickrate of the channel, e.g. i50 = 25 hz, p50 = 50 hz\n    double               fps; // actual fieldrate, e.g. i50 = 50 fps, p50 = 50 fps\n    boost::rational<int> framerate;\n    int                  time_scale;\n    int                  duration;\n    std::size_t          size; // frame size in bytes\n    std::wstring         name; // name of output format\n\n    int              audio_channels = 16;\n    int              audio_sample_rate;\n    std::vector<int> audio_cadence; // rotating optimal number of samples per frame\n\n    video_format_desc(video_format     format,\n                      int              field_count,\n                      int              width,\n                      int              height,\n                      int              square_width,\n                      int              square_height,\n                      int              time_scale,\n                      int              duration,\n                      std::wstring     name,\n                      std::vector<int> audio_cadence);\n\n    video_format_desc();\n};\n\nbool operator==(const video_format_desc& rhs, const video_format_desc& lhs);\nbool operator!=(const video_format_desc& rhs, const video_format_desc& lhs);\n\nstd::wostream& operator<<(std::wostream& out, const video_format_desc& format_desc);\n\nclass video_format_repository\n{\n  public:\n    explicit video_format_repository();\n\n    video_format_desc find(const std::wstring& name) const;\n    video_format_desc find_format(const video_format& format) const;\n    void              store(const video_format_desc& format);\n\n    std::size_t get_max_video_format_size() const;\n\n    static video_format_desc invalid();\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\n}} // namespace caspar::core\n"
  },
  {
    "path": "src/modules/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject(\"modules\")\n\nadd_subdirectory(image)\nadd_subdirectory(ffmpeg)\nadd_subdirectory(oal)\nadd_subdirectory(decklink)\nadd_subdirectory(screen)\nadd_subdirectory(newtek)\nadd_subdirectory(artnet)\n\nif (ENABLE_HTML)\n\tadd_subdirectory(html)\nendif ()\n\nif (MSVC)\n\tadd_subdirectory(flash)\n\tadd_subdirectory(bluefish)\nendif()\n\n"
  },
  {
    "path": "src/modules/artnet/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (artnet)\n\nset(SOURCES\n\tconsumer/artnet_consumer.cpp\n\tconsumer/artnet_consumer.h\n\n\tutil/fixture_calculation.cpp\n\tutil/fixture_calculation.h\n\n\tartnet.cpp\n\tartnet.h\n)\n\ncasparcg_add_module_project(artnet\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"artnet::init\"\n)\n\nset_target_properties(artnet PROPERTIES FOLDER modules)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources\\\\util util/*)\nsource_group(sources ./*)\n\n"
  },
  {
    "path": "src/modules/artnet/artnet.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Eliyah Sundström eliyah@sundstroem.com\n */\n\n#include \"artnet.h\"\n\n#define WIN32_LEAN_AND_MEAN\n\n#include \"consumer/artnet_consumer.h\"\n\n#include <core/consumer/frame_consumer.h>\n\n#include <common/utf.h>\n\nnamespace caspar { namespace artnet {\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"artnet\", create_preconfigured_consumer);\n}\n\n}} // namespace caspar::artnet\n"
  },
  {
    "path": "src/modules/artnet/artnet.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Eliyah Sundström eliyah@sundstroem.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace artnet {\n\nvoid init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::artnet\n"
  },
  {
    "path": "src/modules/artnet/consumer/artnet_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Eliyah Sundström eliyah@sundstroem.com\n */\n\n#include \"artnet_consumer.h\"\n\n#undef NOMINMAX\n// ^^ This is needed to avoid a conflict between boost asio and other header files defining NOMINMAX\n\n#include <common/future.h>\n#include <common/log.h>\n#include <common/ptree.h>\n\n#include <core/consumer/channel_info.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/asio.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <thread>\n#include <utility>\n#include <vector>\n\nusing namespace boost::asio;\nusing namespace boost::asio::ip;\n\nnamespace caspar { namespace artnet {\n\nstruct configuration\n{\n    int            universe = 0;\n    std::wstring   host     = L\"127.0.0.1\";\n    unsigned short port     = 6454;\n\n    int refreshRate = 10;\n\n    std::vector<fixture> fixtures;\n};\n\nstruct artnet_consumer : public core::frame_consumer\n{\n    const configuration           config;\n    std::vector<computed_fixture> computed_fixtures;\n\n  public:\n    // frame_consumer\n\n    explicit artnet_consumer(configuration config)\n        : config(std::move(config))\n        , io_context_()\n        , socket(io_context_)\n    {\n        socket.open(udp::v4());\n\n        std::string host_ = u8(this->config.host);\n        remote_endpoint   = boost::asio::ip::udp::endpoint(boost::asio::ip::make_address(host_), this->config.port);\n\n        compute_fixtures();\n    }\n\n    void initialize(const core::video_format_desc& /*format_desc*/,\n                    const core::channel_info& channel_info,\n                    int                       port_index) override\n    {\n        thread_ = std::thread([this] {\n            long long time      = 1000 / config.refreshRate;\n            auto      last_send = std::chrono::system_clock::now();\n\n            while (!abort_request_) {\n                try {\n                    auto                          now             = std::chrono::system_clock::now();\n                    std::chrono::duration<double> elapsed_seconds = now - last_send;\n                    long long                     elapsed_ms =\n                        std::chrono::duration_cast<std::chrono::milliseconds>(elapsed_seconds).count();\n\n                    long long sleep_time = time - elapsed_ms * 1000;\n                    if (sleep_time > 0)\n                        std::this_thread::sleep_for(std::chrono::milliseconds(sleep_time));\n\n                    last_send = now;\n\n                    frame_mutex_.lock();\n                    auto frame = last_frame_;\n\n                    frame_mutex_.unlock();\n                    if (!frame)\n                        continue; // No frame available\n\n                    uint8_t dmx_data[512];\n                    memset(dmx_data, 0, 512);\n\n                    for (auto computed_fixture : computed_fixtures) {\n                        auto     color = average_color(frame, computed_fixture.rectangle);\n                        uint8_t* ptr   = dmx_data + computed_fixture.address;\n\n                        switch (computed_fixture.type) {\n                            case FixtureType::DIMMER:\n                                ptr[0] = (uint8_t)(0.279 * color.r + 0.547 * color.g + 0.106 * color.b);\n                                break;\n                            case FixtureType::RGB:\n                                ptr[0] = color.r;\n                                ptr[1] = color.g;\n                                ptr[2] = color.b;\n                                break;\n                            case FixtureType::RGBW:\n                                uint8_t w = std::min(std::min(color.r, color.g), color.b);\n                                ptr[0]    = color.r - w;\n                                ptr[1]    = color.g - w;\n                                ptr[2]    = color.b - w;\n                                ptr[3]    = w;\n                                break;\n                        }\n                    }\n\n                    send_dmx_data(dmx_data, 512);\n                } catch (...) {\n                    CASPAR_LOG_CURRENT_EXCEPTION();\n                }\n            }\n        });\n    }\n\n    ~artnet_consumer()\n    {\n        abort_request_ = true;\n        if (thread_.joinable())\n            thread_.join();\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        std::lock_guard<std::mutex> lock(frame_mutex_);\n        last_frame_ = frame;\n\n        return make_ready_future(true);\n    }\n\n    std::wstring print() const override { return L\"artnet[]\"; }\n\n    std::wstring name() const override { return L\"artnet\"; }\n\n    int index() const override { return 1337; }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"artnet/computed-fixtures\"] = computed_fixtures.size();\n        state[\"artnet/fixtures\"]          = config.fixtures.size();\n        state[\"artnet/universe\"]          = config.universe;\n        state[\"artnet/host\"]              = config.host;\n        state[\"artnet/port\"]              = config.port;\n        state[\"artnet/refresh-rate\"]      = config.refreshRate;\n\n        return state;\n    }\n\n  private:\n    core::const_frame last_frame_;\n    std::mutex        frame_mutex_;\n\n    std::thread       thread_;\n    std::atomic<bool> abort_request_{false};\n\n    io_context    io_context_;\n    udp::socket   socket;\n    udp::endpoint remote_endpoint;\n\n    void compute_fixtures()\n    {\n        computed_fixtures.clear();\n        for (auto fixture : config.fixtures) {\n            for (unsigned short i = 0; i < fixture.fixtureCount; i++) {\n                computed_fixture computed_fixture{};\n                computed_fixture.type    = fixture.type;\n                computed_fixture.address = fixture.startAddress + i * fixture.fixtureChannels;\n\n                computed_fixture.rectangle = compute_rect(fixture.fixtureBox, i, fixture.fixtureCount);\n                computed_fixtures.push_back(computed_fixture);\n            }\n        }\n    }\n\n    void send_dmx_data(const std::uint8_t* data, std::size_t length)\n    {\n        int universe = this->config.universe;\n\n        std::uint8_t hUni = (universe >> 8) & 0xff;\n        std::uint8_t lUni = universe & 0xff;\n\n        std::uint8_t hLen = (length >> 8) & 0xff;\n        std::uint8_t lLen = (length & 0xff);\n\n        std::uint8_t header[] = {65, 114, 116, 45, 78, 101, 116, 0, 0, 80, 0, 14, 0, 0, lUni, hUni, hLen, lLen};\n        std::uint8_t buffer[18 + 512];\n\n        for (int i = 0; i < 18 + 512; i++) {\n            if (i < 18) {\n                buffer[i] = header[i];\n                continue;\n            }\n\n            if (i - 18 < length) {\n                buffer[i] = data[i - 18];\n                continue;\n            }\n\n            buffer[i] = 0;\n        }\n\n        boost::system::error_code err;\n        socket.send_to(boost::asio::buffer(buffer), remote_endpoint, 0, err);\n        if (err)\n            CASPAR_THROW_EXCEPTION(io_error() << msg_info(err.message()));\n    }\n};\n\nstd::vector<fixture> get_fixtures_ptree(const boost::property_tree::wptree& ptree)\n{\n    std::vector<fixture> fixtures;\n\n    using boost::property_tree::wptree;\n\n    for (auto& xml_channel : ptree | witerate_children(L\"fixtures\") | welement_context_iteration) {\n        ptree_verify_element_name(xml_channel, L\"fixture\");\n\n        fixture f{};\n\n        int startAddress = xml_channel.second.get(L\"start-address\", 0);\n        if (startAddress < 1)\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Fixture start address must be specified\"));\n\n        f.startAddress = (unsigned short)startAddress - 1;\n\n        int fixtureCount = xml_channel.second.get(L\"fixture-count\", -1);\n        if (fixtureCount < 1)\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Fixture count must be specified\"));\n\n        f.fixtureCount = (unsigned short)fixtureCount;\n\n        std::wstring type = xml_channel.second.get(L\"type\", L\"\");\n        if (type.empty())\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Fixture type must be specified\"));\n\n        if (boost::iequals(type, L\"DIMMER\")) {\n            f.type = FixtureType::DIMMER;\n        } else if (boost::iequals(type, L\"RGB\")) {\n            f.type = FixtureType::RGB;\n        } else if (boost::iequals(type, L\"RGBW\")) {\n            f.type = FixtureType::RGBW;\n        } else {\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Unknown fixture type\"));\n        }\n\n        int fixtureChannels = xml_channel.second.get(L\"fixture-channels\", -1);\n        if (fixtureChannels < 0)\n            fixtureChannels = f.type;\n        if (fixtureChannels < f.type)\n            CASPAR_THROW_EXCEPTION(\n                user_error() << msg_info(\n                    L\"Fixture channel count must be at least enough channels for current color mode\"));\n\n        f.fixtureChannels = (unsigned short)fixtureChannels;\n\n        box b{};\n\n        auto x = xml_channel.second.get(L\"x\", 0.0f);\n        auto y = xml_channel.second.get(L\"y\", 0.0f);\n\n        b.x = x;\n        b.y = y;\n\n        auto width  = xml_channel.second.get(L\"width\", 0.0f);\n        auto height = xml_channel.second.get(L\"height\", 0.0f);\n\n        b.width  = width;\n        b.height = height;\n\n        auto rotation = xml_channel.second.get(L\"rotation\", 0.0f);\n\n        b.rotation   = rotation;\n        f.fixtureBox = b;\n\n        fixtures.push_back(f);\n    }\n\n    return fixtures;\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info)\n{\n    configuration config;\n\n    if (channel_info.depth != common::bit_depth::bit8)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Artnet consumer only supports 8-bit color depth.\"));\n\n    config.universe    = ptree.get(L\"universe\", config.universe);\n    config.host        = ptree.get(L\"host\", config.host);\n    config.port        = ptree.get(L\"port\", config.port);\n    config.refreshRate = ptree.get(L\"refresh-rate\", config.refreshRate);\n\n    if (config.refreshRate < 1)\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Refresh rate must be at least 1\"));\n\n    config.fixtures = get_fixtures_ptree(ptree);\n\n    return spl::make_shared<artnet_consumer>(config);\n}\n}} // namespace caspar::artnet\n"
  },
  {
    "path": "src/modules/artnet/consumer/artnet_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Eliyah Sundström eliyah@sundstroem.com\n */\n\n#pragma once\n\n#include \"../util/fixture_calculation.h\"\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/consumer/frame_consumer.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace artnet {\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info);\n}} // namespace caspar::artnet\n"
  },
  {
    "path": "src/modules/artnet/util/fixture_calculation.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Eliyah Sundström eliyah@sundstroem.com\n */\n\n#include \"fixture_calculation.h\"\n\n#define M_PI 3.14159265358979323846 /* pi */\n\nnamespace caspar { namespace artnet {\n\nrect compute_rect(box fixtureBox, int index, int count)\n{\n    // Calculates the corners of a rectangle that is part of a fixture\n    // The count represents how many fixtures exist in the box and the index which one to calculate\n\n    auto f_count = (float)count;\n    auto f_index = (float)index;\n\n    float x = fixtureBox.x;\n    float y = fixtureBox.y;\n\n    float width  = fixtureBox.width;\n    float height = fixtureBox.height;\n\n    float  rotation = fixtureBox.rotation;\n    double angle    = M_PI * rotation / 180.0f;\n\n    double sin_ = sin(angle);\n    double cos_ = cos(angle);\n\n    // Half width and height of the rectangle for this fixture\n    float hx = width / (2 * f_count);\n    float hy = height / 2.0f;\n\n    // Offset distance from the center of the box to the center of the fixture\n    float od = (2 * f_index - f_count + 1) * hx;\n\n    // Center of the fixture\n    double ox = x + od * cos_;\n    double oy = y + od * sin_;\n\n    // Calculate the corners of the rectangle, by offsetting the center with the half width and height\n    // in the direction of the corners and the box's rotation\n\n    point p1{\n        static_cast<float>(ox + -hx * cos_ + -hy * -sin_),\n        static_cast<float>(oy + -hx * sin_ + -hy * cos_),\n    };\n\n    point p2{\n        static_cast<float>(ox + hx * cos_ + -hy * -sin_),\n        static_cast<float>(oy + hx * sin_ + -hy * cos_),\n    };\n\n    point p3{\n        static_cast<float>(ox + hx * cos_ + hy * -sin_),\n        static_cast<float>(oy + hx * sin_ + hy * cos_),\n    };\n\n    point p4{\n        static_cast<float>(ox + -hx * cos_ + hy * -sin_),\n        static_cast<float>(oy + -hx * sin_ + hy * cos_),\n    };\n\n    rect rectangle{p1, p2, p3, p4};\n\n    return rectangle;\n}\n\ncolor average_color(const core::const_frame& frame, rect& rectangle)\n{\n    int width  = (int)frame.width();\n    int height = (int)frame.height();\n\n    float x_values[] = {rectangle.p1.x, rectangle.p2.x, rectangle.p3.x, rectangle.p4.x};\n    float y_values[] = {rectangle.p1.y, rectangle.p2.y, rectangle.p3.y, rectangle.p4.y};\n\n    // Sort the points by y value, then by x value if y is equal\n    for (int i = 0; i < 3; i++) {\n        for (int j = 3; j > i; j--) {\n            if (y_values[j] > y_values[j - 1])\n                continue;\n            if (y_values[j] < y_values[j - 1]) {\n                float x = x_values[j];\n                float y = y_values[j];\n\n                x_values[j] = x_values[j - 1];\n                y_values[j] = y_values[j - 1];\n\n                x_values[j - 1] = x;\n                y_values[j - 1] = y;\n\n                continue;\n            }\n\n            if (x_values[j] < x_values[j - 1]) {\n                float x = x_values[j];\n\n                x_values[j]     = x_values[j - 1];\n                x_values[j - 1] = x;\n            }\n        }\n    }\n\n    // Below is a rasterization algorithm that goes through the pixels in rectangle\n    // and calculates the average color\n\n    // Which lines to use for the rasterization\n    // in the format [a, b, c, d] => a -> b, c -> d\n    // the numbers are indices into the x_values, y_values arrays\n    const int indices[3][4] = {\n        {0, 1, 0, 2}, // Line 1, Line 2\n        {0, 2, 1, 3}, // Line 2, Line 3\n        {1, 3, 2, 3}, // Line 3, Line 4\n    };\n\n    // The y values of the top and bottom of the rectangle, clamped to the image size\n    int y_min = std::max(0, std::min(height - 1, (int)y_values[0]));\n    int y_max = std::max(0, std::min(height - 1, (int)y_values[3]));\n\n    const array<const std::uint8_t>& values    = frame.image_data(0);\n    const std::uint8_t*              value_ptr = values.data();\n\n    // Total color values, as well as the number of pixels in the rectangle\n    // used to calculate the average without loss of precision\n    unsigned long long tr = 0;\n    unsigned long long tg = 0;\n    unsigned long long tb = 0;\n\n    unsigned long long count = 0;\n\n    // Go through the vertical lines of the rectangle, and then through the pixels in the line\n    // that are inside the rectangle\n    for (int y = y_min; y <= y_max; y++) {\n        // Determine which lines to use for the rasterization, if one line has passed we should use the next one\n        int index = 0;\n        if (y >= (int)y_values[1])\n            index = 1;\n        if (y >= (int)y_values[2])\n            index = 2;\n\n        // The x and y values of the first line\n        float ax1 = x_values[indices[index][0]];\n        float ay1 = y_values[indices[index][0]];\n\n        float bx1 = x_values[indices[index][1]];\n        float by1 = y_values[indices[index][1]];\n\n        // The x and y values of the second line\n        float ax2 = x_values[indices[index][2]];\n        float ay2 = y_values[indices[index][2]];\n\n        float bx2 = x_values[indices[index][3]];\n        float by2 = y_values[indices[index][3]];\n\n        int x1 = 0;\n        int x2 = width - 1;\n\n        // If the lines are horizontal, we can skip the calculations\n        // This only happens if the box is oriented in 90 degree increments\n        if (by2 != ay2) {\n            // The slopes of the lines\n            float d1 = (bx1 - ax1) / (by1 - ay1);\n            float d2 = (bx2 - ax2) / (by2 - ay2);\n\n            // The x values of the lines at the current y value\n            auto x1_ = (int)(ax1 + ((float)y - ay1) * d1);\n            auto x2_ = (int)(ax2 + ((float)y - ay2) * d2);\n\n            // The clamped x values\n            x1 = std::max(0, std::min(width - 1, x1_));\n            x2 = std::max(0, std::min(width - 1, x2_));\n        }\n\n        // The left and right x values\n        int min_x = std::min(x1, x2);\n        int max_x = std::max(x1, x2);\n\n        // Go through the pixels in the line\n        for (int x = min_x; x <= max_x; x++) {\n            int                 pos      = y * width + x;\n            const std::uint8_t* base_ptr = value_ptr + pos * 4;\n\n            float a = (float)base_ptr[3] / 255.0f;\n\n            float r = (float)base_ptr[2] * a;\n            float g = (float)base_ptr[1] * a;\n            float b = (float)base_ptr[0] * a;\n\n            tr += (unsigned long long)(r);\n            tg += (unsigned long long)(g);\n            tb += (unsigned long long)(b);\n\n            count++;\n        }\n    }\n\n    color c{(std::uint8_t)(tr / count), (std::uint8_t)(tg / count), (std::uint8_t)(tb / count)};\n\n    return c;\n}\n\n}} // namespace caspar::artnet"
  },
  {
    "path": "src/modules/artnet/util/fixture_calculation.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Eliyah Sundström eliyah@sundstroem.com\n */\n\n#pragma once\n\n#include <core/frame/frame.h>\n\n#include <cmath>\n#include <utility>\n\nnamespace caspar { namespace artnet {\n\nenum FixtureType\n{\n    DIMMER = 1,\n    RGB    = 3,\n    RGBW   = 4,\n};\n\nstruct point\n{\n    float x;\n    float y;\n};\n\nstruct rect\n{\n    point p1;\n    point p2;\n    point p3;\n    point p4;\n};\n\nstruct computed_fixture\n{\n    FixtureType    type;\n    unsigned short address;\n\n    rect rectangle;\n};\n\nstruct color\n{\n    std::uint8_t r;\n    std::uint8_t g;\n    std::uint8_t b;\n};\n\nstruct box\n{\n    float x;\n    float y;\n\n    float width;\n    float height;\n\n    float rotation; // degrees\n};\n\nstruct fixture\n{\n    FixtureType    type;\n    unsigned short startAddress;    // DMX address of the first channel in the fixture\n    unsigned short fixtureCount;    // number of fixtures in the chain, dividing along the width\n    unsigned short fixtureChannels; // number of channels per fixture\n\n    box fixtureBox;\n};\n\nrect  compute_rect(box fixtureBox, int index, int count);\ncolor average_color(const core::const_frame& frame, rect& rectangle);\n\n}} // namespace caspar::artnet"
  },
  {
    "path": "src/modules/bluefish/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (bluefish)\n\nset(SOURCES\n\t\tconsumer/bluefish_consumer.cpp\n\t\tconsumer/bluefish_consumer.h\n        producer/bluefish_producer.cpp\n\t\tproducer/bluefish_producer.h\n\t\tutil/blue_velvet.cpp\n\t\tutil/blue_velvet.h\n\t\tutil/memory.h\n\t\tbluefish.cpp\n\t\tbluefish.h\n\t\tStdAfx.h\n)\n\ncasparcg_add_module_project(bluefish\n    SOURCES ${SOURCES}\n\tINIT_FUNCTION \"bluefish::init\"\n)\ntarget_include_directories(bluefish PRIVATE\n    ..\n    ${FFMPEG_INCLUDE_PATH}\n    )\ntarget_precompile_headers(bluefish PRIVATE \"StdAfx.h\")\n\nset_target_properties(bluefish PROPERTIES FOLDER modules)\nsource_group(sources ./*)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources\\\\util util/*)\nsource_group(sources\\\\interop interop/*)\n\ntarget_link_libraries(bluefish PRIVATE ffmpeg)\n"
  },
  {
    "path": "src/modules/bluefish/StdAfx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#if defined _DEBUG && defined _MSC_VER\n#include <crtdbg.h>\n#endif\n\n#define NOMINMAX\n\n#include <Windows.h>\n\n#include <algorithm>\n#include <array>\n#include <deque>\n#include <functional>\n#include <math.h>\n#include <memory>\n#include <queue>\n#include <string>\n#include <vector>\n\n#include <common/memory.h>\n#include <common/utf.h>\n// #include <common/executor.h\" // Can't include this due to MSVC lambda bug\n\n#include <common/except.h>\n#include <common/log.h>\n\n#include <assert.h>\n#include <boost/property_tree/ptree.hpp>\n"
  },
  {
    "path": "src/modules/bluefish/bluefish.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n *         James Wise,  james.wise@bluefish444.com\n */\n\n#include \"StdAfx.h\"\n\n#include \"bluefish.h\"\n\n#include \"consumer/bluefish_consumer.h\"\n#include \"producer/bluefish_producer.h\"\n\n#include \"util/blue_velvet.h\"\n\n#include <common/utf.h>\n\n#include <core/consumer/frame_consumer.h>\n\nnamespace caspar { namespace bluefish {\n\nstd::wstring version()\n{\n    try {\n        bvc_wrapper blue;\n        return u16(blue.get_version());\n    } catch (...) {\n        return L\"Not found\";\n    }\n}\n\nstd::vector<std::wstring> device_list()\n{\n    std::vector<std::wstring> devices;\n\n    try {\n        bvc_wrapper blue;\n        int         numCards = 0;\n        blue.enumerate(&numCards);\n\n        for (int n = 1; n < numCards + 1; n++) {\n            blue.attach(n);\n            devices.push_back(std::wstring(get_card_desc(blue, n)) + L\" [\" + std::to_wstring(n) + L\"] \" +\n                              get_sdi_inputs(blue) + L\"i\" + get_sdi_outputs(blue) + L\"o\");\n            blue.detach();\n        }\n    } catch (...) {\n    }\n\n    return devices;\n}\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    try {\n        bvc_wrapper blue;\n        int         num_cards = 0;\n        blue.enumerate(&num_cards);\n    } catch (...) {\n    }\n\n    dependencies.consumer_registry->register_consumer_factory(L\"Bluefish Consumer\", create_consumer);\n    dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"bluefish\", create_preconfigured_consumer);\n    dependencies.producer_registry->register_producer_factory(L\"Bluefish Producer\", create_producer);\n}\n\n}} // namespace caspar::bluefish\n"
  },
  {
    "path": "src/modules/bluefish/bluefish.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace bluefish {\n\nstd::wstring get_version();\nvoid         init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::bluefish\n"
  },
  {
    "path": "src/modules/bluefish/consumer/bluefish_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n *         James Wise, james.wise@bluefish444.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"../util/blue_velvet.h\"\n#include \"../util/memory.h\"\n\n#include <core/consumer/channel_info.h>\n#include <core/consumer/frame_consumer.h>\n#include <core/frame/frame.h>\n\n#include <common/diagnostics/graph.h>\n#include <common/executor.h>\n#include <common/param.h>\n#include <common/timer.h>\n\n#include <boost/property_tree/ptree.hpp>\n#include <boost/range/algorithm.hpp>\n\n#include <atomic>\n#include <condition_variable>\n#include <future>\n#include <mutex>\n\nnamespace caspar { namespace bluefish {\n\n#define BLUEFISH_MAX_SOFTWARE_BUFFERS 4\n#define SIZE_TEMP_AUDIO_BUFFER                                                                                         \\\n    (2048 * 16) // max 2002 samples across 16 channels, use 2048 for safety cos sometimes caspar gives us too many...\n\nenum class hardware_downstream_keyer_mode\n{\n    disable  = 0,\n    external = 1,\n    internal = 2, // Bluefish dedicated HW keyer - only available on some models.\n};\n\nenum class hardware_downstream_keyer_audio_source\n{\n    SDIVideoInput      = 1,\n    VideoOutputChannel = 2\n};\n\nenum class bluefish_hardware_output_channel\n{\n    channel_1 = 1,\n    channel_2 = 2,\n    channel_3 = 3,\n    channel_4 = 4,\n    channel_5 = 5,\n    channel_6 = 6,\n    channel_7 = 7,\n    channel_8 = 8,\n};\n\nenum class uhd_output_option\n{\n    disable_BVC_MultiLink = 0,\n    auto_uhd              = 1,\n    force_2si             = 2,\n    force_square_division = 3,\n};\n\nstruct configuration\n{\n    unsigned int                           device_index         = 1;\n    bluefish_hardware_output_channel       device_stream        = bluefish_hardware_output_channel::channel_1;\n    bool                                   embedded_audio       = true;\n    hardware_downstream_keyer_mode         hardware_keyer_value = hardware_downstream_keyer_mode::disable;\n    hardware_downstream_keyer_audio_source keyer_audio_source =\n        hardware_downstream_keyer_audio_source::VideoOutputChannel;\n    unsigned int      watchdog_timeout = 2;\n    uhd_output_option uhd_mode         = uhd_output_option::disable_BVC_MultiLink;\n};\n\nbool get_videooutput_channel_routing_info_from_streamid(bluefish_hardware_output_channel streamid,\n                                                        EEpochRoutingElements&           channelSrcElement,\n                                                        EEpochRoutingElements&           sdioutputDstElement)\n{\n    switch (streamid) {\n        case bluefish_hardware_output_channel::channel_1:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH1;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_1;\n            break;\n        case bluefish_hardware_output_channel::channel_2:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH2;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_2;\n            break;\n        case bluefish_hardware_output_channel::channel_3:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH3;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_3;\n            break;\n        case bluefish_hardware_output_channel::channel_4:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH4;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_4;\n            break;\n        case bluefish_hardware_output_channel::channel_5:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH5;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_5;\n            break;\n        case bluefish_hardware_output_channel::channel_6:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH6;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_6;\n            break;\n        case bluefish_hardware_output_channel::channel_7:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH7;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_7;\n            break;\n        case bluefish_hardware_output_channel::channel_8:\n            channelSrcElement   = EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH8;\n            sdioutputDstElement = EPOCH_DEST_SDI_OUTPUT_8;\n            break;\n\n        default:\n            return false;\n    }\n    return true;\n}\n\nEBlueVideoChannel get_bluesdk_videochannel_from_streamid(bluefish_hardware_output_channel streamid)\n{\n    /*This function would return the corresponding EBlueVideoChannel from the device output channel*/\n    switch (streamid) {\n        case bluefish_hardware_output_channel::channel_1:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_1;\n        case bluefish_hardware_output_channel::channel_2:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_2;\n        case bluefish_hardware_output_channel::channel_3:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_3;\n        case bluefish_hardware_output_channel::channel_4:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_4;\n        case bluefish_hardware_output_channel::channel_5:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_5;\n        case bluefish_hardware_output_channel::channel_6:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_6;\n        case bluefish_hardware_output_channel::channel_7:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_7;\n        case bluefish_hardware_output_channel::channel_8:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_8;\n        default:\n            return BLUE_VIDEO_OUTPUT_CHANNEL_1;\n    }\n}\n\nstruct bluefish_consumer\n{\n    const int           channel_index_;\n    const configuration config_;\n\n    spl::shared_ptr<bvc_wrapper> blue_         = create_blue(config_.device_index);\n    spl::shared_ptr<bvc_wrapper> watchdog_bvc_ = create_blue(config_.device_index);\n\n    std::mutex         exception_mutex_;\n    std::exception_ptr exception_;\n\n    std::wstring                  model_name_;\n    const core::video_format_desc format_desc_;\n\n    std::mutex              buffer_mutex_;\n    std::condition_variable buffer_cond_;\n\n    std::atomic<int64_t> scheduled_frames_completed_{0};\n\n    int               field_count_;\n    std::atomic<bool> abort_request_{false};\n\n    unsigned int mode_; // ie bf video mode / format\n    bool         interlaced_ = false;\n\n    std::array<blue_dma_buffer_ptr, BLUEFISH_MAX_SOFTWARE_BUFFERS> all_frames_;\n    tbb::concurrent_bounded_queue<blue_dma_buffer_ptr>             reserved_frames_;\n    tbb::concurrent_bounded_queue<blue_dma_buffer_ptr>             live_frames_;\n\n    std::atomic<int64_t> audio_frames_filled_{0};\n    blue_dma_buffer_ptr  last_field_buf_ = nullptr;\n\n    std::vector<uint32_t> tmp_audio_buf_;\n    unsigned int          tmp_audio_buf_contains_samples = 0;\n\n    std::shared_ptr<std::thread> dma_present_thread_;\n    std::shared_ptr<std::thread> hardware_watchdog_thread_;\n    std::atomic<bool>            end_hardware_watchdog_thread_;\n    unsigned int                 interrupts_to_wait_ = config_.watchdog_timeout;\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n    caspar::timer                       tick_timer_;\n    caspar::timer                       sync_timer_;\n\n    bluefish_consumer(const bluefish_consumer&)            = delete;\n    bluefish_consumer& operator=(const bluefish_consumer&) = delete;\n\n    bluefish_consumer(const configuration& config, const core::video_format_desc& format_desc, int channel_index)\n        : channel_index_(channel_index)\n        , config_(config)\n        , format_desc_(format_desc)\n    {\n        // OK this is the Guts of it, lets see what we can do to get a compile working, and then some actual\n        // functionality eh?\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"flushed-frame\", diagnostics::color(0.4f, 0.3f, 0.8f));\n        graph_->set_color(\"buffered-audio\", diagnostics::color(0.9f, 0.9f, 0.5f));\n        graph_->set_color(\"buffered-video\", diagnostics::color(0.2f, 0.9f, 0.9f));\n\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        reserved_frames_.set_capacity(BLUEFISH_MAX_SOFTWARE_BUFFERS);\n        live_frames_.set_capacity(BLUEFISH_MAX_SOFTWARE_BUFFERS);\n\n        // get BF video mode\n        mode_ = get_bluefish_video_format(format_desc_.format);\n        if (mode_ == VID_FMT_EXT_1080I_5000 || mode_ == VID_FMT_EXT_1080I_5994 || mode_ == VID_FMT_EXT_1080I_6000 ||\n            mode_ == VID_FMT_EXT_PAL || mode_ == VID_FMT_EXT_NTSC) {\n            interlaced_ = true;\n        }\n\n        // Specify the video channel\n        setup_hardware_output_channel(); // ie stream id\n\n        model_name_ = get_card_desc(*blue_.get(), (int)config_.device_index);\n\n        // disable the video output while we do all the config.\n        disable_video_output();\n\n        // check if we need to set Multilink, and configure if required\n        setup_multlink();\n\n        // Setting output Video mode\n        if (blue_->set_card_property32(VIDEO_MODE_EXT_OUTPUT, mode_))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to set videomode.\"));\n\n        // Select Update Mode for output\n        if (blue_->set_card_property32(VIDEO_UPDATE_TYPE, UPD_FMT_FRAME))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to set update type.\"));\n\n        setup_hardware_output_channel_routing();\n\n        // Select output memory format\n        if (blue_->set_card_property32(VIDEO_MEMORY_FORMAT, MEM_FMT_ARGB_PC))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to set memory format.\"));\n\n        // Select image orientation\n        if (blue_->set_card_property32(VIDEO_IMAGE_ORIENTATION, ImageOrientation_Normal))\n            CASPAR_LOG(warning) << print() << L\" Failed to set image orientation to normal.\";\n\n        // Select data range\n        if (blue_->set_card_property32(VIDEO_RGB_DATA_RANGE, CGR_RANGE))\n            CASPAR_LOG(warning) << print() << L\" Failed to set RGB data range to CGR.\";\n\n        // configure audio\n        if (!config_.embedded_audio ||\n            (config_.hardware_keyer_value == hardware_downstream_keyer_mode::internal &&\n             config.keyer_audio_source == hardware_downstream_keyer_audio_source::SDIVideoInput)) {\n            if (blue_->set_card_property32(EMBEDEDDED_AUDIO_OUTPUT, 0))\n                CASPAR_LOG(warning) << TEXT(\"BLUECARD ERROR: Failed to disable embedded audio.\");\n            CASPAR_LOG(info) << print() << TEXT(\" Disabled embedded-audio.\");\n        } else {\n            ULONG audio_value = blue_emb_audio_enable | blue_emb_audio_group1_enable;\n            if (format_desc_.audio_channels > 4)\n                audio_value |= blue_emb_audio_group2_enable;\n\n            if (format_desc_.audio_channels > 8)\n                audio_value |= blue_emb_audio_group3_enable;\n\n            if (format_desc_.audio_channels > 12)\n                audio_value |= blue_emb_audio_group4_enable;\n\n            if (blue_->set_card_property32(EMBEDEDDED_AUDIO_OUTPUT, audio_value))\n                CASPAR_LOG(warning) << print() << TEXT(\" Failed to enable embedded audio.\");\n            CASPAR_LOG(info) << print() << TEXT(\" Enabled embedded-audio.\");\n        }\n\n        if (blue_->set_card_property32(VIDEO_OUTPUT_ENGINE, VIDEO_ENGINE_PLAYBACK))\n            CASPAR_LOG(warning) << print() << TEXT(\" Failed to set video engine.\");\n\n        if (is_epoch_card(*blue_) && is_epoch_neutron_1i2o_card(*blue_))\n            setup_hardware_downstream_keyer(config.hardware_keyer_value, config.keyer_audio_source);\n\n        // ok here we create a bunch of Bluefish buffers, that contain video and encoded hanc....\n        // this is the software Q. / software buffers\n        int n = 0;\n        boost::range::generate(\n            all_frames_, [&] { return std::make_shared<blue_dma_buffer>(static_cast<int>(format_desc_.size), n++); });\n\n        for (size_t i = 0; i < all_frames_.size(); i++)\n            reserved_frames_.push(all_frames_[i]);\n\n        tmp_audio_buf_.reserve(SIZE_TEMP_AUDIO_BUFFER);\n\n        // start the thread if required.\n        if (dma_present_thread_ == nullptr) {\n            dma_present_thread_ = std::make_shared<std::thread>([this] { dma_present_thread_actual(); });\n#if defined(_WIN32)\n            HANDLE handle = (HANDLE)dma_present_thread_->native_handle();\n            SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST);\n#endif\n        }\n\n        configure_watchdog();\n        enable_video_output();\n    }\n\n    ~bluefish_consumer()\n    {\n        try {\n            abort_request_ = true;\n            buffer_cond_.notify_all();\n\n            if (!end_hardware_watchdog_thread_)\n                disable_watchdog();\n\n            disable_video_output();\n            watchdog_bvc_->detach();\n            blue_->detach();\n\n            if (dma_present_thread_)\n                dma_present_thread_->join();\n\n            if (hardware_watchdog_thread_)\n                hardware_watchdog_thread_->join();\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n    }\n\n    void watchdog_thread_actual()\n    {\n        watchdog_bvc_->attach(config_.device_index);\n        EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream);\n        watchdog_bvc_->set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel);\n\n        unsigned long fc = 0;\n        unsigned int  blue_prop =\n            EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_keepalive, config_.watchdog_timeout);\n\n        while (!end_hardware_watchdog_thread_) {\n            watchdog_bvc_->wait_video_output_sync(UPD_FMT_FIELD, &fc);\n            watchdog_bvc_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop);\n        }\n\n        disable_watchdog();\n        watchdog_bvc_->detach();\n    }\n\n    void configure_watchdog()\n    {\n        // First test if we even want to enable the watchdog, only on Ch 1 and if user has not explicitly set count to\n        // 0, and only if card has at least 1  input sdi, else dont do anything\n        unsigned int val = 0;\n        blue_->get_card_property32(CARD_FEATURE_STREAM_INFO, &val);\n        unsigned int num_input_streams = CARD_FEATURE_GET_SDI_INPUT_STREAM_COUNT(val);\n        if ((interrupts_to_wait_ != 0u) && config_.device_stream == bluefish_hardware_output_channel::channel_1 &&\n            (num_input_streams != 0u)) {\n            // check if it is already running\n            unsigned int blue_prop =\n                EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_get_timer_activated_status, 0);\n            blue_->get_card_property32(EPOCH_APP_WATCHDOG_TIMER, &blue_prop);\n            if (EPOCH_WATCHDOG_TIMER_GET_VALUE_MACRO(blue_prop)) {\n                // watchdog timer is running already, switch it off.\n                blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_start_stop, (unsigned int)0);\n                blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop);\n            }\n\n            // Setting up the watchdog properties\n            unsigned int watchdog_timer_gpo_port = 1; // GPO port to use: 0 = none, 1 = port A, 2 = port B\n            blue_prop =\n                EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_enable_gpo_on_active, watchdog_timer_gpo_port);\n            blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop);\n\n            if (interrupts_to_wait_ == 1) // using too low a value can cause instability on the watchdog so always make\n                                          // sure we use a value of 2 or more...\n                interrupts_to_wait_++;\n\n            blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_start_stop, interrupts_to_wait_);\n            blue_->set_card_property32(EPOCH_APP_WATCHDOG_TIMER, blue_prop);\n\n            // start the thread if required.\n            if (hardware_watchdog_thread_ == nullptr) {\n                end_hardware_watchdog_thread_ = false;\n                hardware_watchdog_thread_     = std::make_shared<std::thread>([this] { watchdog_thread_actual(); });\n            }\n        }\n    }\n\n    void disable_watchdog()\n    {\n        end_hardware_watchdog_thread_ = true;\n        unsigned int stop_value       = 0;\n        unsigned int blue_prop = EPOCH_WATCHDOG_TIMER_SET_MACRO(enum_blue_app_watchdog_timer_start_stop, stop_value);\n        watchdog_bvc_->get_card_property32(EPOCH_APP_WATCHDOG_TIMER, &blue_prop);\n    }\n\n    void setup_hardware_output_channel()\n    {\n        // This function would be used to setup the logic video channel in the bluefish hardware\n        EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream);\n        if (is_epoch_card(*blue_) || is_kronos_card(*blue_)) {\n            if (out_vid_channel != BLUE_VIDEOCHANNEL_INVALID) {\n                if (blue_->set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel))\n                    CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\" Failed to set video stream.\"));\n\n                blue_->video_playback_stop(0, 0);\n            }\n        }\n    }\n\n    void setup_multlink()\n    {\n        // We only want to enable multi-link in specific scenarios, so lets check all those conditions first\n        EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream);\n        if (is_kronos_card(*blue_) &&\n            (out_vid_channel == BLUE_VIDEO_OUTPUT_CHANNEL_1 || out_vid_channel == BLUE_VIDEO_OUTPUT_CHANNEL_5) &&\n            (config_.uhd_mode != uhd_output_option::disable_BVC_MultiLink) && (format_desc_.width > 2048)) {\n            unsigned int val = mode_;\n            blue_->set_multilink(config_.device_index, out_vid_channel);\n\n            // Now lest test to see if our MultiLink enable instance can support the video Mode in Q.\n            blue_->get_card_property32(IS_VIDEO_MODE_EXT_SUPPORTED_OUTPUT, &val);\n            if (val)\n                return;\n            else {\n                blue_->set_multilink(0, -1);\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\" Failed to set video stream.\"));\n            }\n        }\n    }\n\n    void setup_hardware_output_channel_routing()\n    {\n        // This function would be used to setup the dual link and any other routing that would be required .\n        if (is_epoch_card(*blue_) || is_kronos_card(*blue_)) {\n            EBlueVideoChannel blue_video_output_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream);\n            EEpochRoutingElements src_element           = (EEpochRoutingElements)0;\n            EEpochRoutingElements dst_element           = (EEpochRoutingElements)0;\n            get_videooutput_channel_routing_info_from_streamid(config_.device_stream, src_element, dst_element);\n            bool duallink_4224_enabled = false;\n\n            if ((config_.device_stream == bluefish_hardware_output_channel::channel_1 ||\n                 config_.device_stream == bluefish_hardware_output_channel::channel_3) &&\n                    config_.hardware_keyer_value == hardware_downstream_keyer_mode::external ||\n                config_.hardware_keyer_value == hardware_downstream_keyer_mode::internal) {\n                duallink_4224_enabled = true;\n            }\n\n            // Enable/Disable dual link output\n            if (blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT, duallink_4224_enabled))\n                CASPAR_THROW_EXCEPTION(caspar_exception()\n                                       << msg_info(print() + L\" Failed to enable/disable dual link.\"));\n\n            if (!duallink_4224_enabled) {\n                if (blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE,\n                                               Signal_FormatType_Independent_422))\n                    CASPAR_THROW_EXCEPTION(caspar_exception()\n                                           << msg_info(print() + L\" Failed to set dual link format type to 4:2:2.\"));\n\n                //   ULONG routingValue = EPOCH_SET_ROUTING(src_element, dst_element, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                //    if (blue_->set_card_property32(MR2_ROUTING, routingValue))\n                //        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\" Failed to MR 2 routing.\"));\n\n                // If single link 422, but on second channel AND on Neutron we need to set Genlock to Aux.\n                if (is_epoch_neutron_1i2o_card(*blue_)) {\n                    if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_B) {\n                        ULONG genlock_source = BlueGenlockAux;\n                        if (blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genlock_source))\n                            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                                   << msg_info(\"Failed to set GenLock to Aux Input.\"));\n                    }\n                }\n                if (is_epoch_neutron_3o_card(*blue_)) {\n                    if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_C) {\n                        ULONG genlock_source = BlueGenlockAux;\n                        if (blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genlock_source))\n                            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                                   << msg_info(\"Failed to set GenLock to Aux Input.\"));\n                    } else if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_B) {\n                        ULONG routing_value = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB,\n                                                                EPOCH_DEST_SDI_OUTPUT_B,\n                                                                BLUE_CONNECTOR_PROP_DUALLINK_LINK_1);\n                        if (blue_->set_card_property32(MR2_ROUTING, routing_value))\n                            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to MR 2 routing.\"));\n                    }\n                }\n            } else // dual Link IS enabled, ie. 4224 Fill and Key\n            {\n                if (blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE, Signal_FormatType_4224))\n                    CASPAR_THROW_EXCEPTION(caspar_exception()\n                                           << msg_info(print() + L\" Failed to set dual link format type to 4:2:2:4.\"));\n\n                if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_1) {\n                    ULONG routing_value = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA,\n                                                            EPOCH_DEST_SDI_OUTPUT_A,\n                                                            BLUE_CONNECTOR_PROP_DUALLINK_LINK_1);\n                    if (blue_->set_card_property32(MR2_ROUTING, routing_value))\n                        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to MR 2 routing.\"));\n\n                    routing_value = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA,\n                                                      EPOCH_DEST_SDI_OUTPUT_B,\n                                                      BLUE_CONNECTOR_PROP_DUALLINK_LINK_2);\n                    if (blue_->set_card_property32(MR2_ROUTING, routing_value))\n                        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to MR 2 routing.\"));\n\n                    if (is_epoch_neutron_1i2o_card(*blue_)) // Neutron cards require setting the Genlock connector to\n                                                            // Aux to enable them to do Dual-Link\n                    {\n                        ULONG genLockSource = BlueGenlockAux;\n                        if (blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource))\n                            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                                   << msg_info(\"Failed to set GenLock to Aux Input.\"));\n                    } else if (is_epoch_neutron_3o_card(*blue_)) {\n                        if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_C) {\n                            ULONG genLockSource = BlueGenlockAux;\n                            if (blue_->set_card_property32(VIDEO_GENLOCK_SIGNAL, genLockSource))\n                                CASPAR_THROW_EXCEPTION(caspar_exception()\n                                                       << msg_info(\"Failed to set GenLock to Aux Input.\"));\n                        }\n                    }\n                } else {\n                    // using channel C for 4224 on other configurations requires explicit routing\n                    if (blue_video_output_channel == BLUE_VIDEO_OUTPUT_CHANNEL_C) {\n                        ULONG routingValue = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC,\n                                                               EPOCH_DEST_SDI_OUTPUT_C,\n                                                               BLUE_CONNECTOR_PROP_DUALLINK_LINK_1);\n                        if (blue_->set_card_property32(MR2_ROUTING, routingValue))\n                            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to MR 2 routing.\"));\n                        routingValue = EPOCH_SET_ROUTING(EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC,\n                                                         EPOCH_DEST_SDI_OUTPUT_D,\n                                                         BLUE_CONNECTOR_PROP_DUALLINK_LINK_2);\n                        if (blue_->set_card_property32(MR2_ROUTING, routingValue))\n                            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to MR 2 routing.\"));\n                    }\n                }\n            }\n        }\n    }\n\n    void setup_hardware_downstream_keyer(hardware_downstream_keyer_mode         keyer,\n                                         hardware_downstream_keyer_audio_source audio_source)\n    {\n        unsigned int keyer_control_value = 0;\n        if (keyer == hardware_downstream_keyer_mode::disable || keyer == hardware_downstream_keyer_mode::external) {\n            keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLED(keyer_control_value);\n            keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(keyer_control_value);\n        } else if (keyer == hardware_downstream_keyer_mode::internal) {\n            unsigned int input_video_mode = 0;\n            if (blue_->get_card_property32(VIDEO_MODE_EXT_INPUT, &input_video_mode))\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\" Failed to get invalid video mode flag\"));\n\n            // The bluefish HW keyer is NOT going to pre-multiply the RGB with the A.\n            keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_PREMULTIPLIED(keyer_control_value);\n\n            keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLED(keyer_control_value);\n            if (blue_->get_card_property32(VIDEO_INPUT_SIGNAL_VIDEO_MODE, &input_video_mode))\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\" Failed to get video input signal mode\"));\n\n            if (input_video_mode == VID_FMT_EXT_INVALID)\n                keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLE_OVER_BLACK(keyer_control_value);\n            else\n                keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(keyer_control_value);\n\n            // lock to input\n            if (blue_->set_card_property32(\n                    VIDEO_GENLOCK_SIGNAL,\n                    BlueSDI_A_BNC)) // todo: will need to adjust when we support keyer on all channels...\n                CASPAR_THROW_EXCEPTION(caspar_exception()\n                                       << msg_info(\" Failed to set the genlock to the input for the HW keyer\"));\n        }\n\n        if (audio_source == hardware_downstream_keyer_audio_source::SDIVideoInput &&\n            keyer == hardware_downstream_keyer_mode::internal)\n            keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_USE_INPUT_ANCILLARY(keyer_control_value);\n        else if (audio_source == hardware_downstream_keyer_audio_source::VideoOutputChannel)\n            keyer_control_value = VIDEO_ONBOARD_KEYER_SET_STATUS_USE_OUTPUT_ANCILLARY(keyer_control_value);\n\n        if (blue_->set_card_property32(VIDEO_ONBOARD_KEYER, keyer_control_value))\n            CASPAR_LOG(error) << print() << TEXT(\" Failed to set keyer control.\");\n    }\n\n    void enable_video_output()\n    {\n        if (config_.device_stream == bluefish_hardware_output_channel::channel_1)\n            blue_->set_card_property32(BYPASS_RELAY_A_ENABLE, 0);\n        else if (config_.device_stream == bluefish_hardware_output_channel::channel_2)\n            blue_->set_card_property32(BYPASS_RELAY_B_ENABLE, 0);\n\n        if (blue_->set_card_property32(VIDEO_BLACKGENERATOR, 0))\n            CASPAR_LOG(error) << print() << TEXT(\" Failed to disable video output.\");\n    }\n\n    void disable_video_output()\n    {\n        blue_->video_playback_stop(0, 0);\n        blue_->set_card_property32(VIDEO_DUAL_LINK_OUTPUT, 0);\n\n        if (blue_->set_card_property32(VIDEO_BLACKGENERATOR, 1))\n            CASPAR_LOG(error) << print() << TEXT(\" Failed to disable video output.\");\n        if (blue_->set_card_property32(EMBEDEDDED_AUDIO_OUTPUT, 0))\n            CASPAR_LOG(error) << print() << TEXT(\" Failed to disable audio output.\");\n    }\n\n    bool send(core::video_field field, core::const_frame frame)\n    {\n        // TODO - field alignment\n        {\n            std::lock_guard<std::mutex> lock(exception_mutex_);\n            if (exception_ != nullptr) {\n                std::rethrow_exception(exception_);\n            }\n        }\n\n        if (!frame) {\n            return !abort_request_;\n        }\n\n        try {\n            std::unique_lock<std::mutex> lock(buffer_mutex_);\n            copy_frame(frame);\n            graph_->set_value(\"tick-time\", static_cast<float>(tick_timer_.elapsed() * format_desc_.fps * 0.5));\n            tick_timer_.restart();\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n\n        return !abort_request_;\n    }\n\n    void dma_present_thread_actual()\n    {\n        bvc_wrapper wait_b;\n        wait_b.attach(config_.device_index);\n        EBlueVideoChannel out_vid_channel = get_bluesdk_videochannel_from_streamid(config_.device_stream);\n        wait_b.set_card_property32(DEFAULT_VIDEO_OUTPUT_CHANNEL, out_vid_channel);\n        int           frames_to_buffer = 1;\n        unsigned long buffer_id        = 0;\n        unsigned long underrun         = 0;\n\n        while (!abort_request_) {\n            blue_dma_buffer_ptr buf = nullptr;\n            if (live_frames_.try_pop(buf) && (blue_->video_playback_allocate(&buffer_id, &underrun) == 0)) {\n                // Send and display\n                if (config_.embedded_audio) {\n                    // Do video first, then do hanc DMA...\n                    blue_->system_buffer_write(const_cast<uint8_t*>(buf->image_data()),\n                                               static_cast<unsigned long>(buf->image_size()),\n                                               BlueImage_HANC_DMABuffer(buffer_id, BLUE_DATA_IMAGE),\n                                               0);\n\n                    blue_->system_buffer_write(buf->hanc_data(),\n                                               static_cast<unsigned long>(buf->hanc_size()),\n                                               BlueImage_HANC_DMABuffer(buffer_id, BLUE_DATA_HANC),\n                                               0);\n\n                    if (blue_->video_playback_present(BlueBuffer_Image_HANC(buffer_id), 1, 0, 0))\n                        CASPAR_LOG(warning) << print() << TEXT(\" video_playback_present failed.\");\n                } else {\n                    blue_->system_buffer_write(const_cast<uint8_t*>(buf->image_data()),\n                                               static_cast<unsigned long>(buf->image_size()),\n                                               BlueImage_DMABuffer(buffer_id, BLUE_DATA_IMAGE),\n                                               0);\n\n                    if (blue_->video_playback_present(BlueBuffer_Image(buffer_id), 1, 0, 0))\n                        CASPAR_LOG(warning) << print() << TEXT(\" video_playback_present failed.\");\n                }\n\n                ++scheduled_frames_completed_;\n                reserved_frames_.push(buf);\n            }\n\n            {\n                // Sync and Update timer\n                unsigned long n_field = 0;\n                wait_b.wait_video_output_sync(UPD_FMT_FRAME, &n_field);\n                graph_->set_value(\"sync-time\", sync_timer_.elapsed() * format_desc_.fps * 0.5);\n                sync_timer_.restart();\n            }\n\n            if (frames_to_buffer > 0) {\n                frames_to_buffer--;\n                if (frames_to_buffer == 0) {\n                    if (blue_->video_playback_start(0, 0))\n                        CASPAR_LOG(warning) << print() << TEXT(\"Error video playback start failed\");\n                }\n            }\n        }\n        wait_b.detach();\n        blue_->video_playback_stop(0, 0);\n    }\n\n    void copy_frame(core::const_frame frame)\n    {\n        int audio_samples_for_next_frame =\n            blue_->get_num_audio_samples_for_frame(mode_, static_cast<unsigned int>(audio_frames_filled_));\n\n        if (interlaced_) {\n            if (!last_field_buf_) // field 1\n            {\n                if (reserved_frames_.try_pop(last_field_buf_)) {\n                    // copy video data into holding buf\n                    void* dest = last_field_buf_->image_data();\n                    if (frame.image_data(0).size()) {\n                        std::memcpy(dest, frame.image_data(0).begin(), frame.image_data(0).size());\n                    } else\n                        std::memset(dest, 0, last_field_buf_->image_size());\n\n                    // now copy Some of the Audio bytes that we need\n                    if (config_.embedded_audio) {\n                        auto audio_size = frame.audio_data().size() * 4;\n                        if (audio_size) {\n                            tmp_audio_buf_.insert(\n                                tmp_audio_buf_.end(), frame.audio_data().begin(), frame.audio_data().end());\n                        }\n                    }\n                }\n            } else // field 2\n            {\n                // we have already done the video... just grab the last bit of audio, encode and push to Q.\n                if (config_.embedded_audio) {\n                    auto audio_size = frame.audio_data().size() * 4;\n                    if (audio_size) {\n                        tmp_audio_buf_.insert(\n                            tmp_audio_buf_.end(), frame.audio_data().begin(), frame.audio_data().end());\n\n                        encode_hanc(reinterpret_cast<BLUE_U32*>(last_field_buf_->hanc_data()),\n                                    reinterpret_cast<void*>(tmp_audio_buf_.data()),\n                                    audio_samples_for_next_frame,\n                                    static_cast<int>(format_desc_.audio_channels));\n                        ++audio_frames_filled_;\n                    }\n                }\n                // push to in use Q.\n                live_frames_.push(last_field_buf_);\n                last_field_buf_ = nullptr;\n                tmp_audio_buf_.clear();\n            }\n        } else {\n            blue_dma_buffer_ptr buf = nullptr;\n            // Copy to local buffers\n            if (reserved_frames_.try_pop(buf)) {\n                void* dest = buf->image_data();\n                if (frame.image_data(0).size()) {\n                    if (config_.uhd_mode == uhd_output_option::force_2si) {\n                        // Do the Square Division top 2si conversion here.\n                        blue_->convert_sq_to_2si(\n                            (int)frame.width(), (int)frame.height(), (void*)frame.image_data(0).begin(), dest);\n                    } else\n                        std::memcpy(dest, frame.image_data(0).begin(), frame.image_data(0).size());\n                } else\n                    std::memset(dest, 0, buf->image_size());\n\n                // encode and copy hanc data\n                if (config_.embedded_audio) {\n                    if (frame.audio_data().size()) {\n                        encode_hanc(reinterpret_cast<BLUE_U32*>(buf->hanc_data()),\n                                    (void*)frame.audio_data().data(),\n                                    audio_samples_for_next_frame,\n                                    static_cast<int>(format_desc_.audio_channels));\n                        ++audio_frames_filled_;\n                    }\n                }\n                // push to in use Q.\n                live_frames_.push(buf);\n            }\n        }\n\n        // Sync\n        unsigned long n_field = 0;\n        if (interlaced_)\n            blue_->wait_video_output_sync(UPD_FMT_FIELD, &n_field);\n        else\n            blue_->wait_video_output_sync(UPD_FMT_FRAME, &n_field);\n        graph_->set_value(\"sync-time\", sync_timer_.elapsed() * format_desc_.fps * 0.5);\n        sync_timer_.restart();\n    }\n\n    void encode_hanc(BLUE_U32* hanc_data, void* audio_data, int audio_samples, int audio_nchannels)\n    {\n        const auto sample_type    = AUDIO_CHANNEL_LITTLEENDIAN;\n        auto       emb_audio_flag = blue_emb_audio_enable | blue_emb_audio_group1_enable;\n        if (audio_nchannels > 4)\n            emb_audio_flag |= blue_emb_audio_group2_enable;\n        if (audio_nchannels > 8)\n            emb_audio_flag |= blue_emb_audio_group3_enable;\n        if (audio_nchannels > 12)\n            emb_audio_flag |= blue_emb_audio_group4_enable;\n\n        hanc_stream_info_struct hanc_stream_info;\n        std::memset(&hanc_stream_info, 0, sizeof(hanc_stream_info));\n\n        hanc_stream_info.AudioDBNArray[0] = -1;\n        hanc_stream_info.AudioDBNArray[1] = -1;\n        hanc_stream_info.AudioDBNArray[2] = -1;\n        hanc_stream_info.AudioDBNArray[3] = -1;\n        hanc_stream_info.hanc_data_ptr    = hanc_data;\n        hanc_stream_info.video_mode       = get_bluefish_video_format(format_desc_.format);\n\n        int card_type = CRD_INVALID;\n        blue_->query_card_type(&card_type, config_.device_index);\n        blue_->encode_hanc_frame(\n            card_type, &hanc_stream_info, audio_data, audio_nchannels, audio_samples, sample_type, emb_audio_flag);\n    }\n\n    std::wstring print() const\n    {\n        return model_name_ + L\" [\" + std::to_wstring(channel_index_) + L\"-\" + std::to_wstring(config_.device_index) +\n               L\"Stream: \" + std::to_wstring(static_cast<unsigned int>(config_.device_stream)) + L\"|\" +\n               format_desc_.name + L\"]\";\n    }\n\n    int64_t presentation_delay_millis() const { return 0; }\n};\n\nstruct bluefish_consumer_proxy : public core::frame_consumer\n{\n    const configuration                config_;\n    std::unique_ptr<bluefish_consumer> consumer_;\n    core::video_format_desc            format_desc_;\n    executor                           executor_;\n\n  public:\n    explicit bluefish_consumer_proxy(const configuration& config)\n        : config_(config)\n        , executor_(L\"bluefish_consumer[\" + std::to_wstring(config.device_index) + L\"]\")\n    {\n    }\n\n    ~bluefish_consumer_proxy()\n    {\n        executor_.invoke([=, this] { consumer_.reset(); });\n    }\n\n    // frame_consumer\n    void initialize(const core::video_format_desc& format_desc,\n                    const core::channel_info&      channel_info,\n                    int                            port_index) override\n    {\n        format_desc_ = format_desc;\n        executor_.invoke([=, this] {\n            consumer_.reset();\n            consumer_.reset(new bluefish_consumer(config_, format_desc, channel_info.index));\n        });\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        return executor_.begin_invoke([=, this] { return consumer_->send(field, frame); });\n    }\n\n    std::wstring print() const override { return consumer_ ? consumer_->print() : L\"[bluefish_consumer]\"; }\n\n    std::wstring name() const override { return L\"bluefish\"; }\n\n    int index() const override { return 400 + config_.device_index; }\n\n    bool has_synchronization_clock() const override { return true; }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"bluefish/index\"]          = config_.device_index;\n        state[\"bluefish/stream\"]         = static_cast<unsigned int>(config_.device_stream);\n        state[\"bluefish/embedded_audio\"] = config_.embedded_audio;\n        return state;\n    }\n};\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info)\n{\n    if (params.size() < 1 || !boost::iequals(params.at(0), L\"BLUEFISH\")) {\n        return core::frame_consumer::empty();\n    }\n\n    if (channel_info.depth != common::bit_depth::bit8)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Bluefish consumer only supports 8-bit color depth.\"));\n\n    configuration config;\n\n    // const auto device_index       = params.size() > 1 ? std::stoi(params.at(1)) : 1;\n    // const auto device_stream      = contains_param(L\"SDI-STREAM\", params);\n    // const auto embedded_audio     = contains_param(L\"EMBEDDED_AUDIO\", params);\n    // const auto keyer_option       = contains_param(L\"KEYER\", params);\n    // const auto keyer_audio_option = contains_param(L\"INTERNAL-KEYER-AUDIO-SOURCE\", params);\n\n    config.device_stream = bluefish_hardware_output_channel::channel_1;\n    if (contains_param(L\"1\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_1;\n    else if (contains_param(L\"2\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_2;\n    else if (contains_param(L\"3\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_3;\n    else if (contains_param(L\"4\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_4;\n    else if (contains_param(L\"5\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_5;\n    else if (contains_param(L\"6\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_6;\n    else if (contains_param(L\"7\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_7;\n    else if (contains_param(L\"8\", params))\n        config.device_stream = bluefish_hardware_output_channel::channel_8;\n\n    config.hardware_keyer_value = hardware_downstream_keyer_mode::disable;\n    if (contains_param(L\"DISABLED\", params))\n        config.hardware_keyer_value = hardware_downstream_keyer_mode::disable;\n    else if (contains_param(L\"EXTERNAL\", params))\n        config.hardware_keyer_value = hardware_downstream_keyer_mode::external;\n    else if (contains_param(L\"INTERNAL\", params))\n        config.hardware_keyer_value = hardware_downstream_keyer_mode::internal;\n\n    config.keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput;\n    if (contains_param(L\"SDIVIDEOINPUT\", params))\n        config.keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput;\n    else if (contains_param(L\"VIDEOOUTPUTCHANNEL\", params))\n        config.keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel;\n\n    config.embedded_audio   = contains_param(L\"EMBEDDED_AUDIO\", params);\n    config.watchdog_timeout = 2;\n\n    return spl::make_shared<bluefish_consumer_proxy>(config);\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info)\n{\n    configuration config;\n    auto          device_index = ptree.get(L\"device\", 1);\n    config.device_index        = device_index;\n\n    if (channel_info.depth != common::bit_depth::bit8)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Bluefish consumer only supports 8-bit color depth.\"));\n\n    auto device_stream = ptree.get(L\"sdi-stream\", L\"1\");\n    if (device_stream == L\"1\")\n        config.device_stream = bluefish_hardware_output_channel::channel_1;\n    else if (device_stream == L\"2\")\n        config.device_stream = bluefish_hardware_output_channel::channel_2;\n    else if (device_stream == L\"3\")\n        config.device_stream = bluefish_hardware_output_channel::channel_3;\n    else if (device_stream == L\"4\")\n        config.device_stream = bluefish_hardware_output_channel::channel_4;\n    else if (device_stream == L\"5\")\n        config.device_stream = bluefish_hardware_output_channel::channel_5;\n    else if (device_stream == L\"6\")\n        config.device_stream = bluefish_hardware_output_channel::channel_6;\n    else if (device_stream == L\"7\")\n        config.device_stream = bluefish_hardware_output_channel::channel_7;\n    else if (device_stream == L\"8\")\n        config.device_stream = bluefish_hardware_output_channel::channel_8;\n\n    auto embedded_audio   = ptree.get(L\"embedded-audio\", false);\n    config.embedded_audio = embedded_audio;\n\n    auto hardware_keyer_value = ptree.get(L\"keyer\", L\"disabled\");\n    if (hardware_keyer_value == L\"disabled\")\n        config.hardware_keyer_value = hardware_downstream_keyer_mode::disable;\n    else if (hardware_keyer_value == L\"external\")\n        config.hardware_keyer_value = hardware_downstream_keyer_mode::external;\n    else if (hardware_keyer_value == L\"internal\")\n        config.hardware_keyer_value = hardware_downstream_keyer_mode::internal;\n\n    auto keyer_audio_source_value = ptree.get(L\"internal-keyer-audio-source\", L\"videooutputchannel\");\n    if (keyer_audio_source_value == L\"videooutputchannel\")\n        config.keyer_audio_source = hardware_downstream_keyer_audio_source::VideoOutputChannel;\n    else if (keyer_audio_source_value == L\"sdivideoinput\")\n        config.keyer_audio_source = hardware_downstream_keyer_audio_source::SDIVideoInput;\n\n    auto watchdog_timeout   = ptree.get(L\"watchdog\", 2);\n    config.watchdog_timeout = watchdog_timeout;\n\n    auto uhd_mode   = ptree.get(L\"uhd-mode\", 0);\n    config.uhd_mode = uhd_output_option::disable_BVC_MultiLink;\n    if (uhd_mode == 1)\n        config.uhd_mode = uhd_output_option::auto_uhd;\n    else if (uhd_mode == 2)\n        config.uhd_mode = uhd_output_option::force_2si;\n    else if (uhd_mode == 3)\n        config.uhd_mode = uhd_output_option::force_square_division;\n\n    return spl::make_shared<bluefish_consumer_proxy>(config);\n}\n\n}} // namespace caspar::bluefish\n"
  },
  {
    "path": "src/modules/bluefish/consumer/bluefish_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n *         James Wise,  james.wise@bluefish444.com\n */\n\n#pragma once\n\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <common/bit_depth.h>\n#include <common/memory.h>\n#include <core/fwd.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace bluefish {\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info);\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info);\n\n}} // namespace caspar::bluefish\n"
  },
  {
    "path": "src/modules/bluefish/interop/BlueDriver_p.h",
    "content": "/*///////////////////////////////////////////////////////////////////////////\r\n// File:        BlueDriver_p.h\r\n// Author:      Tim Bragulla\r\n//\r\n// Description: Legacy definitions for usage with legacy Bluefish APIs\r\n//              (BlueVelvet and BlueVelvetC)\r\n//\r\n// (C) Copyright 2017 by Bluefish Technologies Pty Ltd. All Rights Reserved.\r\n///////////////////////////////////////////////////////////////////////////*/\r\n\r\n\r\n#ifndef HG_BLUE_DRIVER_P_LEGACY_HG\r\n#define HG_BLUE_DRIVER_P_LEGACY_HG\r\n\r\n#include \"BlueTypes.h\"\r\n\r\n/*///////////////////////////////////////////////////////////////////////////\r\n// L E G A C Y   D E C L A R A T I O N S - BEGIN\r\n///////////////////////////////////////////////////////////////////////////*/\r\n\r\n#define BLUE_LITTLE_ENDIAN\t0\r\n#define BLUE_BIG_ENDIAN\t\t1\r\n\r\n#define BLUE_CARD_BUFFER_TYPE_OFFSET\t\t(12)\r\n#define BLUE_DMA_DATA_TYPE_OFFSET\t\t\t(16)\r\n#define GetDMACardBufferId(value)\t\t\t( value & 0x00000FFF)\r\n#define GetCardBufferType(value)\t\t\t((value & 0x0000F000) >> BLUE_CARD_BUFFER_TYPE_OFFSET)\r\n#define GetDMADataType(value)\t\t\t\t((value & 0x000F0000) >> BLUE_DMA_DATA_TYPE_OFFSET)\r\n\r\n/* FLAGS FOR DMA FUNCTION CALLS */\r\n#define Blue_DMABuffer(CardBufferType, BufferId, DataType)\t\t( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( CardBufferType<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ((ULONG)BufferId&0xFFF)) | 0)\r\n\r\n#define BlueImage_VBI_DMABuffer(BufferId, DataType)\t\t\t\t( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( BLUE_CARDBUFFER_IMAGE_VBI<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ((ULONG)BufferId&0xFFF)) | 0)\r\n\r\n#define BlueImage_DMABuffer(BufferId, DataType)\t\t\t\t\t( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( BLUE_CARDBUFFER_IMAGE<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ((ULONG)BufferId&0xFFF)) | 0)\r\n\r\n#define BlueImage_VBI_HANC_DMABuffer(BufferId, DataType)\t\t( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( BLUE_CARDBUFFER_IMAGE_VBI_HANC<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ((ULONG)BufferId&0xFFF)) | 0)\r\n\r\n#define BlueImage_HANC_DMABuffer(BufferId, DataType)\t\t\t( (((ULONG)DataType&0xF)<<(ULONG)BLUE_DMA_DATA_TYPE_OFFSET)| \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( BLUE_CARDBUFFER_IMAGE_HANC<<(ULONG)BLUE_CARD_BUFFER_TYPE_OFFSET) | \\\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t( ((ULONG)BufferId&0xFFF)) | 0)\r\n\r\n/* FLAGS FOR CAPTURE AND PLAYBACK FUNCTION CALLS */\r\n#define BlueBuffer(CardBufferType,BufferId)\t\t\t(((CardBufferType)<<BLUE_CARD_BUFFER_TYPE_OFFSET)|((BufferId&0xFFF))|0)\r\n#define BlueBuffer_Image_VBI(BufferId)\t\t\t\t(((BLUE_CARDBUFFER_IMAGE_VBI)<<BLUE_CARD_BUFFER_TYPE_OFFSET)|((BufferId&0xFFF))|0)\r\n#define BlueBuffer_Image(BufferId)\t\t\t\t\t(((BLUE_CARDBUFFER_IMAGE)<<BLUE_CARD_BUFFER_TYPE_OFFSET)|((BufferId&0xFFF))|0)\r\n#define BlueBuffer_Image_VBI_HANC(BufferId)\t\t\t(((BLUE_CARDBUFFER_IMAGE_VBI_HANC)<<BLUE_CARD_BUFFER_TYPE_OFFSET)|((BufferId&0xFFF))|0)\r\n#define BlueBuffer_Image_HANC(BufferId)\t\t\t\t(((BLUE_CARDBUFFER_IMAGE_HANC)<<BLUE_CARD_BUFFER_TYPE_OFFSET)|((BufferId&0xFFF))|0)\r\n#define BlueBuffer_HANC(BufferId)\t\t\t\t\t(((BLUE_CARDBUFFER_HANC)<<BLUE_CARD_BUFFER_TYPE_OFFSET)|((BufferId&0xFFF))|0)\r\n\r\n\r\n/* Buffer identifiers */\r\n#define\tBUFFER_ID_AUDIO_IN\t\t(0)\r\n#define\tBUFFER_ID_AUDIO_OUT\t\t(1)\r\n#define\tBUFFER_ID_VIDEO0\t\t(2)\r\n#define\tBUFFER_ID_VIDEO1\t\t(3)\r\n#define\tBUFFER_ID_VIDEO2\t\t(4)\r\n#define\tBUFFER_ID_VIDEO3\t\t(5)\r\n\r\n/* AUDIO_OUTPUT_PROP/AUDIO_CHANNEL_ROUTING */\r\n#define GET_ANALOG_AUDIO_LEFT_ROUTINGCHANNEL(value)\t\t\t\t(value&0xFF)\r\n#define GET_ANALOG_AUDIO_RIGHT_ROUTINGCHANNEL(value)\t\t\t((value&0xFF00)>>8)\r\n#define SET_ANALOG_AUDIO_ROUTINGCHANNEL(left,right)\t\t\t\t(((right & 0xFF)<<8)|(left & 0xFF))\r\n#define SET_AUDIO_OUTPUT_ROUTINGCHANNEL(output_type,src_channel_id,_output_channel_id) ((1<<31)|((output_type&3)<<29)|((_output_channel_id &0x3F)<<23)|((src_channel_id & 0x3F)<<16))\r\n#define GET_AUDIO_OUTPUT_SRC_CHANNEL_ROUTING(value)\t\t\t\t((value>>16) & 0x3F)\r\n#define GET_AUDIO_OUTPUT_CHANNEL_ROUTING(value)\t\t\t\t\t((value>>23) & 0x3F)\r\n#define GET_AUDIO_OUTPUT_TYPE_ROUTING(value)\t\t\t\t\t((value & 0x60000000)>>29)\r\n\r\n/* AES_OUTPUT_ROUTING */\r\n#define SET_AES_OUTPUT_ROUTING(OutputVideoChannel, AudioSrcChannel, AudioDstChannel)\t(((OutputVideoChannel & 0xFF) << 16) | ((AudioDstChannel & 0xFF) << 8) | (AudioSrcChannel & 0xFF))\r\n#define GET_AES_OUTPUT_ROUTING_STREAM(value)\t\t\t\t\t\t\t\t\t\t\t((value >> 16) & 0xFF)\r\n#define GET_AES_OUTPUT_ROUTING_DST_CHANNEL(value)\t\t\t\t\t\t\t\t\t\t((value >> 8) & 0xFF)\r\n#define GET_AES_OUTPUT_ROUTING_SRC_CHANNEL(value)\t\t\t\t\t\t\t\t\t\t(value & 0xFF)\r\n\r\n/* MUTE_AES_OUTPUT_CHANNEL */\r\n#define SET_MUTE_AES_OUTPUT_CHANNEL(AudioDstChannel, Mute)\t(((Mute & 0x1) << 31) | AudioDstChannel & 0xFF)\r\n\r\n#define AUDIO_INPUT_SOURCE_SELECT_FLAG\t\t\t\t\t\t\t(1<<16)\t\r\n#define AUDIO_INPUT_SOURCE_SELECT(SynchCount,AudioInputSource)\t(AUDIO_INPUT_SOURCE_SELECT_FLAG|(SynchCount)|(AudioInputSource<<17))\r\n\r\n#define EPOCH_WATCHDOG_TIMER_SET_MACRO(prop, value) (prop|(value &0xFFFF))\r\n#define EPOCH_WATCHDOG_TIMER_QUERY_MACRO(prop)\t\t(prop)\r\n#define EPOCH_WATCHDOG_TIMER_GET_VALUE_MACRO(value)\t(value&0xFFFF)\r\n\r\n#define EPOCH_RS422_PORT_FLAG_SET_MACRO(portid,value)\t((portid&0x3)|(value<<3))\r\n#define EPOCH_RS422_PORT_FLAG_GET_FLAG_MACRO(value)\t\t((value>>3)&0xFFFF)\r\n#define EPOCH_RS422_PORT_FLAG_GET_PORTID_MACRO(value)\t(value&0x3)\r\n\r\n#define RS422_SERIALPORT_FLAG(timeout, port, RxFlushBuffer) (((unsigned long)(timeout)<<16)|(port & 0x3) | (RxFlushBuffer<<15))\r\n#define RS422_SERIALPORT_FLAG2(timeout, port, RxFlushBuffer, RXIntWaitReturnOnAvailData) (((unsigned long)(timeout)<<16)|(port & 0x3) | (RxFlushBuffer<<15)|(RXIntWaitReturnOnAvailData<<14))\r\n\r\n/* Epoch scaler not supported */\r\n#define SET_EPOCH_SCALER_MODE(scaler_id,video_mode) ((scaler_id << 16) | video_mode)\r\n#define GET_EPOCH_SCALER_MODE(value)                (value & 0xFFFF)\r\n#define GET_EPOCH_SCALER_ID(value)                  ((value & 0xFFFF0000) >> 16)\r\n\r\n/* use these macros for retrieving the temp and fan speed on epoch range of cards. */\r\n#define EPOCH_CORE_TEMP(value)\t\t\t\t\t(value & 0xFF)\r\n#define EPOCH_BOARD_TEMP(value)\t\t\t\t\t((value>>16) & 0xFF)\r\n#define EPOCH_FAN_SPEED(value)\t\t\t\t\t((value>>24) & 0xFF)\r\n\r\n/*\tUse these macro for doing the MR2 routing  on epoch range of cards. MR2 routing can be controlled using the property MR_ROUTING. */\r\n#define EPOCH_SET_ROUTING(routing_src,routing_dest,data_link_type) ((routing_src & 0xFF) | ((routing_dest & 0xFF)<<8) | ((data_link_type&0xFFFF)<<16))\r\n#define EPOCH_ROUTING_GET_SRC_DATA(value)\t\t(value & 0xFF)\r\n#define EPOCH_ROUTING_GET_DEST_DATA(value)\t\t((value>>8) & 0xFF)\r\n#define EPOCH_ROUTING_GET_LINK_TYPE_DATA(value)\t((value>>16) & 0xFFFF)\r\n\r\n/* MACROS for card property BYPASS_RELAY_ENABLE */\r\n#define BLUE_ENABLE_BYPASS_RELAY(RelayNumber)       ((RelayNumber << 16) | 1)\r\n#define BLUE_DISABLE_BYPASS_RELAY(RelayNumber)      ((RelayNumber << 16))\r\n#define BLUE_GET_BYPASS_RELAY_SETTING(RelayNumber)  (RelayNumber << 16)\r\n#define GPIO_TX_PORT_A\t(1)\r\n#define GPIO_TX_PORT_B\t(2)\r\n\r\n#define EPOCH_GPIO_TX(port,value)\t(port<<16|value)    /* if want to set each of the GPO ports individually you should use this macro.\r\n                                                           without the macro it would set both the GPO ports on the card */\r\n\r\n#define VPEnableFieldCountTrigger\t\t((BLUE_U64)1<<63)\r\n#define VPTriggerGetFieldCount(value)\t((BLUE_U64)value & 0xFFFFFFFF)\r\n\r\n#define VIDEO_CAPS_INPUT_SDI\t\t\t\t\t(0x00000001)    /**<  Capable of input of SDI Video */\r\n#define VIDEO_CAPS_OUTPUT_SDI\t\t\t\t\t(0x00000002)    /**<  Capable of output of SDI Video */\r\n#define VIDEO_CAPS_INPUT_COMP\t\t\t\t\t(0x00000004)    /**<  Capable of capturing Composite Video input */\r\n#define VIDEO_CAPS_OUTPUT_COMP\t\t\t\t\t(0x00000008)    /**<  Capable of capturing Composite Video output */\r\n\r\n#define VIDEO_CAPS_INPUT_YUV\t\t\t\t\t(0x00000010)    /**<  Capable of capturing Component Video input */\r\n#define VIDEO_CAPS_OUTPUT_YUV\t\t\t\t\t(0x00000020)    /**<  Capable of capturing Component Video output */\r\n#define VIDEO_CAPS_INPUT_SVIDEO\t\t\t\t\t(0x00000040)    /**<  Capable of capturing SVideo input */\r\n#define VIDEO_CAPS_OUTPUT_SVIDEO\t\t\t\t(0x00000080)    /**<  Capable of capturing SVideo output */\r\n\r\n#define VIDEO_CAPS_GENLOCK\t\t\t\t\t\t(0x00000100)    /**<  Able to adjust Vert & Horiz timing */\r\n#define VIDEO_CAPS_VERTICAL_FLIP\t\t\t\t(0x00000200)    /**<  Able to flip rasterisation */\r\n#define VIDEO_CAPS_KEY_OUTPUT\t\t\t\t\t(0x00000400)    /**<  Video keying output capable */\r\n#define VIDEO_CAPS_4444_OUTPUT\t\t\t\t\t(0x00000800)    /**<  Capable of outputting 4444 (dual link) */\r\n\r\n#define VIDEO_CAPS_DUALLINK_INPUT\t\t\t\t(0x00001000)\t/**<  Dual Link input   */\r\n#define VIDEO_CAPS_INTERNAL_KEYER\t\t\t\t(0x00002000)\t/**<  Has got an internal Keyer */\r\n#define VIDEO_CAPS_RGB_COLORSPACE_SDI_CONN\t\t(0x00004000)\t/**<  Support RGB colorspace  in on an  SDI connector  */\r\n#define VIDEO_CAPS_HAS_PILLOR_BOX\t\t\t\t(0x00008000)\t/**<  Has got support for pillor box */\r\n\r\n#define VIDEO_CAPS_OUTPUT_RGB \t\t\t\t\t(0x00010000)    /**<  Has Analog RGB output connector  */\r\n#define VIDEO_CAPS_SCALED_RGB \t\t\t\t\t(0x00020000)    /**<  Can scale RGB colour space */\r\n#define AUDIO_CAPS_PLAYBACK \t\t\t\t\t(0x00040000)\t/**<  Has got audio output */\r\n#define AUDIO_CAPS_CAPTURE \t\t\t\t\t\t(0x00080000)\r\n\r\n#define VIDEO_CAPS_DOWNCONVERTER\t\t\t\t(0x00100000)\r\n#define VIDEO_CAPS_DUALOUTPUT_422_IND_STREAM\t(0x00200000)\t/**<  Specifies whether the card supports Dual Independent 422 output streams */\r\n#define VIDEO_CAPS_DUALINPUT_422_IND_STREAM\t\t(0x00400000)\t/**<  Specifies whether the card supports Dual Independent 422 input streams */\r\n\r\n#define VIDEO_CAPS_VBI_OUTPUT\t\t\t\t\t(0x00800000)\t/**<  Specifies whether the card supports VBI output */\r\n#define VIDEO_CAPS_VBI_INPUT\t\t\t\t\t(0x04000000)\t/**<  Specifies whether the card supports VBI input */\t\r\n\r\n#define VIDEO_CAPS_HANC_OUTPUT\t\t\t\t\t(0x02000000)\r\n#define VIDEO_CAPS_HANC_INPUT\t\t\t\t\t(0x04000000)\r\n\r\n#define ANALOG_CHANNEL_0                        MONO_CHANNEL_9\r\n#define ANALOG_CHANNEL_1                        MONO_CHANNEL_10\r\n#define ANALOG_AUDIO_PAIR                       (ANALOG_CHANNEL_0 | ANALOG_CHANNEL_1)\r\n\r\n#define STEREO_PAIR_1                           (MONO_CHANNEL_1 | MONO_CHANNEL_2)\r\n#define STEREO_PAIR_2                           (MONO_CHANNEL_3 | MONO_CHANNEL_4)\r\n#define STEREO_PAIR_3                           (MONO_CHANNEL_5 | MONO_CHANNEL_6)\r\n#define STEREO_PAIR_4                           (MONO_CHANNEL_7 | MONO_CHANNEL_8)\r\n\r\n#define IGNORE_SYNC_WAIT_TIMEOUT_VALUE          (0xFFFFFFFF)\r\n\r\n#define AUDIO_INPUT_SOURCE_EMB      0\r\n#define AUDIO_INPUT_SOURCE_AES      1\r\n\r\n/*///////////////////////////////////////////////////////////////////////////////////\r\n//H E L P E R   M A C R O S\r\n///////////////////////////////////////////////////////////////////////////////////*/\r\n\r\n/* the following macros are used with card property OVERRIDE_OUTPUT_VPID_DEFAULT */\r\n#define OUTPUT_VPID_SET_ENABLED(value)\t\t\t\t\t\t\t\t((value) |= 0x8000000000000000ULL )\r\n#define OUTPUT_VPID_SET_DISABLED(value)\t\t\t\t\t\t\t\t((value) &= ~(0x8000000000000000ULL))\r\n#define OUTPUT_VPID_SET_BYTES(value, byte1, byte2, byte3, byte4)\t(value = ((value & 0xFFFFFFFF00000000ULL) | ((((BLUE_U64)(byte4 & 0xFF)) << 24) | ((byte3 & 0xFF) << 16) | ((byte2 & 0xFF) << 8) | (byte1 & 0xFF))))\r\n#define OUTPUT_VPID_SET_SDI_CONNECTOR(value, outputconnector)\t\t(value = ((value & 0xFFFF0000FFFFFFFFULL) | ((outputconnector & 0xFFFFULL) << 32)))\r\n#define OUTPUT_VPID_GET_ENABLED(value)\t\t\t\t\t\t\t\t((value) & 0x8000000000000000ULL )\r\n#define OUTPUT_VPID_GET_SDI_CONNECTOR(value)\t\t\t\t\t\t((value >> 32) & 0xFFFFULL)\r\n#define OUTPUT_VPID_GET_VPID_BYTE1(value)\t\t\t\t\t\t\t(value & 0xFFLL)\r\n#define OUTPUT_VPID_GET_VPID_BYTE2(value)\t\t\t\t\t\t\t((value >> 8) & 0xFFULL)\r\n#define OUTPUT_VPID_GET_VPID_BYTE3(value)\t\t\t\t\t\t\t((value >> 16) & 0xFFULL)\r\n#define OUTPUT_VPID_GET_VPID_BYTE4(value)\t\t\t\t\t\t\t((value >> 24) & 0xFFULL)\r\n\r\n/* the following macros are used with card property INTERLOCK_REFERENCE */\r\n#define INTERLOCK_REFERENCE_GET_OUTPUT_ENABLED(value)\t\t((value)\t\t& 0x01)\r\n#define INTERLOCK_REFERENCE_GET_INPUT_DETECTED(value)\t\t((value >> 1)\t& 0x01)\r\n#define INTERLOCK_REFERENCE_GET_SLAVE_POSITION(value)\t\t((value >> 2)\t& 0x1F)\r\n\r\n/* the following macros are used with card property CARD_FEATURE_STREAM_INFO */\r\n#define CARD_FEATURE_GET_SDI_OUTPUT_STREAM_COUNT(value)\t\t((value)\t\t& 0xF)\r\n#define CARD_FEATURE_GET_SDI_INPUT_STREAM_COUNT(value)\t\t((value >> 4)\t& 0xF)\r\n#define CARD_FEATURE_GET_ASI_OUTPUT_STREAM_COUNT(value)\t\t((value >> 8)\t& 0xF)\r\n#define CARD_FEATURE_GET_ASI_INPUT_STREAM_COUNT(value)\t\t((value >> 12)\t& 0xF)\r\n#define CARD_FEATURE_GET_3G_SUPPORT(value)\t\t\t\t\t((value >> 16)\t& 0xF)\r\n\r\n/* the following macros are used with card property CARD_FEATURE_CONNECTOR_INFO */\r\n#define CARD_FEATURE_GET_SDI_OUTPUT_CONNECTOR_COUNT(value)    ((value)\t\t& 0xF)\r\n#define CARD_FEATURE_GET_SDI_INPUT_CONNECTOR_COUNT(value)     ((value >> 4)\t& 0xF)\r\n#define CARD_FEATURE_GET_AES_CONNECTOR_SUPPORT(value)         ((value >> 8)\t& 0x1)\r\n#define CARD_FEATURE_GET_RS422_CONNECTOR_SUPPORT(value)       ((value >> 9)\t& 0x1)\r\n#define CARD_FEATURE_GET_LTC_CONNECTOR_SUPPORT(value)         ((value >> 10)\t& 0x1)\r\n#define CARD_FEATURE_GET_GPIO_CONNECTOR_SUPPORT(value)        ((value >> 11)\t& 0x1)\r\n#define CARD_FEATURE_GET_HDMI_CONNECTOR_SUPPORT(value)        ((value >> 12)\t& 0x1)\r\n#define CARD_FEATURE_GET_HDMI_OUTPUT_CONNECTOR_SUPPORT(value) ((value >> 12)\t& 0x1)\r\n#define CARD_FEATURE_GET_HDMI_INPUT_CONNECTOR_SUPPORT(value)  ((value >> 13)\t& 0x1)\r\n\r\n/* the following macros are used with card property VIDEO_ONBOARD_KEYER */\r\n#define VIDEO_ONBOARD_KEYER_GET_STATUS_ENABLED(value)\t\t\t\t\t((value) & 0x1)\r\n#define VIDEO_ONBOARD_KEYER_GET_STATUS_OVER_BLACK(value)\t\t\t\t((value) & 0x2)\r\n#define VIDEO_ONBOARD_KEYER_GET_STATUS_USE_INPUT_ANCILLARY(value)\t\t((value) & 0x4)\r\n#define VIDEO_ONBOARD_KEYER_GET_STATUS_DATA_IS_PREMULTIPLIED(value)\t\t((value) & 0x8)\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLED(value)\t\t\t\t\t(value |= 0x1)\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLED(value)\t\t\t\t\t(value &= ~(0x1))\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_ENABLE_OVER_BLACK(value)\t\t\t(value |= 0x2)\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_DISABLE_OVER_BLACK(value)\t\t(value &= ~(0x2))\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_USE_INPUT_ANCILLARY(value)\t\t(value |= 0x4)      /* only use this setting when keying over valid input (input must also match output video mode), includes HANC and VANC */\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_USE_OUTPUT_ANCILLARY(value)\t\t(value &= ~(0x4))\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_PREMULTIPLIED(value)\t\t(value |= 0x8)\r\n#define VIDEO_ONBOARD_KEYER_SET_STATUS_DATA_IS_NOT_PREMULTIPLIED(value)\t(value &= ~(0x8))\r\n\r\n/* the following macros are used with card property EPOCH_HANC_INPUT_FLAGS */\r\n#define HANC_FLAGS_IS_ARRI_RECORD_FLAG_SET(value)\t((value) & 0x1)\r\n\r\n/* the following macros are used with card property EPOCH_RAW_VIDEO_INPUT_TYPE */\r\n#define RAW_VIDEO_INPUT_TYPE_IS_10BIT\t\t(0x01)\r\n#define RAW_VIDEO_INPUT_TYPE_IS_12BIT\t\t(0x02)\r\n#define RAW_VIDEO_INPUT_TYPE_IS_WEISSCAM\t(0x10)\r\n#define RAW_VIDEO_INPUT_TYPE_IS_ARRI\t\t(0x20)\r\n\r\n/* the following macros are used with card property EPOCH_PCIE_CONFIG_INFO */\r\n#define PCIE_CONFIG_INFO_GET_MAX_PAYLOAD_SIZE(value) ((value) & 0xFFFF)\r\n#define PCIE_CONFIG_INFO_GET_MAX_READREQUEST_SIZE(value) ((value >> 16) & 0xFFFF)\r\n\r\n/* the following macros are used with card property MISC_CONNECTOR_OUT */\r\n#define MISC_CONNECTOR_OUT_SET_CONNECTOR_ID(value, ID)               (value = (ID & 0x0000FFFF) << 16)\r\n#define MISC_CONNECTOR_OUT_SET_SIGNAL_TYPE_LTC(value)                (value = (value & 0xFFFF0000) | 0x0002)\r\n#define MISC_CONNECTOR_OUT_SET_SIGNAL_TYPE_INTERLOCK(value)          (value = (value & 0xFFFF0000) | 0x0004)\r\n#define MISC_CONNECTOR_OUT_SET_SIGNAL_TYPE_SPG(value)                (value = (value & 0xFFFF0000) | 0x0008)\r\n#define MISC_CONNECTOR_OUT_IS_SIGNAL_TYPE_LTC(value)                 (value & 0x0002)\r\n#define MISC_CONNECTOR_OUT_IS_SIGNAL_TYPE_INTERLOCK(value)           (value & 0x0004)\r\n#define MISC_CONNECTOR_OUT_IS_SIGNAL_TYPE_SPG(value)                 (value & 0x0008)\r\n\r\n/* the following macros are used with card property MISC_CONNECTOR_IN */\r\n#define MISC_CONNECTOR_IN_SET_CONNECTOR_ID(value, ID)       (value = (ID & 0xFFFF) << 16)\r\n#define MISC_CONNECTOR_IN_IS_SIGNAL_DETECTED(value)         (value & 0x0001)\r\n#define MISC_CONNECTOR_IN_IS_SIGNAL_TYPE_LTC(value)         (value & 0x0002)\r\n#define MISC_CONNECTOR_IN_IS_SIGNAL_TYPE_INTERLOCK(value)   (value & 0x0004)\r\n\r\n\r\ntypedef enum _EBlueCardProperty\r\n{\r\n\tVIDEO_DUAL_LINK_OUTPUT =\t\t\t\t\t\t0,\t/**< Use this property to enable/diable cards dual link output property */\r\n\tVIDEO_DUAL_LINK_INPUT =\t\t\t\t\t\t\t1,\t/**< Use this property to enable/diable cards dual link input property */\r\n\tVIDEO_DUAL_LINK_OUTPUT_SIGNAL_FORMAT_TYPE =\t\t2,\t/**< Use this property to select signal format type that should be used\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twhen dual link output is enabled. Possible values this property can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taccept is defined in the enumerator EDualLinkSignalFormatType */\r\n\tVIDEO_DUAL_LINK_INPUT_SIGNAL_FORMAT_TYPE =\t\t3,\t/**< Use this property to select signal format type that should be used\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twhen dual link input is enabled. Possible values this property can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taccept is defined in the enumerator EDualLinkSignalFormatType */\r\n\tVIDEO_OUTPUT_SIGNAL_COLOR_SPACE =\t\t\t\t4,\t/**< Use this property to select color space of the signal when dual link output is set to\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tuse 4:4:4/4:4:4:4 signal format type. Possible values this property can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taccept is defined in the enumerator EConnectorSignalColorSpace */\r\n\tVIDEO_INPUT_SIGNAL_COLOR_SPACE =\t\t\t\t5,\t/**< Use this property to select color space of the signal when dual link input is set to\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   use 4:4:4/4:4:4:4 signal format type. Possible values this property can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   accept is defined in the enumerator EConnectorSignalColorSpace */\r\n\tVIDEO_MEMORY_FORMAT =\t\t\t\t\t\t\t6, /**< Use this property to set the pixel format that should be used by\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t video output channels.  Possible values this property can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t accept is defined in the enumerator EMemoryFormat*/\r\n\tVIDEO_MODE =\t\t\t\t\t\t\t\t\t7,\t/**< Use this property to set the video mode that should be used by\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvideo output channels.  Possible values this property can\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\taccept is defined in the enumerator EVideoMode*/\r\n\tVIDEO_UPDATE_TYPE =\t\t\t\t\t\t\t\t8,\t/**< Use this property to set the framestore update type that should be used by\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  video output channels.  Card can update video framestore at field/frame rate.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  Possible values this property can accept is defined in the enumerator EUpdateMethod */\r\n\tVIDEO_ENGINE =\t\t\t\t\t\t\t\t\t9,\r\n\tVIDEO_IMAGE_ORIENTATION =\t\t\t\t\t\t10,\t/**< Use this property to set the image orientation of the video output framestore.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t This property must be set before frame is transferred to on card memory using\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t DMA transfer functions(system_buffer_write_async). It is recommended to use\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t vertical flipped image orientation only on RGB pixel formats.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Possible values this property can accept is defined in the enumerator EImageOrientation */\r\n\tVIDEO_USER_DEFINED_COLOR_MATRIX =\t\t\t\t11,\r\n\tVIDEO_PREDEFINED_COLOR_MATRIX =\t\t\t\t\t12,\t/* EPreDefinedColorSpaceMatrix */\r\n\tVIDEO_RGB_DATA_RANGE =\t\t\t\t\t\t\t13, /**< Use this property to set the data range of RGB pixel format, user can specify\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twhether the RGB data is in either SMPTE or CGR range. Based on this information\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdriver is decide which color matrix should be used.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator ERGBDataRange\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFor SD cards this property will set the input and the output to the specified value.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFor Epoch/Create/SuperNova cards this property will only set the output to the specified value.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFor setting the input on Epoch/Create/SuperNova cards see EPOCH_VIDEO_INPUT_RGB_DATA_RANGE */\r\n\tVIDEO_KEY_OVER_BLACK =\t\t\t\t\t\t\t14, /**< DEPRECATED */\r\n\tVIDEO_KEY_OVER_INPUT_SIGNAL =\t\t\t\t\t15,\t/**< DEPRECATED */\r\n\tVIDEO_SET_DOWN_CONVERTER_VIDEO_MODE =\t\t\t16,\t/**< DEPRECATED */\r\n\tVIDEO_LETTER_BOX =\t\t\t\t\t\t\t\t17,\t/**< DEPRECATED */\r\n\tVIDEO_PILLOR_BOX_LEFT =\t\t\t\t\t\t\t18,\t/**< DEPRECATED */\r\n\tVIDEO_PILLOR_BOX_RIGHT =\t\t\t\t\t\t19,\t/**< DEPRECATED */\r\n\tVIDEO_PILLOR_BOX_TOP =\t\t\t\t\t\t\t20,\t/**< DEPRECATED */\r\n\tVIDEO_PILLOR_BOX_BOTTOM =\t\t\t\t\t\t21,\t/**< DEPRECATED */\r\n\tVIDEO_SAFE_PICTURE =\t\t\t\t\t\t\t22,\t/**< DEPRECATED */\r\n\tVIDEO_SAFE_TITLE =\t\t\t\t\t\t\t\t23,\t/**< DEPRECATED */\r\n\tVIDEO_INPUT_SIGNAL_VIDEO_MODE =\t\t\t\t\t24,\t/**< Use this property to retrieve the video input signal information on the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tdefault video input channel used by that SDK object.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tWhen calling SetCardProperty with a valid video mode on this property, the SDK\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twill will use this video mode \"Hint\" if the card buffers are set up despite there being a valid\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tinput signal; the card buffers will be set up when calling one of these card properties:\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tVIDEO_INPUT_MEMORY_FORMAT\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tVIDEO_INPUT_UPDATE_TYPE\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tVIDEO_INPUT_ENGINE\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tNote: QueryCardProperty(VIDEO_INPUT_SIGNAL_VIDEO_MODE) will still return the actual video input signal */\r\n\tVIDEO_COLOR_MATRIX_MODE =\t\t\t\t\t\t25,\r\n\tVIDEO_OUTPUT_MAIN_LUT =\t\t\t\t\t\t\t26,\t/**< DEPRECATED */\r\n\tVIDEO_OUTPUT_AUX_LUT =\t\t\t\t\t\t\t27,\t/**< DEPRECATED */\r\n\tVIDEO_LTC =\t\t\t\t\t\t\t\t\t\t28,\t/**< DEPRECATED; To retreive/ outputting LTC information you can use the HANC decoding and encoding functions. */\r\n\tVIDEO_GPIO =\t\t\t\t\t\t\t\t\t29,\r\n\tVIDEO_PLAYBACK_FIFO_STATUS =\t\t\t\t\t30, /**< This property can be used to retrieve how many frames are buffered in the video playback fifo. */\r\n\tRS422_RX_BUFFER_LENGTH =\t\t\t\t\t\t31,\r\n\tRS422_RX_BUFFER_FLUSH =\t\t\t\t\t\t\t32,\r\n\tVIDEO_INPUT_UPDATE_TYPE =\t\t\t\t\t\t33,\t/**< Use this property to set the framestore update type that should be used by\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t video input  channels.  Card can update video framestore at field/frame rate.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Possible values this property can accept is defined in the enumerator EUpdateMethod */\r\n\tVIDEO_INPUT_MEMORY_FORMAT =\t\t\t\t\t\t34,\t/**< Use this property to set the pixel format that should be used by\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   video input channels when it is capturing a frame from video input source.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Possible values this property can accept is defined in the enumerator EMemoryFormat*/\r\n\tVIDEO_GENLOCK_SIGNAL =\t\t\t\t\t\t\t35,\t/**< Use this property to retrieve video signal of the reference source that is used by the card.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tThis can also be used to select the reference signal source that should be used.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tSee application note AN004_Genlock.pdf for more information */\r\n\tAUDIO_OUTPUT_PROP =\t\t\t\t\t\t\t\t36,\t/**< this can be used to route PCM audio data onto respective audio output connectors. */\r\n\tAUDIO_CHANNEL_ROUTING =\t\t\t\t\t\t\tAUDIO_OUTPUT_PROP,\r\n\tAUDIO_INPUT_PROP =\t\t\t\t\t\t\t\t37,\t/**< Use this property to select audio input source that should be used when doing an audio capture.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator Blue_Audio_Connector_Type. */\r\n\tVIDEO_ENABLE_LETTERBOX =\t\t\t\t\t\t38,\t/**< DEPRECATED */\r\n\tVIDEO_DUALLINK_OUTPUT_INVERT_KEY_COLOR =\t\t39,\t/**< this property is deprecated and no longer supported on epoch/create range of cards. */\r\n\tVIDEO_DUALLINK_OUTPUT_DEFAULT_KEY_COLOR =\t\t40,\t/**< this property is deprecated and no longer supported on epoch/create range of cards. */\r\n\tVIDEO_BLACKGENERATOR =\t\t\t\t\t\t\t41,\t/**< Use this property to control the black generator on the video output channel. */\r\n\tVIDEO_INPUTFRAMESTORE_IMAGE_ORIENTATION =\t\t42,\r\n\tVIDEO_INPUT_SOURCE_SELECTION =\t\t\t\t\t43, /**< The video input source that should be used by the SDK default video input channel\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tcan be configured using this property.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator EBlueConnectorIdentifier. */\r\n\tDEFAULT_VIDEO_OUTPUT_CHANNEL =\t\t\t\t\t44,\r\n\tDEFAULT_VIDEO_INPUT_CHANNEL =\t\t\t\t\t45,\r\n\tVIDEO_REFERENCE_SIGNAL_TIMING =\t\t\t\t\t46,\r\n\tEMBEDEDDED_AUDIO_OUTPUT =\t\t\t\t\t\t47,\t/**< the embedded audio output property can be configured using this property.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator EBlueEmbAudioOutput. */\r\n\tEMBEDDED_AUDIO_OUTPUT =\t\t\t\t\t\t\tEMBEDEDDED_AUDIO_OUTPUT,\r\n\tVIDEO_PLAYBACK_FIFO_FREE_STATUS =\t\t\t\t48, /**< this will return the number of free buffer in the fifo.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  If the video engine  is framestore this will give you the number of buffers that the framestore mode\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  can you use with that video output channel. */\r\n\tVIDEO_IMAGE_WIDTH =\t\t\t\t\t\t\t\t49,\t/**< selective output DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_IMAGE_HEIGHT =\t\t\t\t\t\t\t50,\t/**< selective output DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_SELECTIVE_OUTPUT_DMA_DST_PITCH =\t\t\tVIDEO_IMAGE_WIDTH,\t/* pitch (bytes per line) of destination buffer (card memory) */\r\n\tVIDEO_SELECTIVE_OUTPUT_DMA_SRC_LINES =\t\t\tVIDEO_IMAGE_HEIGHT,\t/* number of video lines to extract from source image (system memory)*/\r\n\tVIDEO_SCALER_MODE =\t\t\t\t\t\t\t\t51,\r\n\tAVAIL_AUDIO_INPUT_SAMPLE_COUNT =\t\t\t\t52,\t/* DEPRECATED */\r\n\tVIDEO_PLAYBACK_FIFO_ENGINE_STATUS =\t\t\t\t53,\t/**< this will return the playback fifo status. The values returned by this property\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tare defined in the enumerator BlueVideoFifoStatus. */\r\n\tVIDEO_CAPTURE_FIFO_ENGINE_STATUS =\t\t\t\t54,\t/**< this will return the capture  fifo status.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tThe values returned by this property are defined in the enumerator BlueVideoFifoStatus. */\r\n\tVIDEO_2K_1556_PANSCAN =\t\t\t\t\t\t\t55,\t/**< DEPRECATED */\r\n\tVIDEO_OUTPUT_ENGINE =\t\t\t\t\t\t\t56,\t/**< Use this property to set the video engine of the video output channels.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator EEngineMode */\r\n\tVIDEO_INPUT_ENGINE =\t\t\t\t\t\t\t57, /**< Use this property to set the video engine of the video input channels.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator EEngineMode */\r\n\tBYPASS_RELAY_A_ENABLE =\t\t\t\t\t\t\t58, /**< use this property to control the bypass relay on SDI A output. */\r\n\tBYPASS_RELAY_B_ENABLE =\t\t\t\t\t\t\t59,\t/**< use this property to control the bypass relay on SDI B output. */\r\n\tVIDEO_PREMULTIPLIER =\t\t\t\t\t\t\t60,\r\n\tVIDEO_PLAYBACK_START_TRIGGER_POINT =\t\t\t61, /**< Using this property you can instruct the driver to start the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t video playback fifo on a particular video output field count.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Normally video playback fifo is started on the next video interrupt after\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t the video_playback_start call. */\r\n\tGENLOCK_TIMING =\t\t\t\t\t\t\t\t62,\r\n\tVIDEO_IMAGE_PITCH =\t\t\t\t\t\t\t\t63,\t/**< selective output DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_IMAGE_OFFSET =\t\t\t\t\t\t\t64,\t/**< currently not used; selective output DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_SELECTIVE_OUTPUT_DMA_SRC_PITCH =\t\t\tVIDEO_IMAGE_PITCH,\t/* pitch (bytes per line) of source buffer (system memory) */\r\n\tVIDEO_INPUT_IMAGE_WIDTH =\t\t\t\t\t\t65,\t/**< selective input DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_INPUT_IMAGE_HEIGHT =\t\t\t\t\t\t66,\t/**< selective input DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_INPUT_IMAGE_PITCH =\t\t\t\t\t\t67,\t/**< selective input DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_INPUT_IMAGE_OFFSET =\t\t\t\t\t\t68,\t/**< currently not used; selective input DMA: see application note AN008_SelectiveDMA.pdf for more details */\r\n\tVIDEO_SELECTIVE_INPUT_DMA_SRC_PITCH =\t\t\tVIDEO_INPUT_IMAGE_WIDTH,\t/* pitch (bytes per line) of source buffer (card memory) */\r\n\tVIDEO_SELECTIVE_INPUT_DMA_SRC_LINES =\t\t\tVIDEO_INPUT_IMAGE_HEIGHT,\t/* number of video lines to extract from source image (card memory) */\r\n\tVIDEO_SELECTIVE_INPUT_DMA_DST_PITCH =\t\t\tVIDEO_INPUT_IMAGE_PITCH,\t/* pitch (bytes per line) of destination buffer (system memory) */\r\n\tTIMECODE_RP188 =\t\t\t\t\t\t\t\t69,\t/**< this property is deprecated and no longer supported on epoch/create range of cards.*/\r\n\tBOARD_TEMPERATURE =\t\t\t\t\t\t\t\t70, /**<This property can be used to retrieve the Board temperature, core temperature and\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   RPM of the Fan on epoch/create range of cards.<br/>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   Use the macro's EPOCH_CORE_TEMP ,EPOCH_BOARD_TEMP and EPOCH_FAN_SPEED\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   to retireive the respective values from the property. */\r\n\tMR2_ROUTING =\t\t\t\t\t\t\t\t\t71,\t/**< Use this property to control the MR2 functionality on epoch range of cards.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tUse the following macro with this property.<br/>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t1) EPOCH_SET_ROUTING --> for setting the source, destination and link type of the routing connection,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t2) EPOCH_ROUTING_GET_SRC_DATA --> for getting the routing source.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tThe possible source and destination elements supported by the routing matrix are defined in the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tenumerator EEpochRoutingElements. */\r\n\tSAVEAS_POWERUP_SETTINGS =\t\t\t\t\t\t72,\t/**< DEPRECATED */\r\n\tVIDEO_CAPTURE_AVAIL_BUFFER_COUNT =\t\t\t\t73, /**< This property will return the number of captured frame avail in the fifo at present.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   If the video engine  is framestore this will give you the number of buffers that the framestore mode\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   can you use with that video input channel */\r\n\tEPOCH_APP_WATCHDOG_TIMER =\t\t\t\t\t\t74,/**< Use this property to control the application  watchdog timer functionality.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator enum_blue_app_watchdog_timer_prop. */\r\n\tEPOCH_RESET_VIDEO_INPUT_FIELDCOUNT =\t\t\t75, /**< Use this property to reset the field count on both the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t video channels of the card. You can pass the value that\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t should be used as starting fieldcount after the reset.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t This property can be used to keep track  sync between left and right signal\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t when you are capturing in stereoscopic mode. */\r\n\tEPOCH_RS422_PORT_FLAGS =\t\t\t\t\t\t76,\t/**< Use this property to set the master/slave property of the RS422 ports.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tPossible values this property can accept is defined in the enumerator enum_blue_rs422_port_flags. */\r\n\tEPOCH_DVB_ASI_INPUT_TIMEOUT =\t\t\t\t\t77,\t/**< Current DVB ASI input firmware does not support this property in hardware,\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis is a future addition.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tUse this property to set the timeout  of the DVB ASI input stream.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\ttimeout is specified in  milliseconds.If hardware did not get the required no of\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tpackets( specified using EPOCH_DVB_ASI_INPUT_LATENCY_PACKET_COUNT)\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twithin the period specified in the timeout, hardware would generate a video input interrupt\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tand it would be safe to read the dvb asi packet from the card. */\r\n\tEPOCH_DVB_ASI_INPUT_PACKING_FORMAT =\t\t\t78, /**< Use this property to specify the packing method that should be used\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t when capturing DVB ASI packets.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t The possible packing methods are defined in the enumerator enum_blue_dvb_asi_packing_format. */\r\n\tEPOCH_DVB_ASI_INPUT_LATENCY_PACKET_COUNT =\t\t79, /**< Use this property to set  how many asi packets should be captured by the card , before it\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tnotifies the driver of available data using video input interrupt. */\r\n\tVIDEO_PLAYBACK_FIFO_CURRENT_FRAME_UNIQUEID =\t80, /**< This property can be used to query the current unique id of\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t the frame that is being displayed currently by the video output channel. This\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t property is only useful in the context of video fifo.<br/>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t You get a uniqueid when you present a frame using video_playback_present function.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t Alternative ways to get this information are <br/>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 1) using blue_wait_video_sync_async , the member current_display_frame_uniqueid contains the same information<br/>\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t 2) using wait_video_output_sync function on epoch cards, if\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t the flag UPD_FMT_FLAG_RETURN_CURRENT_UNIQUEID is appended with\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t either UPD_FMT_FRAME or UPD_FMT_FIELD , the return value of\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t the function wait_video_output_sync would contain the current display frames uniqueid. */\r\n\r\n\tEPOCH_DVB_ASI_INPUT_GET_PACKET_SIZE =\t\t\t81,\t/**< use this property to get the size of each asi transport stream packet (whether it is 188 or 204.*/\r\n\tEPOCH_DVB_ASI_INPUT_PACKET_COUNT =\t\t\t\t82,\t/**< this property would give you the number of packets captured during the last\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  interrupt time frame. For ASI interrupt is generated if\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t  hardware captured the requested number of packets or it hit the timeout value */\r\n\tEPOCH_DVB_ASI_INPUT_LIVE_PACKET_COUNT =\t\t\t83,\t/**< this property would give you the number of packets that\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tis being captured during the current interrupt time frame.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tFor ASI interrupt is generated when has hardware captured the\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\trequested number of packets specified using\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tEPOCH_DVB_ASI_INPUT_LATENCY_PACKET_COUNT property. */\r\n\tEPOCH_DVB_ASI_INPUT_AVAIL_PACKETS_IN_FIFO =\t\t84,\t/**< This property would return the number of ASI packets that has been captured into card memory, that\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   can be retrieved. This property is only valid when the video input\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t   channel is being used in FIFO modes. */\r\n\tEPOCH_ROUTING_SOURCE_VIDEO_MODE =\t\t\t\tVIDEO_SCALER_MODE,\t/**< Use this property to change the video mode that scaler should be set to.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tUSe the macro SET_EPOCH_SCALER_MODE when using this property, as this macro\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twould allow you to select which one of the scaler blocks video mode should be updated. */\r\n\tEPOCH_AVAIL_VIDEO_SCALER_COUNT =\t\t\t\t85,\t/**< DEPRECATED */\r\n\tEPOCH_ENUM_AVAIL_VIDEO_SCALERS_ID =\t\t\t\t86,\t/**< DEPRECATED */\r\n\tEPOCH_ALLOCATE_VIDEO_SCALER =\t\t\t\t\t87,\t/**< DEPRECATED */\r\n\tEPOCH_RELEASE_VIDEO_SCALER =\t\t\t\t\t88,\t/**< DEPRECATED */\r\n\tEPOCH_DMA_CARDMEMORY_PITCH =\t\t\t\t\t89,\t/**< DEPRECATED */\r\n\tEPOCH_OUTPUT_CHANNEL_AV_OFFSET =\t\t\t\t90,\t/**< DEPRECATED */\r\n\tEPOCH_SCALER_CHANNEL_MUX_MODE =\t\t\t\t\t91,\t/**< DEPRECATED */\r\n\tEPOCH_INPUT_CHANNEL_AV_OFFSET =\t\t\t\t\t92,\t/**< DEPRECATED */\r\n\tEPOCH_AUDIOOUTPUT_MANUAL_UCZV_GENERATION =\t\t93,\t/* ASI firmware only */\r\n\tEPOCH_SAMPLE_RATE_CONVERTER_BYPASS =\t\t\t94,\t\t/** bypasses the sample rate converter for AES audio; only turn on for Dolby-E support\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\tpass in a flag to signal which audio stereo pair should be bypassed:\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\tbit 0:\tAES channels 0 and 1\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\tbit 1:\tAES channels 2 and 3\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\tbit 2:\tAES channels 4 and 5\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\tbit 3:\tAES channels 6 and 7\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t*\tFor example: bypass the sample rate converter for channels 0 to 3: flag = 0x3;\t*/\r\n\tEPOCH_GET_PRODUCT_ID =\t\t\t\t\t\t\t95,\t/* returns the enum for the firmware type EEpochFirmwareProductID */\r\n\tEPOCH_GENLOCK_IS_LOCKED =\t\t\t\t\t\t96,\r\n\tEPOCH_DVB_ASI_OUTPUT_PACKET_COUNT =\t\t\t\t97,\t\t/* ASI firmware only */\r\n\tEPOCH_DVB_ASI_OUTPUT_BIT_RATE =\t\t\t\t\t98,\t\t/* ASI firmware only */\r\n\tEPOCH_DVB_ASI_DUPLICATE_OUTPUT_A =\t\t\t\t99,\t\t/* ASI firmware only */\r\n\tEPOCH_DVB_ASI_DUPLICATE_OUTPUT_B =\t\t\t\t100,\t/* ASI firmware only */\r\n\tEPOCH_SCALER_HORIZONTAL_FLIP =\t\t\t\t\t101,\t/* see SideBySide_3D sample application */\r\n\tEPOCH_CONNECTOR_DIRECTION =\t\t\t\t\t\t102,\t/* deprecated / not supported */\r\n\tEPOCH_AUDIOOUTPUT_VALIDITY_BITS =\t\t\t\t103,\t/* ASI firmware only */\r\n\tEPOCH_SIZEOF_DRIVER_ALLOCATED_MEMORY =\t\t\t104,\t/**< DEPRECATED */\r\n\tINVALID_VIDEO_MODE_FLAG =\t\t\t\t\t\t105,\t/* returns the enum for VID_FMT_INVALID that this SDK/Driver was compiled with;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tit changed between 5.9.x.x and 5.10.x.x driver branch and has to be handled differently for\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\teach driver if the application wants to use the VID_FMT_INVALID flag and support both driver branches */\r\n\tEPOCH_VIDEO_INPUT_VPID =\t\t\t\t\t\t106,\t/* returns the VPID for the current video input signal. Input value is of type EBlueConnectorIdentifier */\r\n\tEPOCH_LOW_LATENCY_DMA =\t\t\t\t\t\t\t107,\t/**< DEPRECATED; use new feature EPOCH_SUBFIELD_INPUT_INTERRUPTS instead */\r\n\tEPOCH_VIDEO_INPUT_RGB_DATA_RANGE =\t\t\t\t108,\r\n\tEPOCH_DVB_ASI_OUTPUT_PACKET_SIZE =\t\t\t\t109,\t/* firmware supports either 188 or 204 bytes per ASI packet; set to either\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum_blue_dvb_asi_packet_size_188_bytes or\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tenum_blue_dvb_asi_packet_size_204_bytes */\r\n\tEPOCH_SUBFIELD_INPUT_INTERRUPTS =\t\t\t\t110,\t/* similar to the EPOCH_LOW_LATENCY_DMA card feature, but this doesn't influence the DMA;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tit simply adds interrupts between the frame/field interrupts that trigger when a corresponding\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tvideo chunk has been captured required minimum driver: 5.10.1.8*/\r\n\tEPOCH_AUDIOOUTPUT_METADATA_SETTINGS =\t\t\t111,\t/* Use the EAudioMetaDataSettings enumerator to change the audio output metadata settings */\r\n\tEPOCH_HD_SDI_TRANSPORT =\t\t\t\t\t\t112,\t/* output only: available modes are defined in the enum EHdSdiTransport; for inputs see EPOCH_HD_SDI_TRANSPORT_INPUT */\r\n\tCARD_FEATURE_STREAM_INFO =\t\t\t\t\t\t113,\t/* only supported from driver 5.10.2.x; info on how many in/out SDI/ASI streams are supported */\r\n\tCARD_FEATURE_CONNECTOR_INFO =\t\t\t\t\t114,\t/* only supported from driver 5.10.2.x; info on which connectors are supported: SDI in/out, AES, RS422, LTC, GPIO */\r\n\tEPOCH_HANC_INPUT_FLAGS =\t\t\t\t\t\t115,\t/* this property can be queried to test flags being set in the HANC space (e.g. HANC_FLAGS_IS_ARRI_RECORD_FLAG_SET) */\r\n\tEPOCH_INPUT_VITC =\t\t\t\t\t\t\t\t116,\t/* this property retrieves the current input VITC timecode; set .vt = VT_UI8 as this is a 64bit value; */\r\n\tEPOCH_RAW_VIDEO_INPUT_TYPE =\t\t\t\t\t117,\t/* specifies if the raw/bayer input is ARRI 10/12 bit or Weisscam; set to 0 to revert back to normal SDI mode */\r\n\tEPOCH_PCIE_CONFIG_INFO =\t\t\t\t\t\t118,\t/* only supported from driver 5.10.2.x; provides info on PCIE maximum payload size and maximum read request siize */\r\n\tEPOCH_4K_QUADLINK_CHANNEL =\t\t\t\t\t\t119,\t/* use this property to set the 4K quadrant number for the current channel in 4K output mode; quadrant numbers are 1 - 4 */\r\n\tEXTERNAL_LTC_SOURCE_SELECTION =\t\t\t\t\t120,\t/* use the enum EBlueExternalLtcSource to set the input source for the external LTC */\r\n\tEPOCH_HD_SDI_TRANSPORT_INPUT =\t\t\t\t\t121,\t/* can only be queried; return values are defined in the enum EHdSdiTransport. Input value is of type EBlueConnectorIdentifier */\r\n\tCARD_CONNECTED_VIA_TB =\t\t\t\t\t\t\t122,\t/* MAC only: use this to check if the Card is connected via ThunderBolt */\r\n\tINTERLOCK_REFERENCE =\t\t\t\t\t\t\t123,\t/* this feature is only supported on Epoch Neutron cards; check application note AN004_Genlock.pdf for more information */\r\n\tVIDEO_ONBOARD_KEYER =\t\t\t\t\t\t\t124,\t/* this property is currently only supported by Epoch Neutron cards; use the VIDEO_ONBOARD_KEYER_GET_STATUS macros for this property*/\r\n\tEPOCH_OUTPUT_VITC_MANUAL_CONTROL =\t\t\t\t125,\t/* Epoch Neutron only: this property enables the feature to allow output of a custom VITC timecode on a field by field basis (low frame rates only); for high frame rates the conventional way (using the HANC buffer) must be used */\r\n\tEPOCH_OUTPUT_VITC =\t\t\t\t\t\t\t\t126,\t/* Epoch Neutron only: this property sets the custom VITC timecode (64 bit value) on a field by field basis (for low frame rates only); set .vt = VT_UI8 as this is a 64bit value; */\r\n\tEPOCH_INPUT_VITC_SOURCE =\t\t\t\t\t\t127,\t/* this property selects the source for the card property EPOCH_INPUT_VITC for SD video modes; in SD video modes the VITC source can be either\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tfrom VBI space or from RP188 packets; the default (value = 0) is set to RP188; setting this to 1 will select VBI space as the source for EPOCH_INPUT_VITC; set .vt = VT_UI4 */\r\n\tTWO_SAMPLE_INTERLEAVE_OUTPUT =\t\t\t\t\t128,\t/* enables two sample interleave mode for 4K video modes using two output channels; options are: 0 = turn feature off, 1 = turn feature on */\r\n\tTWO_SAMPLE_INTERLEAVE_INPUT =\t\t\t\t\t129,\t/* enables two sample interleave mode for 4K video modes using two input channels; options are: 0 = turn feature off, 1 = turn feature on  */\r\n\tBTC_TIMER =\t\t\t\t\t\t\t\t\t\t130,\t/* BTC: Coordinated Bluefish Time; this timer has microsecond granularity and is started/reset when the driver starts; set .vt = VT_UI8 as this is a 64bit value; */\r\n\tBFLOCK_SIGNAL_ENABLE =\t\t\t\t\t\t\t131,\t/* S+ cards can generate a proprietary lock signal on the S+ connector (connector 0); options are 0 = turn off signal (connector 0 will be copy of SDI A output); 1 = turn on lock signal output; set .vt = VT_UI4 */\r\n\tAES_OUTPUT_ROUTING =\t\t\t\t\t\t\t132,\t/* set the stream source and source channels for the AES output; .vt = VT_UI4 */\r\n\tMUTE_AES_OUTPUT_CHANNEL =\t\t\t\t\t\t133,\t/* mute any of the AES output channels (0..7); to enable/disable mute use the SET_MUTE_AES_OUTPUT_CHANNEL macro; to query an AES output channels mute status\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tset VT.ulVal to the AES output channel number (0..7) then call QueryCardProperty(); the return value will be 1 = muted or 0 = enabled; set .vt to VT_UI4\t*/\r\n\tFORCE_SD_VBI_OUTPUT_BUFFER_TO_V210 =\t\t\t134,\t/* this card property forces the VBI buffer to V210 memory format in SD video modes (default for HD video modes) so that it can handle 10 bit VANC packets.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tset 1 = force to V210 or 0 = follow video memory format (default); set .vt to VT_UI4; when changing this property the video output mode and video output engine need to be set again manually! */\r\n\tEMBEDDED_AUDIO_INPUT_INFO =\t\t\t\t\t\t135,\t/*\tthis card property returns info on how which embedded audio input channels are available (channel mask for channels 1 - 16 in lower 16 bits).\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tit also returns the data payload for each channel (1 - 16) in the upper 16 bits (0 = embedded audio, 1 = other (e.g. Dolby Digital)) */\r\n\tOVERRIDE_OUTPUT_VPID_DEFAULT =\t\t\t\t\t136,\t/*\tthis card property should only be used for debugging purposes if the default VPID needs to be changed; it will override the output VPID that is set up by default depending on the video mode, pixel format and signal format type.\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tthis property takes a 64 bit value (set .vt to VT_UI8) and is defined as follows (there are helper MACROS defined in the MACROS section at the end of this header file):\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t7...0: Byte 1 of VPID\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t15...8: Byte 2 of VPID\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t23..16: Byte 3 of VPID\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t31..24: Byte 4 of VPID\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t47..32: SDI output connector (EBlueConnectorIdentifier)\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t62..48: reserved (set to 0)\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t63: enable/disable VPID output (0 = disabled, 1 = enabled) */\r\n    FORCE_SD_VBI_INPUT_BUFFER_TO_V210 =             137,\t/* this card property forces the VBI input buffer to V210 memory format in SD video modes (default for HD video modes) so that it can handle 10 bit VANC packets.\r\n                                                               set 1 = force to V210 or 0 = follow video memory format (default); set .vt to VT_UI4; when changing this property the video input engine needs to be set again manually! */\r\n    BYPASS_RELAY_ENABLE =                           138,    /* Enable/Disable the bypass relays; use MACROs BLUE_SET_ENABLE_BYPASS_RELAY(), BLUE_SET_DISABLE_BYPASS_RELAY() and BLUE_GET_BYPASS_RELAY_SETTING() to initialise the value (.vt = VT_UI4) */\r\n    VIDEO_MODE_EXT_OUTPUT =                         139,    /* Query or set the video mode for the output channel using the _EVideoModeExt enums. */\r\n    VIDEO_MODE_EXT_INPUT =                          140,    /* Query the current video mode on the input channel using the _EVideoModeExt enums. In case of no valid video mode present the input FIFOs can be set up for an expected video mode by setting this card property*/\r\n    IS_VIDEO_MODE_EXT_SUPPORTED_OUTPUT =            141,\r\n    IS_VIDEO_MODE_EXT_SUPPORTED_INPUT =             142,\r\n    MISC_CONNECTOR_OUT =                            143,    /* KRONOS and above: 32 bit value, query and set. Use MACROS MISC_CONNECTOR_OUT_***; supported connectors to set/query: BLUE_CONNECTOR_REF_OUT, BLUE_CONNECTOR_INTERLOCK_OUT */\r\n    MISC_CONNECTOR_IN =                             144,    /* KRONOS and above: 32 bit value, query only. Use MACROS MISC_CONNECTOR_IN_***; supported connectors to query: BLUE_CONNECTOR_REF_IN, BLUE_CONNECTOR_INTERLOCK_IN */\r\n \tSUB_IMAGE_MAPPING =                             145,    /* Valid on input and output, but only has an effect on 4k/UHD and larger buffers.   Use ESubImageMapping enum to specify value; default value is IMAGE_MAPPING_TWO_SAMPLE_INTERLEAVE. set to IMAGE_MAPPING_SQUARE_DIVISION to specify that the 4K/UHD buffers handled by this channel are in SD (Square Division) mode */\r\n\r\n\r\n\tVIDEO_CARDPROPERTY_INVALID =\t\t\t\t\t1000\r\n}EBlueCardProperty;\r\n\r\ntypedef enum _ESubImageMapping\r\n{\r\n    IMAGE_MAPPING_INVALID =                 0,\r\n    IMAGE_MAPPING_TWO_SAMPLE_INTERLEAVE =   1,\r\n    IMAGE_MAPPING_SQUARE_DIVISION =         2,\r\n}ESubImageMapping;\r\n\r\ntypedef enum _EHdSdiTransport\r\n{\r\n    HD_SDI_TRANSPORT_INVALID =      0,      /* Invalid input signal */\r\n\tHD_SDI_TRANSPORT_1_5G =         0x1,\t/* HD as 1.5G */\r\n\tHD_SDI_TRANSPORT_3G_LEVEL_A =   0x2,\t/* 3G Level A */\r\n\tHD_SDI_TRANSPORT_3G_LEVEL_B =   0x3,\t/* 3G Level B */\r\n}EHdSdiTransport;\r\n\r\ntypedef enum _EAudioMetaDataSettings\r\n{\r\n\tAUDIO_METADATA_KEEP_ALIVE = 0x1\t\t/*\tWhen setting this bit for the EPOCH_AUDIOOUTPUT_METADATA_SETTINGS card property the audio meta data (like RP188 timecode\r\n\t\t\t\t\t\t\t\t\t\twill still be played out even after stopping audio playback; this is a static settings and only needs to be set once;\r\n\t\t\t\t\t\t\t\t\t\tit is channel based and can be changed for all output channels independently */\r\n}EAudioMetaDataSettings;\r\n\r\n/* This enumerator is still supported, but deprecated */\r\n/* Please use _EVideoModeExt instead and card properties VIDEO_MODE_EXT_OUTPUT and VIDEO_MODE_EXT_INPUT */\r\ntypedef enum _EVideoMode\r\n{\r\n\tVID_FMT_PAL =\t\t\t\t0,\r\n\tVID_FMT_NTSC =\t\t\t\t1,\r\n\tVID_FMT_576I_5000 =\t\t\tVID_FMT_PAL,\r\n\tVID_FMT_486I_5994 =\t\t\tVID_FMT_NTSC,\r\n\tVID_FMT_720P_5994 =\t\t\t2,\r\n\tVID_FMT_720P_6000 =\t\t\t3,\r\n\tVID_FMT_1080PSF_2397 =\t\t4,\r\n\tVID_FMT_1080PSF_2400 =\t\t5,\r\n\tVID_FMT_1080P_2397 =\t\t6,\r\n\tVID_FMT_1080P_2400 =\t\t7,\r\n\tVID_FMT_1080I_5000 =\t\t8,\r\n\tVID_FMT_1080I_5994 =\t\t9,\r\n\tVID_FMT_1080I_6000 =\t\t10,\r\n\tVID_FMT_1080P_2500 =\t\t11,\r\n\tVID_FMT_1080P_2997 =\t\t12,\r\n\tVID_FMT_1080P_3000 =\t\t13,\r\n\tVID_FMT_HSDL_1498 =\t\t\t14,\r\n\tVID_FMT_HSDL_1500 =\t\t\t15,\r\n\tVID_FMT_720P_5000 =\t\t\t16,\r\n\tVID_FMT_720P_2398 =\t\t\t17,\r\n\tVID_FMT_720P_2400 =\t\t\t18,\r\n\tVID_FMT_2048_1080PSF_2397 =\t19,\r\n\tVID_FMT_2048_1080PSF_2400 =\t20,\r\n\tVID_FMT_2048_1080P_2397 =\t21,\r\n\tVID_FMT_2048_1080P_2400 =\t22,\r\n\tVID_FMT_1080PSF_2500 =\t\t23,\r\n\tVID_FMT_1080PSF_2997 =\t\t24,\r\n\tVID_FMT_1080PSF_3000 =\t\t25,\r\n\tVID_FMT_1080P_5000 =\t\t26,\r\n\tVID_FMT_1080P_5994 =\t\t27,\r\n\tVID_FMT_1080P_6000 =\t\t28,\r\n\tVID_FMT_720P_2500 =\t\t\t29,\r\n\tVID_FMT_720P_2997 =\t\t\t30,\r\n\tVID_FMT_720P_3000 =\t\t\t31,\r\n\tVID_FMT_DVB_ASI =\t\t\t32,\r\n\tVID_FMT_2048_1080PSF_2500 =\t33,\r\n\tVID_FMT_2048_1080PSF_2997 =\t34,\r\n\tVID_FMT_2048_1080PSF_3000 =\t35,\r\n\tVID_FMT_2048_1080P_2500 =\t36,\r\n\tVID_FMT_2048_1080P_2997 =\t37,\r\n\tVID_FMT_2048_1080P_3000 =\t38,\r\n\tVID_FMT_2048_1080P_5000 =\t39,\r\n\tVID_FMT_2048_1080P_5994 =\t40,\r\n\tVID_FMT_2048_1080P_6000 =\t41,\r\n\tVID_FMT_1080P_4800 =\t\t42,\r\n\tVID_FMT_2048_1080P_4800 =\t43,\r\n    VID_FMT_1080P_4795 =        44,\r\n    VID_FMT_2048_1080P_4795 =   45,\r\n\r\n\tVID_FMT_INVALID =\t\t\t46\r\n} EVideoMode;\r\n\r\ntypedef enum _EVideoModeExt\r\n{\r\n    VID_FMT_EXT_INVALID =           1024,\r\n    VID_FMT_EXT_CUSTOM =            1025,\r\n    VID_FMT_EXT_DVB_ASI =           1026,\r\n    VID_FMT_EXT_576I_5000 =         1027,\r\n    VID_FMT_EXT_486I_5994 =         1028,\r\n    VID_FMT_EXT_720P_2398 =         1029,\r\n    VID_FMT_EXT_720P_2400 =         1030,\r\n    VID_FMT_EXT_720P_2500 =         1031,\r\n    VID_FMT_EXT_720P_2997 =         1032,\r\n    VID_FMT_EXT_720P_3000 =         1033,\r\n    VID_FMT_EXT_720P_4795 =         1034,\r\n    VID_FMT_EXT_720P_4800 =         1035,\r\n    VID_FMT_EXT_720P_5000 =         1036,\r\n    VID_FMT_EXT_720P_5994 =         1037,\r\n    VID_FMT_EXT_720P_6000 =         1038,\r\n    VID_FMT_EXT_1080I_5000 =        1039,\r\n    VID_FMT_EXT_1080I_5994 =        1040,\r\n    VID_FMT_EXT_1080I_6000 =        1041,\r\n    VID_FMT_EXT_1080PSF_2398 =      1042,\r\n    VID_FMT_EXT_1080PSF_2400 =      1043,\r\n    VID_FMT_EXT_1080PSF_2500 =      1044,\r\n    VID_FMT_EXT_1080PSF_2997 =      1045,\r\n    VID_FMT_EXT_1080PSF_3000 =      1046,\r\n    VID_FMT_EXT_1080P_2398 =        1047,\r\n    VID_FMT_EXT_1080P_2400 =        1048,\r\n    VID_FMT_EXT_1080P_2500 =        1049,\r\n    VID_FMT_EXT_1080P_2997 =        1050,\r\n    VID_FMT_EXT_1080P_3000 =        1051,\r\n    VID_FMT_EXT_1080P_4795 =        1052,\r\n    VID_FMT_EXT_1080P_4800 =        1053,\r\n    VID_FMT_EXT_1080P_5000 =        1054,\r\n    VID_FMT_EXT_1080P_5994 =        1055,\r\n    VID_FMT_EXT_1080P_6000 =        1056,\r\n    VID_FMT_EXT_2K_1080PSF_2398 =   1057,\r\n    VID_FMT_EXT_2K_1080PSF_2400 =   1058,\r\n    VID_FMT_EXT_2K_1080PSF_2500 =   1059,\r\n    VID_FMT_EXT_2K_1080PSF_2997 =   1060,\r\n    VID_FMT_EXT_2K_1080PSF_3000 =   1061,\r\n    VID_FMT_EXT_2K_1080P_2398 =     1062,\r\n    VID_FMT_EXT_2K_1080P_2400 =     1063,\r\n    VID_FMT_EXT_2K_1080P_2500 =     1064,\r\n    VID_FMT_EXT_2K_1080P_2997 =     1065,\r\n    VID_FMT_EXT_2K_1080P_3000 =     1066,\r\n    VID_FMT_EXT_2K_1080P_4795 =     1067,\r\n    VID_FMT_EXT_2K_1080P_4800 =     1068,\r\n    VID_FMT_EXT_2K_1080P_5000 =     1069,\r\n    VID_FMT_EXT_2K_1080P_5994 =     1070,\r\n    VID_FMT_EXT_2K_1080P_6000 =     1071,\r\n    VID_FMT_EXT_2K_1556I_1499 =     1072,\r\n    VID_FMT_EXT_2K_1556I_1500 =     1073,\r\n    VID_FMT_EXT_2160P_2398 =        1074,\r\n    VID_FMT_EXT_2160P_2400 =        1075,\r\n    VID_FMT_EXT_2160P_2500 =        1076,\r\n    VID_FMT_EXT_2160P_2997 =        1077,\r\n    VID_FMT_EXT_2160P_3000 =        1078,\r\n    VID_FMT_EXT_2160P_4795 =        1079,\r\n    VID_FMT_EXT_2160P_4800 =        1080,\r\n    VID_FMT_EXT_2160P_5000 =        1081,\r\n    VID_FMT_EXT_2160P_5994 =        1082,\r\n    VID_FMT_EXT_2160P_6000 =        1083,\r\n    VID_FMT_EXT_4K_2160P_2398 =     1084,\r\n    VID_FMT_EXT_4K_2160P_2400 =     1085,\r\n    VID_FMT_EXT_4K_2160P_2500 =     1086,\r\n    VID_FMT_EXT_4K_2160P_2997 =     1087,\r\n    VID_FMT_EXT_4K_2160P_3000 =     1088,\r\n    VID_FMT_EXT_4K_2160P_4795 =     1089,\r\n    VID_FMT_EXT_4K_2160P_4800 =     1090,\r\n    VID_FMT_EXT_4K_2160P_5000 =     1091,\r\n    VID_FMT_EXT_4K_2160P_5994 =     1092,\r\n    VID_FMT_EXT_4K_2160P_6000 =     1093,\r\n    VID_FMT_EXT_4320P_2398 =        1094,\r\n    VID_FMT_EXT_4320P_2400 =        1095,\r\n    VID_FMT_EXT_4320P_2500 =        1096,\r\n    VID_FMT_EXT_4320P_2997 =        1097,\r\n    VID_FMT_EXT_4320P_3000 =        1098,\r\n    VID_FMT_EXT_4320P_4795 =        1099,\r\n    VID_FMT_EXT_4320P_4800 =        1100,\r\n    VID_FMT_EXT_4320P_5000 =        1101,\r\n    VID_FMT_EXT_4320P_5994 =        1102,\r\n    VID_FMT_EXT_4320P_6000 =        1103,\r\n    VID_FMT_EXT_8K_4320P_2398 =     1104,\r\n    VID_FMT_EXT_8K_4320P_2400 =     1105,\r\n    VID_FMT_EXT_8K_4320P_2500 =     1106,\r\n    VID_FMT_EXT_8K_4320P_2997 =     1107,\r\n    VID_FMT_EXT_8K_4320P_3000 =     1108,\r\n    VID_FMT_EXT_8K_4320P_4795 =     1109,\r\n    VID_FMT_EXT_8K_4320P_4800 =     1110,\r\n    VID_FMT_EXT_8K_4320P_5000 =     1111,\r\n    VID_FMT_EXT_8K_4320P_5994 =     1112,\r\n    VID_FMT_EXT_8K_4320P_6000 =     1113,\r\n    VID_FMT_EXT_LAST_ENTRY_V1 =     VID_FMT_EXT_8K_4320P_6000,\r\n\r\n    /* aliases */\r\n    VID_FMT_EXT_PAL =               VID_FMT_EXT_576I_5000,\r\n    VID_FMT_EXT_NTSC =              VID_FMT_EXT_486I_5994,\r\n    VID_FMT_EXT_HSDL_1499 =         VID_FMT_EXT_2K_1556I_1499,\r\n    VID_FMT_EXT_HSDL_1500 =         VID_FMT_EXT_2K_1556I_1500,\r\n\r\n}EVideoModeExt;\r\n\r\ntypedef enum _EBFLockSignalType\r\n{\r\n\tBFLOCK_SIGNAL_UNKNOWN =\t0x1000,\r\n\tBFLOCK_SIGNAL_2398 =\t0x1001,\r\n\tBFLOCK_SIGNAL_2400 =\t0x1002,\r\n\tBFLOCK_SIGNAL_2500 =\t0x1003,\r\n\tBFLOCK_SIGNAL_2997 =\t0x1004,\r\n\tBFLOCK_SIGNAL_3000 =\t0x1005,\r\n\tBFLOCK_SIGNAL_4795 =\t0x1006,\r\n\tBFLOCK_SIGNAL_4800 =\t0x1007,\r\n\tBFLOCK_SIGNAL_5000 =\t0x1008,\r\n\tBFLOCK_SIGNAL_5994 =\t0x1009,\r\n\tBFLOCK_SIGNAL_6000 =\t0x100A,\r\n}EBFLockSignalType;\r\n\r\ntypedef enum _EMemoryFormat\r\n{\r\n\tMEM_FMT_ARGB =\t\t\t\t\t0,\r\n\tMEM_FMT_BV10 =\t\t\t\t\t1,\t/* not supported */\r\n\tMEM_FMT_BV8 =\t\t\t\t\t2,\r\n\tMEM_FMT_YUVS =\t\t\t\t\tMEM_FMT_BV8,\r\n\tMEM_FMT_V210 =\t\t\t\t\t3,\r\n\tMEM_FMT_RGBA =\t\t\t\t\t4,\r\n\tMEM_FMT_CINEON_LITTLE_ENDIAN =\t5,\r\n\tMEM_FMT_ARGB_PC =\t\t\t\t6,\r\n\tMEM_FMT_BGRA =\t\t\t\t\tMEM_FMT_ARGB_PC,\r\n\tMEM_FMT_CINEON =\t\t\t\t7,\r\n\tMEM_FMT_2VUY =\t\t\t\t\t8,\r\n\tMEM_FMT_BGR =\t\t\t\t\t9,\r\n\tMEM_FMT_BGR_16_16_16 =\t\t\t10,\r\n\tMEM_FMT_BGR_48 =\t\t\t\tMEM_FMT_BGR_16_16_16,\r\n\tMEM_FMT_BGRA_16_16_16_16 =\t\t11,\r\n\tMEM_FMT_BGRA_64 =\t\t\t\tMEM_FMT_BGRA_16_16_16_16,\r\n\tMEM_FMT_VUYA_4444 =\t\t\t\t12,\r\n\tMEM_FMT_V216 =\t\t\t\t\t13,\r\n\tMEM_FMT_Y210 =\t\t\t\t\t14,\r\n\tMEM_FMT_Y216 =\t\t\t\t\t15,\r\n\tMEM_FMT_RGB =\t\t\t\t\t16,\r\n\tMEM_FMT_YUV_ALPHA =\t\t\t\t17,\r\n\tMEM_FMT_RGB_16_16_16 =\t\t\t18,\r\n\tMEM_FMT_RGB_48 =\t\t\t\tMEM_FMT_RGB_16_16_16,\r\n\tMEM_FMT_RGBA_16_16_16_16 =\t\t19,\r\n\tMEM_FMT_RGBA_64 =\t\t\t\tMEM_FMT_RGBA_16_16_16_16,\r\n\tMEM_FMT_YCA8 =\t\t\t\t\t20,\r\n\tMEM_FMT_CYA8 =\t\t\t\t\t21,\r\n\tMEM_FMT_YUV_ALPHA_10 =\t\t\t22,\r\n\tMEM_FMT_YCA10 =\t\t\t\t\t23,\r\n\tMEM_FMT_CYA10 =\t\t\t\t\t24,\r\n\tMEM_FMT_YAC10 =\t\t\t\t\t25,\r\n\tMEM_FMT_CAY10 =\t\t\t\t\t26,\r\n\r\n\tMEM_FMT_INVALID =\t\t\t\t27\r\n} EMemoryFormat;\r\n\r\ntypedef enum _EUpdateMethod\r\n{\r\n\tUPD_FMT_FIELD =\t\t\t\t\t\t\t0,\r\n\tUPD_FMT_FRAME =\t\t\t\t\t\t\t1,\r\n\tUPD_FMT_FRAME_DISPLAY_FIELD1 =\t\t\t2,\r\n\tUPD_FMT_FRAME_DISPLAY_FIELD2 =\t\t\t3,\r\n\tUPD_FMT_INVALID =\t\t\t\t\t\t4,\r\n\tUPD_FMT_FLAG_RETURN_CURRENT_UNIQUEID =\t0x80000000,\t/*\tif this flag is used on epoch cards, function would\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\treturn the unique id of the current frame as the return value. */\r\n} EUpdateMethod;\r\n\r\ntypedef enum _EResoFormat\r\n{\r\n\tRES_FMT_NORMAL = 0,\r\n\tRES_FMT_HALF,\r\n\tRES_FMT_INVALID\r\n} EResoFormat;\r\n\r\ntypedef enum _EEngineMode\r\n{\r\n\tVIDEO_ENGINE_FRAMESTORE =\t0,\t/* Low latency mode for capture and playback; buffer cycling must be done by the user */\r\n\tVIDEO_ENGINE_PLAYBACK =\t\t1,\t/* deprecated; use VIDEO_ENGINE_DUPLEX instead */\r\n\tVIDEO_ENGINE_CAPTURE =\t\t2,\t/* FIFO mode for capturing Video/VANC/HANC and have driver do automatic playthrough on the output.\r\n\t\t\t\t\t\t\t\t\t\toutput channel cannot be used for anything else */\r\n\tVIDEO_ENGINE_PAGEFLIP =\t\t3,\t/* deprecated/not supported */\r\n\tVIDEO_ENGINE_DUPLEX =\t\t4,\t/* FIFO mode for either capture or playback; capture and playback side can be used independently at the same time*/\r\n\tVIDEO_ENGINE_INVALID =\t\t5\r\n} EEngineMode;\r\n\r\ntypedef enum\r\n{\r\n\tBLUE_FIFO_CLOSED =\t\t\t0,\t/**< Fifo has not been initialized*/\r\n\tBLUE_FIFO_STARTING =\t\t1,\t/**< Fifo is starting */\r\n\tBLUE_FIFO_RUNNING =\t\t\t2,\t/**< Fifo is running */\r\n\tBLUE_FIFO_STOPPING =\t\t3,\t/**< Fifo is in the process of stopping */\r\n\tBLUE_FIFO_PASSIVE =\t\t\t5,\t/**< Fifo is currently stopped or not active*/\r\n\tBLUE_FIFO_STATUS_INVALID =\t10\r\n}BlueVideoFifoStatus;\r\n\r\ntypedef enum\r\n{\r\n\tBLUE_FIFO_NULL_ATTRIBUTE =\t\t0x0,\r\n\tBLUE_FIFO_ECHOPORT_ENABLED =\t0x1,\r\n\tBLUE_FIFO_STEPMODE =\t\t\t0x2,\r\n\tBLUE_FIFO_LOOPMODE =\t\t\t0x4\r\n}BlueVideoFifo_Attributes;\r\n\r\ntypedef enum _ECardType\r\n{\r\n    CRD_BLUEDEEP_LT =               0,   /*  not supported */\r\n    CRD_BLUEDEEP_SD =               1,   /*  not supported */\r\n    CRD_BLUEDEEP_AV =               2,   /*  not supported */\r\n    CRD_BLUEDEEP_IO =               3,   /*  not supported */\r\n    CRD_BLUEWILD_AV =               4,   /*  not supported */\r\n    CRD_IRIDIUM_HD =                5,   /*  not supported */\r\n    CRD_BLUEWILD_RT =               6,   /*  not supported */\r\n    CRD_BLUEWILD_HD =               7,   /*  not supported */\r\n    CRD_REDDEVIL =                  8,   /*  not supported */\r\n    CRD_BLUEDEEP_HD =               9,   /*  not supported, but value used for CRD_BLUE_EPOCH_2K */\r\n    CRD_BLUEDEEP_HDS =              10,  /*  not supported */\r\n    CRD_BLUE_ENVY =                 11,  /*  not supported */\r\n    CRD_BLUE_PRIDE =                12,  /*  not supported */\r\n    CRD_BLUE_GREED =                13,  /*  not supported */\r\n    CRD_BLUE_INGEST =               14,  /*  not supported */\r\n    CRD_BLUE_SD_DUALLINK =          15,  /*  not supported */\r\n    CRD_BLUE_CATALYST =             16,  /*  not supported */\r\n    CRD_BLUE_SD_DUALLINK_PRO =      17,  /*  not supported */\r\n    CRD_BLUE_SD_INGEST_PRO =        18,  /*  not supported */\r\n    CRD_BLUE_SD_DEEPBLUE_LITE_PRO = 19,  /*  not supported */\r\n    CRD_BLUE_SD_SINGLELINK_PRO =    20,  /*  not supported */\r\n    CRD_BLUE_SD_IRIDIUM_AV_PRO =    21,  /*  not supported */\r\n    CRD_BLUE_SD_FIDELITY =          22,  /*  not supported */\r\n    CRD_BLUE_SD_FOCUS =             23,  /*  not supported */\r\n    CRD_BLUE_SD_PRIME =             24,  /*  not supported */\r\n\r\n    CRD_BLUE_EPOCH_2K =             9,\r\n\tCRD_BLUE_EPOCH_2K_HORIZON =\t\tCRD_BLUE_EPOCH_2K,\r\n\tCRD_BLUE_EPOCH_2K_CORE =\t\t25,\r\n\tCRD_BLUE_EPOCH_2K_ULTRA =\t\t26,\r\n\tCRD_BLUE_EPOCH_HORIZON =\t\t27,\r\n\tCRD_BLUE_EPOCH_CORE =\t\t\t28,\r\n\tCRD_BLUE_EPOCH_ULTRA =\t\t\t29,\r\n\tCRD_BLUE_CREATE_HD =\t\t\t30,\r\n\tCRD_BLUE_CREATE_2K =\t\t\t31,\r\n\tCRD_BLUE_CREATE_2K_ULTRA =\t\t32,\r\n\tCRD_BLUE_CREATE_3D =\t\t\tCRD_BLUE_CREATE_2K,\r\n\tCRD_BLUE_CREATE_3D_ULTRA =\t\tCRD_BLUE_CREATE_2K_ULTRA,\r\n\tCRD_BLUE_SUPER_NOVA =\t\t\t33,\r\n\tCRD_BLUE_SUPER_NOVA_S_PLUS =\t34,\r\n\tCRD_BLUE_SUPER_NOVA_MICRO =\t\t35,\r\n\tCRD_BLUE_NEUTRON =\t\t\t\tCRD_BLUE_SUPER_NOVA_MICRO,\r\n\tCRD_BLUE_EPOCH_CG =\t\t\t\t36,\r\n\tCRD_BLUE_KRONOS_ELEKTRON =\t\t37,\r\n\tCRD_BLUE_KRONOS_OPTIKOS =\t\t38,\r\n    CRD_BLUE_KRONOS_K8 =            39,\r\n\r\n\tCRD_INVALID =\t\t\t\t\t500\r\n} ECardType;\r\n\r\ntypedef enum _EHDCardSubType\r\n{\r\n    CRD_HD_FURY =       1,   /* not supported */\r\n    CRD_HD_VENGENCE =   2,   /* not supported */\r\n    CRD_HD_IRIDIUM_XP = 3,   /* not supported */\r\n    CRD_HD_IRIDIUM =    4,   /* not supported */\r\n    CRD_HD_LUST =       5,   /* not supported */\r\n    CRD_HD_INVALID           /* not supported */\r\n}EHDCardSubType;\r\n\r\nenum EEpochFirmwareProductID\r\n{\r\n\tORAC_FILMPOST_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t\t(0x01),\t /* Epoch (2K) Horizon/Core/Ultra, Create/Create3D/Create3D Ultra */\r\n\tORAC_BROADCAST_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t\t(0x02),\t /* Epoch (2K) Horizon/Core/Ultra, Create/Create3D/Create3D Ultra */\r\n\tORAC_ASI_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t\t\t(0x03),\t /* Epoch (2K) Horizon/Core/Ultra */\r\n\tORAC_4SDIINPUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t\t(0x04),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_4SDIOUTPUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t(0x05),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_2SDIINPUT_2SDIOUTPUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x06),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_1SDIINPUT_3SDIOUTPUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x08),\t /* Epoch Supernova/Supernova S+, deprecated */\r\n\tORAC_INPUT_1SDI_1CHANNEL_OUTPUT_4SDI_3CHANNEL_FIRMWARE_PRODUCTID =\t(0x09),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_INPUT_2SDI_2CHANNEL_OUTPUT_3SDI_2CHANNEL_FIRMWARE_PRODUCTID =\t(0x0A),\t /* Epoch Supernova/Supernova S+, deprecated */\r\n\tORAC_INPUT_3SDI_3CHANNEL_OUTPUT_1SDI_1CHANNEL_FIRMWARE_PRODUCTID =\t(0x0B),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_BNC_ASI_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t\t(0x0C),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_NEUTRON_2_IN_0_OUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x0D),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_0_IN_2_OUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x0E),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_1_IN_1_OUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x0F),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_2_IN_0_OUT_SCALER_FIRMWARE_PRODUCTID =\t\t\t\t\t(0x10),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_0_IN_2_OUT_SCALER_FIRMWARE_PRODUCTID =\t\t\t\t\t(0x11),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_1_IN_1_OUT_SCALER_FIRMWARE_PRODUCTID =\t\t\t\t\t(0x12),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_ASI_FIRMWARE_PRODUCTID =\t\t\t\t\t\t\t\t(0x13),\t /* Epoch Neutron */\r\n\tORAC_INPUT_1SDI_1CHANNEL_OUTPUT_3SDI_3CHANNEL_FIRMWARE_PRODUCTID =\t(0x14),\t /* Epoch Supernova/Supernova S+ */\r\n\tORAC_NEUTRON_1_IN_2_OUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x15),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_3_IN_0_OUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x16),\t /* Epoch Neutron */\r\n\tORAC_NEUTRON_0_IN_3_OUT_FIRMWARE_PRODUCTID =\t\t\t\t\t\t(0x17),\t /* Epoch Neutron */\r\n\tORAC_INPUT_1SDI_1CHANNEL_OUTPUT_3SDI_2CHANNEL_FIRMWARE_PRODUCTID =  (0x18),\t /* Epoch Supernova/Supernova S+ */\r\n    ORAC_NEUTRON_2_IN_1_OUT_FIRMWARE_PRODUCTID =                        (0x19),\t /* Epoch Neutron */\r\n    ZEUS_4_IN_4_OUT_FIRMWARE_PRODUCTID =                                (0x1A),  /* Kronos Elektron/Optikos */\r\n    ZEUS_8_IN_FIRMWARE_PRODUCTID =                                      (0x1B),  /* Kronos Elektron/Optikos */\r\n    ZEUS_8_OUT_FIRMWARE_PRODUCTID =                                     (0x1C),  /* Kronos Elektron/Optikos */\r\n    ZEUS_RECOVERY_FIRMWARE_PRODUCTID =                                  (0x1D),  /* Kronos Elektron/Optikos */\r\n};\r\n\r\ntypedef enum _EBlueLUTType\r\n{\r\n\tBLUE_MAIN_LUT_B_Pb =\t0,\r\n\tBLUE_MAIN_LUT_G_Y =\t\t1,\r\n\tBLUE_MAIN_LUT_R_Pr =\t2,\r\n\tBLUE_AUX_LUT_B_Pb =\t\t3,\r\n\tBLUE_AUX_LUT_G_Y =\t\t4,\r\n\tBLUE_AUX_LUT_R_Pr =\t\t5,\r\n}EBlueLUTType;\r\n\r\ntypedef enum _EBlueConnectorIdentifier\r\n{\r\n\tBLUE_CONNECTOR_INVALID =\t\t-1,\r\n\r\n\tBLUE_CONNECTOR_BNC_A =\t\t\t0,\r\n\tBLUE_CONNECTOR_BNC_B =\t\t\t1,\r\n\tBLUE_CONNECTOR_BNC_C =\t\t\t2,\r\n\tBLUE_CONNECTOR_BNC_D =\t\t\t3,\r\n\tBLUE_CONNECTOR_BNC_E =\t\t\t4,\r\n\tBLUE_CONNECTOR_BNC_F =\t\t\t5,\r\n\tBLUE_CONNECTOR_GENLOCK =\t\t6,\r\n\r\n    BLUE_CONNECTOR_REF_IN =         BLUE_CONNECTOR_GENLOCK,\r\n    BLUE_CONNECTOR_REF_OUT =        7,\r\n    BLUE_CONNECTOR_INTERLOCK_IN =   8,\r\n    BLUE_CONNECTOR_INTERLOCK_OUT =  9,\r\n\r\n\tBLUE_CONNECTOR_ANALOG_VIDEO_1 =\t100,\r\n\tBLUE_CONNECTOR_ANALOG_VIDEO_2 =\t101,\r\n\tBLUE_CONNECTOR_ANALOG_VIDEO_3 =\t102,\r\n\tBLUE_CONNECTOR_ANALOG_VIDEO_4 =\t103,\r\n\tBLUE_CONNECTOR_ANALOG_VIDEO_5 =\t104,\r\n\tBLUE_CONNECTOR_ANALOG_VIDEO_6 =\t105,\r\n\r\n\tBLUE_CONNECTOR_DVID_1 =\t\t\t200,\r\n\tBLUE_CONNECTOR_DVID_2 =\t\t\t201,\r\n\tBLUE_CONNECTOR_DVID_3 =\t\t\t202,\r\n\tBLUE_CONNECTOR_DVID_4 =\t\t\t203,\r\n\tBLUE_CONNECTOR_DVID_5 =\t\t\t204,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_A =   BLUE_CONNECTOR_DVID_1,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_B =   BLUE_CONNECTOR_DVID_2,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_C\t=\t205,\r\n\tBLUE_CONNECTOR_SDI_OUTPUT_D =\t206,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_E\t=\t207,\r\n\tBLUE_CONNECTOR_SDI_OUTPUT_F =\t208,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_G\t=\t209,\r\n\tBLUE_CONNECTOR_SDI_OUTPUT_H =\t210,\r\n\r\n    BLUE_CONNECTOR_SDI_OUTPUT_1 =   BLUE_CONNECTOR_SDI_OUTPUT_A,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_2 =   BLUE_CONNECTOR_SDI_OUTPUT_B,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_3 =   BLUE_CONNECTOR_SDI_OUTPUT_C,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_4 =   BLUE_CONNECTOR_SDI_OUTPUT_D,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_5 =   BLUE_CONNECTOR_SDI_OUTPUT_E,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_6 =   BLUE_CONNECTOR_SDI_OUTPUT_F,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_7 =   BLUE_CONNECTOR_SDI_OUTPUT_G,\r\n    BLUE_CONNECTOR_SDI_OUTPUT_8 =   BLUE_CONNECTOR_SDI_OUTPUT_H,\r\n\r\n\tBLUE_CONNECTOR_AES =\t\t\t300,\r\n\tBLUE_CONNECTOR_ANALOG_AUDIO_1 =\t301,\r\n\tBLUE_CONNECTOR_ANALOG_AUDIO_2 =\t302,\r\n    BLUE_CONNECTOR_DVID_6 =\t\t\t303,\r\n\tBLUE_CONNECTOR_DVID_7 =\t\t\t304,\r\n\r\n    BLUE_CONNECTOR_SDI_INPUT_A =    BLUE_CONNECTOR_DVID_3,\r\n    BLUE_CONNECTOR_SDI_INPUT_B =    BLUE_CONNECTOR_DVID_4,\r\n    BLUE_CONNECTOR_SDI_INPUT_C =    BLUE_CONNECTOR_DVID_6,\r\n    BLUE_CONNECTOR_SDI_INPUT_D =    BLUE_CONNECTOR_DVID_7,\r\n    BLUE_CONNECTOR_SDI_INPUT_E =    305,\r\n    BLUE_CONNECTOR_SDI_INPUT_F =    306,\r\n    BLUE_CONNECTOR_SDI_INPUT_G =    307,\r\n    BLUE_CONNECTOR_SDI_INPUT_H =    308,\r\n\r\n    BLUE_CONNECTOR_SDI_INPUT_1 =    BLUE_CONNECTOR_SDI_INPUT_A,\r\n    BLUE_CONNECTOR_SDI_INPUT_2 =    BLUE_CONNECTOR_SDI_INPUT_B,\r\n    BLUE_CONNECTOR_SDI_INPUT_3 =    BLUE_CONNECTOR_SDI_INPUT_C,\r\n    BLUE_CONNECTOR_SDI_INPUT_4 =    BLUE_CONNECTOR_SDI_INPUT_D,\r\n    BLUE_CONNECTOR_SDI_INPUT_5 =    BLUE_CONNECTOR_SDI_INPUT_E,\r\n    BLUE_CONNECTOR_SDI_INPUT_6 =    BLUE_CONNECTOR_SDI_INPUT_F,\r\n    BLUE_CONNECTOR_SDI_INPUT_7 =    BLUE_CONNECTOR_SDI_INPUT_G,\r\n    BLUE_CONNECTOR_SDI_INPUT_8 =    BLUE_CONNECTOR_SDI_INPUT_H,\r\n\r\n}EBlueConnectorIdentifier;\r\n\r\ntypedef enum _EBlueConnectorSignalDirection\r\n{\r\n\tBLUE_CONNECTOR_SIGNAL_INVALID = -1,\r\n\tBLUE_CONNECTOR_SIGNAL_INPUT = 0,\r\n\tBLUE_CONNECTOR_SIGNAL_OUTPUT = 1,\r\n}EBlueConnectorSignalDirection;\r\n\r\ntypedef enum _EBlueConnectorProperty\r\n{\r\n\tBLUE_INVALID_CONNECTOR_PROPERTY =\t\t\t\t-1,\r\n\r\n\t/* signal property */\r\n\tBLUE_CONNECTOR_PROP_INPUT_SIGNAL =\t\t\t\t0,\r\n\tBLUE_CONNECTOR_PROP_OUTPUT_SIGNAL =\t\t\t\t1,\r\n\r\n    /* Video output */\r\n\tBLUE_CONNECTOR_PROP_SDI =\t\t\t\t\t\t0,\r\n\tBLUE_CONNECTOR_PROP_YUV_Y =\t\t\t\t\t\t1,\r\n\tBLUE_CONNECTOR_PROP_YUV_U =\t\t\t\t\t\t2,\r\n\tBLUE_CONNECTOR_PROP_YUV_V =\t\t\t\t\t\t3,\r\n\tBLUE_CONNECTOR_PROP_RGB_R =\t\t\t\t\t\t4,\r\n\tBLUE_CONNECTOR_PROP_RGB_G =\t\t\t\t\t\t5,\r\n\tBLUE_CONNECTOR_PROP_RGB_B =\t\t\t\t\t\t6,\r\n\tBLUE_CONNECTOR_PROP_CVBS =\t\t\t\t\t\t7,\r\n\tBLUE_CONNECTOR_PROP_SVIDEO_Y =\t\t\t\t\t8,\r\n\tBLUE_CONNECTOR_PROP_SVIDEO_C =\t\t\t\t\t9,\r\n\r\n    /* Audio output */\r\n\tBLUE_CONNECTOR_PROP_AUDIO_AES =\t\t\t\t\t0x2000,\r\n\tBLUE_CONNECTOR_PROP_AUDIO_EMBEDDED =\t\t\t0x2001,\r\n\tBLUE_CONNECTOR_PROP_AUDIO_ANALOG =\t\t\t\t0x2002,\r\n\r\n\r\n\tBLUE_CONNECTOR_PROP_SINGLE_LINK =\t\t\t\t0x3000,\r\n\tBLUE_CONNECTOR_PROP_DUALLINK_LINK_1 =\t\t\t0x3001,\r\n\tBLUE_CONNECTOR_PROP_DUALLINK_LINK_2 =\t\t\t0x3002,\r\n\tBLUE_CONNECTOR_PROP_DUALLINK_LINK =\t\t\t\t0x3003,\r\n\r\n\tBLUE_CONNECTOR_PROP_STEREO_MODE_SIDE_BY_SIDE =\t0x3004,\r\n\tBLUE_CONNECTOR_PROP_STEREO_MODE_TOP_DOWN =\t\t0x3005,\r\n\tBLUE_CONNECTOR_PROP_STEREO_MODE_LINE_BY_LINE =\t0x3006,\r\n\r\n}EBlueConnectorProperty;\r\n\r\ntypedef enum\r\n{\r\n\tBLUE_AUDIO_AES =\t\t0,\t\t\t\t\t/** 8 channels of AES */\r\n\tBLUE_AUDIO_ANALOG =\t\t1,\t\t\t\t\t/** 2 channels of analog audio */\r\n\tBLUE_AUDIO_SDIA =\t\t2,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_EMBEDDED =\tBLUE_AUDIO_SDIA,\t/** use BLUE_AUDIO_EMBEDDED for any embedded audio stream; the stream is associated with the SDK object (BlueVelvet4/BlueVelvetC) */\r\n\tBLUE_AUDIO_SDIB =\t\t3,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_AES_PAIR0 =\t4,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_AES_PAIR1 =\t5,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_AES_PAIR2 =\t6,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_AES_PAIR3 =\t7,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_SDIC =\t\t8,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_SDID =\t\t9,\t\t\t\t\t/** deprecated, do not use */\r\n    BLUE_AUDIO_SDIE =\t\t10,\t\t\t\t\t/** deprecated, do not use */\r\n    BLUE_AUDIO_SDIF =\t\t11,\t\t\t\t\t/** deprecated, do not use */\r\n    BLUE_AUDIO_SDIG =\t\t12,\t\t\t\t\t/** deprecated, do not use */\r\n    BLUE_AUDIO_SDIH =\t\t13,\t\t\t\t\t/** deprecated, do not use */\r\n\tBLUE_AUDIO_INVALID =\t100\r\n} Blue_Audio_Connector_Type;\r\n\r\ntypedef enum _EAudioRate\r\n{\r\n\tAUDIO_SAMPLE_RATE_48K =\t\t48000,\r\n\tAUDIO_SAMPLE_RATE_96K =\t\t96000,\r\n\tAUDIO_SAMPLE_RATE_UNKNOWN =\t-1\r\n} EAudioRate;\r\n\r\ntypedef enum _EDMADataType\r\n{\r\n    BLUE_DATA_FRAME =               0,\r\n    BLUE_DATA_IMAGE =               BLUE_DATA_FRAME,\r\n    BLUE_DATA_FIELD1 =              1,\r\n    BLUE_DATA_FIELD2 =              2,              /** deprecated, do not use */\r\n    BLUE_DATA_VBI =                 3,\r\n    BLUE_DATA_HANC =                4,\r\n    BLUE_DATA_AUDIO_IN =            5,              /** deprecated, do not use */\r\n    BLUE_DATA_AUDIO_OUT =           6,              /** deprecated, do not use */\r\n    BLUE_DATA_FRAME_RDOM =          7,              /** deprecated, do not use */\r\n    BLUE_DATA_FRAME_STEREO_LEFT =   BLUE_DATA_FRAME,\r\n    BLUE_DATA_FRAME_STEREO_RIGHT =  8,\r\n    BLUE_DMADATA_INVALID =          9,\r\n\r\n    // preferred aliases and new types\r\n    BLUE_DMA_DATA_TYPE_IMAGE =       BLUE_DATA_FRAME,\r\n    BLUE_DMA_DATA_TYPE_IMAGE_FRAME = BLUE_DMA_DATA_TYPE_IMAGE,\r\n    BLUE_DMA_DATA_TYPE_IMAGE_FIELD = BLUE_DATA_FIELD1,\r\n    BLUE_DMA_DATA_TYPE_VANC =        BLUE_DATA_VBI,\r\n    BLUE_DMA_DATA_TYPE_VANC_A =      BLUE_DMA_DATA_TYPE_VANC,\r\n    BLUE_DMA_DATA_TYPE_VANC_B =      10,\r\n    BLUE_DMA_DATA_TYPE_HANC_AUDIO =  BLUE_DATA_HANC,\r\n    BLUE_DMA_DATA_TYPE_HANC_RAW_A =  11,\r\n    BLUE_DMA_DATA_TYPE_HANC_RAW_B =  12,\r\n}EDMADataType;\r\n\r\ntypedef enum _EDMADirection\r\n{\r\n\tDMA_WRITE =\t\t0,\r\n\tDMA_READ =\t\t1,\r\n\tDMA_INVALID =\t2\r\n}EDMADirection;\r\n\r\ntypedef enum _EBlueVideoAuxInfoType\r\n{\r\n\tBLUE_VIDEO_AUX_MEMFMT_CHANGE = 1,\r\n\tBLUE_VIDEO_AUX_UPDATE_LTC = 2,\r\n\tBLUE_VIDEO_AUX_UPDATE_GPIO = 4,\r\n\tBLUE_VIDEO_AUX_VIDFMT_CHANGE = 8,\r\n}EBlueVideoAuxInfoType;\r\n\r\ntypedef enum _MatrixColType\r\n{\r\n\tCOL_BLUE_PB = 0,\r\n\tCOL_RED_PR = 1,\r\n\tCOL_GREEN_Y = 2,\r\n\tCOL_KEY = 3\r\n}MatrixColType;\r\n\r\n/*\tThis enumerator can be used to set the image orientation of the frame. */\r\ntypedef enum _EImageOrientation\r\n{\r\n\tImageOrientation_Normal = 0,\t/* in this configuration frame is top to bottom and left to right */\r\n\tImageOrientation_VerticalFlip = 1,\t/* in this configuration frame is bottom to top and left to right */\r\n\tImageOrientation_Invalid = 2,\r\n}EImageOrientation;\r\n\r\n/* This enumerator defines the reference signal source that can be used with bluefish cards */\r\ntypedef enum _EBlueGenlockSource\r\n{\r\n\tBlueGenlockBNC =    0x00000000,     /** Genlock is used as reference signal source */\r\n\tBlueSDIBNC =        0x00010000,\t    /** SDI input B is used as reference signal source */\r\n\tBlueSDI_B_BNC =     BlueSDIBNC,\r\n\tBlueSDI_A_BNC =     0x00020000,\t    /** SDI input A is used as reference signal source */\r\n\tBlueAnalog_BNC =    0x00040000,\t    /** deprecated, not supported */\r\n\tBlueSoftware =      0x00080000,\r\n\tBlueFreeRunning =   BlueSoftware,   /** free running, but phase can be software controlled */\r\n\tBlueGenlockAux =    0x00100000,     /** auxiliary genlock connector on Epoch Neutron cards */\r\n\tBlueInterlock =     0x00200000,     /** interlock connector on Epoch Neutron and Kronos cards */\r\n\r\n    /* aliases and new definitions */\r\n    BlueRefSrc_FreeRunning = BlueFreeRunning,\r\n    BlueRefSrc_RefIn =       BlueGenlockBNC,    /* genlock signal on ref in BNC connector      (Epoch/Kronos) */\r\n    BlueRefSrc_RefInAux =    BlueGenlockAux,    /* genlock signal on ref in AUX BNC connector  (Epoch Neutron only) */\r\n    BlueRefSrc_InterlockIn = BlueInterlock,     /* interlock signal on internal MMCX connector (Epoch/Kronos) */\r\n    BlueRefSrc_SdiInput1 =   BlueSDI_A_BNC,\r\n    BlueRefSrc_SdiInput2 =   BlueSDI_B_BNC,\r\n    BlueRefSrc_SdiInput3 =   0x01000000,\r\n    BlueRefSrc_SdiInput4 =   0x01100000,\r\n    BlueRefSrc_SdiInput5 =   0x01200000,\r\n    BlueRefSrc_SdiInput6 =   0x01300000,\r\n    BlueRefSrc_SdiInput7 =   0x01400000,\r\n    BlueRefSrc_SdiInput8 =   0x01500000,\r\n}EBlueGenlockSource;\r\n\r\ntypedef enum _EBlueVideoChannel\r\n{\r\n\tBLUE_VIDEOCHANNEL_A = 0,\r\n\tBLUE_VIDEOCHANNEL_B = 1,\r\n\tBLUE_VIDEOCHANNEL_C = 2,\r\n\tBLUE_VIDEOCHANNEL_D = 3,\r\n\tBLUE_VIDEOCHANNEL_E = 4,\r\n\tBLUE_VIDEOCHANNEL_F = 5,\r\n\tBLUE_VIDEOCHANNEL_G = 6,\r\n\tBLUE_VIDEOCHANNEL_H = 7,\r\n\tBLUE_VIDEOCHANNEL_I = 8,\r\n\tBLUE_VIDEOCHANNEL_J = 9,\r\n\tBLUE_VIDEOCHANNEL_K = 10,\r\n\tBLUE_VIDEOCHANNEL_L = 11,\r\n\tBLUE_VIDEOCHANNEL_M = 12,\r\n\tBLUE_VIDEOCHANNEL_N = 13,\r\n\tBLUE_VIDEOCHANNEL_O = 14,\r\n\tBLUE_VIDEOCHANNEL_P = 15,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_A = BLUE_VIDEOCHANNEL_A,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_B = BLUE_VIDEOCHANNEL_B,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_A = BLUE_VIDEOCHANNEL_C,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_B = BLUE_VIDEOCHANNEL_D,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_C = BLUE_VIDEOCHANNEL_E,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_D = BLUE_VIDEOCHANNEL_F,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_C = BLUE_VIDEOCHANNEL_G,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_D = BLUE_VIDEOCHANNEL_H,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_E = BLUE_VIDEOCHANNEL_I,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_F = BLUE_VIDEOCHANNEL_J,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_G = BLUE_VIDEOCHANNEL_K,\r\n\tBLUE_VIDEO_OUTPUT_CHANNEL_H = BLUE_VIDEOCHANNEL_L,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_E = BLUE_VIDEOCHANNEL_M,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_F = BLUE_VIDEOCHANNEL_N,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_G = BLUE_VIDEOCHANNEL_O,\r\n\tBLUE_VIDEO_INPUT_CHANNEL_H = BLUE_VIDEOCHANNEL_P,\r\n\r\n    BLUE_VIDEO_INPUT_CHANNEL_1 = BLUE_VIDEO_INPUT_CHANNEL_A,\r\n    BLUE_VIDEO_INPUT_CHANNEL_2 = BLUE_VIDEO_INPUT_CHANNEL_B,\r\n    BLUE_VIDEO_INPUT_CHANNEL_3 = BLUE_VIDEO_INPUT_CHANNEL_C,\r\n    BLUE_VIDEO_INPUT_CHANNEL_4 = BLUE_VIDEO_INPUT_CHANNEL_D,\r\n    BLUE_VIDEO_INPUT_CHANNEL_5 = BLUE_VIDEO_INPUT_CHANNEL_E,\r\n    BLUE_VIDEO_INPUT_CHANNEL_6 = BLUE_VIDEO_INPUT_CHANNEL_F,\r\n    BLUE_VIDEO_INPUT_CHANNEL_7 = BLUE_VIDEO_INPUT_CHANNEL_G,\r\n    BLUE_VIDEO_INPUT_CHANNEL_8 = BLUE_VIDEO_INPUT_CHANNEL_H,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_1 = BLUE_VIDEO_OUTPUT_CHANNEL_A,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_2 = BLUE_VIDEO_OUTPUT_CHANNEL_B,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_3 = BLUE_VIDEO_OUTPUT_CHANNEL_C,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_4 = BLUE_VIDEO_OUTPUT_CHANNEL_D,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_5 = BLUE_VIDEO_OUTPUT_CHANNEL_E,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_6 = BLUE_VIDEO_OUTPUT_CHANNEL_F,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_7 = BLUE_VIDEO_OUTPUT_CHANNEL_G,\r\n    BLUE_VIDEO_OUTPUT_CHANNEL_8 = BLUE_VIDEO_OUTPUT_CHANNEL_H,\r\n\r\n\tBLUE_VIDEOCHANNEL_INVALID = 30\r\n}EBlueVideoChannel;\r\n\r\ntypedef enum _EEpochRoutingElements\r\n{\r\n\tEPOCH_SRC_DEST_SCALER_0 =               0x1,\r\n\tEPOCH_SRC_DEST_SCALER_1 =               0x2,\r\n\tEPOCH_SRC_DEST_SCALER_2 =               0x3,\r\n\tEPOCH_SRC_DEST_SCALER_3 =               0x4,\r\n\r\n\tEPOCH_SRC_SDI_INPUT_A =                 0x5,\r\n\tEPOCH_SRC_SDI_INPUT_B =                 0x6,\r\n\tEPOCH_SRC_SDI_INPUT_C =                 0x7,\r\n\tEPOCH_SRC_SDI_INPUT_D =                 0x8,\r\n\r\n\tEPOCH_DEST_SDI_OUTPUT_A =               0x9,\r\n\tEPOCH_DEST_SDI_OUTPUT_B =               0xA,\r\n\tEPOCH_DEST_SDI_OUTPUT_C =               0xB,\r\n\tEPOCH_DEST_SDI_OUTPUT_D =               0xC,\r\n\r\n\tEPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA =    0xD,\r\n\tEPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB =    0xE,\r\n\r\n\tEPOCH_DEST_INPUT_MEM_INTERFACE_CHA =    0xF,\r\n\tEPOCH_DEST_INPUT_MEM_INTERFACE_CHB =    0x10,\r\n\r\n\tEPOCH_DEST_AES_ANALOG_AUDIO_OUTPUT =    0x11,\r\n\r\n\tEPOCH_SRC_AV_SIGNAL_GEN =               0x12,\r\n\tEPOCH_SRC_DEST_VPIO_SCALER_0 =          0x13,\r\n\tEPOCH_SRC_DEST_VPIO_SCALER_1 =          0x14,\r\n\r\n\tEPOCH_DEST_VARIVUE_HDMI =               0x15,\r\n\r\n\tEPOCH_DEST_INPUT_MEM_INTERFACE_CHC =    0x16,\r\n\tEPOCH_DEST_INPUT_MEM_INTERFACE_CHD =    0x17,\r\n\r\n\tEPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC =    0x18,\r\n\tEPOCH_SRC_OUTPUT_MEM_INTERFACE_CHD =    0x19,\r\n\r\n\tEPOCH_SRC_SDI_INPUT_A_3GB_LINK_B =      0x1A,\r\n\tEPOCH_SRC_SDI_INPUT_B_3GB_LINK_B =      0x1B,\r\n\tEPOCH_SRC_SDI_INPUT_C_3GB_LINK_B =      0x1C,\r\n\tEPOCH_SRC_SDI_INPUT_D_3GB_LINK_B =      0x1D,\r\n\r\n\tEPOCH_DEST_SDI_OUTPUT_A_3GB_LINK_B =    0x1E,\r\n\tEPOCH_DEST_SDI_OUTPUT_B_3GB_LINK_B =    0x1F,\r\n\tEPOCH_DEST_SDI_OUTPUT_C_3GB_LINK_B =    0x20,\r\n\tEPOCH_DEST_SDI_OUTPUT_D_3GB_LINK_B =    0x21,\r\n\r\n\tEPOCH_DEST_HDMI_OUTPUT =                0x22,\r\n\tEPOCH_DEST_HDMI_OUTPUT_LINK_A =         EPOCH_DEST_HDMI_OUTPUT,\r\n\tEPOCH_DEST_HDMI_OUTPUT_LINK_B =         0x23,\r\n\r\n    EPOCH_SRC_SDI_INPUT_E =                 0x24,\r\n    EPOCH_SRC_SDI_INPUT_F =                 0x25,\r\n    EPOCH_SRC_SDI_INPUT_G =                 0x26,\r\n    EPOCH_SRC_SDI_INPUT_H =                 0x27,\r\n    \r\n    EPOCH_SRC_SDI_INPUT_E_3GB_LINK_B =      0x28,\r\n\tEPOCH_SRC_SDI_INPUT_F_3GB_LINK_B =      0x29,\r\n\tEPOCH_SRC_SDI_INPUT_G_3GB_LINK_B =      0x2A,\r\n\tEPOCH_SRC_SDI_INPUT_H_3GB_LINK_B =      0x2B,\r\n\r\n    EPOCH_DEST_SDI_OUTPUT_E =               0x2C,\r\n\tEPOCH_DEST_SDI_OUTPUT_F =               0x2D,\r\n\tEPOCH_DEST_SDI_OUTPUT_G =               0x2E,\r\n\tEPOCH_DEST_SDI_OUTPUT_H =               0x2F,\r\n\r\n    EPOCH_DEST_SDI_OUTPUT_E_3GB_LINK_B =    0x30,\r\n\tEPOCH_DEST_SDI_OUTPUT_F_3GB_LINK_B =    0x31,\r\n\tEPOCH_DEST_SDI_OUTPUT_G_3GB_LINK_B =    0x32,\r\n\tEPOCH_DEST_SDI_OUTPUT_H_3GB_LINK_B =    0x33,\r\n\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHE =    0x34,\r\n\tEPOCH_SRC_OUTPUT_MEM_INTERFACE_CHF =    0x35,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHG =    0x36,\r\n\tEPOCH_SRC_OUTPUT_MEM_INTERFACE_CHH =    0x37,\r\n\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CHE =    0x38,\r\n\tEPOCH_DEST_INPUT_MEM_INTERFACE_CHF =    0x39,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CHG =    0x3C,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CHH =    0x3D,\r\n\r\n    /* aliases */\r\n    EPOCH_SRC_SDI_INPUT_1 =                 EPOCH_SRC_SDI_INPUT_A,\r\n    EPOCH_SRC_SDI_INPUT_2 =                 EPOCH_SRC_SDI_INPUT_B,\r\n    EPOCH_SRC_SDI_INPUT_3 =                 EPOCH_SRC_SDI_INPUT_C,\r\n    EPOCH_SRC_SDI_INPUT_4 =                 EPOCH_SRC_SDI_INPUT_D,\r\n    EPOCH_SRC_SDI_INPUT_5 =                 EPOCH_SRC_SDI_INPUT_E,\r\n    EPOCH_SRC_SDI_INPUT_6 =                 EPOCH_SRC_SDI_INPUT_F,\r\n    EPOCH_SRC_SDI_INPUT_7 =                 EPOCH_SRC_SDI_INPUT_G,\r\n    EPOCH_SRC_SDI_INPUT_8 =                 EPOCH_SRC_SDI_INPUT_H,\r\n    EPOCH_SRC_SDI_INPUT_A_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_A,\r\n\tEPOCH_SRC_SDI_INPUT_B_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_B,\r\n\tEPOCH_SRC_SDI_INPUT_C_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_C,\r\n\tEPOCH_SRC_SDI_INPUT_D_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_D,\r\n    EPOCH_SRC_SDI_INPUT_E_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_E,\r\n\tEPOCH_SRC_SDI_INPUT_F_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_F,\r\n\tEPOCH_SRC_SDI_INPUT_G_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_G,\r\n\tEPOCH_SRC_SDI_INPUT_H_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_H,\r\n    EPOCH_SRC_SDI_INPUT_1_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_A,\r\n\tEPOCH_SRC_SDI_INPUT_2_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_B,\r\n\tEPOCH_SRC_SDI_INPUT_3_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_C,\r\n\tEPOCH_SRC_SDI_INPUT_4_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_D,\r\n    EPOCH_SRC_SDI_INPUT_5_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_E,\r\n\tEPOCH_SRC_SDI_INPUT_6_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_F,\r\n\tEPOCH_SRC_SDI_INPUT_7_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_G,\r\n\tEPOCH_SRC_SDI_INPUT_8_3GB_LINK_A =      EPOCH_SRC_SDI_INPUT_H,\r\n    EPOCH_SRC_SDI_INPUT_1_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_A_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_2_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_B_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_3_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_C_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_4_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_D_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_5_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_E_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_6_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_F_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_7_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_G_3GB_LINK_B,\r\n    EPOCH_SRC_SDI_INPUT_8_3GB_LINK_B =      EPOCH_SRC_SDI_INPUT_H_3GB_LINK_B,\r\n    \r\n    EPOCH_DEST_SDI_OUTPUT_1 =               EPOCH_DEST_SDI_OUTPUT_A,\r\n    EPOCH_DEST_SDI_OUTPUT_2 =               EPOCH_DEST_SDI_OUTPUT_B,\r\n    EPOCH_DEST_SDI_OUTPUT_3 =               EPOCH_DEST_SDI_OUTPUT_C,\r\n    EPOCH_DEST_SDI_OUTPUT_4 =               EPOCH_DEST_SDI_OUTPUT_D,\r\n    EPOCH_DEST_SDI_OUTPUT_5 =               EPOCH_DEST_SDI_OUTPUT_E,\r\n    EPOCH_DEST_SDI_OUTPUT_6 =               EPOCH_DEST_SDI_OUTPUT_F,\r\n    EPOCH_DEST_SDI_OUTPUT_7 =               EPOCH_DEST_SDI_OUTPUT_G,\r\n    EPOCH_DEST_SDI_OUTPUT_8 =               EPOCH_DEST_SDI_OUTPUT_H,\r\n    EPOCH_DEST_SDI_OUTPUT_A_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_A,\r\n\tEPOCH_DEST_SDI_OUTPUT_B_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_C_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_C,\r\n\tEPOCH_DEST_SDI_OUTPUT_D_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_D,\r\n    EPOCH_DEST_SDI_OUTPUT_E_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_E,\r\n\tEPOCH_DEST_SDI_OUTPUT_F_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_F,\r\n\tEPOCH_DEST_SDI_OUTPUT_G_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_G,\r\n\tEPOCH_DEST_SDI_OUTPUT_H_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_H,\r\n    EPOCH_DEST_SDI_OUTPUT_1_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_A,\r\n\tEPOCH_DEST_SDI_OUTPUT_2_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_3_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_C,\r\n\tEPOCH_DEST_SDI_OUTPUT_4_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_D,\r\n    EPOCH_DEST_SDI_OUTPUT_5_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_E,\r\n\tEPOCH_DEST_SDI_OUTPUT_6_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_F,\r\n\tEPOCH_DEST_SDI_OUTPUT_7_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_G,\r\n\tEPOCH_DEST_SDI_OUTPUT_8_3GB_LINK_A =    EPOCH_DEST_SDI_OUTPUT_H,\r\n    EPOCH_DEST_SDI_OUTPUT_1_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_A_3GB_LINK_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_2_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_B_3GB_LINK_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_3_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_C_3GB_LINK_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_4_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_D_3GB_LINK_B,\r\n    EPOCH_DEST_SDI_OUTPUT_5_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_E_3GB_LINK_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_6_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_F_3GB_LINK_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_7_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_G_3GB_LINK_B,\r\n\tEPOCH_DEST_SDI_OUTPUT_8_3GB_LINK_B =    EPOCH_DEST_SDI_OUTPUT_H_3GB_LINK_B,\r\n    \r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH1 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHA,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH2 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHB,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH3 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHC,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH4 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHD,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH5 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHE,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH6 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHF,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH7 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHG,\r\n    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CH8 =    EPOCH_SRC_OUTPUT_MEM_INTERFACE_CHH,\r\n\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH1 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHA,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH2 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHB,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH3 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHC,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH4 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHD,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH5 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHE,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH6 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHF,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH7 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHG,\r\n    EPOCH_DEST_INPUT_MEM_INTERFACE_CH8 =    EPOCH_DEST_INPUT_MEM_INTERFACE_CHH,\r\n\r\n}EEpochRoutingElements;\r\n\r\ntypedef enum _BlueAudioChannelDesc\r\n{\r\n\tMONO_FLAG\t\t= 0xC0000000,\r\n\tMONO_CHANNEL_1\t= 0x00000001,\r\n\tMONO_CHANNEL_2\t= 0x00000002,\r\n\tMONO_CHANNEL_3\t= 0x00000004,\r\n\tMONO_CHANNEL_4\t= 0x00000008,\r\n\tMONO_CHANNEL_5\t= 0x00000010,\r\n\tMONO_CHANNEL_6\t= 0x00000020,\r\n\tMONO_CHANNEL_7\t= 0x00000040,\r\n\tMONO_CHANNEL_8\t= 0x00000080,\r\n\tMONO_CHANNEL_9\t= 0x00000100,   /* to be used by analog audio output channels */\r\n\tMONO_CHANNEL_10\t= 0x00000200,   /* to be used by analog audio output channels */\r\n\tMONO_CHANNEL_11\t= 0x00000400,   /* actual channel 9  */\r\n\tMONO_CHANNEL_12\t= 0x00000800,   /* actual channel 10 */\r\n\tMONO_CHANNEL_13\t= 0x00001000,   /* actual channel 11 */\r\n\tMONO_CHANNEL_14\t= 0x00002000,   /* actual channel 12 */\r\n\tMONO_CHANNEL_15\t= 0x00004000,   /* actual channel 13 */\r\n\tMONO_CHANNEL_16\t= 0x00008000,   /* actual channel 14 */\r\n\tMONO_CHANNEL_17\t= 0x00010000,   /* actual channel 15 */\r\n\tMONO_CHANNEL_18\t= 0x00020000    /* actual channel 16 */\r\n}BlueAudioChannelDesc;\r\n\r\n/* Use this enumerator to define the color space of the video signal on the SDI cable */\r\ntypedef enum _EConnectorSignalColorSpace\r\n{\r\n\tRGB_ON_CONNECTOR = 0x00400000,\t/*\tUse this enumerator if the colorspace of video data on the SDI cable is RGB\r\n\t\t\t\t\t\t\t\t\tWhen using dual link capture/playback, user can choose the color space of the data.\r\n\t\t\t\t\t\t\t\t\tIn single link SDI the color space of the signal is always YUV */\r\n\tYUV_ON_CONNECTOR = 0\t\t\t/*\tUse this enumerator if color space of video data on the SDI cable is RGB. */\r\n}EConnectorSignalColorSpace;\r\n\r\n/* Use this enumerator to define the data range of the RGB video frame data. */\r\ntypedef enum _ERGBDataRange\r\n{\r\n\tCGR_RANGE = 0,\t/*\tIn this mode RGB data expected by the user (capture) or provided by the user(playback) is\r\n\t\t\t\t\tin the range of 0-255(8 bit) or 0-1023(10 bit0).\r\n\t\t\t\t\tdriver uses this information to choose the appropriate YUV conversion matrices. */\r\n\tSMPTE_RANGE = 1  /*\tIn this mode RGB data expected by the user (capture) or provided by the user(playback) is\r\n\t\t\t\t\t in the range of 16-235(8 bit) or 64-940(10 bit0).\r\n\t\t\t\t\t driver uses this information to choose the appropriate YUV conversion matrices. */\r\n}ERGBDataRange;\r\n\r\ntypedef enum _EPreDefinedColorSpaceMatrix\r\n{\r\n\tUNITY_MATRIX = 0,\r\n\tMATRIX_709_CGR = 1,\r\n\tMATRIX_RGB_TO_YUV_709_CGR = MATRIX_709_CGR,\r\n\tMATRIX_709 = 2,\r\n\tMATRIX_RGB_TO_YUV_709 = MATRIX_709,\r\n\tRGB_FULL_RGB_SMPTE = 3,\r\n\tMATRIX_601_CGR = 4,\r\n\tMATRIX_RGB_TO_YUV_601_CGR = MATRIX_601_CGR,\r\n\tMATRIX_601 = 5,\r\n\tMATRIX_RGB_TO_YUV_601 = MATRIX_601,\r\n\tMATRIX_VUYA = 6,\r\n\tUNITY_MATRIX_INPUT = 7,\r\n\tMATRIX_YUV_TO_RGB_709_CGR = 8,\r\n\tMATRIX_YUV_TO_RGB_709 = 9,\r\n\tRGB_SMPTE_RGB_FULL = 10,\r\n\tMATRIX_YUV_TO_RGB_601_CGR = 11,\r\n\tMATRIX_YUV_TO_RGB_601 = 12,\r\n\tMATRIX_USER_DEFINED = 13,\r\n} EPreDefinedColorSpaceMatrix;\r\n\r\n/* Use this enumerator for controlling the dual link functionality. */\r\ntypedef enum _EDualLinkSignalFormatType\r\n{\r\n\tSignal_FormatType_4224 = 0,\t\t/* sets the card to work in 4:2:2:4 mode */\r\n\tSignal_FormatType_4444 = 1,\t\t/* sets the card to work in 4:4:4 10 bit dual link mode */\r\n\tSignal_FormatType_444_10BitSDI = Signal_FormatType_4444,\r\n\tSignal_FormatType_444_12BitSDI = 0x4,\t/* sets the card to work in 4:4:4 12 bit dual link mode */\r\n\tSignal_FormatType_Independent_422 = 0x2,\r\n\tSignal_FormatType_Key_Key = 0x8000\t/* not used currently on epoch cards */\r\n\r\n}EDualLinkSignalFormatType;\r\n\r\nenum ECardOperatingMode\r\n{\r\n\tCardOperatingMode_SingleLink = 0x0,\r\n\tCardOperatingMode_Independent_422 = CardOperatingMode_SingleLink,\r\n\tCardOperatingMode_DualLink = 0x1,\r\n\tCardOperatingMode_StereoScopic_422 = 0x3,\r\n\tCardOperatingMode_Dependent_422 = CardOperatingMode_StereoScopic_422,\t/* not used currently on epoch cards */\r\n\tCardOperatingMode_DualLink_Dual3G = 0x4,\r\n};\r\n\r\ntypedef enum _blue_output_hanc_ioctl_enum\r\n{\r\n\tblue_get_output_hanc_buffer = 0,\r\n\tblue_put_output_hanc_buffer = 1,\r\n\tblue_get_valid_silent_hanc_data_status = 3,\r\n\tblue_set_valid_silent_hanc_data_status = 4,\r\n\tblue_start_output_fifo = 5,\r\n\tblue_stop_output_fifo = 6,\r\n\tblue_init_output_fifo = 7,\r\n\tblue_get_queues_info = 8,\r\n\tblue_get_output_fifo_info = blue_get_queues_info,\r\n\tblue_get_output_fifo_status = 9,\r\n\tblue_start_output_fifo_no_auto_turn_off = 10\t/* this is used when we don't really use the FIFO, but handle audio playback ourselves in DirectShow;\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t   need to make sure that our HANC output FIFO doesn't turn off audio as there are never any HANC frames to be played */\r\n}blue_output_hanc_ioctl_enum;\r\n\r\ntypedef enum _blue_input_hanc_ioctl_enum\r\n{\r\n\tblue_get_input_hanc_buffer = 0,\r\n\tblue_start_input_fifo = 3,\r\n\tblue_stop_input_fifo = 4,\r\n\tblue_init_input_fifo = 5,\r\n\tblue_playthru_input_fifo = 6,\r\n\tblue_release_input_hanc_buffer = 7,\r\n\tblue_map_input_hanc_buffer = 8,\r\n\tblue_unmap_input_hanc_buffer = 9,\r\n\tblue_get_info_input_hanc_fifo = 10,\r\n\tblue_get_input_rp188 = 11,\r\n\tblue_get_input_fifo_status = 12,\r\n}blue_input_hanc_ioctl_enum;\r\n\r\n#define HANC_PLAYBACK_INIT\t\t\t\t(0x00000001)\r\n#define HANC_PLAYBACK_START\t\t\t\t(0x00000002)\r\n#define HANC_PLAYBACK_STOP\t\t\t\t(0x00000004)\r\n\r\n#define HANC_CAPTURE_INIT\t\t\t\t(0x00000010)\r\n#define HANC_CAPTURE_START\t\t\t\t(0x00000020)\r\n#define HANC_CAPTURE_STOP\t\t\t\t(0x00000040)\r\n#define HANC_CAPTURE_PLAYTHRU\t\t\t(0x00000080)\r\n\r\ntypedef enum _EDMACardBufferType\r\n{\r\n\tBLUE_CARDBUFFER_IMAGE = 0,\r\n\tBLUE_CARDBUFFER_IMAGE_VBI_HANC = 1,\r\n\tBLUE_CARDBUFFER_IMAGE_VBI = 2,\r\n\tBLUE_CARDBUFFER_AUDIO_OUT = 3,\r\n\tBLUE_CARDBUFFER_AUDIO_IN = 4,\r\n\tBLUE_CARDBUFFER_HANC = 5,\r\n\tBLUE_CARDBUFFER_IMAGE_HANC = 6,\r\n}EDMACardBufferType;\r\n\r\nenum enum_blue_dvb_asi_packing_format\r\n{\r\n\tenum_blue_dvb_asi_packed_format = 1,\t/* In this packing method the asi packets are stored as 188 or 204 bytes */\r\n\tenum_blue_dvb_asi_packed_format_with_timestamp = 2,\t/* In this packing method the asi packets are stored as (8+188) or (8+204) bytes\r\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tThe timestamp is stored at the begininig of the packet, using 8 bytes */\r\n\tenum_blue_dvb_asi_256byte_container_format = 3,\r\n\tenum_blue_dvb_asi_256byte_container_format_with_timestamp = 4\r\n};\r\n\r\nenum enum_blue_dvb_asi_packet_size\r\n{\r\n\tenum_blue_dvb_asi_packet_size_188_bytes = 1,\r\n\tenum_blue_dvb_asi_packet_size_204_bytes = 2\r\n};\r\n\r\ntypedef enum _blue_blackgenerator_status\r\n{\r\n\tENUM_BLACKGENERATOR_OFF = 0,            /* producing normal video output */\r\n\tENUM_BLACKGENERATOR_ON = 1,             /* producing black video output  */\r\n\tENUM_BLACKGENERATOR_SDI_SYNC_OFF = 2    /* no valid SDI signal is coming out of our SDI output connector; only available in Epoch ASI firmware */\r\n}blue_blackgenerator_status;\r\n\r\ntypedef enum _EBlueExternalLtcSource\r\n{\r\n    EXT_LTC_SRC_BREAKOUT_HEADER = 0,    /* default; header on the PCB board/Shield (Epoch only) */\r\n    EXT_LTC_SRC_GENLOCK_BNC =     1,    /* Genlock input BNC connector (Epoch and Kronos) */\r\n    EXT_LTC_SRC_INTERLOCK =       2,    /* Interlock input MMCX connector (Kronos only) */\r\n    EXT_LTC_SRC_STEM_PORT =       3,    /* STEM port (Kronos only) */\r\n}EBlueExternalLtcSource;\r\n\r\n/**< use this enumerator for controlling emb audio output properties using the property EMBEDDED_AUDIO_OUTPUT. */\r\ntypedef enum _EBlueEmbAudioOutput\r\n{\r\n\tblue_emb_audio_enable =              0x01,  /**< Switches off/on the whole HANC output from connecotrs associated with the channel */\r\n\tblue_auto_aes_to_emb_audio_encoder = 0x02,  /**< control whether the auto aes to emb thread should be running or not */\r\n\tblue_emb_audio_group1_enable =       0x04,  /**< enables group1(ch  0 -  3) emb audio */\r\n\tblue_emb_audio_group2_enable =       0x08,  /**< enables group2(ch  4 -  7) emb audio */\r\n\tblue_emb_audio_group3_enable =       0x10,  /**< enables group3(ch  8 - 11) emb audio */\r\n\tblue_emb_audio_group4_enable =       0x20,  /**< enables group4(ch 12 - 16) emb audio */\r\n\tblue_enable_hanc_timestamp_pkt =     0x40\r\n}EBlueEmbAudioOutput;\r\n\r\nenum SerialPort_struct_flags\r\n{\r\n\tSerialPort_Read = 1,\r\n\tSerialPort_Write = 2,\r\n\tSerialPort_TX_Queue_Status = 4,\r\n\tSerialPort_RX_Queue_Status = 8,\r\n\tSerialPort_RX_FlushBuffer = 16,\r\n\tSerialPort_RX_IntWait_Return_On_Data = 32,\r\n};\r\n\r\n/*\tUse these macros for controlling epoch application watch dog settings. The card property EPOCH_APP_WATCHDOG_TIMER can be used to control\r\nthe watchdog timer functionality. */\r\nenum enum_blue_app_watchdog_timer_prop\r\n{\r\n\tenum_blue_app_watchdog_timer_start_stop = (1 << 31),            /* can be used to enable/disable timer */\r\n\tenum_blue_app_watchdog_timer_keepalive = (1 << 30),             /* can be used to reset the timer value */\r\n\tenum_blue_app_watchdog_timer_get_present_time = (1 << 29),      /* can query to get the value of the timer */\r\n\tenum_blue_app_watchdog_get_timer_activated_status = (1 << 28),  /* can query to get whether the timer has been activated */\r\n\tenum_blue_app_watchdog_get_timer_start_stop_status = (1 << 27), /* can query whether the timer has been set. */\r\n\tenum_blue_app_watchdog_enable_gpo_on_active = (1 << 26),        /* using this enumerator you can tell the system that when */\r\n                                                                    /* application watchdog timer has expired whether a GPO output should be triggered or not. */\r\n                                                                    /* you can use also use this  enumerator  to select */\r\n                                                                    /* which GPO output should be triggered with this. to use GPO port A pass a value of */\r\n                                                                    /* GPIO_TX_PORT_A when this enumerator is used. */\r\n    enum_blue_hardware_watchdog_enable_gpo = (1 << 25)              /* can be used to enable/disable GPO trigger when hardware watchdog timer has been triggered */\r\n};\r\n\r\nenum enum_blue_rs422_port_flags\r\n{\r\n\tenum_blue_rs422_port_set_as_slave = (1 << 0)    /*  If this flag is set the RS422 port would be set to slave mode.\r\n                                                        by default port is setup to work in master mode , where it would be acting \r\n                                                        as master in the transactions. */\r\n};\r\n\r\ntypedef enum\r\n{\r\n\tAUDIO_CHANNEL_LOOPING_OFF\t\t= 0x00000000,   /**< deprecated not used any more */\r\n\tAUDIO_CHANNEL_LOOPING\t\t\t= 0x00000001,   /**< deprecated not used any more */\r\n\tAUDIO_CHANNEL_LITTLEENDIAN\t\t= 0x00000000,   /**< if the audio data is little endian this flag must be set*/\r\n\tAUDIO_CHANNEL_BIGENDIAN\t\t\t= 0x00000002,   /**< if the audio data is big  endian this flag must be set*/\r\n\tAUDIO_CHANNEL_OFFSET_IN_BYTES\t= 0x00000004,   /**< deprecated not used any more */\r\n\tAUDIO_CHANNEL_16BIT\t\t\t\t= 0x00000008,   /**< if the audio channel bit depth is 16 bits this flag must be set*/\r\n\tAUDIO_CHANNEL_BLIP_PENDING\t\t= 0x00000010,   /**< deprecated not used any more */\r\n\tAUDIO_CHANNEL_BLIP_COMPLETE\t\t= 0x00000020,   /**< deprecated not used any more */\r\n\tAUDIO_CHANNEL_SELECT_CHANNEL\t= 0x00000040,   /**< deprecated not used any more */\r\n\tAUDIO_CHANNEL_24BIT\t\t\t\t= 0x00000080    /**< if the audio channel bit depth is 24 bits this flag must be set*/\r\n} EAudioFlags;\r\n\r\n\r\n\r\n\r\n\r\n/*///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r\n/////////////// S T R U C T S ////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\r\n#pragma pack(push, video_frame, 1)\r\n\r\nstruct blue_videoframe_info\r\n{\r\n\tBLUE_U64      ltcTimeCode;\r\n\tunsigned long videochannel;\r\n\tunsigned long BufferId;\r\n\tunsigned long Count;\r\n\tunsigned long DroppedFrameCount;\r\n};\r\n\r\nstruct blue_videoframe_info_ex\r\n{\r\n\tBLUE_U64\t\tltcTimeCode;        /* LTC timecode, not used */\r\n\tunsigned long\tvideochannel;       /* the channel this frame was captured from */\r\n\tlong\t\t\tBufferId;           /* this buffer contains the captured frame */\r\n\tunsigned long\tCount;              /* total captured frames */\r\n    unsigned long\tDroppedFrameCount;  /* dropped frame count */\r\n\tunsigned long\tnFrameTimeStamp;    /* field count the frame was captured at */\r\n\tunsigned long\tnVideoSignalType;   /* video mode of this frame _EVideoMode */\r\n\tunsigned int\tnASIPktCount;       /* only for DVB-ASI; how many ASI packets are in this frame */\r\n\tunsigned int\tnASIPktSize;        /* only for DVB-ASI; how many bytes per packet */\r\n\tunsigned int\tnAudioValidityBits; /* part of the channels status block for audio */\r\n\tBLUE_U64\t\tbtcTimeStamp;       /* Coordinated Bluefish Time timestamp */\r\n\tunsigned char\tucVideoModeLinkA;   /* only used in 1.5G dual link mode */\r\n\tunsigned char\tucVideoModeLinkB;   /* only used in 1.5G dual link mode */\r\n    unsigned long\tVideoModeExt;       /* video mode of this frame _EVideoModeExt */\r\n\tunsigned char\tpad[6];             /* not used */\r\n};\r\n\r\ntypedef struct _AUXILLARY_VIDEO_INFO\r\n{\r\n\tBLUE_U32 video_channel_id;\r\n\tBLUE_U32 lVideoMode;\r\n\tBLUE_U32 lUniqueId;\r\n\tBLUE_U32 lInfoType;\r\n\tBLUE_U32 lMemFmt;\r\n\tBLUE_U32 lGpio;\r\n\tBLUE_U64 lLTC;\r\n}Auxillary_Video_Info;\r\n\r\ntypedef struct\r\n{\r\n\tBLUE_S32 inputConnector;    /* ANALOG_VIDEO_INPUT_CONNECTOR, EAnalogInputConnectorType */\r\n\tBLUE_S32 inputPed;          /* ANALOG_VIDEO_INPUT_PED, */\r\n\tBLUE_S32 inputBrightness;   /* ANALOG_VIDEO_INPUT_BRIGHTNESS, */\r\n\tBLUE_S32 inputHue;          /* ANALOG_VIDEO_INPUT_HUE, */\r\n\tBLUE_S32 inputLumaGain;     /* ANALOG_VIDEO_INPUT_LUMA_GAIN, */\r\n\tBLUE_S32 inputChromaGain;   /* ANALOG_VIDEO_INPUT_CHROMA_GAIN, */\r\n\tBLUE_S32 inputAutoGain;     /* ANALOG_VIDEO_INPUT_AUTO_GAIN, */\r\n\tBLUE_S32 outputPed;         /* ANALOG_VIDEO_OUTPUT_PED, */\r\n\tBLUE_S32 outputBrightness;  /* ANALOG_VIDEO_OUTPUT_BRIGHTNESS, */\r\n\tBLUE_S32 outputHue;         /* ANALOG_VIDEO_OUTPUT_HUE, */\r\n\tBLUE_S32 outputYGain;       /* ANALOG_VIDEO_OUTPUT_Y_GAIN, */\r\n\tBLUE_S32 outputUGain;       /* ANALOG_VIDEO_OUTPUT_U_GAIN, */\r\n\tBLUE_S32 outputVGain;       /* ANALOG_VIDEO_OUTPUT_V_GAIN, */\r\n\tBLUE_S32 outputSharpness;   /* ANALOG_VIDEO_OUTPUT_SHARPNESS, */\r\n\tBLUE_S32 outputAutoGain;    /* ANALOG_VIDEO_OUTPUT_AUTO_GAIN, */\r\n\tBLUE_S32 outputSignalTypes; /* EAnalogConnectorSignalType */\r\n}AnalogCardState;\r\n\r\nstruct SerialPort_struct\r\n{\r\n\tunsigned char \tBuffer[64];\r\n\tunsigned int\tnBufLength;\r\n\tunsigned int\tnSerialPortId;\r\n\tunsigned int\tbFlag; /* SerialPort_struct_flags */\r\n\tunsigned short\tsTimeOut;\r\n};\r\n\r\nstruct blue_color_matrix_struct\r\n{\r\n\tBLUE_U32 VideoChannel;\r\n\tBLUE_U32 MatrixColumn;  /* MatrixColType enumerator defines this */\r\n\tdouble Coeff_B;\r\n\tdouble Coeff_R;\r\n\tdouble Coeff_G;\r\n\tdouble Coeff_K;\r\n\tdouble const_value;\r\n};\r\n\r\ntypedef struct _blue_video_sync_struct\r\n{\r\n\tBLUE_U32 sync_wait_type;                    /* field or frame (UPD_FMT_FIELD or UPD_FMT_FRAME) */\r\n\tBLUE_U32 video_channel;                     /* which video channel interrupt should the interrupt wait for, e.g. BLUE_VIDEO_INPUT_CHANNEL_A, BLUE_VIDEO_OUTPUT_CHANNEL_A, etc. */\r\n\tBLUE_U32 timeout_video_msc;                 /* field count when to return or IGNORE_SYNC_WAIT_TIMEOUT_VALUE to return at next field/frame sync */\r\n\tBLUE_U32 video_msc;                         /* current video msc (field count) */\r\n\tBLUE_U32 current_display_frame_id;          /* current buffer id which is being displayed */\r\n\tBLUE_U32 current_display_frame_uniqueid;    /* unique id associated with current buffer id which is being displayedl; this is only valid when using fifo modes. */\r\n\tBLUE_U16 subfield_interrupt;                /* subfield interrupt number; 0 == main frame sync */\r\n\tBLUE_U16 subfield_lines;                    /* number of lines of video captured at this subfield interrupt */\r\n\tBLUE_U64 btcTimeStamp;                      /* Coordinated Bluefish Time timestamp of field/frame which is currently being displayed */\r\n\tBLUE_U8  pad[12];\r\n}blue_video_sync_struct;\r\n\r\ntypedef struct sync_options\r\n{\r\n    BLUE_U32    SyncWaitType;                   /* required: field or frame (UPD_FMT_FIELD or UPD_FMT_FRAME) */\r\n    BLUE_U32    VideoChannel;                   /* required: */\r\n    BLUE_U32    FieldCountTimeout;              /* field count when to return or IGNORE_SYNC_WAIT_TIMEOUT_VALUE to return at next field/frame sync ( not yet supported on linux) */\r\n    BLUE_U32    FieldCount;                     /* Current FieldCount */\r\n    BLUE_U64    BtcTimeStamp;                   /* BTC at time of interrupt */\r\n    BLUE_U32    SubFieldInterrupt;              /* returned value, input only. subfield interrupt number; 0 == main frame sync */\r\n    BLUE_U32    SubFieldLines;                  /* returned value, input only. number of lines of video captured at this subfield interrupt */\r\n    BLUE_U32    CurrentDisplayFrameID;          /* returned value, output only. current buffer id which is being displayed on the output */\r\n    BLUE_U32    CurrentDisplayFrameUniqueID;    /* returned value, output only. unique id associated with current buffer id which is being displayed on the output */\r\n    BLUE_U64    pad[5];\r\n}sync_options;\r\n\r\ntypedef struct blue_external_ltc_input_sync_struct\r\n{\r\n\tBLUE_U64 TimeCodeValue;\r\n\tBLUE_U32 TimeCodeIsValid;\r\n\tBLUE_U8  pad[20];\r\n}blue_external_ltc_input_sync_struct;\r\n\r\nstruct blue_dma_request_struct\r\n{\r\n\tunsigned char* pBuffer;\r\n\tBLUE_U32 video_channel;\r\n\tBLUE_U32 BufferId;\r\n\tBLUE_U32 BufferDataType;\r\n\tBLUE_U32 FrameType;\r\n\tBLUE_U32 BufferSize;\r\n\tBLUE_U32 Offset;\r\n\tunsigned long\tBytesTransferred;\r\n\tunsigned char pad[64];\r\n};\r\n\r\nstruct blue_1d_lookup_table_struct\r\n{\r\n\tBLUE_U32 nVideoChannel;\r\n\tBLUE_U32 nLUTId;\r\n\tBLUE_U16* pLUTData;\r\n\tBLUE_U32 nLUTElementCount;\r\n\tBLUE_U8 pad[256];\r\n};\r\n\r\nstruct blue_multi_link_info_struct\r\n{\r\n    BLUE_U32 Link1_Device;\r\n    BLUE_U32 Link1_MemChannel;\r\n    BLUE_U32 Link2_Device;\r\n    BLUE_U32 Link2_MemChannel;\r\n    BLUE_U32 Link3_Device;\r\n    BLUE_U32 Link3_MemChannel;\r\n    BLUE_U32 Link4_Device;\r\n    BLUE_U32 Link4_MemChannel;\r\n    BLUE_U32 Link5_Device;\r\n    BLUE_U32 Link5_MemChannel;\r\n    BLUE_U32 Link6_Device;\r\n    BLUE_U32 Link6_MemChannel;\r\n    BLUE_U32 Link7_Device;\r\n    BLUE_U32 Link7_MemChannel;\r\n    BLUE_U32 Link8_Device;\r\n    BLUE_U32 Link8_MemChannel;\r\n    BLUE_U32 Link9_Device;\r\n    BLUE_U32 Link9_MemChannel;\r\n    BLUE_U32 Link10_Device;\r\n    BLUE_U32 Link10_MemChannel;\r\n    BLUE_U32 Link11_Device;\r\n    BLUE_U32 Link11_MemChannel;\r\n    BLUE_U32 Link12_Device;\r\n    BLUE_U32 Link12_MemChannel;\r\n    BLUE_U32 Link13_Device;\r\n    BLUE_U32 Link13_MemChannel;\r\n    BLUE_U32 Link14_Device;\r\n    BLUE_U32 Link14_MemChannel;\r\n    BLUE_U32 Link15_Device;\r\n    BLUE_U32 Link15_MemChannel;\r\n    BLUE_U32 Link16_Device;\r\n    BLUE_U32 Link16_MemChannel;\r\n    BLUE_U32 InputControl;\r\n    BLUE_U32 Padding[15];\r\n};\r\n\r\nstruct hanc_stream_info_struct\r\n{\r\n    BLUE_S32 AudioDBNArray[4];\t\t\t    /**< Contains the DBN values that should be used for each of the embedded audio groups*/\r\n    BLUE_S32 AudioChannelStatusBlock[4];\t/**< channel status block information for each of the embedded audio group*/\r\n    BLUE_U32 flag_valid_time_code;\t\t    /**< deprecated/unused flag; set to 0*/\r\n    BLUE_U64 time_code; \t\t\t\t\t/**< RP188 time code that was extracted from the HANC buffer or RP188 timecode which should be inserted into the HANC buffer*/\r\n    BLUE_U32* hanc_data_ptr;\t\t\t\t/**< Hanc Buffer which should be used as the source or destination for either extraction or insertion */\r\n    BLUE_U32 video_mode;\t\t\t\t\t/**< video mode which this hanc buffer which be used with. We need this information for do the required audio distribution especially NTSC */\r\n    BLUE_U64 ltc_time_code;\r\n    BLUE_U64 sd_vitc_time_code;\r\n    BLUE_U64 rp188_ltc_time_code;\r\n    BLUE_U32 pad[126];\r\n};\r\n\r\nstruct hanc_decode_struct\r\n{\r\n    BLUE_VOID* audio_pcm_data_ptr;               /* Buffer which would be used to store the extracted PCM audio data. Must be filled in by app before calling function. */\r\n    BLUE_U32 audio_ch_required_mask;             /* Defines which audio channels should be extracted; Use enumerator BlueAudioChannelDesc to set up this mask. Must be filled in by app before calling function. */\r\n    BLUE_U32 type_of_sample_required;            /* Defines sample characteristics:\r\n                                                 AUDIO_CHANNEL_16BIT: for 16 bit pcm data\r\n                                                 AUDIO_CHANNEL_24BIT: for 24 bit pcm data\r\n                                                 If neither AUDIO_CHANNEL_16BIT nor AUDIO_CHANNEL_24BIT are set 32 bit pcm data will be extracted\r\n                                                 Must be filled in by app before calling function. */\r\n    BLUE_U32 no_audio_samples;\t\t            /* number of audio samples that have decoded the hanc buffer */\r\n    BLUE_U64 timecodes[7];\t\t\t            /* Only the first four elements are currently defined:\r\n                                                hanc_decode_struct::timcodes[0] ---> RP188 VITC timecode\r\n                                                hanc_decode_struct::timcodes[1] ---> RP188 LTC timecode\r\n                                                hanc_decode_struct::timcodes[2] ---> SD VITC timecode\r\n                                                hanc_decode_struct::timcodes[3] ---> External LTC timecode */\r\n    BLUE_VOID* raw_custom_anc_pkt_data_ptr;     /* This buffer  would contain the raw ANC packets that was found in the orac hanc buffer.\r\n                                                this would contain any ANC packets that is not of type embedded audio and RP188 TC.\r\n                                                Must be filled in by app before calling function. can be NULL */\r\n    BLUE_U32 sizeof_custom_anc_pkt_data_ptr;    /* size of the ANC buffer array; Must be filled in by app before calling function. can be NULL */\r\n    BLUE_U32 avail_custom_anc_pkt_data_bytes;   /* how many custom ANC packets has been decoded into raw_hanc_pkt_data_ptr; Must be filled in by app before calling function. can be NULL */\r\n    BLUE_U32 audio_input_source;                /* Used to select the audio input source, whether it is AES or Embedded. Must be filled in by app before calling function. */\r\n    BLUE_U32 audio_temp_buffer[16];             /* deprecated/not used; Must be initialised to zero by app before first instantiating the function. */\r\n    BLUE_U32 audio_split_buffer_mask;           /* deprecated/not used; Must be initialised to zero by app before first instantiating the  function. */\r\n    BLUE_U32 max_expected_audio_sample_count;   /* specify the maximum number of audio samples that the provided audio pcm buffer can contain. Must be filled in by app before calling function. */\r\n    BLUE_U32 pad[124];\r\n};\r\n\r\ntypedef struct hardware_firmware_versions\r\n{\r\n    BLUE_U32 FirmwareMajor;\r\n    BLUE_U32 FirmwareMinor;\r\n    BLUE_U32 FirmwareBuild;\r\n    BLUE_U32 FirmwareLoadedFrom;\r\n\r\n    BLUE_U32 CpldConfig;\r\n    BLUE_U32 CpldStemPort;\r\n    BLUE_U32 CpldIOExpander;\r\n\r\n    BLUE_U32 HardwareBaseBoardFamily;\r\n    BLUE_U32 HardwareBaseBoardModel;\r\n    BLUE_U32 HardwareBaseBoardRevision;\r\n    BLUE_U32 HardwareBaseBoardBuildMajor;\r\n    BLUE_U32 HardwareBaseBoardBuildMinor;\r\n    BLUE_U32 HardwareRegulatorBoardFamily;\r\n    BLUE_U32 HardwareRegulatorBoardModel;\r\n    BLUE_U32 HardwareRegulatorBoardRevision;\r\n    BLUE_U32 HardwareRegulatorBoardBuildMajor;\r\n    BLUE_U32 HardwareRegulatorBoardBuildMinor;\r\n\r\n    BLUE_U32 Padding[12];\r\n}hardware_firmware_versions;\r\n\r\n#pragma pack(pop, video_frame)\r\n\r\n/*///////////////////////////////////////////////////////////////////////////\r\n// L E G A C Y   D E C L A R A T I O N S - END\r\n///////////////////////////////////////////////////////////////////////////*/\r\n\r\n\r\n\r\n#endif /* HG_BLUE_DRIVER_P_LEGACY_HG */\r\n"
  },
  {
    "path": "src/modules/bluefish/interop/BlueTypes.h",
    "content": "////////////////////////////////////////////////////////////////////////////\n// File:        BlueTypes.h\n//\n// Description: Declaration for Bluefish types\n//\n// (C) Copyright 2017 by Bluefish Technologies Pty Ltd. All Rights Reserved.\n////////////////////////////////////////////////////////////////////////////\n\n\n#ifndef HG_BLUE_TYPES_HG\n#define HG_BLUE_TYPES_HG\n\n\n#define BLUE_TRUE\t1\n#define BLUE_FALSE\t0\n\ntypedef int                BERR;\ntypedef int                BErr;\ntypedef long long          BGERROR;\ntypedef void               BLUE_VOID;\ntypedef int                BLUE_BOOL;\ntypedef unsigned char      BLUE_U8;\ntypedef unsigned short     BLUE_U16;\ntypedef unsigned int       BLUE_U32;\ntypedef unsigned long long BLUE_U64;\ntypedef char               BLUE_S8;\ntypedef short              BLUE_S16;\ntypedef int                BLUE_S32;\ntypedef long long          BLUE_S64;\ntypedef BLUE_U8            BLUE_UINT8;\ntypedef BLUE_U16           BLUE_UINT16;\ntypedef BLUE_U32           BLUE_UINT32;\ntypedef BLUE_U64           BLUE_UINT64;\ntypedef BLUE_S8            BLUE_INT8;\ntypedef BLUE_S16           BLUE_INT16;\ntypedef BLUE_S32           BLUE_INT32;\ntypedef BLUE_S64           BLUE_INT64;\n\n// TODO: maybe make a macro to do all this ifndef def etuff.\n#ifdef __linux__\n\n#ifndef ULONG\n    #define ULONG BLUE_U32\n#endif\n#ifndef BOOLEAN \n    #define BOOLEAN bool\n#endif\n#ifndef BOOL\n    #define BOOL bool\n#endif\n#ifndef LPVOID\n    #define LPVOID void*\n#endif\n#ifndef LPDWORD\n    #define LPDWORD BLUE_U32*\n#endif    \n#ifndef LPOVERLAPPED\n    #define LPOVERLAPPED void*\n#endif\n\ntypedef void*              PVOID;\ntypedef void*              PVOID64;\ntypedef BLUE_U64           LARGE_INTEGER;\ntypedef BLUE_U32           DWORD;\n#endif\n\n#endif //#define HG_BLUE_TYPES_HG\n"
  },
  {
    "path": "src/modules/bluefish/interop/BlueVelvetCFuncPtr.h",
    "content": "/*\n  Copyright (c) Bluefish444. All rights reserved.\n\n  NOTE: Please add\n        #define IMPLEMENTATION_BLUEVELVETC_FUNC_PTR\n        before including this file so that all the SDK functions are defined\n        in your project. If including this header files from multiple c/c++\n        files make sure that only one c/c++ file which includes this header\n        file defines IMPLEMENTATION_BLUEVELVETC_FUNC_PTR\n\n        #define IMPLEMENTATION_BLUEVELVETC_CONVERSION_FUNC_PTR\n        before including this file so that all conversion functions are defined\n        in your project. If including this header files from multiple c/c++\n        files make sure that only one c/c++ file which includes this header\n        file defines IMPLEMENTATION_BLUEVELVETC_CONVERSION_FUNC_PTR\n*/\n\n#ifndef HG_BLUEVELVETC_FUNC_PTR\n#define HG_BLUEVELVETC_FUNC_PTR\n\n\n#if defined (_WIN32)\n    #define GET_PROCADDR_FOR_FUNC(module, available, name) { name = (pFunc_##name)GetProcAddress(module, #name); if(!name) { *available = false; OutputDebugStringA(#name); break; } }\n    \n    #ifndef WIN32_LEAN_AND_MEAN\n        #define WIN32_LEAN_AND_MEAN\n    #endif\n\t#include <Windows.h>\n    #include \"BlueDriver_p.h\"\n#elif defined (__linux__)\n    #define GET_PROCADDR_FOR_FUNC(module, available, name) { name = (pFunc_##name)dlsym(module, #name); if(!name) { *available = false; break; } }\n\n    #include <dlfcn.h>\n    #define __cdecl\n\n    #include \"../../hal/BlueTypes.h\"\n    #include \"../../hal/BlueDriver_p.h\"\n\n#endif\n\n\ntypedef void* BLUEVELVETC_HANDLE;\ntypedef void* BFC_SYNC_INFO;\n#define\tBLUE_OK(a)      (!a)    /* Test for success of a method returning BErr */\n#define\tBLUE_FAIL(a)    (a)     /* Test for failure of a method returning BErr */\n\n\n/* FUNCTION PROTOTYPES FOR BLUEVELVETC */\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n    typedef const char* (__cdecl *pFunc_bfcGetVersion)();\n    typedef const wchar_t* (__cdecl *pFunc_bfcGetVersionW)();\n    typedef BLUEVELVETC_HANDLE(__cdecl *pFunc_bfcFactory)();\n    typedef BLUE_VOID(__cdecl *pFunc_bfcDestroy)(BLUEVELVETC_HANDLE pHandle);\n    typedef BLUE_S32(__cdecl *pFunc_bfcEnumerate)(BLUEVELVETC_HANDLE pHandle, BLUE_S32* pDeviceCount);\n    typedef BLUE_S32(__cdecl *pFunc_bfcQueryCardType)(BLUEVELVETC_HANDLE pHandle, BLUE_S32* pCardType, BLUE_S32 DeviceID);\n    typedef BLUE_S32(__cdecl *pFunc_bfcAttach)(BLUEVELVETC_HANDLE pHandle, BLUE_S32 DeviceId);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSetMultiLinkMode)(BLUEVELVETC_HANDLE pHandle, blue_multi_link_info_struct* pMultiLinkInfo);\n    typedef BLUE_S32(__cdecl *pFunc_bfcQueryMultiLinkMode)(BLUEVELVETC_HANDLE pHandle, blue_multi_link_info_struct* pMultiLinkInfo);\n    typedef BLUE_S32(__cdecl *pFunc_bfcDetach)(BLUEVELVETC_HANDLE pHandle);\n    typedef BLUE_S32(__cdecl *pFunc_bfcQueryCardProperty32)(BLUEVELVETC_HANDLE pHandle, const BLUE_S32 Property, BLUE_U32* pValue32);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSetCardProperty32)(BLUEVELVETC_HANDLE pHandle, const BLUE_S32 Property, const BLUE_U32 Value32);\n    typedef BLUE_S32(__cdecl *pFunc_bfcQueryCardProperty64)(BLUEVELVETC_HANDLE pHandle, const BLUE_S32 Property, BLUE_U64* pValue64);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSetCardProperty64)(BLUEVELVETC_HANDLE pHandle, const BLUE_S32 Property, const BLUE_U64 Value64);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetCardSerialNumber)(BLUEVELVETC_HANDLE pHandle, BLUE_S8* pSerialNumber, BLUE_U32 StringSize);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetCardFwVersion)(BLUEVELVETC_HANDLE pHandle, BLUE_U32* pValue);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetCardHwFwVersions)(BLUEVELVETC_HANDLE pHandle, hardware_firmware_versions* pVersions);\n#if defined (_WIN32)\n    typedef BLUE_S32(__cdecl *pFunc_bfcWaitVideoSyncAsync)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, blue_video_sync_struct* pSyncData);\n#endif\n    typedef BLUE_S32(__cdecl *pFunc_bfcWaitVideoSync)(BLUEVELVETC_HANDLE pHandle, sync_options* pSyncData, BFC_SYNC_INFO SyncInfo);\n    typedef BLUE_S32(__cdecl *pFunc_bfcWaitVideoInputSync)(BLUEVELVETC_HANDLE pHandle, unsigned long UpdateType, unsigned long* pFieldCount);\n    typedef BLUE_S32(__cdecl *pFunc_bfcWaitVideoOutputSync)(BLUEVELVETC_HANDLE pHandle, unsigned long UpdateType, unsigned long* pFieldCount);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoOutputCurrentFieldCount)(BLUEVELVETC_HANDLE pHandle, unsigned long* pFieldCount);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoInputCurrentFieldCount)(BLUEVELVETC_HANDLE pHandle, unsigned long* pFieldCount);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoCaptureStart)(BLUEVELVETC_HANDLE pHandle);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoCaptureStop)(BLUEVELVETC_HANDLE pHandle);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoPlaybackStart)(BLUEVELVETC_HANDLE pHandle, BLUE_S32 Step, BLUE_S32 Loop);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoPlaybackStop)(BLUEVELVETC_HANDLE pHandle, BLUE_S32 Wait, BLUE_S32 Flush);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoPlaybackAllocate)(BLUEVELVETC_HANDLE pHandle, BLUE_VOID** pAddress, unsigned long* pBufferID, unsigned long* pUnderrun);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoPlaybackPresent)(BLUEVELVETC_HANDLE pHandle, unsigned long* UniqueID, unsigned long BufferID, unsigned long Count, BLUE_S32 Keep, BLUE_S32 Odd);\n    typedef BLUE_S32(__cdecl *pFunc_bfcVideoPlaybackRelease)(BLUEVELVETC_HANDLE pHandle, unsigned long BufferID);\n#if defined (_WIN32)\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetCaptureVideoFrameInfoEx)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, struct blue_videoframe_info_ex* pVideoFrameInfo, BLUE_S32 iCompostLater, BLUE_U32* CaptureFifoSize);\n#elif defined(__linux__)\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetCaptureVideoFrameInfoEx)(BLUEVELVETC_HANDLE pHandle, struct blue_videoframe_info_ex* pVideoFrameInfo);\n#endif\n    typedef BLUE_S32(__cdecl *pFunc_bfcRenderBufferCapture)(BLUEVELVETC_HANDLE pHandle, unsigned long BufferID);\n    typedef BLUE_S32(__cdecl *pFunc_bfcRenderBufferUpdate)(BLUEVELVETC_HANDLE pHandle, unsigned long BufferID);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetRenderBufferCount)(BLUEVELVETC_HANDLE pHandle, unsigned long* pCount);\n    typedef BLUE_S32(__cdecl *pFunc_bfcEncodeHancFrameEx)(BLUEVELVETC_HANDLE pHandle, BLUE_U32 CardType, struct hanc_stream_info_struct* pHancEncodeInfo, BLUE_VOID* pAudioBuffer, BLUE_U32 AudioChannels, BLUE_U32 AudioSamples, BLUE_U32 SampleType, BLUE_U32 AudioFlags);\n    typedef BLUE_S32(__cdecl *pFunc_bfcEncodeHancFrameWithUCZ)(BLUEVELVETC_HANDLE pHandle, BLUE_U32 CardType, struct hanc_stream_info_struct* pHancEncodeInfo, BLUE_VOID* pAudioBuffer, BLUE_U32 AudioChannels, BLUE_U32 AudioSamples, BLUE_U32 SampleType, BLUE_U8* pUCZBuffer);\n    typedef BLUE_S32(__cdecl *pFunc_bfcDecodeHancFrameEx)(BLUEVELVETC_HANDLE pHandle, BLUE_U32 CardType, BLUE_U32* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo);\n#if defined(_WIN32)\n    typedef BLUE_S32(__cdecl *pFunc_bfcSystemBufferReadAsync)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSystemBufferWriteAsync)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, OVERLAPPED* pOverlap, unsigned long ulBufferID, unsigned long ulOffset);\n#elif defined(__linux__)\n    typedef BLUE_S32(__cdecl *pFunc_bfcSystemBufferRead)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSystemBufferWrite)(BLUEVELVETC_HANDLE pHandle, unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset);\n#endif\n    typedef BFC_SYNC_INFO(__cdecl *pFunc_bfcSyncInfoCreate)(BLUEVELVETC_HANDLE pHandle);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSyncInfoDelete)(BLUEVELVETC_HANDLE pHandle, BFC_SYNC_INFO SyncInfo);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSyncInfoWait)(BLUEVELVETC_HANDLE pHandle, BFC_SYNC_INFO SyncInfo, const BLUE_U32 nTimeOutInMilliSec);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSyncInfoWaitWithSyncOptions)(BLUEVELVETC_HANDLE pHandle, BFC_SYNC_INFO SyncInfo, sync_options* pSyncOptions, const BLUE_U32 TimeOutInMilliSec);\n    typedef BLUE_S32(__cdecl *pFunc_bfcDmaReadFromCardAsync)(BLUEVELVETC_HANDLE pHandle, BLUE_U8* pData, unsigned long Size, BFC_SYNC_INFO SyncInfo, unsigned long BufferID, unsigned long Offset);\n    typedef BLUE_S32(__cdecl *pFunc_bfcDmaWriteToCardAsync)(BLUEVELVETC_HANDLE pHandle, BLUE_U8* pData, unsigned long Size, BFC_SYNC_INFO SyncInfo, unsigned long BufferID, unsigned long Offset);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSerialPortWaitForInputData)(BLUEVELVETC_HANDLE pHandle, BLUE_U32 PortFlags, BLUE_U32* pBufferLength);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSerialPortRead)(BLUEVELVETC_HANDLE pHandle, BLUE_U32 nPortFlags, BLUE_U8* pBuffer, BLUE_U32 ReadLength);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSerialPortWrite)(BLUEVELVETC_HANDLE pHandle, BLUE_U32 nPortFlags, BLUE_U8* pBuffer, BLUE_U32 WriteLength);\n#if defined (_WIN32)\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetReferenceClockPhaseSettings)(BLUEVELVETC_HANDLE pHandle, BLUE_U32* pHPhase, BLUE_U32* pVPhase, BLUE_U32* pHPhaseMax, BLUE_U32* pVPhaseMax);\n    typedef BLUE_S32(__cdecl *pFunc_bfcLoadOutputLUT1D)(BLUEVELVETC_HANDLE pHandle, struct blue_1d_lookup_table_struct* pLutData);\n#endif\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoWidth)(BLUE_S32 VideoMode, BLUE_U32* pWidth);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoHeight)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_U32* pHeight);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoBytesPerLineV2)(BLUE_S32 VideoMode, BLUE_S32 MemoryFormat, BLUE_U32* pBytesPerLine);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoBytesPerFrame)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pBytesPerFrame);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoBytesPerFrameGolden)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pGoldenBytes);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoInfo)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pWidth, BLUE_U32* pHeight, BLUE_U32* pBytesPerLine, BLUE_U32* pBytesPerFrame, BLUE_U32* pGoldenBytes);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVancWidth)(BLUE_S32 VideoMode, BLUE_U32* pWidth);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVancHeight)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_U32* pHeight);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVancBytesPerLineV2)(BLUE_S32 VideoMode, BLUE_S32 MemoryFormat, BLUE_U32* pBytesPerLine);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVancBytesPerFrame)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pBytesPerFrame);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVancInfo)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pWidth, BLUE_U32* pHeight, BLUE_U32* pBytesPerLine, BLUE_U32* pBytesPerFrame);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetBytesForGroupPixels)(EMemoryFormat MemoryFormat, BLUE_U32 VideoWidth, BLUE_U32* pVideoPitchBytes);\n#if defined (_WIN32)\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetWindowsDriverHandle)(BLUEVELVETC_HANDLE pHandle, HANDLE* pDriverHandle);\n    typedef BLUE_S32(__cdecl *pFunc_bfcSetDynamicMemoryFormatChange)(BLUEVELVETC_HANDLE pHandle, OVERLAPPED* pOverlap, BLUE_U32 nUniqueId, EMemoryFormat MemoryFormat);\n#elif defined(__linux__)\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetFileHandle)(BLUEVELVETC_HANDLE pHandle, BLUE_U32* pFileHandle);\n#endif\n    /* BlueVelvetC utils functions */\n    typedef void*(__cdecl *pFunc_bfAlloc)(BLUE_U32 nMemorySize);\n    typedef void(__cdecl *pFunc_bfFree)(BLUE_U32 nMemSize, BLUE_VOID* pMemory); \n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForCardType)(const BLUE_S32 CardType);\n    typedef wchar_t*(__cdecl *pFunc_bfcUtilsGetWStringForCardType)(const BLUE_S32 CardType);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForBlueProductId)(const BLUE_U32 ProductId);\n    typedef wchar_t*(__cdecl *pFunc_bfcUtilsGetWStringForBlueProductId)(const BLUE_U32 ProductId);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForVideoMode)(const BLUE_U32 VideoMode);\n    typedef wchar_t*(__cdecl *pFunc_bfcUtilsGetWStringForVideoMode)(const BLUE_U32 VideoMode);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForMemoryFormat)(const BLUE_U32 MemoryFormat);\n    typedef wchar_t*(__cdecl *pFunc_bfcUtilsGetWStringForMemoryFormat)(const BLUE_U32 MemoryFormat);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForUpdateFormat)(const BLUE_U32 UpdateFormat);\n    typedef wchar_t*(__cdecl *pFunc_bfcUtilsGetWStringForUpdateFormat)(const BLUE_U32 UpdateFormat);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForVideoEngine)(const BLUE_U32 VideoEngine);\n    typedef wchar_t*(__cdecl *pFunc_bfcUtilsGetWStringForVideoEngine)(const BLUE_U32 VideoEngine);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetStringForMr2Node)(const BLUE_U32 Mr2Node);\n    typedef char*(__cdecl *pFunc_bfcUtilsGetWStringForMr2Node)(const BLUE_U32 Mr2Node);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetMR2Routing)(const BLUEVELVETC_HANDLE pHandle, BLUE_U32* pSrcNode, const BLUE_U32 DestNode, BLUE_U32* LinkType);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsSetMR2Routing)(const BLUEVELVETC_HANDLE pHandle, const BLUE_U32 SrcNode, const BLUE_U32 DestNode, const BLUE_U32 LinkType);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetAudioOutputRouting)(const BLUEVELVETC_HANDLE pHandle, const BLUE_U32 AudioConnectorType, BLUE_U32* pAudioSourceChannelId, BLUE_U32 AudioConnectorId);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsSetAudioOutputRouting)(const BLUEVELVETC_HANDLE pHandle, const BLUE_U32 AudioConnectorType, BLUE_U32 AudioSourceChannelId, BLUE_U32 AudioConnectorId);\n    typedef bool(__cdecl *pFunc_bfcUtilsIsVideoModeProgressive)(const BLUE_U32 VideoMode);\n    typedef bool(__cdecl *pFunc_bfcUtilsIsVideoMode1001Framerate)(const BLUE_U32 VideoMode);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetFpsForVideoMode)(const BLUE_U32 VideoMode);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetVideoModeExtForFrameInfo)(const BLUE_U32 Width, const BLUE_U32 Height, const BLUE_U32 Rate, const BLUE_U32 bIs1001, const BLUE_U32 bIsProgressive, BLUE_U32* pVideoModeExt);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetFrameInfoForVideoModeExt)(const BLUE_U32 VideoModeExt, BLUE_U32* pWidth, BLUE_U32* pHeight, BLUE_U32* pRate, BLUE_U32* pIs1001, BLUE_U32* pIsProgressive);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetAudioSamplesPerFrame)(const BLUE_U32 VideoMode, const BLUE_U32 FrameNo);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsInitVancBuffer)(BLUE_U32 nCardType, BLUE_U32 VideoMode, BLUE_U32 PixelsPerLine, BLUE_U32 nLinesPerFrame, BLUE_U32* pVancBuffer);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsVancPktExtract)(BLUE_U32 nCardType, BLUE_U32 nVancPktType, BLUE_U32* pSrcVancBuffer, BLUE_U32 nSrcVancBufferSize, BLUE_U32 PixelsPerLine, BLUE_U32 nVancPktDid, BLUE_U16* pVancPktSdid, BLUE_U16* pVancPktDataLength, BLUE_U16* pVancPktData, BLUE_U16* pVancPktLineNo);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsVancPktInsert)(BLUE_U32 nCardType, BLUE_U32 nVancPktType, BLUE_U32 nVancPktLineNumber, BLUE_U32* pVancPktBuffer, BLUE_U32 nVancPktBufferSize, BLUE_U32* pDestVancBuffer, BLUE_U32 PixelsPerLine);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsDecodeEia708bPkt)(BLUE_U32 CardType, BLUE_U16* pVancPacketData, BLUE_U16 PacketUdwCount, BLUE_U16 EiaPacketSubtype, BLUE_U8* pDecodedString);\n\n    /* deprecated */\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetVideoModeForFrameInfo)(const BLUE_U32 Width, const BLUE_U32 Height, const BLUE_U32 Rate, const BLUE_U32 bIs1001, const BLUE_U32 bIsProgressive, BLUE_U32* pVideoMode);\n    typedef BLUE_S32(__cdecl *pFunc_bfcUtilsGetFrameInfoForVideoMode)(const BLUE_U32 VideoMode, BLUE_U32* pWidth, BLUE_U32* pHeight, BLUE_U32* pRate, BLUE_U32* pIs1001, BLUE_U32* pIsProgressive);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVideoBytesPerLine)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pBytesPerLine);\n    typedef BLUE_S32(__cdecl *pFunc_bfcGetVancBytesPerLine)(BLUE_S32 VideoMode, BLUE_S32 UpdateMethod, BLUE_S32 MemoryFormat, BLUE_U32* pBytesPerLine);\n\n#if defined(__cplusplus)\n}\t//\textern \"C\"\n#endif\n\n#ifdef IMPLEMENTATION_BLUEVELVETC_FUNC_PTR\npFunc_bfcGetVersion bfcGetVersion;\npFunc_bfcGetVersionW bfcGetVersionW;\npFunc_bfcFactory bfcFactory;\npFunc_bfcDestroy bfcDestroy;\npFunc_bfcEnumerate bfcEnumerate;\npFunc_bfcQueryCardType bfcQueryCardType;\npFunc_bfcAttach bfcAttach;\npFunc_bfcSetMultiLinkMode bfcSetMultiLinkMode;\npFunc_bfcQueryMultiLinkMode bfcQueryMultiLinkMode;\npFunc_bfcDetach bfcDetach;\npFunc_bfcQueryCardProperty32 bfcQueryCardProperty32;\npFunc_bfcQueryCardProperty64 bfcQueryCardProperty64;\npFunc_bfcSetCardProperty32 bfcSetCardProperty32;\npFunc_bfcSetCardProperty64 bfcSetCardProperty64;\npFunc_bfcGetCardSerialNumber bfcGetCardSerialNumber;\npFunc_bfcGetCardFwVersion bfcGetCardFwVersion;\npFunc_bfcGetCardHwFwVersions bfcGetCardHwFwVersions;\n#if defined(_WIN32)\npFunc_bfcWaitVideoSyncAsync bfcWaitVideoSyncAsync;\n#endif\npFunc_bfcWaitVideoSync  bfcWaitVideoSync;\npFunc_bfcWaitVideoInputSync bfcWaitVideoInputSync;\npFunc_bfcWaitVideoOutputSync bfcWaitVideoOutputSync;\npFunc_bfcGetVideoOutputCurrentFieldCount bfcGetVideoOutputCurrentFieldCount;\npFunc_bfcGetVideoInputCurrentFieldCount bfcGetVideoInputCurrentFieldCount;\npFunc_bfcVideoCaptureStart bfcVideoCaptureStart;\npFunc_bfcVideoCaptureStop bfcVideoCaptureStop;\npFunc_bfcVideoPlaybackStart bfcVideoPlaybackStart;\npFunc_bfcVideoPlaybackStop bfcVideoPlaybackStop;\npFunc_bfcVideoPlaybackAllocate bfcVideoPlaybackAllocate;\npFunc_bfcVideoPlaybackPresent bfcVideoPlaybackPresent;\npFunc_bfcVideoPlaybackRelease bfcVideoPlaybackRelease;\npFunc_bfcGetCaptureVideoFrameInfoEx bfcGetCaptureVideoFrameInfoEx;\npFunc_bfcRenderBufferCapture bfcRenderBufferCapture;\npFunc_bfcRenderBufferUpdate bfcRenderBufferUpdate;\npFunc_bfcGetRenderBufferCount bfcGetRenderBufferCount;\npFunc_bfcEncodeHancFrameEx bfcEncodeHancFrameEx;\npFunc_bfcEncodeHancFrameWithUCZ bfcEncodeHancFrameWithUCZ;\npFunc_bfcDecodeHancFrameEx bfcDecodeHancFrameEx;\n#if defined(_WIN32)\npFunc_bfcSystemBufferReadAsync bfcSystemBufferReadAsync;\npFunc_bfcSystemBufferWriteAsync bfcSystemBufferWriteAsync;\n#elif defined(__linux__)\npFunc_bfcSystemBufferRead bfcSystemBufferRead;\npFunc_bfcSystemBufferWrite bfcSystemBufferWrite;\n#endif\npFunc_bfcSyncInfoCreate bfcSyncInfoCreate;\npFunc_bfcSyncInfoDelete bfcSyncInfoDelete;\npFunc_bfcSyncInfoWait bfcSyncInfoWait;\npFunc_bfcSyncInfoWaitWithSyncOptions bfcSyncInfoWaitWithSyncOptions;\npFunc_bfcDmaReadFromCardAsync bfcDmaReadFromCardAsync;\npFunc_bfcDmaWriteToCardAsync bfcDmaWriteToCardAsync;\npFunc_bfcSerialPortWaitForInputData bfcSerialPortWaitForInputData;\npFunc_bfcSerialPortRead bfcSerialPortRead;\npFunc_bfcSerialPortWrite bfcSerialPortWrite;\n#if defined(_WIN32)\npFunc_bfcGetReferenceClockPhaseSettings bfcGetReferenceClockPhaseSettings;\npFunc_bfcLoadOutputLUT1D bfcLoadOutputLUT1D;\n#endif\npFunc_bfcGetVideoWidth bfcGetVideoWidth;\npFunc_bfcGetVideoHeight bfcGetVideoHeight;\npFunc_bfcGetVideoBytesPerLineV2 bfcGetVideoBytesPerLineV2;\npFunc_bfcGetVideoBytesPerFrame bfcGetVideoBytesPerFrame;\npFunc_bfcGetVideoBytesPerFrameGolden bfcGetVideoBytesPerFrameGolden;\npFunc_bfcGetVideoInfo bfcGetVideoInfo;\npFunc_bfcGetVancWidth bfcGetVancWidth;\npFunc_bfcGetVancHeight bfcGetVancHeight;\npFunc_bfcGetVancBytesPerLineV2 bfcGetVancBytesPerLineV2;\npFunc_bfcGetVancBytesPerFrame bfcGetVancBytesPerFrame;\npFunc_bfcGetVancInfo bfcGetVancInfo;\npFunc_bfcGetBytesForGroupPixels bfcGetBytesForGroupPixels;\n#if defined(_WIN32)\npFunc_bfcGetWindowsDriverHandle bfcGetWindowsDriverHandle;\npFunc_bfcSetDynamicMemoryFormatChange bfcSetDynamicMemoryFormatChange;\n#elif defined(__linux__)\npFunc_bfcGetFileHandle bfcGetFileHandle;\n#endif\n\n/* BlueVelvetC utils functions */\npFunc_bfAlloc bfAlloc;\npFunc_bfFree bfFree;\npFunc_bfcUtilsGetStringForCardType bfcUtilsGetStringForCardType;\npFunc_bfcUtilsGetWStringForCardType bfcUtilsGetWStringForCardType;\npFunc_bfcUtilsGetStringForBlueProductId bfcUtilsGetStringForBlueProductId;\npFunc_bfcUtilsGetWStringForBlueProductId bfcUtilsGetWStringForBlueProductId;\npFunc_bfcUtilsGetStringForVideoMode bfcUtilsGetStringForVideoMode;\npFunc_bfcUtilsGetWStringForVideoMode bfcUtilsGetWStringForVideoMode;\npFunc_bfcUtilsGetStringForMemoryFormat bfcUtilsGetStringForMemoryFormat;\npFunc_bfcUtilsGetWStringForMemoryFormat bfcUtilsGetWStringForMemoryFormat;\npFunc_bfcUtilsGetStringForUpdateFormat bfcUtilsGetStringForUpdateFormat;\npFunc_bfcUtilsGetWStringForUpdateFormat bfcUtilsGetWStringForUpdateFormat;\npFunc_bfcUtilsGetStringForVideoEngine bfcUtilsGetStringForVideoEngine;\npFunc_bfcUtilsGetWStringForVideoEngine bfcUtilsGetWStringForVideoEngine;\npFunc_bfcUtilsGetStringForMr2Node bfcUtilsGetStringForMr2Node;\npFunc_bfcUtilsGetWStringForMr2Node bfcUtilsGetWStringForMr2Node;\npFunc_bfcUtilsGetMR2Routing bfcUtilsGetMR2Routing;\npFunc_bfcUtilsSetMR2Routing bfcUtilsSetMR2Routing;\npFunc_bfcUtilsGetAudioOutputRouting bfcUtilsGetAudioOutputRouting;\npFunc_bfcUtilsSetAudioOutputRouting bfcUtilsSetAudioOutputRouting;\npFunc_bfcUtilsIsVideoModeProgressive bfcUtilsIsVideoModeProgressive;\npFunc_bfcUtilsIsVideoMode1001Framerate bfcUtilsIsVideoMode1001Framerate;\npFunc_bfcUtilsGetFpsForVideoMode bfcUtilsGetFpsForVideoMode;\npFunc_bfcUtilsGetVideoModeExtForFrameInfo bfcUtilsGetVideoModeExtForFrameInfo;\npFunc_bfcUtilsGetFrameInfoForVideoModeExt bfcUtilsGetFrameInfoForVideoModeExt;\npFunc_bfcUtilsGetAudioSamplesPerFrame bfcUtilsGetAudioSamplesPerFrame;\npFunc_bfcUtilsInitVancBuffer bfcUtilsInitVancBuffer;\npFunc_bfcUtilsVancPktExtract bfcUtilsVancPktExtract;\npFunc_bfcUtilsVancPktInsert bfcUtilsVancPktInsert;\npFunc_bfcUtilsDecodeEia708bPkt bfcUtilsDecodeEia708bPkt;\n\n/* deprecated start */\npFunc_bfcUtilsGetVideoModeForFrameInfo bfcUtilsGetVideoModeForFrameInfo;\npFunc_bfcUtilsGetFrameInfoForVideoMode bfcUtilsGetFrameInfoForVideoMode; \npFunc_bfcGetVideoBytesPerLine bfcGetVideoBytesPerLine;\npFunc_bfcGetVancBytesPerLine bfcGetVancBytesPerLine;\n/* deprecated end */\n\nbool LoadFunctionPointers_BlueVelvetC()\n{\n    bool bAllFunctionsAvailable = false;\n#if defined(_WIN32)\n    #if defined(_WIN64)\n        #if defined(_DEBUG)\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC64_d.dll\", NULL, 0);\n        #else\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC64.dll\", NULL, 0);\n        #endif\n    #else\n        #if defined(_DEBUG)\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC_d.dll\", NULL, 0);\n        #else\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC.dll\", NULL, 0);\n        #endif\n    #endif\n#endif\n\n\n#if defined(__linux__)\n    void* hLib = dlopen(\"libBlueVelvetC64.so\", RTLD_LAZY | RTLD_GLOBAL);\n#endif\n\n    if(hLib)\n    {\n        bAllFunctionsAvailable = true;\n        do\n        {\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVersion);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVersionW);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcFactory);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcDestroy);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcEnumerate);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcQueryCardType);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcAttach);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSetMultiLinkMode);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcQueryMultiLinkMode);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcDetach);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcQueryCardProperty32);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcQueryCardProperty64);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSetCardProperty32);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSetCardProperty64);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetCardSerialNumber);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetCardFwVersion);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetCardHwFwVersions);\n#if defined(_WIN32)\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcWaitVideoSyncAsync);\n#endif\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcWaitVideoSync);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcWaitVideoInputSync);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcWaitVideoOutputSync);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoOutputCurrentFieldCount);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoInputCurrentFieldCount);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoCaptureStart);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoCaptureStop);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoPlaybackStart);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoPlaybackStop);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoPlaybackAllocate);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoPlaybackPresent);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcVideoPlaybackRelease);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetCaptureVideoFrameInfoEx);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcRenderBufferCapture);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcRenderBufferUpdate);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetRenderBufferCount);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcEncodeHancFrameEx);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcEncodeHancFrameWithUCZ);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcDecodeHancFrameEx);\n#if defined(_WIN32)\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSystemBufferReadAsync);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSystemBufferWriteAsync);\n#elif defined(__linux__)\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSystemBufferRead);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSystemBufferWrite);\n#endif\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSyncInfoCreate);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSyncInfoDelete);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSyncInfoWait);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSyncInfoWaitWithSyncOptions);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcDmaReadFromCardAsync);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcDmaWriteToCardAsync);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSerialPortWaitForInputData);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSerialPortRead);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSerialPortWrite);\n#if defined(_WIN32)\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetReferenceClockPhaseSettings);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcLoadOutputLUT1D);\n#endif\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoWidth);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoHeight);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoBytesPerLineV2);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoBytesPerFrame);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoBytesPerFrameGolden);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoInfo);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVancWidth);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVancHeight);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVancBytesPerLineV2);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVancBytesPerFrame);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVancInfo);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetBytesForGroupPixels);\n#if defined(_WIN32)\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetWindowsDriverHandle);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcSetDynamicMemoryFormatChange);\n#elif defined(__linux__)\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetFileHandle);\n#endif\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfAlloc);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfFree);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForCardType);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForCardType);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForBlueProductId);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForBlueProductId);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForVideoMode);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForVideoMode);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForMemoryFormat);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForMemoryFormat);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForUpdateFormat);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForUpdateFormat);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForVideoEngine);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForVideoEngine);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetStringForMr2Node);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetWStringForMr2Node);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetMR2Routing);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsSetMR2Routing);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetAudioOutputRouting);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsSetAudioOutputRouting);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsIsVideoModeProgressive);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsIsVideoMode1001Framerate);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetFpsForVideoMode);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetVideoModeExtForFrameInfo);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetFrameInfoForVideoModeExt);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetAudioSamplesPerFrame);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsInitVancBuffer);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsVancPktExtract);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsVancPktInsert);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsDecodeEia708bPkt);\n\n/* deprecated start */\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetVideoModeForFrameInfo);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcUtilsGetFrameInfoForVideoMode);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVideoBytesPerLine);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcGetVancBytesPerLine);\n/* deprecated end */\n\n\n        } while(0);\n    }\n\n    return bAllFunctionsAvailable;\n}\n#endif /* IMPLEMENTATION_BLUEVELVETC_FUNC_PTR */\n\n\ntypedef void* BFC_CONVERSION_HANDLE;\n\n/* FUNCTION PROTOTYPES FOR BLUEVELVETC CONVERSION FUNCTIONS */\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n    typedef BFC_CONVERSION_HANDLE(__cdecl* pFunc_bfcConversionFactory)();\n    typedef BLUE_VOID(__cdecl* pFunc_bfcConversionDestroy)(BFC_CONVERSION_HANDLE pHandle);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConversionGetAvailableThreadCount)(BFC_CONVERSION_HANDLE pHandle, BLUE_S32* pMaxThreadCount, BLUE_U32* pCurrentThreadCount);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConversionSetThreadCountLimit)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 MaxThreadCount);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_SquareDivisionToTsi_2VUY)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_SquareDivisionToTsi_ARGB32)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_SquareDivisionToTsi_BGR48)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_SquareDivisionToTsi_V210)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_TsiToSquareDivision_2VUY)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_TsiToSquareDivision_V210)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_TsiToSquareDivision_RGB)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_Single4KV210ToAligned4KV210Quadrants_SSE2)(BFC_CONVERSION_HANDLE pHandle, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_HalfFloatRGBATo16bitRGBA)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_HalfFloatRGBATo16bitRGB)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_FloatRGBATo16bitRGBA)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n    typedef BLUE_S32(__cdecl* pFunc_bfcConvert_FloatRGBATo16bitRGB)(BFC_CONVERSION_HANDLE pHandle, BLUE_U32 Width, BLUE_U32 Height, BLUE_VOID* pSrcBuffer, BLUE_VOID* pDstBuffer);\n\n#if defined(__cplusplus)\n} //\textern \"C\"\n#endif\n\n#ifdef IMPLEMENTATION_BLUEVELVETC_CONVERSION_FUNC_PTR\npFunc_bfcConversionFactory                                  bfcConversionFactory;\npFunc_bfcConversionDestroy                                  bfcConversionDestroy;\npFunc_bfcConversionGetAvailableThreadCount                  bfcConversionGetAvailableThreadCount;\npFunc_bfcConversionSetThreadCountLimit                      bfcConversionSetThreadCountLimit;\npFunc_bfcConvert_SquareDivisionToTsi_2VUY                   bfcConvert_SquareDivisionToTsi_2VUY;\npFunc_bfcConvert_SquareDivisionToTsi_ARGB32                 bfcConvert_SquareDivisionToTsi_ARGB32;\npFunc_bfcConvert_SquareDivisionToTsi_BGR48                  bfcConvert_SquareDivisionToTsi_BGR48;\npFunc_bfcConvert_SquareDivisionToTsi_V210                   bfcConvert_SquareDivisionToTsi_V210;\npFunc_bfcConvert_TsiToSquareDivision_2VUY                   bfcConvert_TsiToSquareDivision_2VUY;\npFunc_bfcConvert_TsiToSquareDivision_V210                   bfcConvert_TsiToSquareDivision_V210;\npFunc_bfcConvert_TsiToSquareDivision_RGB                    bfcConvert_TsiToSquareDivision_RGB;\npFunc_bfcConvert_Single4KV210ToAligned4KV210Quadrants_SSE2  bfcConvert_Single4KV210ToAligned4KV210Quadrants_SSE2;\npFunc_bfcConvert_HalfFloatRGBATo16bitRGBA                   bfcConvert_HalfFloatRGBATo16bitRGBA;\npFunc_bfcConvert_HalfFloatRGBATo16bitRGB                    bfcConvert_HalfFloatRGBATo16bitRGB;\npFunc_bfcConvert_FloatRGBATo16bitRGBA                       bfcConvert_FloatRGBATo16bitRGBA;\npFunc_bfcConvert_FloatRGBATo16bitRGB                        bfcConvert_FloatRGBATo16bitRGB;\n\nbool LoadFunctionPointers_BlueConversion()\n{\n    bool bAllFunctionsAvailable = false;\n#if defined(_WIN32)\n    #if defined(_WIN64)\n        #if defined(_DEBUG)\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC64_d.dll\", NULL, 0);\n        #else\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC64.dll\", NULL, 0);\n        #endif\n    #else\n        #if defined(_DEBUG)\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC_d.dll\", NULL, 0);\n        #else\n            HMODULE hLib = LoadLibraryExA(\"BlueVelvetC.dll\", NULL, 0);\n        #endif\n    #endif\n#endif\n\n    if(hLib)\n    {\n        bAllFunctionsAvailable = true;\n        do\n        {\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConversionFactory);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConversionDestroy);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConversionGetAvailableThreadCount);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConversionSetThreadCountLimit);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_SquareDivisionToTsi_2VUY);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_SquareDivisionToTsi_ARGB32);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_SquareDivisionToTsi_BGR48);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_SquareDivisionToTsi_V210);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_TsiToSquareDivision_2VUY);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_TsiToSquareDivision_V210);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_TsiToSquareDivision_RGB);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_Single4KV210ToAligned4KV210Quadrants_SSE2);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_HalfFloatRGBATo16bitRGBA);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_HalfFloatRGBATo16bitRGB);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_FloatRGBATo16bitRGBA);\n            GET_PROCADDR_FOR_FUNC(hLib, &bAllFunctionsAvailable, bfcConvert_FloatRGBATo16bitRGB);\n\n        } while(0);\n    }\n\n    return bAllFunctionsAvailable;\n}\n#endif /* IMPLEMENTATION_BLUEVELVETC_CONVERSION_FUNC_PTR */\n\n#endif /* HG_BLUEVELVETC_FUNC_PTR */\n\n"
  },
  {
    "path": "src/modules/bluefish/producer/bluefish_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author:Robert Nagy, ronag89@gmail.com\n *\t\t satchit puthenveetil\n *        James Wise, james.wise@bluefish444.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"bluefish_producer.h\"\n\n#include \"../util/blue_velvet.h\"\n#include \"../util/memory.h\"\n\n#include <common/diagnostics/graph.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/log.h>\n#include <common/param.h>\n#include <common/scope_exit.h>\n#include <common/timer.h>\n\n#include <ffmpeg/util/av_util.h>\n\n#include <core/diagnostics/call_context.h>\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <tbb/concurrent_queue.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n\n#include <boost/circular_buffer.hpp>\n#include <boost/format.hpp>\n#include <boost/range/algorithm.hpp>\n\n#include <mutex>\n\nextern \"C\" {\n#include <libavformat/avformat.h>\n#include <libavutil/pixfmt.h>\n#include <libavutil/samplefmt.h>\n#include <libavutil/timecode.h>\n}\n\nusing namespace caspar::ffmpeg;\n\nnamespace caspar { namespace bluefish {\n\nstatic const size_t MAX_DECODED_AUDIO_BUFFER_SIZE = 2002 * 16; // max 2002 samples, 16 channels.\n\nunsigned int get_bluesdk_input_videochannel_from_streamid(int stream_id)\n{\n    /*This function would return the corresponding EBlueVideoChannel from them stream_id argument */\n    switch (stream_id) {\n        case 1:\n            return BLUE_VIDEO_INPUT_CHANNEL_1;\n        case 2:\n            return BLUE_VIDEO_INPUT_CHANNEL_2;\n        case 3:\n            return BLUE_VIDEO_INPUT_CHANNEL_3;\n        case 4:\n            return BLUE_VIDEO_INPUT_CHANNEL_4;\n        case 5:\n            return BLUE_VIDEO_INPUT_CHANNEL_5;\n        case 6:\n            return BLUE_VIDEO_INPUT_CHANNEL_6;\n        case 7:\n            return BLUE_VIDEO_INPUT_CHANNEL_7;\n        case 8:\n            return BLUE_VIDEO_INPUT_CHANNEL_8;\n        default:\n            return BLUE_VIDEO_INPUT_CHANNEL_1;\n    }\n}\n\nunsigned int extract_pcm_data_from_hanc(bvc_wrapper&               blue,\n                                        struct hanc_decode_struct* decode_struct,\n                                        unsigned int               card_type,\n                                        unsigned int*              src_hanc_buffer,\n                                        unsigned int*              pcm_audio_buffer,\n                                        int                        audio_channels_to_extract)\n{\n    decode_struct->audio_pcm_data_ptr              = pcm_audio_buffer;\n    decode_struct->type_of_sample_required         = 0; // No flags indicates default of 32bit samples.\n    decode_struct->max_expected_audio_sample_count = 2002;\n\n    if (audio_channels_to_extract == 2)\n        decode_struct->audio_ch_required_mask = MONO_CHANNEL_1 | MONO_CHANNEL_2;\n    else if (audio_channels_to_extract == 8)\n        decode_struct->audio_ch_required_mask = MONO_CHANNEL_1 | MONO_CHANNEL_2 | MONO_CHANNEL_3 | MONO_CHANNEL_4 |\n                                                MONO_CHANNEL_5 | MONO_CHANNEL_6 | MONO_CHANNEL_7 | MONO_CHANNEL_8;\n    else if (audio_channels_to_extract == 16)\n        decode_struct->audio_ch_required_mask = MONO_CHANNEL_1 | MONO_CHANNEL_2 | MONO_CHANNEL_3 | MONO_CHANNEL_4 |\n                                                MONO_CHANNEL_5 | MONO_CHANNEL_6 | MONO_CHANNEL_7 | MONO_CHANNEL_8 |\n                                                MONO_CHANNEL_11 | MONO_CHANNEL_12 | MONO_CHANNEL_13 | MONO_CHANNEL_14 |\n                                                MONO_CHANNEL_15 | MONO_CHANNEL_16 | MONO_CHANNEL_17 | MONO_CHANNEL_18;\n\n    blue.decode_hanc_frame(card_type, src_hanc_buffer, decode_struct);\n    return decode_struct->no_audio_samples;\n}\n\nbool is_video_format_interlaced(const core::video_format format)\n{\n    bool interlaced = false;\n    if (format == core::video_format::x1080i5000 || format == core::video_format::x1080i5994 ||\n        format == core::video_format::x1080i6000 || format == core::video_format::pal ||\n        format == core::video_format::ntsc)\n        interlaced = true;\n\n    return interlaced;\n}\n\nbool is_bluefish_format_interlaced(unsigned int vid_mode)\n{\n    bool interlaced = false;\n    if (vid_mode == VID_FMT_EXT_PAL || vid_mode == VID_FMT_EXT_NTSC || vid_mode == VID_FMT_EXT_1080I_5000 ||\n        vid_mode == VID_FMT_EXT_1080I_5994 || vid_mode == VID_FMT_EXT_1080I_6000)\n        interlaced = true;\n\n    return interlaced;\n}\n\nstruct bluefish_producer\n{\n    const int                    device_index_;\n    const int                    stream_index_;\n    spl::shared_ptr<bvc_wrapper> blue_;\n\n    core::monitor::state                state_;\n    mutable std::mutex                  state_mutex_;\n    spl::shared_ptr<diagnostics::graph> graph_;\n    caspar::timer                       tick_timer_;\n    caspar::timer                       processing_benchmark_timer_;\n\n    std::vector<int>   audio_cadence_;\n    const std::wstring model_name_ = std::wstring(L\"bluefish\");\n\n    std::atomic_bool                   process_capture_ = true;\n    std::shared_ptr<std::thread>       capture_thread_;\n    std::array<blue_dma_buffer_ptr, 1> reserved_frames_;\n\n    core::video_format_desc format_desc_;\n    core::video_format_desc channel_format_desc_;\n    unsigned int            mode_;\n\n    spl::shared_ptr<core::frame_factory> frame_factory_;\n    const core::video_format_repository  format_repository_;\n    std::vector<uint8_t>                 conversion_buffer_;\n\n    tbb::concurrent_bounded_queue<core::draw_frame> frame_buffer_;\n    std::exception_ptr                              exception_;\n\n    ULONG schedule_capture_frame_id_   = 0;\n    ULONG capturing_frame_id_          = std::numeric_limits<ULONG>::max();\n    ULONG dma_ready_captured_frame_id_ = std::numeric_limits<ULONG>::max();\n\n    struct hanc_decode_struct hanc_decode_struct_;\n    std::vector<uint32_t>     decoded_audio_bytes_;\n    unsigned int              memory_format_on_card_;\n    unsigned int              sync_format_;\n    bool                      first_frame_              = true;\n    int                       frames_captured           = 0;\n    uint64_t                  capture_ts                = 0;\n    int                       remainaing_audio_samples_ = 0;\n    int uhd_mode_ = 0; // 0 -> Do Not Allow BVC-ML, 1 -> Auto ( ie. Native buffers will do default mode, or BVC will do\n                       // SQ.),  2 -> Force 2SI, 3 -> Force SQ\n\n    bluefish_producer(const bluefish_producer&)            = delete;\n    bluefish_producer& operator=(const bluefish_producer&) = delete;\n\n    bluefish_producer(const core::video_format_desc&              format_desc,\n                      int                                         device_index,\n                      int                                         stream_index,\n                      int                                         uhd_mode,\n                      const spl::shared_ptr<core::frame_factory>& frame_factory,\n                      const core::video_format_repository&        format_repository)\n        : device_index_(device_index)\n        , stream_index_(stream_index)\n        , blue_(create_blue(device_index))\n        , model_name_(get_card_desc(*blue_, device_index))\n        , channel_format_desc_(format_desc)\n        , frame_factory_(frame_factory)\n        , format_repository_(format_repository)\n        , memory_format_on_card_(MEM_FMT_RGB)\n        , sync_format_(UPD_FMT_FRAME)\n        , uhd_mode_(uhd_mode)\n    {\n        mode_ = static_cast<unsigned int>(VID_FMT_EXT_INVALID);\n        frame_buffer_.set_capacity(2);\n\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        graph_->set_color(\"frame-time\", diagnostics::color(1.0f, 0.0f, 0.0f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"output-buffer\", diagnostics::color(0.0f, 1.0f, 0.0f));\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        std::memset(&hanc_decode_struct_, 0, sizeof(hanc_decode_struct_));\n        hanc_decode_struct_.audio_input_source = AUDIO_INPUT_SOURCE_EMB;\n\n        decoded_audio_bytes_.resize(MAX_DECODED_AUDIO_BUFFER_SIZE);\n\n        // Configure input connector and routing\n        unsigned int bf_channel = get_bluesdk_input_videochannel_from_streamid(stream_index);\n        if (blue_->set_card_property32(DEFAULT_VIDEO_INPUT_CHANNEL, bf_channel))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to set input channel.\"));\n\n        if (configure_input_routing(bf_channel, true, uhd_mode_)) // to do: tofix pass rgba vs use actual dual link!!\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to set input routing.\"));\n\n        // Look for a valid input video mode\n        blue_->get_card_property32(VIDEO_MODE_EXT_INPUT, &mode_);\n        if (mode_ != VID_FMT_EXT_INVALID) {\n            if (uhd_mode_ == 1 || uhd_mode_ == 2 || uhd_mode_ == 3) {\n                blue_->set_multilink(device_index_, bf_channel);\n            }\n\n            blue_->get_card_property32(VIDEO_MODE_EXT_INPUT, &mode_);\n            format_desc_   = get_format_desc(format_repository,\n                                           *blue_,\n                                           static_cast<EVideoModeExt>(mode_),\n                                           static_cast<EMemoryFormat>(memory_format_on_card_));\n            audio_cadence_ = format_desc_.audio_cadence;\n\n            if (format_desc_.size == 0) {\n                CASPAR_LOG(warning) << print()\n                                    << TEXT(\"Problem getting the size of video buffer from SDK, calculating instead.\");\n                format_desc_.size = format_desc_.width * format_desc_.height * 3;\n            }\n\n            // Select input memory format\n            if (blue_->set_card_property32(VIDEO_INPUT_MEMORY_FORMAT, memory_format_on_card_))\n                CASPAR_THROW_EXCEPTION(caspar_exception()\n                                       << msg_info(print() + L\" Failed to set input memory format.\"));\n\n            // Select image orientation\n            if (blue_->set_card_property32(VIDEO_INPUTFRAMESTORE_IMAGE_ORIENTATION, ImageOrientation_Normal))\n                CASPAR_LOG(warning) << print() << L\" Failed to set image orientation to normal.\";\n\n            // Select data range   - // todo: confirm if we want to pass CGR or SMPTE range to caspar!!!!\n            if (blue_->set_card_property32(EPOCH_VIDEO_INPUT_RGB_DATA_RANGE, CGR_RANGE))\n                CASPAR_LOG(warning) << print() << L\" Failed to set RGB data range to CGR.\";\n\n            // If we have an interlaced input AND and interlaced project then we need to handle the incoming frames\n            // differently and sync on fields, instead of frame barriers\n            if (is_video_format_interlaced(format_desc.format) && is_bluefish_format_interlaced(mode_))\n                sync_format_ = UPD_FMT_FIELD;\n\n            // Select Update Mode for input\n            // HERE: this *might need to be sync format, but\n            // currently we will leave as Frame UPD\n            if (blue_->set_card_property32(VIDEO_INPUT_UPDATE_TYPE, UPD_FMT_FRAME))\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to set input update type.\"));\n\n            // Generate dma buffers\n            int n = 0;\n            boost::range::generate(reserved_frames_, [&] {\n                return std::make_shared<blue_dma_buffer>(static_cast<int>(format_desc_.size), n++);\n            });\n\n            // Allocate a single UHD buffer for conversion Buffer if we need it! .\n            if (uhd_mode_ == 2) {\n                conversion_buffer_.resize(static_cast<int>(format_desc_.size));\n            }\n\n            // Set Video Engine\n            if (blue_->set_card_property32(VIDEO_INPUT_ENGINE, VIDEO_ENGINE_FRAMESTORE))\n                CASPAR_LOG(warning) << print() << TEXT(\" Failed to set video engine.\");\n\n            capture_thread_ = std::make_shared<std::thread>([this] { capture_thread_actual(); });\n        }\n    }\n\n    int configure_input_routing(const unsigned int bf_channel, bool dual_link, int uhd_mode)\n    {\n        unsigned int routing_value   = 0;\n        unsigned int routing_value_b = 0;\n\n        /*This function would return the corresponding EBlueVideoChannel from the device output channel*/\n        switch (bf_channel) {\n            case BLUE_VIDEO_INPUT_CHANNEL_1:\n                if (dual_link) {\n                    routing_value = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_1, EPOCH_DEST_INPUT_MEM_INTERFACE_CH1, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1);\n                    routing_value_b = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_2, EPOCH_DEST_INPUT_MEM_INTERFACE_CH1, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2);\n                } else\n                    routing_value = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_1, EPOCH_DEST_INPUT_MEM_INTERFACE_CH1, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                break;\n            case BLUE_VIDEO_INPUT_CHANNEL_2:\n                if (dual_link) {\n                    routing_value = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_2, EPOCH_DEST_INPUT_MEM_INTERFACE_CH2, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1);\n                    routing_value_b = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_3, EPOCH_DEST_INPUT_MEM_INTERFACE_CH2, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2);\n                } else\n                    routing_value = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_2, EPOCH_DEST_INPUT_MEM_INTERFACE_CH2, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                break;\n            case BLUE_VIDEO_INPUT_CHANNEL_3:\n                if (dual_link) {\n                    routing_value = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_3, EPOCH_DEST_INPUT_MEM_INTERFACE_CH3, BLUE_CONNECTOR_PROP_DUALLINK_LINK_1);\n                    routing_value_b = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_4, EPOCH_DEST_INPUT_MEM_INTERFACE_CH3, BLUE_CONNECTOR_PROP_DUALLINK_LINK_2);\n                } else\n                    routing_value = EPOCH_SET_ROUTING(\n                        EPOCH_SRC_SDI_INPUT_3, EPOCH_DEST_INPUT_MEM_INTERFACE_CH3, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                break;\n            case BLUE_VIDEO_INPUT_CHANNEL_4:\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_4, EPOCH_DEST_INPUT_MEM_INTERFACE_CH4, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                break;\n            default:\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_1, EPOCH_DEST_INPUT_MEM_INTERFACE_CH1, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                break;\n        }\n\n        if (dual_link) {\n            blue_->set_card_property32(MR2_ROUTING, routing_value);\n            return blue_->set_card_property32(MR2_ROUTING, routing_value_b);\n        }\n\n        if (((uhd_mode == 1) || (uhd_mode == 2) || (uhd_mode == 3)) &&\n            ((bf_channel == BLUE_VIDEO_INPUT_CHANNEL_1) || (bf_channel == BLUE_VIDEO_INPUT_CHANNEL_5))) {\n            // Configure the input routing for the first 4 input channels\n            if (bf_channel == BLUE_VIDEO_INPUT_CHANNEL_1) {\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_1, EPOCH_DEST_INPUT_MEM_INTERFACE_CH1, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_2, EPOCH_DEST_INPUT_MEM_INTERFACE_CH2, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_3, EPOCH_DEST_INPUT_MEM_INTERFACE_CH3, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_4, EPOCH_DEST_INPUT_MEM_INTERFACE_CH4, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n            } else {\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_5, EPOCH_DEST_INPUT_MEM_INTERFACE_CH5, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_6, EPOCH_DEST_INPUT_MEM_INTERFACE_CH6, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_7, EPOCH_DEST_INPUT_MEM_INTERFACE_CH7, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n                routing_value = EPOCH_SET_ROUTING(\n                    EPOCH_SRC_SDI_INPUT_8, EPOCH_DEST_INPUT_MEM_INTERFACE_CH8, BLUE_CONNECTOR_PROP_SINGLE_LINK);\n                return blue_->set_card_property32(MR2_ROUTING, routing_value);\n            }\n        } else\n            return blue_->set_card_property32(MR2_ROUTING, routing_value);\n    }\n\n    void schedule_capture()\n    {\n        if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_)) {\n            blue_->render_buffer_capture(BlueBuffer_Image_HANC(schedule_capture_frame_id_));\n            dma_ready_captured_frame_id_ = capturing_frame_id_;\n            capturing_frame_id_          = schedule_capture_frame_id_;\n            schedule_capture_frame_id_   = (schedule_capture_frame_id_ + 1) % 4;\n        }\n    }\n\n    void get_capture_time() { blue_->get_card_property64(BTC_TIMER, &capture_ts); }\n\n    HRESULT process_data()\n    {\n        caspar::timer frame_timer;\n\n        // Get info for source video mode\n        unsigned int width          = 0;\n        unsigned int height         = 0;\n        unsigned int rate           = 0;\n        unsigned int is_1001        = 0;\n        unsigned int is_progressive = 0;\n        unsigned int image_size     = 0;\n        blue_->get_frame_info_for_video_mode(mode_, &width, &height, &rate, &is_1001, &is_progressive);\n        blue_->get_bytes_per_frame(static_cast<EVideoModeExt>(mode_),\n                                   static_cast<EMemoryFormat>(memory_format_on_card_),\n                                   static_cast<EUpdateMethod>(sync_format_),\n                                   &image_size);\n        double fps = rate;\n        if (is_1001 != 0u)\n            fps = static_cast<double>(rate) * 1000 / 1001;\n\n        CASPAR_SCOPE_EXIT\n        {\n            {\n                std::lock_guard<std::mutex> lock(state_mutex_);\n                state_[\"file/name\"]              = model_name_;\n                state_[\"file/path\"]              = device_index_;\n                state_[\"file/video/width\"]       = width;\n                state_[\"file/video/height\"]      = height;\n                state_[\"file/audio/sample-rate\"] = format_desc_.audio_sample_rate;\n                state_[\"file/audio/channels\"]    = format_desc_.audio_channels;\n                state_[\"file/fps\"]               = fps;\n                state_[\"profiler/time\"]          = {frame_timer.elapsed(), fps};\n                state_[\"buffer\"]                 = {frame_buffer_.size(), frame_buffer_.capacity()};\n            }\n\n            graph_->set_value(\"frame-time\", frame_timer.elapsed() * fps / format_desc_.field_count * 0.5);\n            graph_->set_value(\"output-buffer\",\n                              static_cast<float>(frame_buffer_.size()) / static_cast<float>(frame_buffer_.capacity()));\n        };\n\n        try {\n            graph_->set_value(\"tick-time\", tick_timer_.elapsed() * fps * 0.5);\n            tick_timer_.restart();\n            {\n                auto src_video = alloc_frame();\n                auto src_audio = alloc_frame();\n\n                // video\n                src_video->format           = AV_PIX_FMT_RGB24;\n                src_video->width            = width;\n                src_video->height           = height;\n                src_video->interlaced_frame = !is_progressive;\n                src_video->top_field_first  = height != 486;\n                src_video->key_frame        = 1;\n                // src_video->display_picture_number = frames_captured;\n                src_video->pts = capture_ts;\n\n                void* video_bytes = reserved_frames_.front()->image_data();\n                if (reserved_frames_.front() && video_bytes) {\n                    src_video->data[0]     = reinterpret_cast<uint8_t*>(reserved_frames_.front()->image_data());\n                    src_video->linesize[0] = static_cast<int>(width * 3); // image_size / height);\n                }\n\n                // Audio\n                src_audio->format = AV_SAMPLE_FMT_S32;\n                av_channel_layout_default(&src_audio->ch_layout, format_desc_.audio_channels);\n                src_audio->sample_rate = format_desc_.audio_sample_rate;\n                src_audio->nb_samples  = 0;\n                int samples_decoded    = 0;\n\n                // hmm is audio on first frame or do we need to wait till snd field to get audio?\n                if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && first_frame_)) {\n                    void* audio_bytes = nullptr;\n                    auto  hanc_buffer = reinterpret_cast<uint8_t*>(reserved_frames_.front()->hanc_data());\n                    if (hanc_buffer) {\n                        int card_type = CRD_INVALID;\n                        blue_->query_card_type(&card_type, device_index_);\n                        auto no_extracted_pcm_samples =\n                            extract_pcm_data_from_hanc(*blue_,\n                                                       &hanc_decode_struct_,\n                                                       card_type,\n                                                       reinterpret_cast<unsigned int*>(hanc_buffer),\n                                                       reinterpret_cast<unsigned int*>(&decoded_audio_bytes_[0]),\n                                                       format_desc_.audio_channels);\n\n                        audio_bytes = reinterpret_cast<int32_t*>(&decoded_audio_bytes_[0]);\n\n                        samples_decoded       = no_extracted_pcm_samples / format_desc_.audio_channels;\n                        src_audio->nb_samples = samples_decoded;\n                        src_audio->data[0]    = reinterpret_cast<uint8_t*>(audio_bytes);\n                        src_audio->linesize[0] =\n                            src_audio->nb_samples * format_desc_.audio_channels *\n                            av_get_bytes_per_sample(static_cast<AVSampleFormat>(src_audio->format));\n                        src_audio->pts = capture_ts;\n                    }\n                }\n\n                if (sync_format_ == UPD_FMT_FIELD) {\n                    // since we provide an entire frame for each field in interlaced modes, we need to adjust the\n                    // src_audio\n                    if (first_frame_) {\n                        remainaing_audio_samples_ = src_audio->nb_samples - src_audio->nb_samples / 2;\n                        src_audio->nb_samples     = src_audio->nb_samples / 2;\n                    } else {\n                        auto audio_bytes = reinterpret_cast<uint8_t*>(&decoded_audio_bytes_[0]);\n                        if (audio_bytes) {\n                            src_audio->nb_samples     = remainaing_audio_samples_;\n                            int bytes_left            = remainaing_audio_samples_ * 4 * format_desc_.audio_channels;\n                            src_audio->data[0]        = audio_bytes + bytes_left;\n                            src_audio->linesize[0]    = bytes_left;\n                            remainaing_audio_samples_ = 0;\n                        }\n                    }\n                }\n\n                if (uhd_mode_ == 2 && conversion_buffer_.size() <= (width * height * 3)) {\n                    // Do additional processing required to handle a 2SI input\n                    memcpy(&conversion_buffer_[0], reserved_frames_.front()->image_data(), (width * height * 3));\n                    blue_->convert_2si_to_sq(\n                        width, height, &conversion_buffer_[0], reserved_frames_.front()->image_data());\n                }\n\n                // pass to caspar\n                auto frame = core::draw_frame(make_frame(this, *frame_factory_, src_video, src_audio));\n                if (!frame_buffer_.try_push(frame)) {\n                    core::draw_frame dummy;\n                    frame_buffer_.try_pop(dummy);\n                    frame_buffer_.try_push(frame);\n                    graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n                    CASPAR_LOG(warning) << print() << TEXT(\" ERROR dropped frame.\");\n                }\n\n                if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_))\n                    boost::range::rotate(audio_cadence_, std::end(audio_cadence_) - 1);\n            }\n        } catch (...) {\n            exception_ = std::current_exception();\n            return E_FAIL;\n        }\n\n        return S_OK;\n    }\n\n    bool grab_frame_from_bluefishcard()\n    {\n        try {\n            if (reserved_frames_.front()->image_data()) {\n                if (sync_format_ == UPD_FMT_FIELD && first_frame_) {\n                    blue_->system_buffer_read(const_cast<uint8_t*>(reserved_frames_.front()->image_data()),\n                                              static_cast<unsigned long>(reserved_frames_.front()->image_size()),\n                                              BlueImage_HANC_DMABuffer(dma_ready_captured_frame_id_, BLUE_DATA_FRAME),\n                                              0);\n                } else if (sync_format_ == UPD_FMT_FRAME) {\n                    blue_->system_buffer_read(const_cast<uint8_t*>(reserved_frames_.front()->image_data()),\n                                              static_cast<unsigned long>(reserved_frames_.front()->image_size()),\n                                              BlueImage_HANC_DMABuffer(dma_ready_captured_frame_id_, BLUE_DATA_IMAGE),\n                                              0);\n                }\n            } else {\n                CASPAR_LOG(warning) << print() << TEXT(\" NO image data in reserved frames list.\");\n                return false;\n            }\n            if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_)) {\n                if (reserved_frames_.front()->hanc_data()) {\n                    blue_->system_buffer_read(const_cast<uint8_t*>(reserved_frames_.front()->hanc_data()),\n                                              static_cast<unsigned long>(reserved_frames_.front()->hanc_size()),\n                                              BlueImage_HANC_DMABuffer(dma_ready_captured_frame_id_, BLUE_DATA_HANC),\n                                              0);\n                    //    CASPAR_LOG(warning) << print() << TEXT(\" Hanc DMA Buf ID: \") << dma_ready_captured_frame_id_;\n                }\n            }\n        } catch (...) {\n            exception_ = std::current_exception();\n        }\n        return true;\n    }\n\n    void capture_thread_actual()\n    {\n        ULONG        current_field_count        = 0;\n        ULONG        last_field_count           = 0;\n        ULONG        start_field_count          = 0;\n        unsigned int current_input_video_signal = VID_FMT_EXT_INVALID;\n\n        last_field_count  = current_field_count;\n        start_field_count = current_field_count;\n\n        blue_->wait_video_input_sync(UPD_FMT_FRAME, &current_field_count);\n        while (process_capture_) {\n            // tell the card to capture another frame at the next interrupt\n            schedule_capture();\n            blue_->wait_video_input_sync((EUpdateMethod)sync_format_, &current_field_count);\n            get_capture_time();\n\n            if (last_field_count + 3 < current_field_count)\n                CASPAR_LOG(warning) << L\"Error: dropped \" << (current_field_count - last_field_count - 2) / 2\n                                    << L\" frames\" << L\"Current \" << current_field_count << L\"  Old \"\n                                    << last_field_count;\n\n            last_field_count = current_field_count;\n            blue_->get_card_property32(VIDEO_MODE_EXT_INPUT, &current_input_video_signal);\n            if (current_input_video_signal != VID_FMT_EXT_INVALID &&\n                dma_ready_captured_frame_id_ != std::numeric_limits<ULONG>::max()) {\n                // DoneID is now what ScheduleID was at the last iteration when we called\n                // render_buffer_capture(ScheduleID) we just checked if the video signal for the buffer “DoneID” was\n                // valid while it was capturing so we can DMA the buffer DMA the frame from the card to our buffer\n                if (grab_frame_from_bluefishcard())\n                    process_data();\n                processing_benchmark_timer_.restart();\n            }\n            if (sync_format_ == UPD_FMT_FRAME || (sync_format_ == UPD_FMT_FIELD && !first_frame_))\n                boost::range::rotate(reserved_frames_, std::begin(reserved_frames_) + 1);\n\n            frames_captured++;\n\n            if (sync_format_ == UPD_FMT_FIELD)\n                first_frame_ = !first_frame_;\n        }\n    }\n\n    ~bluefish_producer()\n    {\n        try {\n            process_capture_ = false;\n            if (capture_thread_) {\n                Sleep(41);\n                capture_thread_->join();\n            }\n\n            blue_->detach();\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n    }\n\n    core::draw_frame get_frame(const core::video_field field)\n    {\n        if (exception_ != nullptr)\n            std::rethrow_exception(exception_);\n\n        // TODO - field\n\n        core::draw_frame frame;\n        if (!frame_buffer_.try_pop(frame)) {\n            graph_->set_tag(diagnostics::tag_severity::WARNING, \"late-frame\");\n        }\n        return frame;\n    }\n\n    bool is_ready() { return !frame_buffer_.empty(); }\n\n    std::wstring print() const\n    {\n        return model_name_ + L\" [\" + std::to_wstring(device_index_) + L\"|\" + format_desc_.name + L\"]\";\n    }\n\n    core::monitor::state state() const\n    {\n        std::lock_guard<std::mutex> lock(state_mutex_);\n        return state_;\n    }\n};\n\nclass bluefish_producer_proxy : public core::frame_producer\n{\n    std::unique_ptr<bluefish_producer> producer_;\n    const uint32_t                     length_;\n    executor                           executor_;\n\n  public:\n    explicit bluefish_producer_proxy(const core::video_format_desc&              format_desc,\n                                     const spl::shared_ptr<core::frame_factory>& frame_factory,\n                                     const core::video_format_repository&        format_repository,\n                                     int                                         device_index,\n                                     int                                         stream_index,\n                                     int                                         uhd_mode,\n                                     uint32_t                                    length)\n        : length_(length)\n        , executor_(L\"bluefish_producer[\" + std::to_wstring(device_index) + L\"]\")\n    {\n        auto ctx = core::diagnostics::call_context::for_thread();\n        executor_.invoke([=, this] {\n            core::diagnostics::call_context::for_thread() = ctx;\n            producer_.reset(new bluefish_producer(\n                format_desc, device_index, stream_index, uhd_mode, frame_factory, format_repository));\n        });\n    }\n\n    ~bluefish_producer_proxy()\n    {\n        executor_.invoke([=, this] { producer_.reset(); });\n    }\n\n    core::monitor::state state() const override { return producer_->state(); }\n\n    // frame_producer\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        return producer_->get_frame(field);\n    }\n\n    core::draw_frame first_frame(const core::video_field field) override { return receive_impl(field, 0); }\n\n    core::draw_frame last_frame(const core::video_field field) override\n    {\n        return core::draw_frame::still(producer_->get_frame(field));\n    }\n\n    bool is_ready() override { return producer_->is_ready(); }\n\n    uint32_t nb_frames() const override { return length_; }\n\n    std::wstring print() const override { return producer_->print(); }\n\n    std::wstring name() const override { return L\"bluefish\"; }\n};\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params)\n{\n    if (params.empty() || !boost::iequals(params.at(0), \"bluefish\"))\n        return core::frame_producer::empty();\n\n    auto device_index = get_param(L\"DEVICE\", params, -1);\n    if (device_index == -1)\n        device_index = std::stoi(params.at(1));\n\n    auto stream_index = get_param(L\"SDI-STREAM\", params, -1);\n    if (stream_index == -1)\n        stream_index = 1;\n\n    auto uhd_mode = get_param(L\"UHD-MODE\", params, -1);\n    if (uhd_mode == -1)\n        uhd_mode = 0;\n\n    auto length         = get_param(L\"LENGTH\", params, std::numeric_limits<uint32_t>::max());\n    auto in_format_desc = dependencies.format_repository.find(get_param(L\"FORMAT\", params, L\"INVALID\"));\n\n    return spl::make_shared<bluefish_producer_proxy>(dependencies.format_desc,\n                                                     dependencies.frame_factory,\n                                                     dependencies.format_repository,\n                                                     device_index,\n                                                     stream_index,\n                                                     uhd_mode,\n                                                     length);\n}\n}} // namespace caspar::bluefish\n"
  },
  {
    "path": "src/modules/bluefish/producer/bluefish_producer.h",
    "content": "/*\r\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r\n *\r\n * This file is part of CasparCG (www.casparcg.com).\r\n *\r\n * CasparCG is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * CasparCG is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r\n *\r\n * Author: Robert Nagy, ronag89@gmail.com\r\n *\t\t  satchit puthenveetil\r\n *         James Wise, james.wise@bluefish444.com\r\n */\r\n\r\n#pragma once\r\n\r\n#include <core/fwd.h>\r\n\r\n#include <string>\r\n#include <vector>\r\n\r\nnamespace caspar { namespace bluefish {\r\n\r\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\r\n                                                      const std::vector<std::wstring>&         params);\r\n\r\n}} // namespace caspar::bluefish\r\n"
  },
  {
    "path": "src/modules/bluefish/util/blue_velvet.cpp",
    "content": "/*\r\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r\n *\r\n * This file is part of CasparCG (www.casparcg.com).\r\n *\r\n * CasparCG is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * CasparCG is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r\n *\r\n * Author: Robert Nagy, ronag89@gmail.com\r\n */\r\n\r\n#include \"blue_velvet.h\"\r\n#include \"../StdAfx.h\"\r\n#include <core/video_format.h>\r\n\r\n#define IMPLEMENTATION_BLUEVELVETC_FUNC_PTR\r\n#define IMPLEMENTATION_BLUEVELVETC_CONVERSION_FUNC_PTR\r\n#include \"../interop/BlueVelvetCFuncPtr.h\"\r\n\r\nnamespace caspar { namespace bluefish {\r\n\r\nbvc_wrapper::bvc_wrapper()\r\n{\r\n    if (LoadFunctionPointers_BlueVelvetC())\r\n        bvc_ = std::shared_ptr<void>(bfcFactory(), bfcDestroy);\r\n\r\n    if (LoadFunctionPointers_BlueConversion())\r\n        bvc_conv_ = std::shared_ptr<void>(bfcConversionFactory(), bfcConversionDestroy);\r\n\r\n    if (!bvc_ || !bvc_conv_)\r\n        CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\r\n                                   \"Bluefish drivers not found.\\nDriver not installed?\\nMinimum Version is V6.3.0.2\"));\r\n}\r\n\r\nconst char* bvc_wrapper::get_version() { return bfcGetVersion(); }\r\n\r\nBLUE_U32 bvc_wrapper::attach(int iDeviceId) { return bfcAttach(bvc_.get(), iDeviceId); }\r\n\r\nBLUE_U32 bvc_wrapper::detach() { return bfcDetach(bvc_.get()); }\r\n\r\nBLUE_U32 bvc_wrapper::set_multilink(const int iDeviceID, const int memChannel)\r\n{\r\n    if (memChannel == -1)\r\n        return (BLUE_U32)bfcSetMultiLinkMode(bvc_.get(), NULL); // ie. detach from multiLink\r\n\r\n    blue_multi_link_info_struct attach_info = {};\r\n    attach_info.InputControl                = 1;\r\n    attach_info.Link1_Device                = iDeviceID;\r\n    attach_info.Link2_Device                = iDeviceID;\r\n    attach_info.Link3_Device                = iDeviceID;\r\n    attach_info.Link4_Device                = iDeviceID;\r\n\r\n    if (memChannel == BLUE_VIDEO_INPUT_CHANNEL_1) {\r\n        attach_info.Link1_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_1;\r\n        attach_info.Link2_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_2;\r\n        attach_info.Link3_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_3;\r\n        attach_info.Link4_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_4;\r\n    } else if (memChannel == BLUE_VIDEO_INPUT_CHANNEL_5) {\r\n        attach_info.Link5_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_5;\r\n        attach_info.Link6_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_6;\r\n        attach_info.Link7_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_7;\r\n        attach_info.Link8_MemChannel = BLUE_VIDEO_INPUT_CHANNEL_8;\r\n    } else if (memChannel == BLUE_VIDEO_OUTPUT_CHANNEL_1) {\r\n        attach_info.Link1_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_1;\r\n        attach_info.Link2_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_2;\r\n        attach_info.Link3_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_3;\r\n        attach_info.Link4_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_4;\r\n    } else if (memChannel == BLUE_VIDEO_OUTPUT_CHANNEL_5) {\r\n        attach_info.Link5_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_5;\r\n        attach_info.Link6_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_6;\r\n        attach_info.Link7_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_7;\r\n        attach_info.Link8_MemChannel = BLUE_VIDEO_OUTPUT_CHANNEL_8;\r\n    }\r\n\r\n    return (BLUE_U32)bfcSetMultiLinkMode(bvc_.get(), &attach_info);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::get_card_property32(const int iProperty, unsigned int* nValue)\r\n{\r\n    return (BLUE_U32)bfcQueryCardProperty32(bvc_.get(), iProperty, nValue);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::set_card_property32(const int iProperty, const unsigned int nValue)\r\n{\r\n    return bfcSetCardProperty32(bvc_.get(), iProperty, nValue);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::get_card_property64(const int iProperty, unsigned long long* nValue)\r\n{\r\n    return (BLUE_U32)bfcQueryCardProperty64(bvc_.get(), iProperty, nValue);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::set_card_property64(const int iProperty, const unsigned long long nValue)\r\n{\r\n    return bfcSetCardProperty64(bvc_.get(), iProperty, nValue);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::enumerate(int* iDevices) { return bfcEnumerate(bvc_.get(), iDevices); }\r\n\r\nBLUE_U32 bvc_wrapper::query_card_type(int* iCardType, int iDeviceID)\r\n{\r\n    return bfcQueryCardType(bvc_.get(), iCardType, iDeviceID);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::system_buffer_write(unsigned char* pPixels,\r\n                                          unsigned long  ulSize,\r\n                                          unsigned long  ulBufferID,\r\n                                          unsigned long  ulOffset)\r\n{\r\n    return bfcSystemBufferWriteAsync(bvc_.get(), pPixels, ulSize, nullptr, ulBufferID, ulOffset);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::system_buffer_read(unsigned char* pPixels,\r\n                                         unsigned long  ulSize,\r\n                                         unsigned long  ulBufferID,\r\n                                         unsigned long  ulOffset)\r\n{\r\n#if 1\r\n    return bfcSystemBufferReadAsync(bvc_.get(), pPixels, ulSize, nullptr, ulBufferID, ulOffset);\r\n#else\r\n    BFC_SYNC_INFO bsi    = bfcSyncInfoCreate(bvc_.get());\r\n    BLUE_U32      retVal = 0;\r\n    retVal               = bfcDmaReadFromCardAsync(bvc_.get(), pPixels, ulSize, bsi, ulBufferID, ulOffset);\r\n    int wrv              = bfcSyncInfoWait(bvc_.get(), bsi, 20);\r\n    int x                = wrv + 0;\r\n    x++;\r\n    bfcSyncInfoDelete(bvc_.get(), bsi);\r\n    return retVal;\r\n#endif\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::video_playback_stop(int iWait, int iFlush)\r\n{\r\n    return bfcVideoPlaybackStop(bvc_.get(), iWait, iFlush);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::video_playback_start(int step, int loop) { return bfcVideoPlaybackStart(bvc_.get(), step, loop); }\r\n\r\nBLUE_U32 bvc_wrapper::video_playback_allocate(unsigned long* buffer_id, unsigned long* underrun)\r\n{\r\n    void* unused = nullptr;\r\n    return bfcVideoPlaybackAllocate(bvc_.get(), &unused, buffer_id, underrun);\r\n}\r\n\r\nBLUE_U32\r\nbvc_wrapper::video_playback_present(unsigned long buffer_id, unsigned long count, unsigned long keep, unsigned long odd)\r\n{\r\n    unsigned long unique_id;\r\n    return bfcVideoPlaybackPresent(bvc_.get(), &unique_id, buffer_id, count, keep, odd);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::wait_video_output_sync(unsigned long ulUpdateType, unsigned long* ulFieldCount)\r\n{\r\n    return bfcWaitVideoOutputSync(bvc_.get(), ulUpdateType, ulFieldCount);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::wait_video_input_sync(unsigned long ulUpdateType, unsigned long* ulFieldCount)\r\n{\r\n    return bfcWaitVideoInputSync(bvc_.get(), ulUpdateType, ulFieldCount);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::render_buffer_update(unsigned long ulBufferID)\r\n{\r\n    return bfcRenderBufferUpdate(bvc_.get(), ulBufferID);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::render_buffer_capture(unsigned long ulBufferID)\r\n{\r\n    return bfcRenderBufferCapture(bvc_.get(), ulBufferID);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::encode_hanc_frame(unsigned int             nCardType,\r\n                                        hanc_stream_info_struct* pHancEncodeInfo,\r\n                                        void*                    pAudioBuffer,\r\n                                        unsigned int             nAudioChannels,\r\n                                        unsigned int             nAudioSamples,\r\n                                        unsigned int             nSampleType,\r\n                                        unsigned int             nAudioFlags)\r\n{\r\n    return bfcEncodeHancFrameEx(bvc_.get(),\r\n                                CRD_BLUE_NEUTRON,\r\n                                pHancEncodeInfo,\r\n                                pAudioBuffer,\r\n                                nAudioChannels,\r\n                                nAudioSamples,\r\n                                nSampleType,\r\n                                nAudioFlags);\r\n}\r\n\r\nBLUE_U32\r\nbvc_wrapper::decode_hanc_frame(unsigned int nCardType, unsigned int* pHancBuffer, hanc_decode_struct* pHancDecodeInfo)\r\n{\r\n    return bfcDecodeHancFrameEx(bvc_.get(), CRD_BLUE_NEUTRON, pHancBuffer, pHancDecodeInfo);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::get_frame_info_for_video_mode(const unsigned int nVideoModeExt,\r\n                                                    unsigned int*      nWidth,\r\n                                                    unsigned int*      nHeight,\r\n                                                    unsigned int*      nRate,\r\n                                                    unsigned int*      bIs1001,\r\n                                                    unsigned int*      bIsProgressive)\r\n{\r\n    return bfcUtilsGetFrameInfoForVideoModeExt(nVideoModeExt, nWidth, nHeight, nRate, bIs1001, bIsProgressive);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::get_bytes_per_frame(EVideoModeExt nVideoModeExt,\r\n                                          EMemoryFormat nMemoryFormat,\r\n                                          EUpdateMethod nUpdateMethod,\r\n                                          unsigned int* nBytesPerFrame)\r\n{\r\n    return bfcGetVideoBytesPerFrame(nVideoModeExt, nUpdateMethod, nMemoryFormat, nBytesPerFrame);\r\n}\r\n\r\nstd::string bvc_wrapper::get_string_for_card_type(unsigned int nCardType)\r\n{\r\n    return bfcUtilsGetStringForCardType(nCardType);\r\n}\r\n\r\nstd::wstring bvc_wrapper::get_wstring_for_video_mode(unsigned int nVideoModeExt)\r\n{\r\n    std::wstring mode_desc;\r\n    switch (nVideoModeExt) {\r\n        case VID_FMT_EXT_PAL:\r\n            mode_desc = L\"pal\";\r\n            break;\r\n        case VID_FMT_EXT_NTSC:\r\n            mode_desc = L\"ntsc\";\r\n            break;\r\n        case VID_FMT_EXT_720P_2398:\r\n            mode_desc = L\"720p23\";\r\n            break;\r\n        case VID_FMT_EXT_720P_2400:\r\n            mode_desc = L\"720p24\";\r\n            break;\r\n        case VID_FMT_EXT_720P_2500:\r\n            mode_desc = L\"720p25\";\r\n            break;\r\n        case VID_FMT_EXT_720P_5000:\r\n            mode_desc = L\"720p50\";\r\n            break;\r\n        case VID_FMT_EXT_720P_2997:\r\n            mode_desc = L\"720p29\";\r\n            break;\r\n        case VID_FMT_EXT_720P_5994:\r\n            mode_desc = L\"720p59\";\r\n            break;\r\n        case VID_FMT_EXT_720P_3000:\r\n            mode_desc = L\"720p30\";\r\n            break;\r\n        case VID_FMT_EXT_720P_6000:\r\n            mode_desc = L\"720p60\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_2398:\r\n            mode_desc = L\"1080p23\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_2400:\r\n            mode_desc = L\"1080p24\";\r\n            break;\r\n        case VID_FMT_EXT_1080I_5000:\r\n            mode_desc = L\"1080i50\";\r\n            break;\r\n        case VID_FMT_1080I_5994:\r\n            mode_desc = L\"1080i59\";\r\n            break;\r\n        case VID_FMT_EXT_1080I_6000:\r\n            mode_desc = L\"1080i60\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_2500:\r\n            mode_desc = L\"1080p25\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_2997:\r\n            mode_desc = L\"1080p29\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_3000:\r\n            mode_desc = L\"1080p30\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_5000:\r\n            mode_desc = L\"1080p50\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_5994:\r\n            mode_desc = L\"1080p59\";\r\n            break;\r\n        case VID_FMT_EXT_1080P_6000:\r\n            mode_desc = L\"1080p60\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_2398:\r\n            mode_desc = L\"2160p23\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_2400:\r\n            mode_desc = L\"2160p24\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_2500:\r\n            mode_desc = L\"2160p25\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_2997:\r\n            mode_desc = L\"2160p29\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_3000:\r\n            mode_desc = L\"2160p30\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_5000:\r\n            mode_desc = L\"2160p50\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_5994:\r\n            mode_desc = L\"2160p59\";\r\n            break;\r\n        case VID_FMT_EXT_2160P_6000:\r\n            mode_desc = L\"2160p60\";\r\n            break;\r\n        default:\r\n            mode_desc = L\"invalid\";\r\n            break;\r\n    }\r\n    return mode_desc;\r\n}\r\n\r\nint bvc_wrapper::get_num_audio_samples_for_frame(const BLUE_U32 nVideoModeExt, const BLUE_U32 nFrameNo)\r\n{\r\n    return bfcUtilsGetAudioSamplesPerFrame(nVideoModeExt, nFrameNo);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::convert_2si_to_sq(const BLUE_U32 Width, const BLUE_U32 Height, BLUE_VOID* pSrc, BLUE_VOID* pDst)\r\n{\r\n    return bfcConvert_TsiToSquareDivision_RGB(bvc_conv_.get(), Width, Height, pSrc, pDst);\r\n}\r\n\r\nBLUE_U32 bvc_wrapper::convert_sq_to_2si(const BLUE_U32 Width, const BLUE_U32 Height, BLUE_VOID* pSrc, BLUE_VOID* pDst)\r\n{\r\n    return bfcConvert_SquareDivisionToTsi_ARGB32(bvc_conv_.get(), Width, Height, pSrc, pDst);\r\n}\r\n\r\nEVideoModeExt vid_fmt_from_video_format(const core::video_format& fmt)\r\n{\r\n    switch (fmt) {\r\n        case core::video_format::pal:\r\n            return VID_FMT_EXT_PAL;\r\n        case core::video_format::ntsc:\r\n            return VID_FMT_EXT_NTSC;\r\n        case core::video_format::x576p2500:\r\n            return VID_FMT_EXT_INVALID; // not supported\r\n        case core::video_format::x720p2398:\r\n            return VID_FMT_EXT_720P_2398;\r\n        case core::video_format::x720p2400:\r\n            return VID_FMT_EXT_720P_2400;\r\n        case core::video_format::x720p2500:\r\n            return VID_FMT_EXT_720P_2500;\r\n        case core::video_format::x720p5000:\r\n            return VID_FMT_EXT_720P_5000;\r\n        case core::video_format::x720p2997:\r\n            return VID_FMT_EXT_720P_2997;\r\n        case core::video_format::x720p5994:\r\n            return VID_FMT_EXT_720P_5994;\r\n        case core::video_format::x720p3000:\r\n            return VID_FMT_EXT_720P_3000;\r\n        case core::video_format::x720p6000:\r\n            return VID_FMT_EXT_720P_6000;\r\n        case core::video_format::x1080p2398:\r\n            return VID_FMT_EXT_1080P_2398;\r\n        case core::video_format::x1080p2400:\r\n            return VID_FMT_EXT_1080P_2400;\r\n        case core::video_format::x1080i5000:\r\n            return VID_FMT_EXT_1080I_5000;\r\n        case core::video_format::x1080i5994:\r\n            return VID_FMT_EXT_1080I_5994;\r\n        case core::video_format::x1080i6000:\r\n            return VID_FMT_EXT_1080I_6000;\r\n        case core::video_format::x1080p2500:\r\n            return VID_FMT_EXT_1080P_2500;\r\n        case core::video_format::x1080p2997:\r\n            return VID_FMT_EXT_1080P_2997;\r\n        case core::video_format::x1080p3000:\r\n            return VID_FMT_EXT_1080P_3000;\r\n        case core::video_format::x1080p5000:\r\n            return VID_FMT_EXT_1080P_5000;\r\n        case core::video_format::x1080p5994:\r\n            return VID_FMT_EXT_1080P_5994;\r\n        case core::video_format::x1080p6000:\r\n            return VID_FMT_EXT_1080P_6000;\r\n        case core::video_format::x2160p2398:\r\n            return VID_FMT_EXT_2160P_2398;\r\n        case core::video_format::x2160p2400:\r\n            return VID_FMT_EXT_2160P_2400;\r\n        case core::video_format::x2160p2500:\r\n            return VID_FMT_EXT_2160P_2500;\r\n        case core::video_format::x2160p2997:\r\n            return VID_FMT_EXT_2160P_2997;\r\n        case core::video_format::x2160p3000:\r\n            return VID_FMT_EXT_2160P_3000;\r\n        case core::video_format::x2160p5000:\r\n            return VID_FMT_EXT_2160P_5000;\r\n        case core::video_format::x2160p5994:\r\n            return VID_FMT_EXT_2160P_5994;\r\n        case core::video_format::x2160p6000:\r\n            return VID_FMT_EXT_2160P_6000;\r\n\r\n        default:\r\n            return VID_FMT_EXT_INVALID;\r\n    }\r\n}\r\n\r\nbool is_epoch_card(bvc_wrapper& blue)\r\n{\r\n    int device_id = 1;\r\n    int card_type = 0;\r\n    blue.query_card_type(&card_type, device_id);\r\n\r\n    switch (card_type) {\r\n        case CRD_BLUE_EPOCH_HORIZON:\r\n        case CRD_BLUE_EPOCH_CORE:\r\n        case CRD_BLUE_EPOCH_ULTRA:\r\n        case CRD_BLUE_EPOCH_2K_HORIZON:\r\n        case CRD_BLUE_EPOCH_2K_CORE:\r\n        case CRD_BLUE_EPOCH_2K_ULTRA:\r\n        case CRD_BLUE_CREATE_HD:\r\n        case CRD_BLUE_CREATE_2K:\r\n        case CRD_BLUE_CREATE_2K_ULTRA:\r\n        case CRD_BLUE_SUPER_NOVA:\r\n        case CRD_BLUE_SUPER_NOVA_S_PLUS:\r\n        case CRD_BLUE_NEUTRON:\r\n        case CRD_BLUE_EPOCH_CG:\r\n            return true;\r\n        default:\r\n            return false;\r\n    }\r\n}\r\n\r\nbool is_kronos_card(bvc_wrapper& blue)\r\n{\r\n    int device_id = 1;\r\n    int card_type = 0;\r\n    blue.query_card_type(&card_type, device_id);\r\n\r\n    switch (card_type) {\r\n        case CRD_BLUE_KRONOS_ELEKTRON:\r\n        case CRD_BLUE_KRONOS_OPTIKOS:\r\n        case CRD_BLUE_KRONOS_K8:\r\n            return true;\r\n        default:\r\n            return false;\r\n    }\r\n}\r\n\r\nbool is_epoch_neutron_1i2o_card(bvc_wrapper& blue)\r\n{\r\n    BLUE_U32 val = 0;\r\n    blue.get_card_property32(EPOCH_GET_PRODUCT_ID, &val);\r\n    if (val == ORAC_NEUTRON_1_IN_2_OUT_FIRMWARE_PRODUCTID)\r\n        return true;\r\n    return false;\r\n}\r\n\r\nbool is_epoch_neutron_3o_card(bvc_wrapper& blue)\r\n{\r\n    BLUE_U32 val = 0;\r\n    blue.get_card_property32(EPOCH_GET_PRODUCT_ID, &val);\r\n\r\n    if (val == ORAC_NEUTRON_0_IN_3_OUT_FIRMWARE_PRODUCTID)\r\n        return true;\r\n    return false;\r\n}\r\n\r\nstd::wstring get_card_desc(bvc_wrapper blue, int device_id)\r\n{\r\n    std::wstring card_desc;\r\n    int          card_type = 0;\r\n    blue.query_card_type(&card_type, device_id);\r\n\r\n    switch (card_type) {\r\n        case CRD_BLUE_EPOCH_2K_CORE:\r\n            card_desc = L\"Bluefish Epoch 2K Core\";\r\n            break;\r\n        case CRD_BLUE_EPOCH_2K_ULTRA:\r\n            card_desc = L\"Bluefish Epoch 2K Ultra\";\r\n            break;\r\n        case CRD_BLUE_EPOCH_HORIZON:\r\n            card_desc = L\"Bluefish Epoch Horizon\";\r\n            break;\r\n        case CRD_BLUE_EPOCH_CORE:\r\n            card_desc = L\"Blufishe Epoch Core\";\r\n            break;\r\n        case CRD_BLUE_EPOCH_ULTRA:\r\n            card_desc = L\"Bluefish Epoch Ultra\";\r\n            break;\r\n        case CRD_BLUE_CREATE_HD:\r\n            card_desc = L\"Bluefish Create HD\";\r\n            break;\r\n        case CRD_BLUE_CREATE_2K:\r\n            card_desc = L\"Bluefish Create 2K\";\r\n            break;\r\n        case CRD_BLUE_CREATE_2K_ULTRA:\r\n            card_desc = L\"Bluefish Create 2K Ultra\";\r\n            break;\r\n        case CRD_BLUE_SUPER_NOVA:\r\n            card_desc = L\"Bluefish SuperNova\";\r\n            break;\r\n        case CRD_BLUE_SUPER_NOVA_S_PLUS:\r\n            card_desc = L\"Bluefish SuperNova s+\";\r\n            break;\r\n        case CRD_BLUE_NEUTRON:\r\n            card_desc = L\"Bluefish Neutron 4k\";\r\n            break;\r\n        case CRD_BLUE_EPOCH_CG:\r\n            card_desc = L\"Bluefish Epoch CG\";\r\n            break;\r\n        case CRD_BLUE_KRONOS_ELEKTRON:\r\n            card_desc = L\"Bluefish Kronos Elektron\";\r\n            break;\r\n        case CRD_BLUE_KRONOS_OPTIKOS:\r\n            card_desc = L\"Bluefish Kronos Optikos\";\r\n            break;\r\n        case CRD_BLUE_KRONOS_K8:\r\n            card_desc = L\"Bluefish Kronos K8\";\r\n            break;\r\n        default:\r\n            card_desc = L\"Unknown\";\r\n    }\r\n    return card_desc;\r\n}\r\n\r\nEVideoModeExt get_video_mode(bvc_wrapper& blue, const core::video_format_desc& format_desc)\r\n{\r\n    EVideoModeExt vid_fmt_ext = VID_FMT_EXT_INVALID;\r\n\r\n    if ((format_desc.width <= 2048) || is_kronos_card(blue))\r\n        vid_fmt_ext = vid_fmt_from_video_format(format_desc.format);\r\n\r\n    if (vid_fmt_ext == VID_FMT_EXT_INVALID)\r\n        CASPAR_THROW_EXCEPTION(not_supported() << msg_info(L\"video-mode not supported: \" + format_desc.name));\r\n\r\n    return vid_fmt_ext;\r\n}\r\n\r\nspl::shared_ptr<bvc_wrapper> create_blue()\r\n{\r\n    auto pWrap = new bvc_wrapper();\r\n    return spl::shared_ptr<bvc_wrapper>(pWrap);\r\n}\r\n\r\nspl::shared_ptr<bvc_wrapper> create_blue(int device_index)\r\n{\r\n    auto blue = create_blue();\r\n\r\n    if (blue->attach(device_index))\r\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to attach device.\"));\r\n\r\n    return blue;\r\n}\r\n\r\ncore::video_format_desc get_format_desc(const core::video_format_repository& format_repository,\r\n                                        bvc_wrapper&                         blue,\r\n                                        EVideoModeExt                        vid_fmt_ext,\r\n                                        EMemoryFormat                        mem_fmt)\r\n{\r\n    core::video_format_desc fmt;\r\n    unsigned int     width, height, duration = 0, time_scale = 0, rate = 0, bIs1001 = 0, is_progressive = 0, size = 0;\r\n    std::vector<int> audio_cadence;\r\n    int              field_count = 1;\r\n\r\n    blue.get_frame_info_for_video_mode(vid_fmt_ext, &width, &height, &rate, &bIs1001, &is_progressive);\r\n    CASPAR_LOG(warning) << L\"vfe is \" << vid_fmt_ext << L\" w: \" << width << L\" h:\" << height << L\" rate:\" << rate\r\n                        << L\"is1001 \" << bIs1001 << L\"isProgressive \" << is_progressive;\r\n    blue.get_bytes_per_frame(vid_fmt_ext, mem_fmt, UPD_FMT_FRAME, &size);\r\n\r\n    CASPAR_LOG(warning) << L\"vfe is \" << vid_fmt_ext << L\" size is: \" << size;\r\n\r\n    switch (vid_fmt_ext) {\r\n        case VID_FMT_EXT_NTSC:\r\n        case VID_FMT_EXT_1080I_5994:\r\n            duration      = 30000;\r\n            time_scale    = 1001;\r\n            audio_cadence = {1601, 1602, 1601, 1602, 1602};\r\n            break;\r\n        case VID_FMT_EXT_2K_1080P_2500:\r\n        case VID_FMT_EXT_2K_1080PSF_2500:\r\n        case VID_FMT_EXT_576I_5000:\r\n        case VID_FMT_EXT_1080P_2500:\r\n        case VID_FMT_EXT_1080I_5000:\r\n        case VID_FMT_EXT_1080PSF_2500:\r\n        case VID_FMT_EXT_720P_2500:\r\n        case VID_FMT_EXT_2160P_2500:\r\n            duration      = 25000;\r\n            time_scale    = 1000;\r\n            audio_cadence = {1920, 1920, 1920, 1920, 1920};\r\n            break;\r\n\r\n        case VID_FMT_EXT_720P_5994:\r\n        case VID_FMT_EXT_2K_1080P_5994:\r\n        case VID_FMT_EXT_1080P_5994:\r\n        case VID_FMT_EXT_2160P_5994:\r\n            duration      = 60000;\r\n            time_scale    = 1001;\r\n            audio_cadence = {801, 800, 801, 800, 800};\r\n            break;\r\n\r\n        case VID_FMT_EXT_1080P_6000:\r\n        case VID_FMT_EXT_2K_1080P_6000:\r\n        case VID_FMT_EXT_720P_6000:\r\n        case VID_FMT_EXT_2160P_6000:\r\n            duration      = 60000;\r\n            time_scale    = 1000;\r\n            audio_cadence = {801, 800, 801, 800, 800};\r\n            break;\r\n\r\n        case VID_FMT_EXT_1080PSF_2398:\r\n        case VID_FMT_EXT_1080P_2398:\r\n        case VID_FMT_EXT_720P_2398:\r\n        case VID_FMT_EXT_2K_1080PSF_2398:\r\n        case VID_FMT_EXT_2K_1080P_2398:\r\n        case VID_FMT_EXT_2160P_2398:\r\n            duration      = 24000;\r\n            time_scale    = 1000;\r\n            audio_cadence = {2002, 2002, 2002, 2002, 2002};\r\n            break;\r\n\r\n        case VID_FMT_EXT_1080PSF_2400:\r\n        case VID_FMT_EXT_1080P_2400:\r\n        case VID_FMT_EXT_720P_2400:\r\n        case VID_FMT_EXT_2K_1080PSF_2400:\r\n        case VID_FMT_EXT_2K_1080P_2400:\r\n        case VID_FMT_EXT_2160P_2400:\r\n            duration      = 24000;\r\n            time_scale    = 1000;\r\n            audio_cadence = {2000, 2000, 2000, 2000, 2000};\r\n            break;\r\n\r\n        case VID_FMT_EXT_1080I_6000:\r\n        case VID_FMT_EXT_1080PSF_3000:\r\n            duration      = 30000;\r\n            time_scale    = 1000;\r\n            audio_cadence = {1600, 1600, 1600, 1600, 1600};\r\n            break;\r\n\r\n        case VID_FMT_EXT_720P_2997:\r\n        case VID_FMT_EXT_1080P_2997:\r\n        case VID_FMT_EXT_2K_1080PSF_2997:\r\n        case VID_FMT_EXT_2K_1080P_2997:\r\n        case VID_FMT_EXT_1080PSF_2997:\r\n        case VID_FMT_EXT_2160P_2997:\r\n            duration      = 30000;\r\n            time_scale    = 1001;\r\n            audio_cadence = {1602, 1601, 1602, 1601, 1602};\r\n            break;\r\n\r\n        case VID_FMT_EXT_720P_3000:\r\n        case VID_FMT_EXT_1080P_3000:\r\n        case VID_FMT_EXT_2K_1080PSF_3000:\r\n        case VID_FMT_EXT_2K_1080P_3000:\r\n        case VID_FMT_EXT_2160P_3000:\r\n            duration      = 30000;\r\n            time_scale    = 1001;\r\n            audio_cadence = {1600, 1600, 1600, 1600, 1600};\r\n            break;\r\n\r\n        case VID_FMT_EXT_720P_5000:\r\n        case VID_FMT_EXT_1080P_5000:\r\n        case VID_FMT_EXT_2K_1080P_5000:\r\n        case VID_FMT_EXT_2160P_5000:\r\n            audio_cadence = {960, 960, 960, 960, 960};\r\n            duration      = 50000;\r\n            time_scale    = 1000;\r\n            break;\r\n    }\r\n\r\n    if (is_progressive == 0u)\r\n        field_count = 2;\r\n\r\n    fmt.field_count   = field_count;\r\n    fmt               = format_repository.find_format(get_caspar_video_format(vid_fmt_ext));\r\n    fmt.size          = size;\r\n    fmt.audio_cadence = std::move(audio_cadence);\r\n    fmt.name          = blue.get_wstring_for_video_mode(vid_fmt_ext);\r\n\r\n    return fmt;\r\n}\r\n\r\nstd::wstring get_sdi_inputs(bvc_wrapper& blue)\r\n{\r\n    BLUE_U32 val = 0;\r\n    blue.get_card_property32(CARD_FEATURE_CONNECTOR_INFO, &val);\r\n    int connectors = CARD_FEATURE_GET_SDI_INPUT_CONNECTOR_COUNT(val);\r\n    return std::to_wstring(connectors);\r\n}\r\n\r\nstd::wstring get_sdi_outputs(bvc_wrapper& blue)\r\n{\r\n    BLUE_U32 val = 0;\r\n    blue.get_card_property32(CARD_FEATURE_CONNECTOR_INFO, &val);\r\n    int connectors = CARD_FEATURE_GET_SDI_OUTPUT_CONNECTOR_COUNT(val);\r\n    return std::to_wstring(connectors);\r\n}\r\n\r\nEVideoModeExt get_bluefish_video_format(core::video_format fmt)\r\n{\r\n    // TODO: add support for UHD 4K formats\r\n\r\n    switch (fmt) {\r\n        case core::video_format::pal:\r\n            return VID_FMT_EXT_PAL;\r\n        case core::video_format::ntsc:\r\n            return VID_FMT_EXT_NTSC;\r\n        case core::video_format::x720p2398:\r\n            return VID_FMT_EXT_720P_2398;\r\n        case core::video_format::x720p2400:\r\n            return VID_FMT_EXT_720P_2400;\r\n        case core::video_format::x720p2500:\r\n            return VID_FMT_EXT_720P_2500;\r\n        case core::video_format::x720p2997:\r\n            return VID_FMT_EXT_720P_2997;\r\n        case core::video_format::x720p3000:\r\n            return VID_FMT_EXT_720P_3000;\r\n        case core::video_format::x720p5000:\r\n            return VID_FMT_EXT_720P_5000;\r\n        case core::video_format::x720p5994:\r\n            return VID_FMT_EXT_720P_5994;\r\n        case core::video_format::x720p6000:\r\n            return VID_FMT_EXT_720P_6000;\r\n        case core::video_format::x1080i5000:\r\n            return VID_FMT_EXT_1080I_5000;\r\n        case core::video_format::x1080i5994:\r\n            return VID_FMT_EXT_1080I_5994;\r\n        case core::video_format::x1080i6000:\r\n            return VID_FMT_EXT_1080I_6000;\r\n        case core::video_format::x1080p2398:\r\n            return VID_FMT_EXT_1080P_2398;\r\n        case core::video_format::x1080p2400:\r\n            return VID_FMT_EXT_1080P_2400;\r\n        case core::video_format::x1080p2500:\r\n            return VID_FMT_EXT_1080P_2500;\r\n        case core::video_format::x1080p2997:\r\n            return VID_FMT_EXT_1080P_2997;\r\n        case core::video_format::x1080p3000:\r\n            return VID_FMT_EXT_1080P_3000;\r\n        case core::video_format::x1080p5000:\r\n            return VID_FMT_EXT_1080P_5000;\r\n        case core::video_format::x1080p5994:\r\n            return VID_FMT_EXT_1080P_5994;\r\n        case core::video_format::x1080p6000:\r\n            return VID_FMT_EXT_1080P_6000;\r\n        case core::video_format::x2160p2398:\r\n            return VID_FMT_EXT_2160P_2398;\r\n        case core::video_format::x2160p2400:\r\n            return VID_FMT_EXT_2160P_2400;\r\n        case core::video_format::x2160p2500:\r\n            return VID_FMT_EXT_2160P_2500;\r\n        case core::video_format::x2160p2997:\r\n            return VID_FMT_EXT_2160P_2997;\r\n        case core::video_format::x2160p3000:\r\n            return VID_FMT_EXT_2160P_3000;\r\n        case core::video_format::x2160p5000:\r\n            return VID_FMT_EXT_2160P_5000;\r\n        case core::video_format::x2160p5994:\r\n            return VID_FMT_EXT_2160P_5994;\r\n        case core::video_format::x2160p6000:\r\n            return VID_FMT_EXT_2160P_6000;\r\n        default:\r\n            return VID_FMT_EXT_INVALID;\r\n    }\r\n}\r\n\r\nstatic core::video_format get_caspar_video_format(EVideoModeExt fmt)\r\n{\r\n    switch (fmt) {\r\n        case VID_FMT_EXT_PAL:\r\n            return core::video_format::pal;\r\n        case VID_FMT_EXT_NTSC:\r\n            return core::video_format::ntsc;\r\n        case VID_FMT_EXT_720P_2398:\r\n            return core::video_format::x720p2398;\r\n        case VID_FMT_EXT_720P_2400:\r\n            return core::video_format::x720p2400;\r\n        case VID_FMT_EXT_720P_2500:\r\n            return core::video_format::x720p2500;\r\n        case VID_FMT_EXT_720P_5000:\r\n            return core::video_format::x720p5000;\r\n        case VID_FMT_EXT_720P_2997:\r\n            return core::video_format::x720p2997;\r\n        case VID_FMT_EXT_720P_5994:\r\n            return core::video_format::x720p5994;\r\n        case VID_FMT_EXT_720P_3000:\r\n            return core::video_format::x720p3000;\r\n        case VID_FMT_EXT_720P_6000:\r\n            return core::video_format::x720p6000;\r\n        case VID_FMT_EXT_1080P_2398:\r\n        case VID_FMT_EXT_1080PSF_2398:\r\n            return core::video_format::x1080p2398;\r\n        case VID_FMT_EXT_1080P_2400:\r\n        case VID_FMT_EXT_1080PSF_2400:\r\n            return core::video_format::x1080p2400;\r\n        case VID_FMT_EXT_1080I_5000:\r\n            return core::video_format::x1080i5000;\r\n        case VID_FMT_EXT_1080I_5994:\r\n            return core::video_format::x1080i5994;\r\n        case VID_FMT_EXT_1080I_6000:\r\n            return core::video_format::x1080i6000;\r\n        case VID_FMT_EXT_1080P_2500:\r\n        case VID_FMT_EXT_1080PSF_2500:\r\n            return core::video_format::x1080p2500;\r\n        case VID_FMT_EXT_1080P_2997:\r\n        case VID_FMT_EXT_1080PSF_2997:\r\n            return core::video_format::x1080p2997;\r\n        case VID_FMT_EXT_1080P_3000:\r\n        case VID_FMT_EXT_1080PSF_3000:\r\n            return core::video_format::x1080p3000;\r\n        case VID_FMT_EXT_1080P_5000:\r\n            return core::video_format::x1080p5000;\r\n        case VID_FMT_EXT_1080P_5994:\r\n            return core::video_format::x1080p5994;\r\n        case VID_FMT_EXT_1080P_6000:\r\n            return core::video_format::x1080p6000;\r\n        case VID_FMT_EXT_2160P_2398:\r\n            return core::video_format::x2160p2398;\r\n        case VID_FMT_EXT_2160P_2400:\r\n            return core::video_format::x2160p2400;\r\n        case VID_FMT_EXT_2160P_2500:\r\n            return core::video_format::x2160p2500;\r\n        case VID_FMT_EXT_2160P_2997:\r\n            return core::video_format::x2160p2997;\r\n        case VID_FMT_EXT_2160P_3000:\r\n            return core::video_format::x2160p3000;\r\n        case VID_FMT_EXT_2160P_5000:\r\n            return core::video_format::x2160p5000;\r\n        case VID_FMT_EXT_2160P_5994:\r\n            return core::video_format::x2160p5994;\r\n        case VID_FMT_EXT_2160P_6000:\r\n            return core::video_format::x2160p6000;\r\n        default:\r\n            return core::video_format::invalid;\r\n    }\r\n}\r\n\r\n}} // namespace caspar::bluefish\r\n"
  },
  {
    "path": "src/modules/bluefish/util/blue_velvet.h",
    "content": "/*\r\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\r\n *\r\n * This file is part of CasparCG (www.casparcg.com).\r\n *\r\n * CasparCG is free software: you can redistribute it and/or modify\r\n * it under the terms of the GNU General Public License as published by\r\n * the Free Software Foundation, either version 3 of the License, or\r\n * (at your option) any later version.\r\n *\r\n * CasparCG is distributed in the hope that it will be useful,\r\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r\n * GNU General Public License for more details.\r\n *\r\n * You should have received a copy of the GNU General Public License\r\n * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.\r\n *\r\n * Author: Robert Nagy, ronag89@gmail.com\r\n */\r\n\r\n#pragma once\r\n\r\n#include <Windows.h>\r\n\r\n#include <common/except.h>\r\n#include <common/memory.h>\r\n#include <core/fwd.h>\r\n#include <core/video_format.h>\r\n\r\n#include \"../interop/BlueDriver_p.h\"\r\n\r\nnamespace caspar { namespace bluefish {\r\n\r\nclass bvc_wrapper\r\n{\r\n  public:\r\n    bvc_wrapper(); // bfcFactory + function pointer lookups\r\n    const char* get_version();\r\n\r\n    BLUE_U32 enumerate(int* iDevices);\r\n    BLUE_U32 query_card_type(int* iCardType, int iDeviceID);\r\n\r\n    BLUE_U32 attach(int iDeviceId);\r\n    BLUE_U32 detach();\r\n    BLUE_U32 set_multilink(const int iDeviceID, const int memChannel);\r\n\r\n    BLUE_U32 get_card_property32(const int iProperty, unsigned int* nValue);\r\n    BLUE_U32 set_card_property32(const int iProperty, const unsigned int nValue);\r\n\r\n    BLUE_U32 get_card_property64(const int iProperty, unsigned long long* nValue);\r\n    BLUE_U32 set_card_property64(const int iProperty, const unsigned long long nValue);\r\n\r\n    BLUE_U32\r\n    system_buffer_write(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset);\r\n    BLUE_U32\r\n    system_buffer_read(unsigned char* pPixels, unsigned long ulSize, unsigned long ulBufferID, unsigned long ulOffset);\r\n\r\n    BLUE_U32 video_playback_stop(int iWait, int iFlush);\r\n    BLUE_U32 video_playback_start(int wait, int loop);\r\n    BLUE_U32 video_playback_allocate(unsigned long* buffer_id, unsigned long* underrun);\r\n    BLUE_U32\r\n    video_playback_present(unsigned long buffer_id, unsigned long count, unsigned long keep, unsigned long odd);\r\n\r\n    BLUE_U32 wait_video_output_sync(unsigned long ulUpdateType, unsigned long* ulFieldCount);\r\n    BLUE_U32 wait_video_input_sync(unsigned long ulUpdateType, unsigned long* ulFieldCount);\r\n\r\n    BLUE_U32 render_buffer_update(unsigned long ulBufferID);\r\n    BLUE_U32 render_buffer_capture(unsigned long ulBufferID);\r\n\r\n    BLUE_U32 encode_hanc_frame(unsigned int                    nCardType,\r\n                               struct hanc_stream_info_struct* pHancEncodeInfo,\r\n                               void*                           pAudioBuffer,\r\n                               unsigned int                    nAudioChannels,\r\n                               unsigned int                    nAudioSamples,\r\n                               unsigned int                    nSampleType,\r\n                               unsigned int                    nAudioFlags);\r\n    BLUE_U32\r\n    decode_hanc_frame(unsigned int nCardType, unsigned int* pHancBuffer, struct hanc_decode_struct* pHancDecodeInfo);\r\n\r\n    BLUE_U32 get_frame_info_for_video_mode(const unsigned int nVideoModeExt,\r\n                                           unsigned int*      nWidth,\r\n                                           unsigned int*      nHeight,\r\n                                           unsigned int*      nRate,\r\n                                           unsigned int*      bIs1001,\r\n                                           unsigned int*      bIsProgressive);\r\n    BLUE_U32 get_bytes_per_frame(EVideoModeExt nVideoMode,\r\n                                 EMemoryFormat nMemoryFormat,\r\n                                 EUpdateMethod nUpdateMethod,\r\n                                 unsigned int* nBytesPerFrame);\r\n\r\n    std::string  get_string_for_card_type(unsigned int nCardType);\r\n    std::wstring get_wstring_for_video_mode(unsigned int nVideoMode);\r\n\r\n    int get_num_audio_samples_for_frame(const BLUE_U32 nVideoMode, const BLUE_U32 nFrameNo);\r\n\r\n    // UHD Conversion functions...\r\n    BLUE_U32 convert_2si_to_sq(const BLUE_U32 Width, const BLUE_U32 Height, BLUE_VOID* pSrc, BLUE_VOID* pDst);\r\n    BLUE_U32 convert_sq_to_2si(const BLUE_U32 Width, const BLUE_U32 Height, BLUE_VOID* pSrc, BLUE_VOID* pDst);\r\n\r\n  private:\r\n    std::shared_ptr<void> bvc_;\r\n    std::shared_ptr<void> bvc_conv_;\r\n};\r\n\r\nspl::shared_ptr<bvc_wrapper> create_blue();\r\nspl::shared_ptr<bvc_wrapper> create_blue(int device_index);\r\n\r\ncore::video_format_desc get_format_desc(const core::video_format_repository& format_repository,\r\n                                        bvc_wrapper&                         blue,\r\n                                        EVideoModeExt                        vid_fmt,\r\n                                        EMemoryFormat                        mem_fmt);\r\n\r\nbool         is_epoch_card(bvc_wrapper& blue);\r\nbool         is_kronos_card(bvc_wrapper& blue);\r\nbool         is_epoch_neutron_1i2o_card(bvc_wrapper& blue);\r\nbool         is_epoch_neutron_3o_card(bvc_wrapper& blue);\r\nstd::wstring get_card_desc(bvc_wrapper blue, int device_id);\r\nstd::wstring get_sdi_inputs(bvc_wrapper& blue);\r\nstd::wstring get_sdi_outputs(bvc_wrapper& blue);\r\n\r\nEVideoModeExt             get_bluefish_video_format(core::video_format fmt);\r\nstatic core::video_format get_caspar_video_format(EVideoModeExt fmt);\r\n\r\n}} // namespace caspar::bluefish\r\n"
  },
  {
    "path": "src/modules/bluefish/util/memory.h",
    "content": "/*\n* Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n*\n* This file is part of CasparCG (www.casparcg.com).\n*\n* CasparCG 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* CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n*\n* Author: Robert Nagy, ronag89@gmail.com\n          James Wise, james.wise@bluefish444.com\n*/\n\n#pragma once\n\n#include <Windows.h>\n#include <boost/align.hpp>\n#include <vector>\n\nnamespace caspar { namespace bluefish {\n\nstatic const size_t MAX_HANC_BUFFER_SIZE = 256 * 1024;\nstatic const size_t MAX_VBI_BUFFER_SIZE  = 36 * 1920 * 4;\n\nstruct blue_dma_buffer\n{\n  public:\n    blue_dma_buffer(int image_size, int id)\n        : id_(id)\n        , image_size_(image_size)\n        , hanc_size_(MAX_HANC_BUFFER_SIZE)\n        , image_buffer_(image_size_)\n        , hanc_buffer_(hanc_size_)\n    {\n    }\n\n    int id() const { return id_; }\n\n    PBYTE image_data() { return image_buffer_.data(); }\n    PBYTE hanc_data() { return hanc_buffer_.data(); }\n\n    size_t image_size() const { return image_size_; }\n    size_t hanc_size() const { return hanc_size_; }\n\n  private:\n    int                                                              id_;\n    size_t                                                           image_size_;\n    size_t                                                           hanc_size_;\n    std::vector<BYTE, boost::alignment::aligned_allocator<BYTE, 64>> image_buffer_;\n    std::vector<BYTE, boost::alignment::aligned_allocator<BYTE, 64>> hanc_buffer_;\n};\nusing blue_dma_buffer_ptr = std::shared_ptr<blue_dma_buffer>;\n\n}} // namespace caspar::bluefish\n"
  },
  {
    "path": "src/modules/decklink/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (decklink)\n\nset(SOURCES\n\t\tconsumer/decklink_consumer.cpp\n\t\tconsumer/decklink_consumer.h\n\t\tconsumer/v210_strategies.cpp\n\t\tconsumer/sdr_bgra_strategy.cpp\n\t\tconsumer/format_strategy.h\n\t\tconsumer/config.cpp\n\t\tconsumer/config.h\n\t\tconsumer/monitor.cpp\n\t\tconsumer/monitor.h\n\t\tconsumer/vanc.cpp\n\t\tconsumer/vanc.h\n\t\tconsumer/vanc_scte104_strategy.cpp\n\t\tconsumer/vanc_op47_strategy.cpp\n\n\t\tproducer/decklink_producer.cpp\n\t\tproducer/decklink_producer.h\n\n\t\tutil/util.h\n\n\t\tdecklink.cpp\n\t\tdecklink.h\n\n\t\tdecklink_api.h\n\t\tStdAfx.h\n)\n\nif (MSVC)\n\tlist(APPEND SOURCES\n\t\t\tinterop/DeckLinkAPI_i.c\n\t\t\tinterop/DeckLinkAPI.h\n\t\t\tinterop/DeckLinkAPIVersion.h\n\t)\nelse()\n\tlist(APPEND SOURCES\n\t\t\tlinux_interop/DeckLinkAPIConfiguration.h\n\t\t\tlinux_interop/DeckLinkAPIDeckControl.h\n\t\t\tlinux_interop/DeckLinkAPIDispatch.cpp\n\t\t\tlinux_interop/DeckLinkAPIModes.h\n\t\t\tlinux_interop/DeckLinkAPI_v10_2.h\n\t\t\tlinux_interop/DeckLinkAPI_v7_3.h\n\t\t\tlinux_interop/DeckLinkAPI_v7_9.h\n\t\t\tlinux_interop/DeckLinkAPI_v8_1.h\n\t\t\tlinux_interop/DeckLinkAPI_v9_9.h\n\t\t\tlinux_interop/LinuxCOM.h\n\t\t\tlinux_interop/DeckLinkAPIConfiguration_v10_2.h\n\t\t\tlinux_interop/DeckLinkAPIDiscovery.h\n\t\t\tlinux_interop/DeckLinkAPI.h\n\t\t\tlinux_interop/DeckLinkAPITypes.h\n\t\t\tlinux_interop/DeckLinkAPI_v7_1.h\n\t\t\tlinux_interop/DeckLinkAPI_v7_6.h\n\t\t\tlinux_interop/DeckLinkAPI_v8_0.h\n\t\t\tlinux_interop/DeckLinkAPI_v9_2.h\n\t\t\tlinux_interop/DeckLinkAPIVersion.h\n\t)\nendif ()\n\ncasparcg_add_module_project(decklink\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"decklink::init\"\n)\ntarget_include_directories(decklink PRIVATE\n    ..\n    ${FFMPEG_INCLUDE_PATH}\n    )\ntarget_precompile_headers(decklink PRIVATE \"StdAfx.h\")\n\nset_target_properties(decklink PROPERTIES FOLDER modules)\nsource_group(sources ./*)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources\\\\interop interop/*)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources\\\\util util/*)\n\nif (MSVC)\n\ttarget_link_libraries(decklink PRIVATE\n\t\t\tffmpeg\n\t)\nelse()\n\ttarget_link_libraries(decklink PRIVATE\n\t\t\tffmpeg\n\n\t\t\tdl\n\t)\nendif ()\n\n"
  },
  {
    "path": "src/modules/decklink/StdAfx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#ifdef __cplusplus\n#if defined _DEBUG && defined _MSC_VER\n#include <crtdbg.h>\n#endif\n\n#define NOMINMAX\n#define WIN32_LEAN_AND_MEAN\n\n#if defined(_MSC_VER)\n#include <Windows.h>\n#endif\n\n#include <algorithm>\n#include <array>\n#include <assert.h>\n#include <atomic>\n#include <boost/algorithm/string.hpp>\n#include <boost/circular_buffer.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/range.hpp>\n#include <boost/range/algorithm.hpp>\n#include <deque>\n#include <functional>\n#include <math.h>\n#include <memory>\n#include <mutex>\n#include <queue>\n#include <string>\n#include <tbb/cache_aligned_allocator.h>\n#include <tbb/concurrent_queue.h>\n#include <vector>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavcodec/avcodec.h>\n}\n\n#if defined(_MSC_VER)\n#include <atlbase.h>\n\n#include <atlcom.h>\n#include <atlhost.h>\n#endif\n\n#include <functional>\n\n#include <common/except.h>\n#include <common/log.h>\n#include <common/memory.h>\n#include <common/timer.h>\n#include <common/utf.h>\n#endif\n\n#if defined(_MSC_VER)\n#include <rpc.h>\n#include <rpcndr.h>\n#endif\n"
  },
  {
    "path": "src/modules/decklink/consumer/config.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"config.h\"\n\n#include <common/param.h>\n#include <common/ptree.h>\n\n#ifdef WIN32\n#include <isa_availability.h>\n\n#define CHECK_INSTRUCTION_SUPPORT(a, v) (__check_arch_support((a), (v)) || __check_isa_support((a), (v)))\n#endif\n\nnamespace caspar { namespace decklink {\n\nport_configuration parse_output_config(const boost::property_tree::wptree&  ptree,\n                                       const core::video_format_repository& format_repository)\n{\n    port_configuration port_config;\n    port_config.device_index = ptree.get(L\"device\", static_cast<int64_t>(-1));\n    port_config.key_only     = ptree.get(L\"key-only\", port_config.key_only);\n\n    auto format_desc_str = ptree.get(L\"video-mode\", L\"\");\n    if (!format_desc_str.empty()) {\n        auto format_desc = format_repository.find(format_desc_str);\n        if (format_desc.format == core::video_format::invalid || format_desc.format == core::video_format::custom)\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid video-mode: \" + format_desc_str));\n        port_config.format = format_desc;\n    }\n\n    auto subregion_tree = ptree.get_child_optional(L\"subregion\");\n    if (subregion_tree) {\n        port_config.src_x    = subregion_tree->get(L\"src-x\", port_config.src_x);\n        port_config.src_y    = subregion_tree->get(L\"src-y\", port_config.src_y);\n        port_config.dest_x   = subregion_tree->get(L\"dest-x\", port_config.dest_x);\n        port_config.dest_y   = subregion_tree->get(L\"dest-y\", port_config.dest_y);\n        port_config.region_w = subregion_tree->get(L\"width\", port_config.region_w);\n        port_config.region_h = subregion_tree->get(L\"height\", port_config.region_h);\n    }\n\n    return port_config;\n}\n\nvanc_configuration parse_vanc_config(const boost::property_tree::wptree& vanc_tree)\n{\n    vanc_configuration vanc_config;\n\n    vanc_config.enable            = true;\n    vanc_config.op47_line         = vanc_tree.get(L\"op47-line\", vanc_config.op47_line);\n    vanc_config.op47_line_field2  = vanc_tree.get(L\"op47-line-field2\", vanc_config.op47_line_field2);\n    vanc_config.enable_op47       = vanc_config.op47_line > 0;\n    vanc_config.op42_sd_line      = vanc_tree.get(L\"op42-sd-line\", vanc_config.op42_sd_line);\n    vanc_config.scte104_line      = vanc_tree.get(L\"scte104-line\", vanc_config.scte104_line);\n    vanc_config.enable_scte104    = vanc_config.scte104_line > 0;\n    vanc_config.op47_dummy_header = vanc_tree.get(L\"op47-dummy-header\", L\"\");\n\n    return vanc_config;\n};\n\ncore::color_space get_color_space(const std::wstring& str)\n{\n    auto color_space_str = boost::to_lower_copy(str);\n    if (color_space_str == L\"bt709\")\n        return core::color_space::bt709;\n    else if (color_space_str == L\"bt2020\")\n        return core::color_space::bt2020;\n    else if (color_space_str == L\"bt601\")\n        return core::color_space::bt601;\n\n    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid decklink color-space, must be bt601, bt709 or bt2020\"));\n}\n\nconfiguration parse_xml_config(const boost::property_tree::wptree&  ptree,\n                               const core::video_format_repository& format_repository,\n                               const core::channel_info&            channel_info)\n{\n    configuration config;\n\n    auto duplex = ptree.get(L\"duplex\", L\"default\");\n    if (duplex == L\"full\") {\n        config.duplex = configuration::duplex_t::full_duplex;\n    } else if (duplex == L\"half\") {\n        config.duplex = configuration::duplex_t::half_duplex;\n    }\n\n    auto latency = ptree.get(L\"latency\", L\"default\");\n    if (latency == L\"low\") {\n        config.latency = configuration::latency_t::low_latency;\n    } else if (latency == L\"normal\") {\n        config.latency = configuration::latency_t::normal_latency;\n    }\n\n    auto wait_for_reference = ptree.get(L\"wait-for-reference\", L\"auto\");\n    if (wait_for_reference == L\"disable\" || wait_for_reference == L\"disabled\") {\n        config.wait_for_reference = configuration::wait_for_reference_t::disabled;\n    } else if (wait_for_reference == L\"enable\" || wait_for_reference == L\"enabled\") {\n        config.wait_for_reference = configuration::wait_for_reference_t::enabled;\n    } else {\n        config.wait_for_reference = configuration::wait_for_reference_t::automatic;\n    }\n    config.wait_for_reference_duration = ptree.get(L\"wait-for-reference-duration\", config.wait_for_reference_duration);\n\n    {\n        auto is_8bit              = channel_info.depth == common::bit_depth::bit8;\n        auto default_pixel_format = is_8bit ? L\"rgba\" : L\"yuv\";\n        auto pixel_format         = ptree.get(L\"pixel-format\", default_pixel_format);\n        if (pixel_format == L\"yuv\") {\n            config.pixel_format = configuration::pixel_format_t::yuv;\n        } else if (pixel_format == L\"rgba\") {\n            config.pixel_format = configuration::pixel_format_t::rgba;\n        } else {\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid pixel format, must be rgba or yuv\"));\n        }\n\n        if (channel_info.depth != common::bit_depth::bit8 &&\n            config.pixel_format == configuration::pixel_format_t::rgba) {\n            CASPAR_THROW_EXCEPTION(user_error()\n                                   << msg_info(L\"The decklink consumer only supports rgba output on 8-bit channels\"));\n        }\n\n        if (config.pixel_format != configuration::pixel_format_t::rgba) {\n#ifdef WIN32\n            if (!CHECK_INSTRUCTION_SUPPORT(__IA_SUPPORT_VECTOR256, 0)) {\n#elif defined(__x86_64__) || defined(__i386__)\n            if (!__builtin_cpu_supports(\"avx2\")) {\n#else\n            if (false) {\n#endif\n                CASPAR_THROW_EXCEPTION(user_error()\n                                       << msg_info(L\"Your cpu does not support the features needed for yuv output\"));\n            }\n        }\n    }\n\n    config.primary = parse_output_config(ptree, format_repository);\n    if (config.primary.device_index == -1)\n        config.primary.device_index = 1;\n\n    auto keyer = ptree.get(L\"keyer\", L\"default\");\n    if (keyer == L\"external\") {\n        config.keyer = configuration::keyer_t::external_keyer;\n    } else if (keyer == L\"internal\") {\n        config.keyer = configuration::keyer_t::internal_keyer;\n    } else if (keyer == L\"external_separate_device\") {\n        config.keyer = configuration::keyer_t::external_keyer;\n\n        auto key_config         = config.primary; // Copy the primary config\n        key_config.device_index = ptree.get(L\"key-device\", static_cast<int64_t>(0));\n        if (key_config.device_index == 0) {\n            key_config.device_index = config.primary.device_index + 1;\n        }\n        key_config.key_only = true;\n        config.secondaries.push_back(key_config);\n    }\n\n    config.embedded_audio    = ptree.get(L\"embedded-audio\", config.embedded_audio);\n    config.base_buffer_depth = ptree.get(L\"buffer-depth\", config.base_buffer_depth);\n\n    if (ptree.get_child_optional(L\"ports\")) {\n        for (auto& xml_port : ptree | witerate_children(L\"ports\") | welement_context_iteration) {\n            ptree_verify_element_name(xml_port, L\"port\");\n\n            port_configuration port_config = parse_output_config(xml_port.second, format_repository);\n\n            config.secondaries.push_back(port_config);\n        }\n    }\n\n    config.color_space   = channel_info.default_color_space;\n    auto color_space_str = ptree.get(L\"color-space\", L\"\");\n    if (!color_space_str.empty())\n        config.color_space = get_color_space(color_space_str);\n\n    auto hdr_metadata = ptree.get_child_optional(L\"hdr-metadata\");\n    if (hdr_metadata) {\n        config.hdr_meta.min_dml  = hdr_metadata->get(L\"min-dml\", config.hdr_meta.min_dml);\n        config.hdr_meta.max_dml  = hdr_metadata->get(L\"max-dml\", config.hdr_meta.max_dml);\n        config.hdr_meta.max_fall = hdr_metadata->get(L\"max-fall\", config.hdr_meta.max_fall);\n        config.hdr_meta.max_cll  = hdr_metadata->get(L\"max-cll\", config.hdr_meta.max_cll);\n    }\n\n    auto vanc = ptree.get_child_optional(L\"vanc\");\n    if (vanc) {\n        config.vanc = parse_vanc_config(vanc.get());\n    }\n\n    return config;\n}\n\nconfiguration parse_amcp_config(const std::vector<std::wstring>&     params,\n                                const core::video_format_repository& format_repository,\n                                const core::channel_info&            channel_info)\n{\n    configuration config;\n\n    if (params.size() > 1)\n        config.primary.device_index = std::stoll(params.at(1));\n\n    if (contains_param(L\"INTERNAL_KEY\", params)) {\n        config.keyer = configuration::keyer_t::internal_keyer;\n    } else if (contains_param(L\"EXTERNAL_KEY\", params)) {\n        config.keyer = configuration::keyer_t::external_keyer;\n    } else {\n        config.keyer = configuration::keyer_t::default_keyer;\n    }\n\n    if (contains_param(L\"FULL_DUPLEX\", params)) {\n        config.duplex = configuration::duplex_t::full_duplex;\n    } else if (contains_param(L\"HALF_DUPLEX\", params)) {\n        config.duplex = configuration::duplex_t::half_duplex;\n    }\n\n    if (contains_param(L\"LOW_LATENCY\", params)) {\n        config.latency = configuration::latency_t::low_latency;\n    }\n\n    config.embedded_audio   = contains_param(L\"EMBEDDED_AUDIO\", params);\n    config.primary.key_only = contains_param(L\"KEY_ONLY\", params);\n\n    config.color_space = channel_info.default_color_space;\n\n    return config;\n}\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/config.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include <boost/property_tree/ptree.hpp>\n\n#include <core/consumer/channel_info.h>\n#include <core/frame/pixel_format.h>\n#include <core/video_format.h>\n\nnamespace caspar { namespace decklink {\n\nstruct port_configuration\n{\n    int64_t device_index = 1; // Either an index, or a persistent id\n    bool    key_only     = false;\n\n    core::video_format_desc format;\n    int                     src_x    = 0;\n    int                     src_y    = 0;\n    int                     dest_x   = 0;\n    int                     dest_y   = 0;\n    int                     region_w = 0;\n    int                     region_h = 0;\n\n    [[nodiscard]] bool has_subregion_geometry() const\n    {\n        return src_x != 0 || src_y != 0 || region_w != 0 || region_h != 0 || dest_x != 0 || dest_y != 0;\n    }\n};\n\nstruct vanc_configuration\n{\n    bool         enable           = false;\n    bool         enable_op47      = false;\n    bool         enable_scte104   = false;\n    uint32_t     op47_line        = 0;\n    uint32_t     op42_sd_line     = 21;\n    uint32_t     op47_line_field2 = 0;\n    uint32_t     scte104_line     = 0;\n    std::wstring op47_dummy_header;\n};\n\nstruct hdr_meta_configuration\n{\n    float min_dml  = 0.005f;\n    float max_dml  = 1000.0f;\n    float max_fall = 100.0f;\n    float max_cll  = 1000.0f;\n};\n\nstruct configuration\n{\n    enum class keyer_t\n    {\n        internal_keyer,\n        external_keyer,\n        default_keyer = external_keyer\n    };\n\n    enum class duplex_t\n    {\n        none,\n        half_duplex,\n        full_duplex,\n        default_duplex = none\n    };\n\n    enum class latency_t\n    {\n        low_latency,\n        normal_latency,\n        default_latency = normal_latency\n    };\n\n    enum class wait_for_reference_t\n    {\n        automatic,\n        enabled,\n        disabled,\n    };\n\n    enum class pixel_format_t\n    {\n        rgba,\n        yuv,\n    };\n\n    bool                 embedded_audio              = false;\n    keyer_t              keyer                       = keyer_t::default_keyer;\n    duplex_t             duplex                      = duplex_t::default_duplex;\n    latency_t            latency                     = latency_t::default_latency;\n    wait_for_reference_t wait_for_reference          = wait_for_reference_t::automatic;\n    int                  wait_for_reference_duration = 10; // seconds\n    int                  base_buffer_depth           = 3;\n    bool                 hdr                         = false;\n    pixel_format_t       pixel_format                = pixel_format_t::rgba;\n\n    port_configuration              primary;\n    std::vector<port_configuration> secondaries;\n\n    core::color_space      color_space = core::color_space::bt709;\n    hdr_meta_configuration hdr_meta;\n\n    vanc_configuration vanc;\n\n    [[nodiscard]] int buffer_depth() const\n    {\n        return base_buffer_depth + (latency == latency_t::low_latency ? 0 : 1) +\n               (embedded_audio ? 1 : 0); // TODO: Do we need this?\n    }\n\n    // int key_device_index() const { return key_device_idx == 0 ? device_index + 1 : key_device_idx; }\n};\n\nconfiguration parse_xml_config(const boost::property_tree::wptree&  ptree,\n                               const core::video_format_repository& format_repository,\n                               const core::channel_info&            channel_info);\n\nconfiguration parse_amcp_config(const std::vector<std::wstring>&     params,\n                                const core::video_format_repository& format_repository,\n                                const core::channel_info&            channel_info);\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/decklink_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"../StdAfx.h\"\n\n#include \"common/os/thread.h\"\n#include \"config.h\"\n#include \"decklink_consumer.h\"\n#include \"format_strategy.h\"\n#include \"monitor.h\"\n#include \"vanc.h\"\n\n#include \"../util/util.h\"\n\n#include <core/consumer/channel_info.h>\n#include <core/consumer/frame_consumer.h>\n#include <core/frame/frame.h>\n#include <core/frame/pixel_format.h>\n#include <core/video_format.h>\n\n#include <common/diagnostics/graph.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/timer.h>\n\n#include <tbb/parallel_for.h>\n\n#include <boost/circular_buffer.hpp>\n\n#include <atomic>\n#include <common/prec_timer.h>\n#include <condition_variable>\n#include <future>\n#include <memory>\n#include <mutex>\n#include <optional>\n#include <queue>\n#include <thread>\n#include <utility>\n\nnamespace caspar { namespace decklink {\n\ntemplate <typename Configuration>\nvoid set_latency(const com_iface_ptr<Configuration>& config,\n                 configuration::latency_t            latency,\n                 const std::wstring&                 print)\n{\n    if (latency == configuration::latency_t::low_latency) {\n        config->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, true);\n        CASPAR_LOG(info) << print << L\" Enabled low-latency mode.\";\n    } else if (latency == configuration::latency_t::normal_latency) {\n        config->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, false);\n        CASPAR_LOG(info) << print << L\" Disabled low-latency mode.\";\n    }\n}\n\ncom_ptr<IDeckLinkDisplayMode> get_display_mode(const com_iface_ptr<IDeckLinkOutput>& device,\n                                               core::video_format                    fmt,\n                                               BMDPixelFormat                        pix_fmt,\n                                               BMDSupportedVideoModeFlags            flag)\n{\n    auto format = get_decklink_video_format(fmt);\n\n    IDeckLinkDisplayMode*         m = nullptr;\n    IDeckLinkDisplayModeIterator* iter;\n    if (SUCCEEDED(device->GetDisplayModeIterator(&iter))) {\n        auto iterator = wrap_raw<com_ptr>(iter, true);\n        while (SUCCEEDED(iterator->Next(&m)) && m != nullptr && m->GetDisplayMode() != format) {\n            m->Release();\n        }\n    }\n\n    if (!m)\n        CASPAR_THROW_EXCEPTION(user_error()\n                               << msg_info(\"Device could not find requested video-format: \" + std::to_string(format)));\n\n    com_ptr<IDeckLinkDisplayMode> mode = wrap_raw<com_ptr>(m, true);\n\n    BMDDisplayMode actualMode = bmdModeUnknown;\n    BOOL           supported  = false;\n\n    auto displayMode = mode->GetDisplayMode();\n    if (FAILED(device->DoesSupportVideoMode(bmdVideoConnectionUnspecified,\n                                            displayMode,\n                                            pix_fmt,\n                                            bmdNoVideoOutputConversion,\n                                            flag,\n                                            &actualMode,\n                                            &supported)))\n        CASPAR_THROW_EXCEPTION(caspar_exception()\n                               << msg_info(L\"Could not determine whether device supports requested video format: \" +\n                                           get_mode_name(mode)));\n    else if (!supported)\n        CASPAR_LOG(info) << L\"Device may not support video-format: \" << get_mode_name(mode);\n    else if (actualMode != bmdModeUnknown && actualMode != displayMode)\n        CASPAR_LOG(warning) << L\"Device supports video-format with conversion: \" << get_mode_name(mode);\n\n    return mode;\n}\n\nvoid set_duplex(const com_iface_ptr<IDeckLinkAttributes_v10_11>&    attributes,\n                const com_iface_ptr<IDeckLinkConfiguration_v10_11>& config,\n                configuration::duplex_t                             duplex,\n                const std::wstring&                                 print)\n{\n    BOOL supportsDuplexModeConfiguration;\n    if (FAILED(\n            attributes->GetFlag(static_cast<BMDDeckLinkAttributeID>(BMDDeckLinkSupportsDuplexModeConfiguration_v10_11),\n                                &supportsDuplexModeConfiguration))) {\n        CASPAR_LOG(error) << print\n                          << L\" Failed to set duplex mode, unable to check if card supports duplex mode setting.\";\n    }\n\n    if (!supportsDuplexModeConfiguration) {\n        CASPAR_LOG(warning) << print << L\" This device does not support setting the duplex mode.\";\n        return;\n    }\n\n    std::map<configuration::duplex_t, BMDDuplexMode_v10_11> config_map{\n        {configuration::duplex_t::full_duplex, bmdDuplexModeFull_v10_11},\n        {configuration::duplex_t::half_duplex, bmdDuplexModeHalf_v10_11},\n    };\n    auto duplex_mode = config_map[duplex];\n\n    if (FAILED(\n            config->SetInt(static_cast<BMDDeckLinkConfigurationID>(bmdDeckLinkConfigDuplexMode_v10_11), duplex_mode))) {\n        CASPAR_LOG(error) << print << L\" Unable to set duplex mode.\";\n        return;\n    }\n    CASPAR_LOG(info) << print << L\" Duplex mode set.\";\n}\n\nvoid set_keyer(const com_iface_ptr<IDeckLinkProfileAttributes>& attributes,\n               const com_iface_ptr<IDeckLinkOutput>&             output,\n               const com_iface_ptr<IDeckLinkKeyer>&             decklink_keyer,\n               configuration::keyer_t                           keyer,\n               BMDDisplayMode                                   display_mode,\n               BMDPixelFormat                                   pixel_format,\n               const std::wstring&                              print)\n{\n    if (keyer == configuration::keyer_t::internal_keyer || keyer == configuration::keyer_t::external_keyer) {\n        BMDDisplayMode actualMode = bmdModeUnknown;\n        BOOL           supported  = FALSE;\n        if (SUCCEEDED(output->DoesSupportVideoMode(bmdVideoConnectionUnspecified,\n                                                   display_mode,\n                                                   pixel_format,\n                                                   bmdNoVideoOutputConversion,\n                                                   bmdSupportedVideoModeKeying,\n                                                   &actualMode,\n                                                   &supported)) &&\n            !supported) {\n            CASPAR_LOG(warning) << print << L\" Keying is not supported by this device for the current video mode. Disabling keyer.\";\n            decklink_keyer->Disable();\n            return;\n        }\n    }\n\n    if (keyer == configuration::keyer_t::internal_keyer) {\n        BOOL value = true;\n        if (SUCCEEDED(attributes->GetFlag(BMDDeckLinkSupportsInternalKeying, &value)) && !value)\n            CASPAR_LOG(error) << print << L\" Failed to enable internal keyer.\";\n        else if (FAILED(decklink_keyer->Enable(FALSE)))\n            CASPAR_LOG(error) << print << L\" Failed to enable internal keyer.\";\n        else if (FAILED(decklink_keyer->SetLevel(255)))\n            CASPAR_LOG(error) << print << L\" Failed to set key-level to max.\";\n        else\n            CASPAR_LOG(info) << print << L\" Enabled internal keyer.\";\n    } else if (keyer == configuration::keyer_t::external_keyer) {\n        BOOL value = true;\n        if (SUCCEEDED(attributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &value)) && !value)\n            CASPAR_LOG(error) << print << L\" Failed to enable external keyer.\";\n        else if (FAILED(decklink_keyer->Enable(TRUE)))\n            CASPAR_LOG(error) << print << L\" Failed to enable external keyer.\";\n        else if (FAILED(decklink_keyer->SetLevel(255)))\n            CASPAR_LOG(error) << print << L\" Failed to set key-level to max.\";\n        else\n            CASPAR_LOG(info) << print << L\" Enabled external keyer.\";\n    }\n}\n\ncore::video_format_desc get_decklink_format(const port_configuration&      config,\n                                            const core::video_format_desc& fallback_format_desc)\n{\n    if (config.format.format != core::video_format::invalid && config.format.format != fallback_format_desc.format) {\n        if (config.format.format != core::video_format::invalid && config.format.format != core::video_format::custom &&\n            config.format.framerate * config.format.field_count ==\n                fallback_format_desc.framerate * fallback_format_desc.field_count &&\n            config.format.duration == fallback_format_desc.duration) {\n            return config.format;\n        }\n    }\n\n    if (fallback_format_desc.format == core::video_format::invalid ||\n        fallback_format_desc.format == core::video_format::custom)\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Decklink does not support the channel format\"));\n\n    return fallback_format_desc;\n}\n\nspl::shared_ptr<format_strategy> create_format_strategy(const configuration& config)\n{\n    if (config.hdr) {\n        return create_hdr_v210_strategy(config.color_space);\n    } else {\n        return config.pixel_format == configuration::pixel_format_t::yuv ? create_sdr_v210_strategy(config.color_space)\n                                                                         : create_sdr_bgra_strategy();\n    }\n}\n\nenum EOTF\n{\n    SDR = 0,\n    HDR = 1,\n    PQ  = 2,\n    HLG = 3\n};\n\nstruct ChromaticityCoordinates\n{\n    double RedX;\n    double RedY;\n    double GreenX;\n    double GreenY;\n    double BlueX;\n    double BlueY;\n    double WhiteX;\n    double WhiteY;\n};\n\nconst auto REC_709  = ChromaticityCoordinates{0.640, 0.330, 0.300, 0.600, 0.150, 0.060, 0.3127, 0.3290};\nconst auto REC_2020 = ChromaticityCoordinates{0.708, 0.292, 0.170, 0.797, 0.131, 0.046, 0.3127, 0.3290};\n\nclass decklink_frame\n    : public IDeckLinkVideoFrame\n    , public IDeckLinkVideoFrameMetadataExtensions\n{\n    core::video_format_desc                      format_desc_;\n    std::shared_ptr<void>                        data_;\n    std::atomic<int>                             ref_count_{0};\n    int                                          nb_samples_;\n    const bool                                   hdr_;\n    core::color_space                            color_space_;\n    hdr_meta_configuration                       hdr_metadata_;\n    BMDFrameFlags                                flags_;\n    BMDPixelFormat                               pix_fmt_;\n    int                                          row_bytes_;\n    com_ptr<IDeckLinkVideoFrameAncillaryPackets> vanc_;\n\n  public:\n    decklink_frame(std::shared_ptr<void>         data,\n                   core::video_format_desc       format_desc,\n                   int                           nb_samples,\n                   bool                          hdr,\n                   BMDPixelFormat                pix_fmt,\n                   int                           row_bytes,\n                   bool                          vanc,\n                   core::color_space             color_space,\n                   const hdr_meta_configuration& hdr_metadata)\n        : format_desc_(std::move(format_desc))\n        , data_(std::move(data))\n        , nb_samples_(nb_samples)\n        , hdr_(hdr)\n        , pix_fmt_(pix_fmt)\n        , row_bytes_(row_bytes)\n        , color_space_(color_space)\n        , hdr_metadata_(hdr_metadata)\n        , flags_(hdr ? bmdFrameFlagDefault | bmdFrameContainsHDRMetadata : bmdFrameFlagDefault)\n        , vanc_(vanc ? create_ancillary_packets() : nullptr)\n    {\n    }\n\n    // IUnknown\n\n    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID* ppv) override\n    {\n        if (ppv == nullptr)\n            return E_INVALIDARG;\n\n        REFIID iunknown = IID_IUnknown;\n\n        if (std::memcmp(&iid, &iunknown, sizeof(REFIID)) == 0) {\n            *ppv = this;\n            AddRef();\n        } else if (std::memcmp(&iid, &IID_IDeckLinkVideoFrame, sizeof(REFIID)) == 0) {\n            *ppv = static_cast<IDeckLinkVideoFrame*>(this);\n            AddRef();\n        } else if (hdr_ && std::memcmp(&iid, &IID_IDeckLinkVideoFrameMetadataExtensions, sizeof(REFIID)) == 0) {\n            *ppv = static_cast<IDeckLinkVideoFrameMetadataExtensions*>(this);\n            AddRef();\n        } else if (vanc_ && std::memcmp(&iid, &IID_IDeckLinkVideoFrameAncillaryPackets, sizeof(REFIID)) == 0) {\n            auto raw = get_raw(vanc_);\n            raw->AddRef();\n            *ppv = raw;\n\n        } else {\n            *ppv = nullptr;\n            return E_NOINTERFACE;\n        }\n\n        return S_OK;\n    }\n\n    ULONG STDMETHODCALLTYPE AddRef() override { return ++ref_count_; }\n\n    ULONG STDMETHODCALLTYPE Release() override\n    {\n        if (--ref_count_ == 0) {\n            delete this;\n\n            return 0;\n        }\n\n        return ref_count_;\n    }\n\n    // IDecklinkVideoFrame\n\n    long STDMETHODCALLTYPE           GetWidth() override { return static_cast<long>(format_desc_.width); }\n    long STDMETHODCALLTYPE           GetHeight() override { return static_cast<long>(format_desc_.height); }\n    long STDMETHODCALLTYPE           GetRowBytes() override { return static_cast<long>(row_bytes_); }\n    BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat() override { return pix_fmt_; }\n    BMDFrameFlags STDMETHODCALLTYPE  GetFlags() override { return flags_; }\n\n    HRESULT STDMETHODCALLTYPE GetBytes(void** buffer) override\n    {\n        *buffer = data_.get();\n        return S_OK;\n    }\n\n    HRESULT STDMETHODCALLTYPE GetTimecode(BMDTimecodeFormat format, IDeckLinkTimecode** timecode) override\n    {\n        return S_FALSE;\n    }\n\n    HRESULT STDMETHODCALLTYPE GetAncillaryData(IDeckLinkVideoFrameAncillary** ancillary) override { return S_FALSE; }\n\n    [[nodiscard]] int nb_samples() const { return nb_samples_; }\n\n    // IDeckLinkVideoFrameMetadataExtensions\n    HRESULT STDMETHODCALLTYPE GetInt(BMDDeckLinkFrameMetadataID metadataID, int64_t* value) override\n    {\n        HRESULT result = S_OK;\n\n        switch (metadataID) {\n            case bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc:\n                *value = EOTF::HLG;\n                break;\n\n            case bmdDeckLinkFrameMetadataColorspace:\n                *value = (color_space_ == core::color_space::bt2020) ? bmdColorspaceRec2020 : bmdColorspaceRec709;\n                break;\n\n            default:\n                value  = nullptr;\n                result = E_INVALIDARG;\n        }\n\n        return result;\n    }\n\n    HRESULT STDMETHODCALLTYPE GetFloat(BMDDeckLinkFrameMetadataID metadataID, double* value) override\n    {\n        const auto color_space = (color_space_ == core::color_space::bt2020) ? &REC_2020 : &REC_709;\n        HRESULT    result      = S_OK;\n\n        switch (metadataID) {\n            case bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX:\n                *value = color_space->RedX;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY:\n                *value = color_space->RedY;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX:\n                *value = color_space->GreenX;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY:\n                *value = color_space->GreenY;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX:\n                *value = color_space->BlueX;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY:\n                *value = color_space->BlueY;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRWhitePointX:\n                *value = color_space->WhiteX;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRWhitePointY:\n                *value = color_space->WhiteY;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance:\n                *value = hdr_metadata_.max_dml;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance:\n                *value = hdr_metadata_.min_dml;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel:\n                *value = hdr_metadata_.max_cll;\n                break;\n\n            case bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel:\n                *value = hdr_metadata_.max_fall;\n                break;\n\n            default:\n                value  = nullptr;\n                result = E_INVALIDARG;\n        }\n\n        return result;\n    }\n\n    HRESULT STDMETHODCALLTYPE GetFlag(BMDDeckLinkFrameMetadataID, BOOL* value) override\n    {\n        // Not expecting GetFlag\n        *value = false;\n        return E_INVALIDARG;\n    }\n\n    HRESULT STDMETHODCALLTYPE GetString(BMDDeckLinkFrameMetadataID, String* value) override\n    {\n        // Not expecting GetString\n        *value = nullptr;\n        return E_INVALIDARG;\n    }\n\n    HRESULT STDMETHODCALLTYPE GetBytes(BMDDeckLinkFrameMetadataID metadataID,\n                                       void*                      buffer,\n                                       uint32_t*                  bufferSize) override\n    {\n        *bufferSize = 0;\n        return E_INVALIDARG;\n    }\n};\n\nstruct decklink_secondary_port final : public IDeckLinkVideoOutputCallback\n{\n    const configuration                       config_;\n    const port_configuration                  output_config_;\n    spl::shared_ptr<format_strategy>          format_strategy_;\n    com_ptr<IDeckLink>                        decklink_      = get_device(output_config_.device_index);\n    com_iface_ptr<IDeckLinkOutput>            output_        = iface_cast<IDeckLinkOutput>(decklink_);\n    com_iface_ptr<IDeckLinkKeyer>             keyer_         = iface_cast<IDeckLinkKeyer>(decklink_, true);\n    com_iface_ptr<IDeckLinkProfileAttributes> attributes_    = iface_cast<IDeckLinkProfileAttributes>(decklink_);\n    com_iface_ptr<IDeckLinkConfiguration>     configuration_ = iface_cast<IDeckLinkConfiguration>(decklink_);\n    int                                       device_sync_group_;\n    std::optional<core::const_frame>          first_field_;\n\n    const std::wstring model_name_ = get_model_name(decklink_);\n\n    // long long video_scheduled_ = 0;\n\n    const core::video_format_desc channel_format_desc_;\n    const core::video_format_desc decklink_format_desc_;\n    com_ptr<IDeckLinkDisplayMode> mode_ = get_display_mode(output_,\n                                                           decklink_format_desc_.format,\n                                                           format_strategy_->get_pixel_format(),\n                                                           bmdSupportedVideoModeDefault);\n\n    decklink_secondary_port(const configuration&           config,\n                            port_configuration             output_config,\n                            core::video_format_desc        channel_format_desc,\n                            const core::video_format_desc& main_decklink_format_desc,\n                            const std::wstring&            print,\n                            int                            device_sync_group)\n        : config_(config)\n        , output_config_(std::move(output_config))\n        , format_strategy_(create_format_strategy(config))\n        , device_sync_group_(device_sync_group)\n        , channel_format_desc_(std::move(channel_format_desc))\n        , decklink_format_desc_(get_decklink_format(output_config_, main_decklink_format_desc))\n    {\n        if (main_decklink_format_desc.format != decklink_format_desc_.format) {\n            CASPAR_LOG(info) << print << L\" Disabling sync group for output with different format.\";\n            device_sync_group_ = 0;\n        }\n\n        if (config.duplex != configuration::duplex_t::default_duplex) {\n            set_duplex(iface_cast<IDeckLinkAttributes_v10_11>(decklink_),\n                       iface_cast<IDeckLinkConfiguration_v10_11>(decklink_),\n                       config.duplex,\n                       print);\n        }\n\n        set_latency(configuration_, config.latency, print);\n        set_keyer(attributes_, output_, keyer_, config.keyer, mode_->GetDisplayMode(), format_strategy_->get_pixel_format(), print);\n\n        if (device_sync_group_ > 0 &&\n            FAILED(configuration_->SetInt(bmdDeckLinkConfigPlaybackGroup, device_sync_group_))) {\n            CASPAR_LOG(error) << print << L\" Failed to enable sync group.\";\n            device_sync_group_ = 0;\n        } else {\n            CASPAR_LOG(trace) << print << L\" Joined sync group \" << device_sync_group;\n        }\n\n        if (FAILED(output_->SetScheduledFrameCompletionCallback(this)))\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(print + L\" Failed to set key playback completion callback.\")\n                                   << boost::errinfo_api_function(\"SetScheduledFrameCompletionCallback\"));\n    }\n\n    ~decklink_secondary_port()\n    {\n        if (output_) {\n            if (device_sync_group_ == 0) {\n                output_->StopScheduledPlayback(0, nullptr, 0);\n            }\n\n            output_->DisableVideoOutput();\n        }\n    }\n\n    [[nodiscard]] std::wstring print() const\n    {\n        return model_name_ + L\" [\" + std::to_wstring(output_config_.device_index) + L\"|\" + decklink_format_desc_.name +\n               L\"]\";\n    }\n\n    template <typename Print>\n    void enable_video(const Print& print)\n    {\n        if (FAILED(output_->EnableVideoOutput(mode_->GetDisplayMode(),\n                                              device_sync_group_ > 0 ? bmdVideoOutputSynchronizeToPlaybackGroup\n                                                                     : bmdVideoOutputFlagDefault)))\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(print() + L\" Could not enable secondary video output.\"));\n    }\n\n    template <typename Print>\n    void start_playback(const Print& print)\n    {\n        if (device_sync_group_ == 0) {\n            if (FAILED(output_->StartScheduledPlayback(0, decklink_format_desc_.time_scale, 1.0))) {\n                CASPAR_THROW_EXCEPTION(caspar_exception()\n                                       << msg_info(print() + L\" Failed to schedule secondary playback.\"));\n            }\n        }\n    }\n\n    void schedule_frame(core::const_frame frame, BMDTimeValue display_time)\n    {\n        bool isInterlaced = decklink_format_desc_.field_count != 1;\n        if (isInterlaced && !first_field_.has_value()) {\n            // If this is interlaced it needs a pair of frames at a time\n            first_field_ = frame;\n            return;\n        }\n\n        // Figure out which frame is which\n        core::const_frame frame1;\n        core::const_frame frame2;\n        if (isInterlaced) {\n            frame1       = *first_field_;\n            first_field_ = {};\n            frame2       = frame;\n        } else {\n            frame1 = frame;\n        }\n\n        auto image_data = format_strategy_->convert_frame_for_port(\n            channel_format_desc_, decklink_format_desc_, output_config_, frame1, frame2, mode_->GetFieldDominance());\n\n        schedule_next_video(image_data, 0, display_time);\n    }\n\n    void schedule_next_video(std::shared_ptr<void> image_data, int nb_samples, BMDTimeValue display_time)\n    {\n        auto packed_frame = wrap_raw<com_ptr, IDeckLinkVideoFrame>(\n            new decklink_frame(std::move(image_data),\n                               decklink_format_desc_,\n                               nb_samples,\n                               config_.hdr,\n                               format_strategy_->get_pixel_format(),\n                               format_strategy_->get_row_bytes(decklink_format_desc_.width),\n                               false,\n                               config_.color_space,\n                               config_.hdr_meta));\n        if (FAILED(output_->ScheduleVideoFrame(get_raw(packed_frame),\n                                               display_time,\n                                               decklink_format_desc_.duration,\n                                               decklink_format_desc_.time_scale))) {\n            CASPAR_LOG(error) << print() << L\" Failed to schedule primary video.\";\n        }\n\n        // video_scheduled_ += decklink_format_desc_.duration;\n    }\n\n    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) override { return E_NOINTERFACE; }\n    ULONG STDMETHODCALLTYPE   AddRef() override { return 1; }\n    ULONG STDMETHODCALLTYPE   Release() override { return 1; }\n\n    HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped() override { return S_OK; }\n\n    HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame*           completed_frame,\n                                                      BMDOutputFrameCompletionResult result) override\n    {\n        // Let the primary callback keep the pace, so no scheduling here.\n\n        return S_OK;\n    }\n};\n\nstruct decklink_consumer final : public IDeckLinkVideoOutputCallback\n{\n    const int                        channel_index_;\n    const configuration              config_;\n    spl::shared_ptr<format_strategy> format_strategy_;\n\n    com_ptr<IDeckLink>                        decklink_      = get_device(config_.primary.device_index);\n    com_iface_ptr<IDeckLinkOutput>            output_        = iface_cast<IDeckLinkOutput>(decklink_);\n    com_iface_ptr<IDeckLinkConfiguration>     configuration_ = iface_cast<IDeckLinkConfiguration>(decklink_);\n    com_iface_ptr<IDeckLinkKeyer>             keyer_         = iface_cast<IDeckLinkKeyer>(decklink_, true);\n    com_iface_ptr<IDeckLinkProfileAttributes> attributes_    = iface_cast<IDeckLinkProfileAttributes>(decklink_);\n\n    std::mutex         exception_mutex_;\n    std::exception_ptr exception_;\n\n    const std::wstring            model_name_ = get_model_name(decklink_);\n    const core::video_format_desc channel_format_desc_;\n    const core::video_format_desc decklink_format_desc_;\n\n    std::mutex                    buffer_mutex_;\n    std::condition_variable       buffer_cond_;\n    std::queue<core::const_frame> buffer_;\n    int                           buffer_capacity_ = channel_format_desc_.field_count;\n\n    const int buffer_size_ = config_.buffer_depth(); // Minimum buffer-size 3.\n\n    long long video_scheduled_ = 0;\n    long long audio_scheduled_ = 0;\n\n    boost::circular_buffer<std::vector<int32_t>> audio_container_{static_cast<unsigned long>(buffer_size_ + 1)};\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n    caspar::timer                       tick_timer_;\n    reference_signal_detector           reference_signal_detector_{output_};\n    // std::atomic<int64_t>                                  scheduled_frames_completed_{0};\n    std::vector<std::unique_ptr<decklink_secondary_port>> secondary_port_contexts_;\n    int                                                   device_sync_group_ = 0;\n\n    com_ptr<IDeckLinkDisplayMode> mode_ = get_display_mode(output_,\n                                                           decklink_format_desc_.format,\n                                                           format_strategy_->get_pixel_format(),\n                                                           bmdSupportedVideoModeDefault);\n\n    std::atomic<bool>              abort_request_{false};\n    std::shared_ptr<decklink_vanc> vanc_;\n\n  public:\n    decklink_consumer(const configuration& config, core::video_format_desc channel_format_desc, int channel_index)\n        : channel_index_(channel_index)\n        , config_(config)\n        , format_strategy_(create_format_strategy(config))\n        , channel_format_desc_(std::move(channel_format_desc))\n        , decklink_format_desc_(get_decklink_format(config.primary, channel_format_desc_))\n    {\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"flushed-frame\", diagnostics::color(0.4f, 0.3f, 0.8f));\n        graph_->set_color(\"buffered-audio\", diagnostics::color(0.9f, 0.9f, 0.5f));\n        graph_->set_color(\"buffered-video\", diagnostics::color(0.2f, 0.9f, 0.9f));\n\n        if (config.duplex != configuration::duplex_t::default_duplex) {\n            set_duplex(iface_cast<IDeckLinkAttributes_v10_11>(decklink_),\n                       iface_cast<IDeckLinkConfiguration_v10_11>(decklink_),\n                       config.duplex,\n                       print());\n        }\n\n        /*\n        if (key_context_) {\n            graph_->set_color(\"key-offset\", diagnostics::color(1.0f, 0.0f, 0.0f));\n        }\n        */\n\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        // If there are additional ports devices, then enable the sync group\n        if (!config.secondaries.empty()) {\n            // A unique id is needed for this group, this is simpler than a random number\n            device_sync_group_ = static_cast<int>(config.primary.device_index);\n\n            if (FAILED(configuration_->SetInt(bmdDeckLinkConfigPlaybackGroup, device_sync_group_))) {\n                device_sync_group_ = 0;\n                CASPAR_LOG(error) << print() << L\" Failed to enable sync group.\";\n            } else {\n                CASPAR_LOG(debug) << print() << L\" Enabled sync group: \" << device_sync_group_;\n            }\n        }\n\n        // create the secondary ports\n        for (auto& secondary_port_config : config_.secondaries) {\n            secondary_port_contexts_.push_back(std::make_unique<decklink_secondary_port>(config,\n                                                                                         secondary_port_config,\n                                                                                         channel_format_desc_,\n                                                                                         decklink_format_desc_,\n                                                                                         print(),\n                                                                                         device_sync_group_));\n        }\n\n        if (config.vanc.enable) {\n            BOOL flag = TRUE;\n            attributes_->GetFlag(BMDDeckLinkVANCRequires10BitYUVVideoFrames, &flag);\n            if (flag) {\n                CASPAR_LOG(warning) << print()\n                                    << L\" DeckLink hardware only supports VANC when the active picture and ancillary \"\n                                       L\"data are both 10-bit YUV pixel format.\";\n            } else {\n                CASPAR_LOG(info) << print() << L\" DeckLink hardware supports VANC.\";\n                vanc_ = create_vanc(config.vanc);\n            }\n        }\n\n        enable_video();\n\n        if (config.embedded_audio) {\n            enable_audio();\n        }\n\n        set_latency(configuration_, config.latency, print());\n        set_keyer(attributes_, output_, keyer_, config.keyer, mode_->GetDisplayMode(), format_strategy_->get_pixel_format(), print());\n\n        if (config.hdr) {\n            BOOL flag = FALSE;\n            if (SUCCEEDED(attributes_->GetFlag(BMDDeckLinkSupportsHDRMetadata, &flag)) && !flag)\n                CASPAR_LOG(error) << print() << L\" Device does not support HDR metadata.\";\n            if (SUCCEEDED(attributes_->GetFlag(BMDDeckLinkSupportsColorspaceMetadata, &flag)) && !flag)\n                CASPAR_LOG(warning) << print() << L\" Device does not support colorspace metadata.\";\n        }\n\n        if (config.embedded_audio) {\n            output_->BeginAudioPreroll();\n        }\n\n        for (int n = 0; n < buffer_size_; ++n) {\n            auto nb_samples = decklink_format_desc_.audio_cadence[n % decklink_format_desc_.audio_cadence.size()] *\n                              decklink_format_desc_.field_count;\n            if (config.embedded_audio) {\n                schedule_next_audio(std::vector<int32_t>(nb_samples * decklink_format_desc_.audio_channels),\n                                    nb_samples);\n            }\n\n            std::shared_ptr<void> image_data = format_strategy_->allocate_frame_data(decklink_format_desc_);\n\n            schedule_next_video(image_data, nb_samples, video_scheduled_);\n            for (auto& context : secondary_port_contexts_) {\n                context->schedule_next_video(image_data, 0, video_scheduled_);\n            }\n\n            video_scheduled_ += decklink_format_desc_.duration;\n        }\n\n        if (config.embedded_audio) {\n            output_->EndAudioPreroll();\n        }\n\n        wait_for_reference_lock();\n\n        start_playback();\n    }\n\n    ~decklink_consumer()\n    {\n        abort_request_ = true;\n        buffer_cond_.notify_all();\n\n        if (output_ != nullptr) {\n            output_->StopScheduledPlayback(0, nullptr, 0);\n            if (config_.embedded_audio) {\n                output_->DisableAudioOutput();\n            }\n            output_->DisableVideoOutput();\n        }\n\n        secondary_port_contexts_.clear();\n    }\n\n    void wait_for_reference_lock()\n    {\n        if (config_.wait_for_reference_duration == 0 ||\n            config_.wait_for_reference == configuration::wait_for_reference_t::disabled) {\n            // Wait disabled\n            return;\n        }\n        if (config_.wait_for_reference == configuration::wait_for_reference_t::automatic && device_sync_group_ == 0) {\n            // Wait is not necessary\n            return;\n        }\n\n        CASPAR_LOG(info) << print() << L\" Reference signal: waiting for lock\";\n\n        // When using the sync group we need a reference lock before starting playback, otherwise the outputs will not\n        // be locked correctly and will be out of sync\n        auto wait_end = std::chrono::system_clock::now() + std::chrono::seconds(config_.wait_for_reference_duration);\n        while (std::chrono::system_clock::now() < wait_end) {\n            BMDReferenceStatus reference_status;\n            if (output_->GetReferenceStatus(&reference_status) != S_OK) {\n                CASPAR_LOG(error) << print() << L\" Reference signal: failed while querying status\";\n                break;\n            }\n\n            if (reference_status & bmdReferenceNotSupportedByHardware) {\n                CASPAR_LOG(info) << print() << L\" Reference signal: not supported by hardware.\";\n                break;\n            } else if (reference_status & bmdReferenceLocked) {\n                CASPAR_LOG(info) << print() << L\" Reference signal: locked\";\n\n                // TODO - is this necessary? This is to give it a chance to stabilise before continuing\n                std::this_thread::sleep_for(std::chrono::milliseconds(100));\n\n                return;\n            }\n\n            std::this_thread::sleep_for(std::chrono::milliseconds(100));\n        }\n\n        CASPAR_LOG(warning) << print() << L\" Reference signal: unable to acquire lock\";\n    }\n\n    void enable_audio()\n    {\n        if (FAILED(output_->EnableAudioOutput(bmdAudioSampleRate48kHz,\n                                              bmdAudioSampleType32bitInteger,\n                                              decklink_format_desc_.audio_channels,\n                                              bmdAudioOutputStreamTimestamped))) {\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Could not enable audio output.\"));\n        }\n\n        CASPAR_LOG(info) << print() << L\" Enabled embedded-audio.\";\n    }\n\n    void enable_video()\n    {\n        BMDVideoOutputFlags output_flags = bmdVideoOutputFlagDefault;\n        if (device_sync_group_ > 0) {\n            output_flags = static_cast<BMDVideoOutputFlags>(output_flags | bmdVideoOutputSynchronizeToPlaybackGroup);\n        }\n        if (vanc_) {\n            output_flags = static_cast<BMDVideoOutputFlags>(output_flags | bmdVideoOutputVANC);\n        }\n\n        if (FAILED(output_->EnableVideoOutput(mode_->GetDisplayMode(), output_flags))) {\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(print() + L\" Could not enable primary video output.\"));\n        }\n\n        if (FAILED(output_->SetScheduledFrameCompletionCallback(this))) {\n            CASPAR_THROW_EXCEPTION(caspar_exception()\n                                   << msg_info(print() + L\" Failed to set primary playback completion callback.\")\n                                   << boost::errinfo_api_function(\"SetScheduledFrameCompletionCallback\"));\n        }\n\n        for (auto& context : secondary_port_contexts_) {\n            context->enable_video([this]() { return print(); });\n        }\n    }\n\n    void start_playback()\n    {\n        if (FAILED(output_->StartScheduledPlayback(0, decklink_format_desc_.time_scale, 1.0))) {\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to schedule primary playback.\"));\n        }\n\n        for (auto& context : secondary_port_contexts_) {\n            context->start_playback([this]() { return print(); });\n        }\n    }\n\n    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) override { return E_NOINTERFACE; }\n    ULONG STDMETHODCALLTYPE   AddRef() override { return 1; }\n    ULONG STDMETHODCALLTYPE   Release() override { return 1; }\n\n    HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped() override\n    {\n        CASPAR_LOG(info) << print() << L\" Scheduled playback has stopped.\";\n        return S_OK;\n    }\n\n    HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted(IDeckLinkVideoFrame*           completed_frame,\n                                                      BMDOutputFrameCompletionResult result) override\n    {\n        thread_local auto priority_set = false;\n        if (!priority_set) {\n            priority_set = true;\n            // set_thread_realtime_priority();\n            set_thread_name(L\"decklink_consumer[\" + std::to_wstring(config_.primary.device_index) +\n                            L\"]-ScheduledFrameCompleted\");\n        }\n        try {\n            auto tick_time = tick_timer_.elapsed() * decklink_format_desc_.hz * 0.5;\n            graph_->set_value(\"tick-time\", tick_time);\n            tick_timer_.restart();\n\n            reference_signal_detector_.detect_change([this]() { return print(); });\n\n            auto dframe = reinterpret_cast<decklink_frame*>(completed_frame);\n            // ++scheduled_frames_completed_;\n\n            /*\n            if (key_context_) {\n                graph_->set_value(\n                    \"key-offset\",\n                    static_cast<double>(scheduled_frames_completed_ - key_context_->scheduled_frames_completed_) * 0.1 +\n                        0.5);\n            }\n            */\n\n            /**\n             * TODO - track how the secondaries are doing by comparing IDeckLinkOutput::GetScheduledStreamTime\n             */\n\n            if (result == bmdOutputFrameDisplayedLate) {\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"late-frame\");\n                video_scheduled_ += decklink_format_desc_.duration;\n                audio_scheduled_ += dframe->nb_samples();\n            } else if (result == bmdOutputFrameDropped) {\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n            } else if (result == bmdOutputFrameFlushed) {\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"flushed-frame\");\n            }\n\n            {\n                UINT32 buffered;\n                output_->GetBufferedVideoFrameCount(&buffered);\n                graph_->set_value(\"buffered-video\", static_cast<double>(buffered) / config_.buffer_depth());\n\n                if (config_.embedded_audio) {\n                    output_->GetBufferedAudioSampleFrameCount(&buffered);\n                    graph_->set_value(\"buffered-audio\",\n                                      static_cast<double>(buffered) /\n                                          (decklink_format_desc_.audio_cadence[0] * decklink_format_desc_.field_count *\n                                           config_.buffer_depth()));\n                }\n            }\n\n            core::const_frame frame1 = pop();\n            core::const_frame frame2;\n\n            bool isInterlaced = mode_->GetFieldDominance() != bmdProgressiveFrame;\n            if (mode_->GetFieldDominance() != bmdProgressiveFrame) {\n                // If the main is not progressive, then pop the second frame\n                frame2 = pop();\n            }\n\n            if (abort_request_)\n                return E_FAIL;\n\n            BMDTimeValue video_display_time = video_scheduled_;\n            video_scheduled_ += decklink_format_desc_.duration;\n\n            std::vector<std::int32_t> audio_data;\n            if (config_.embedded_audio) {\n                audio_data.insert(audio_data.end(), frame1.audio_data().begin(), frame1.audio_data().end());\n                if (isInterlaced) {\n                    audio_data.insert(audio_data.end(), frame2.audio_data().begin(), frame2.audio_data().end());\n                }\n            }\n            // TODO: is this reliable?\n            const int nb_samples = static_cast<int>(audio_data.size()) / decklink_format_desc_.audio_channels;\n\n            // Schedule video\n            tbb::parallel_for(-1, static_cast<int>(secondary_port_contexts_.size()), [&](int i) {\n                if (i == -1) {\n                    // Primary port\n                    std::shared_ptr<void> image_data =\n                        format_strategy_->convert_frame_for_port(channel_format_desc_,\n                                                                 decklink_format_desc_,\n                                                                 config_.primary,\n                                                                 frame1,\n                                                                 frame2,\n                                                                 mode_->GetFieldDominance());\n\n                    schedule_next_video(image_data, nb_samples, video_display_time);\n\n                    if (config_.embedded_audio) {\n                        schedule_next_audio(std::move(audio_data), nb_samples);\n                    }\n                } else {\n                    // Send frame to secondary ports\n                    auto& context = secondary_port_contexts_[i];\n                    context->schedule_frame(frame1, video_display_time);\n                    if (isInterlaced) {\n                        context->schedule_frame(frame2, video_display_time);\n                    }\n\n                    if (config_.embedded_audio) {\n                        // TODO - audio for secondaries?\n                    }\n                }\n            });\n\n        } catch (...) {\n            std::lock_guard<std::mutex> lock(exception_mutex_);\n            exception_ = std::current_exception();\n            return E_FAIL;\n        }\n\n        return S_OK;\n    }\n\n    core::const_frame pop()\n    {\n        core::const_frame frame;\n        {\n            std::unique_lock<std::mutex> lock(buffer_mutex_);\n            buffer_cond_.wait(lock, [&] { return !buffer_.empty() || abort_request_; });\n            if (!abort_request_) {\n                frame = buffer_.front();\n                buffer_.pop();\n            }\n        }\n        buffer_cond_.notify_all();\n        return frame;\n    }\n\n    void schedule_next_audio(std::vector<std::int32_t> audio, int nb_samples)\n    {\n        // TODO (refactor) does ScheduleAudioSamples copy data?\n\n        audio_container_.push_back(std::move(audio));\n\n        if (FAILED(output_->ScheduleAudioSamples(audio_container_.back().data(),\n                                                 nb_samples,\n                                                 audio_scheduled_,\n                                                 decklink_format_desc_.audio_sample_rate,\n                                                 nullptr))) {\n            CASPAR_LOG(error) << print() << L\" Failed to schedule audio.\";\n        }\n\n        audio_scheduled_ += nb_samples; // TODO - what if there are too many/few samples in this frame?\n    }\n\n    void schedule_next_video(std::shared_ptr<void> image_data, int nb_samples, BMDTimeValue display_time)\n    {\n        auto fmt        = format_strategy_->get_pixel_format();\n        auto row_bytes  = format_strategy_->get_row_bytes(decklink_format_desc_.width);\n        auto fill_frame = wrap_raw<com_ptr, IDeckLinkVideoFrame>(new decklink_frame(std::move(image_data),\n                                                                                    decklink_format_desc_,\n                                                                                    nb_samples,\n                                                                                    config_.hdr,\n                                                                                    fmt,\n                                                                                    row_bytes,\n                                                                                    config_.vanc.enable,\n                                                                                    config_.color_space,\n                                                                                    config_.hdr_meta));\n\n        if (vanc_ && vanc_->has_data()) {\n            auto ancillary_packets = iface_cast<IDeckLinkVideoFrameAncillaryPackets>(fill_frame);\n            auto packets           = vanc_->pop_packets();\n            for (auto& packet : packets) {\n                if (FAILED(ancillary_packets->AttachPacket(get_raw(packet)))) {\n                    CASPAR_LOG(error) << print() << L\" Failed to add ancillary packet.\";\n                }\n            }\n\n            bool isInterlaced = mode_->GetFieldDominance() != bmdProgressiveFrame;\n            if (isInterlaced) {\n                auto field2_packets = vanc_->pop_packets(true);\n                for (auto& packet : field2_packets) {\n                    if (FAILED(ancillary_packets->AttachPacket(get_raw(packet)))) {\n                        CASPAR_LOG(error) << print() << L\" Failed to add ancillary packet.\";\n                    }\n                }\n            }\n        }\n        if (FAILED(output_->ScheduleVideoFrame(\n                get_raw(fill_frame), display_time, decklink_format_desc_.duration, decklink_format_desc_.time_scale))) {\n            CASPAR_LOG(error) << print() << L\" Failed to schedule primary video.\";\n        }\n    }\n\n    bool send(core::video_field field, core::const_frame frame)\n    {\n        {\n            std::lock_guard<std::mutex> lock(exception_mutex_);\n            if (exception_ != nullptr) {\n                std::rethrow_exception(exception_);\n            }\n        }\n\n        if (frame) {\n            std::unique_lock<std::mutex> lock(buffer_mutex_);\n            if (field != core::video_field::b) {\n                // Always push a field2, as we have supplied field1\n                buffer_cond_.wait(lock, [&] { return buffer_.size() < buffer_capacity_ || abort_request_; });\n            }\n            buffer_.push(std::move(frame));\n        }\n        buffer_cond_.notify_all();\n\n        return !abort_request_;\n    }\n\n    bool call(const std::vector<std::wstring>& params)\n    {\n        try {\n            bool result = vanc_->try_push_data(params);\n            if (!result) {\n                CASPAR_LOG(warning) << print() << L\" Unknown command: \" << (params.empty() ? L\"N/A\" : params[0]);\n            }\n\n            return result;\n        } catch (...) {\n            CASPAR_LOG(warning) << print() << L\" Failed to apply: \" << (params.empty() ? L\"N/A\" : params[0]);\n        }\n        return false;\n    }\n\n    [[nodiscard]] std::wstring print() const\n    {\n        std::wstringstream buffer;\n\n        buffer << model_name_ << L\" [\" + std::to_wstring(channel_index_) << L\"-\"\n               << std::to_wstring(config_.primary.device_index) << L\"|\" << decklink_format_desc_.name << L\"]\";\n\n        for (auto& context : secondary_port_contexts_) {\n            buffer << L\" && \" + context->print();\n        }\n\n        return buffer.str();\n    }\n};\n\nstruct decklink_consumer_proxy : public core::frame_consumer\n{\n    const configuration                config_;\n    std::unique_ptr<decklink_consumer> consumer_;\n    core::video_format_desc            format_desc_;\n    executor                           executor_;\n\n  public:\n    explicit decklink_consumer_proxy(const configuration& config)\n        : config_(config)\n        , executor_(L\"decklink_consumer[\" + std::to_wstring(config.primary.device_index) + L\"]\")\n    {\n        executor_.begin_invoke([=] { com_initialize(); });\n    }\n\n    ~decklink_consumer_proxy() override\n    {\n        executor_.invoke([=, this] {\n            set_thread_realtime_priority();\n            consumer_.reset();\n            com_uninitialize();\n        });\n    }\n\n    void initialize(const core::video_format_desc& format_desc,\n                    const core::channel_info&      channel_info,\n                    int                            port_index) override\n    {\n        format_desc_ = format_desc;\n        executor_.invoke([=, this] {\n            consumer_.reset();\n            consumer_ = std::make_unique<decklink_consumer>(config_, format_desc, channel_info.index);\n        });\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        return executor_.begin_invoke([=, this] { return consumer_->send(field, frame); });\n    }\n\n    std::future<bool> call(const std::vector<std::wstring>& params) override\n    {\n        return executor_.begin_invoke([=, this] { return consumer_->call(params); });\n    }\n\n    [[nodiscard]] std::wstring print() const override\n    {\n        return consumer_ ? consumer_->print() : L\"[decklink_consumer]\";\n    }\n\n    [[nodiscard]] std::wstring name() const override { return L\"decklink\"; }\n\n    [[nodiscard]] int index() const override { return 300 + static_cast<int>(config_.primary.device_index); }\n\n    [[nodiscard]] bool has_synchronization_clock() const override { return true; }\n\n    [[nodiscard]] core::monitor::state state() const override { return get_state_for_config(config_, format_desc_); }\n};\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info)\n{\n    if (params.empty() || !boost::iequals(params.at(0), L\"DECKLINK\")) {\n        return core::frame_consumer::empty();\n    }\n\n    configuration config = parse_amcp_config(params, format_repository, channel_info);\n\n    config.hdr = (channel_info.depth != common::bit_depth::bit8);\n\n    if (config.hdr && config.primary.key_only) {\n        CASPAR_THROW_EXCEPTION(caspar_exception()\n                               << msg_info(\"Decklink consumer does not support hdr in combination with key only\"));\n    }\n\n    return spl::make_shared<decklink_consumer_proxy>(config);\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info)\n{\n    configuration config = parse_xml_config(ptree, format_repository, channel_info);\n\n    config.hdr = (channel_info.depth != common::bit_depth::bit8);\n\n    if (config.hdr && config.primary.key_only) {\n        CASPAR_THROW_EXCEPTION(caspar_exception()\n                               << msg_info(\"Decklink consumer does not support hdr in combination with key only\"));\n    }\n\n    return spl::make_shared<decklink_consumer_proxy>(config);\n}\n\n}} // namespace caspar::decklink\n\n/*\n##############################################################################\nPre-rolling\n\nMail: 2011-05-09\n\nYoshan\nBMD Developer Support\ndeveloper@blackmagic-design.com\n\n-----------------------------------------------------------------------------\n\nThanks for your inquiry. The minimum number of frames that you can preroll\nfor scheduled playback is three frames for video and four frames for audio.\nAs you mentioned if you preroll less frames then playback will not start or\nplayback will be very sporadic. From our experience with Media Express, we\nrecommended that at least seven frames are prerolled for smooth playback.\n\nRegarding the bmdDeckLinkConfigLowLatencyVideoOutput flag:\nThere can be around 3 frames worth of latency on scheduled output.\nWhen the bmdDeckLinkConfigLowLatencyVideoOutput flag is used this latency is\nreduced  or removed for scheduled playback. If the DisplayVideoFrameSync()\nmethod is used, the bmdDeckLinkConfigLowLatencyVideoOutput setting will\nguarantee that the provided frame will be output as soon the previous\nframe output has been completed.\n################################################################################\n*/\n\n/*\n##############################################################################\nAsync DMA Transfer without redundant copying\n\nMail: 2011-05-10\n\nYoshan\nBMD Developer Support\ndeveloper@blackmagic-design.com\n\n-----------------------------------------------------------------------------\n\nThanks for your inquiry. You could try subclassing IDeckLinkMutableVideoFrame\nand providing a pointer to your video buffer when GetBytes() is called.\nThis may help to keep copying to a minimum. Please ensure that the pixel\nformat is in bmdFormat10BitYUV, otherwise the DeckLink API / driver will\nhave to colourspace convert which may result in additional copying.\n################################################################################\n*/\n"
  },
  {
    "path": "src/modules/decklink/consumer/decklink_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace decklink {\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info);\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info);\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/format_strategy.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas P Andersson, niklas@nxtedition.com\n */\n\n#pragma once\n\n#include \"../StdAfx.h\"\n\n#include \"config.h\"\n\n#include \"../decklink_api.h\"\n\n#include <core/frame/frame.h>\n#include <core/video_format.h>\n\n#include <memory>\n\nnamespace caspar { namespace decklink {\n\nclass format_strategy\n{\n  protected:\n    format_strategy() = default;\n\n  public:\n    format_strategy& operator=(const format_strategy&) = delete;\n    virtual ~format_strategy()                         = default;\n\n    format_strategy(const format_strategy&) = delete;\n\n    virtual BMDPixelFormat        get_pixel_format()                                              = 0;\n    virtual int                   get_row_bytes(int width)                                        = 0;\n    virtual std::shared_ptr<void> allocate_frame_data(const core::video_format_desc& format_desc) = 0;\n    virtual std::shared_ptr<void> convert_frame_for_port(const core::video_format_desc& channel_format_desc,\n                                                         const core::video_format_desc& decklink_format_desc,\n                                                         const port_configuration&      config,\n                                                         const core::const_frame&       frame1,\n                                                         const core::const_frame&       frame2,\n                                                         BMDFieldDominance              field_dominance)       = 0;\n};\n\nspl::shared_ptr<format_strategy> create_sdr_bgra_strategy();\nspl::shared_ptr<format_strategy> create_sdr_v210_strategy(core::color_space colorspace);\nspl::shared_ptr<format_strategy> create_hdr_v210_strategy(core::color_space colorspace);\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/monitor.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"monitor.h\"\n\nnamespace caspar { namespace decklink {\n\ncore::monitor::state get_state_for_port(const port_configuration&      port_config,\n                                        const core::video_format_desc& channel_format)\n{\n    core::monitor::state state;\n\n    state[\"index\"]    = port_config.device_index;\n    state[\"key-only\"] = port_config.key_only;\n\n    if (port_config.format.format == core::video_format::invalid) {\n        state[\"video-mode\"] = channel_format.name;\n    } else {\n        state[\"video-mode\"] = port_config.format.name;\n    }\n\n    if (port_config.has_subregion_geometry()) {\n        state[\"subregion/src-x\"]  = port_config.src_x;\n        state[\"subregion/src-y\"]  = port_config.src_y;\n        state[\"subregion/src-x\"]  = port_config.dest_x;\n        state[\"subregion/dest-y\"] = port_config.dest_y;\n        state[\"subregion/width\"]  = port_config.region_w;\n        state[\"subregion/height\"] = port_config.region_h;\n    }\n\n    return state;\n}\n\ncore::monitor::state get_state_for_config(const configuration& config, const core::video_format_desc& channel_format)\n{\n    core::monitor::state state;\n\n    state[\"decklink\"] = get_state_for_port(config.primary, channel_format);\n\n    state[\"decklink/embedded-audio\"] = config.embedded_audio;\n    state[\"decklink/buffer-depth\"]   = config.base_buffer_depth;\n\n    if (config.keyer == configuration::keyer_t::external_keyer) {\n        state[\"decklink/keyer\"] = std::wstring(L\"external\");\n    } else if (config.keyer == configuration::keyer_t::internal_keyer) {\n        state[\"decklink/keyer\"] = std::wstring(L\"internal\");\n    }\n\n    if (config.latency == configuration::latency_t::low_latency) {\n        state[\"decklink/latency\"] = std::wstring(L\"low\");\n    } else if (config.latency == configuration::latency_t::normal_latency) {\n        state[\"decklink/latency\"] = std::wstring(L\"normal\");\n    }\n\n    int index = 0;\n    for (auto& port_config : config.secondaries) {\n        state[\"decklink/ports\"][index++] = get_state_for_port(port_config, channel_format);\n    }\n\n    return state;\n}\n\n}} // namespace caspar::decklink"
  },
  {
    "path": "src/modules/decklink/consumer/monitor.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include \"config.h\"\n\n#include <core/monitor/monitor.h>\n\nnamespace caspar { namespace decklink {\n\ncore::monitor::state get_state_for_config(const configuration& config, const core::video_format_desc& channel_format);\n\n}} // namespace caspar::decklink"
  },
  {
    "path": "src/modules/decklink/consumer/sdr_bgra_strategy.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n * Author: Niklas Andersson, niklas@nxtedition.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"format_strategy.h\"\n\n#include <common/memshfl.h>\n\n#include <tbb/parallel_for.h>\n#include <tbb/scalable_allocator.h>\n\nnamespace caspar { namespace decklink {\n\nstd::shared_ptr<void> convert_to_key_only(const std::shared_ptr<void>& image_data, std::size_t byte_count)\n{\n    auto key_data = create_aligned_buffer(byte_count);\n\n    aligned_memshfl(key_data.get(), image_data.get(), byte_count, 0x0F0F0F0F, 0x0B0B0B0B, 0x07070707, 0x03030303);\n\n    return key_data;\n}\n\nclass sdr_bgra_strategy\n    : public format_strategy\n    , std::enable_shared_from_this<sdr_bgra_strategy>\n{\n  public:\n    sdr_bgra_strategy() = default;\n\n    BMDPixelFormat get_pixel_format() override { return bmdFormat8BitBGRA; }\n    int            get_row_bytes(int width) override { return width * 4; }\n\n    std::shared_ptr<void> allocate_frame_data(const core::video_format_desc& format_desc) override\n    {\n        return create_aligned_buffer(format_desc.size, 64);\n    }\n\n    std::shared_ptr<void> convert_frame_for_port(const core::video_format_desc& channel_format_desc,\n                                                 const core::video_format_desc& decklink_format_desc,\n                                                 const port_configuration&      config,\n                                                 const core::const_frame&       frame1,\n                                                 const core::const_frame&       frame2,\n                                                 BMDFieldDominance              field_dominance) override\n    {\n        std::shared_ptr<void> image_data = allocate_frame_data(decklink_format_desc);\n\n        if (field_dominance != bmdProgressiveFrame) {\n            convert_frame(channel_format_desc,\n                          decklink_format_desc,\n                          config,\n                          image_data,\n                          field_dominance == bmdUpperFieldFirst,\n                          frame1);\n\n            convert_frame(channel_format_desc,\n                          decklink_format_desc,\n                          config,\n                          image_data,\n                          field_dominance != bmdUpperFieldFirst,\n                          frame2);\n\n        } else {\n            convert_frame(channel_format_desc, decklink_format_desc, config, image_data, true, frame1);\n        }\n\n        if (config.key_only) {\n            image_data = convert_to_key_only(image_data, decklink_format_desc.size);\n        }\n\n        return image_data;\n    }\n\n  private:\n    void convert_frame(const core::video_format_desc& channel_format_desc,\n                       const core::video_format_desc& decklink_format_desc,\n                       const port_configuration&      config,\n                       std::shared_ptr<void>&         image_data,\n                       bool                           topField,\n                       const core::const_frame&       frame)\n    {\n        // No point copying an empty frame\n        if (!frame)\n            return;\n\n        int firstLine = topField ? 0 : 1;\n\n        if (channel_format_desc.format == decklink_format_desc.format && config.src_x == 0 && config.src_y == 0 &&\n            config.region_w == 0 && config.region_h == 0 && config.dest_x == 0 && config.dest_y == 0) {\n            // Fast path\n\n            size_t byte_count_line = (size_t)decklink_format_desc.width * 4;\n            for (int y = firstLine; y < decklink_format_desc.height; y += decklink_format_desc.field_count) {\n                std::memcpy(reinterpret_cast<char*>(image_data.get()) + (long long)y * byte_count_line,\n                            frame.image_data(0).data() + (long long)y * byte_count_line,\n                            byte_count_line);\n            }\n        } else {\n            // Take a sub-region\n\n            // Some repetetive numbers\n            size_t byte_count_dest_line  = (size_t)decklink_format_desc.width * 4;\n            size_t byte_count_src_line   = (size_t)channel_format_desc.width * 4;\n            size_t byte_offset_src_line  = std::max(0, (config.src_x * 4));\n            size_t byte_offset_dest_line = std::max(0, (config.dest_x * 4));\n            int    y_skip_src_lines      = std::max(0, config.src_y);\n            int    y_skip_dest_lines     = std::max(0, config.dest_y);\n\n            size_t byte_copy_per_line =\n                std::min(byte_count_src_line - byte_offset_src_line, byte_count_dest_line - byte_offset_dest_line);\n            if (config.region_w > 0) // If the user chose a width, respect that\n                byte_copy_per_line = std::min(byte_copy_per_line, (size_t)config.region_w * 4);\n\n            size_t byte_pad_end_of_line = std::max(\n                ((size_t)decklink_format_desc.width * 4) - byte_copy_per_line - byte_offset_dest_line, (size_t)0);\n\n            int copy_line_count = std::min(channel_format_desc.height - y_skip_src_lines,\n                                           decklink_format_desc.height - y_skip_dest_lines);\n            if (config.region_h > 0) // If the user chose a height, respect that\n                copy_line_count = std::min(copy_line_count, config.region_h);\n\n            int max_y_content = y_skip_dest_lines + std::min(copy_line_count, channel_format_desc.height);\n\n            for (int y = firstLine; y < y_skip_dest_lines; y += decklink_format_desc.field_count) {\n                // Fill the line with black\n                std::memset(\n                    reinterpret_cast<char*>(image_data.get()) + (byte_count_dest_line * y), 0, byte_count_dest_line);\n            }\n\n            int firstFillLine = y_skip_dest_lines;\n            if (decklink_format_desc.field_count != 1 && firstFillLine % 2 != firstLine)\n                firstFillLine += 1;\n            for (int y = firstFillLine; y < max_y_content; y += decklink_format_desc.field_count) {\n                auto line_start_ptr   = reinterpret_cast<char*>(image_data.get()) + (long long)y * byte_count_dest_line;\n                auto line_content_ptr = line_start_ptr + byte_offset_dest_line;\n\n                // Fill the start with black\n                if (byte_offset_dest_line > 0) {\n                    std::memset(line_start_ptr, 0, byte_offset_dest_line);\n                }\n\n                // Copy the pixels\n                long long src_y = y + y_skip_src_lines - y_skip_dest_lines;\n                std::memcpy(line_content_ptr,\n                            frame.image_data(0).data() + src_y * byte_count_src_line + byte_offset_src_line,\n                            byte_copy_per_line);\n\n                // Fill the end with black\n                if (byte_pad_end_of_line > 0) {\n                    std::memset(line_content_ptr + byte_copy_per_line, 0, byte_pad_end_of_line);\n                }\n            }\n\n            // Calculate the first line number to fill with black\n            if (decklink_format_desc.field_count != 1 && max_y_content % 2 != firstLine)\n                max_y_content += 1;\n            for (int y = max_y_content; y < decklink_format_desc.height; y += decklink_format_desc.field_count) {\n                // Fill the line with black\n                std::memset(\n                    reinterpret_cast<char*>(image_data.get()) + (byte_count_dest_line * y), 0, byte_count_dest_line);\n            }\n        }\n    }\n};\n\nspl::shared_ptr<format_strategy> create_sdr_bgra_strategy()\n{\n    return spl::make_shared<format_strategy, sdr_bgra_strategy>();\n}\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/v210_strategies.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas@nxtedition.com\n */\n\n#include \"../StdAfx.h\"\n\n#if !defined(WIN32) && (defined(__x86_64__) || defined(__i386__))\n// Force this file to compile with avx2, as it has been crafted with intrinsics that require it.\n#pragma GCC target(\"avx2\")\n#endif\n\n#ifdef USE_SIMDE\n#define SIMDE_ENABLE_NATIVE_ALIASES\n#include <simde/x86/avx2.h>\n#endif\n\n#include <type_traits>\n\n#include \"format_strategy.h\"\n\n#include <common/memshfl.h>\n\n#include <tbb/parallel_for.h>\n#include <tbb/scalable_allocator.h>\n\nnamespace caspar { namespace decklink {\n\nstd::vector<int32_t> create_int_matrix(const std::vector<float>& matrix)\n{\n    static const float LumaRangeWidth   = 876.f * (1024.f / 1023.f);\n    static const float ChromaRangeWidth = 896.f * (1024.f / 1023.f);\n\n    std::vector<float> color_matrix_f(matrix);\n\n    color_matrix_f[0] *= LumaRangeWidth;\n    color_matrix_f[1] *= LumaRangeWidth;\n    color_matrix_f[2] *= LumaRangeWidth;\n\n    color_matrix_f[3] *= ChromaRangeWidth;\n    color_matrix_f[4] *= ChromaRangeWidth;\n    color_matrix_f[5] *= ChromaRangeWidth;\n    color_matrix_f[6] *= ChromaRangeWidth;\n    color_matrix_f[7] *= ChromaRangeWidth;\n    color_matrix_f[8] *= ChromaRangeWidth;\n\n    std::vector<int32_t> int_matrix(color_matrix_f.size());\n\n    transform(color_matrix_f.cbegin(), color_matrix_f.cend(), int_matrix.begin(), [](const float& f) {\n        return (int32_t)round(f * 1024.f);\n    });\n\n    return int_matrix;\n};\n\ninline void rgb_to_yuv_avx2(__m256i                     pixel_pairs[4],\n                            const std::vector<int32_t>& color_matrix,\n                            __m256i*                    luma_out,\n                            __m256i*                    chroma_out)\n{\n    /* COMPUTE LUMA */\n    {\n        __m256i y_coeff =\n            _mm256_broadcastsi128_si256(_mm_set_epi32(0, color_matrix[2], color_matrix[1], color_matrix[0]));\n        __m256i y_offset = _mm256_set1_epi32(64 << 20);\n\n        // Multiply by y-coefficients\n        __m256i y4[4];\n        for (int i = 0; i < 4; i++) {\n            y4[i] = _mm256_mullo_epi32(pixel_pairs[i], y_coeff);\n        }\n\n        // sum products\n        __m256i y2_sum0123    = _mm256_hadd_epi32(y4[0], y4[1]);\n        __m256i y2_sum4567    = _mm256_hadd_epi32(y4[2], y4[3]);\n        __m256i y_sum01452367 = _mm256_hadd_epi32(y2_sum0123, y2_sum4567);\n        *luma_out             = _mm256_srli_epi32(_mm256_add_epi32(y_sum01452367, y_offset),\n                                      20); // add offset and shift down to 10 bit precision\n    }\n\n    /* COMPUTE CHROMA */\n    {\n        __m256i cb_coeff =\n            _mm256_broadcastsi128_si256(_mm_set_epi32(0, color_matrix[5], color_matrix[4], color_matrix[3]));\n        __m256i cr_coeff =\n            _mm256_broadcastsi128_si256(_mm_set_epi32(0, color_matrix[8], color_matrix[7], color_matrix[6]));\n        __m256i c_offset = _mm256_set1_epi32((1025) << 19);\n\n        // Multiply by cb-coefficients\n        __m256i cbcr4[4]; // 0 = cb02, 1 = cr02, 2 = cb46, 3 = cr46\n        for (int i = 0; i < 2; i++) {\n            cbcr4[i * 2]     = _mm256_mullo_epi32(pixel_pairs[i * 2], cb_coeff);\n            cbcr4[i * 2 + 1] = _mm256_mullo_epi32(pixel_pairs[i * 2], cr_coeff);\n        }\n\n        // sum products\n        __m256i cbcr_sum02    = _mm256_hadd_epi32(cbcr4[1], cbcr4[0]);\n        __m256i cbcr_sum46    = _mm256_hadd_epi32(cbcr4[3], cbcr4[2]);\n        __m256i cbcr_sum_0426 = _mm256_hadd_epi32(cbcr_sum02, cbcr_sum46);\n        *chroma_out           = _mm256_srli_epi32(_mm256_add_epi32(cbcr_sum_0426, c_offset),\n                                        20); // add offset and shift down to 10 bit precision\n    }\n}\n\ninline void pack_v210_avx2(__m256i luma[6], __m256i chroma[6], __m128i** v210_dest)\n{\n    __m256i luma_16bit[3];\n    __m256i chroma_16bit[3];\n    __m256i offsets = _mm256_set_epi32(7, 3, 6, 2, 5, 1, 4, 0);\n    for (int i = 0; i < 3; i++) {\n        auto y16    = _mm256_packus_epi32(luma[i * 2], luma[i * 2 + 1]);\n        auto cbcr16 = _mm256_packus_epi32(chroma[i * 2],\n                                          chroma[i * 2 + 1]); // cbcr0 cbcr4 cbcr8 cbcr12\n                                                              // cbcr2 cbcr6 cbcr10 cbcr14\n        luma_16bit[i] =\n            _mm256_permutevar8x32_epi32(y16,\n                                        offsets); // layout 0 1   2 3   4 5   6 7   8 9   10 11   12 13   14 15\n        chroma_16bit[i] = _mm256_permutevar8x32_epi32(cbcr16,\n                                                      offsets); // cbcr0 cbcr2 cbcr4 cbcr6   cbcr8 cbcr10 cbcr12 cbcr14\n    }\n\n    __m128i chroma_mult = _mm_set_epi16(0, 0, 4, 16, 1, 4, 16, 1);\n    __m128i chroma_shuf = _mm_set_epi8(-1, 11, 10, -1, 9, 8, 7, 6, -1, 5, 4, -1, 3, 2, 1, 0);\n\n    __m128i luma_mult = _mm_set_epi16(0, 0, 16, 1, 4, 16, 1, 4);\n    __m128i luma_shuf = _mm_set_epi8(11, 10, 9, 8, -1, 7, 6, -1, 5, 4, 3, 2, -1, 1, 0, -1);\n\n    uint16_t* luma_ptr   = reinterpret_cast<uint16_t*>(luma_16bit);\n    uint16_t* chroma_ptr = reinterpret_cast<uint16_t*>(chroma_16bit);\n    for (int i = 0; i < 8; ++i) {\n        __m128i luma_values   = _mm_loadu_si128(reinterpret_cast<__m128i*>(luma_ptr));\n        __m128i chroma_values = _mm_loadu_si128(reinterpret_cast<__m128i*>(chroma_ptr));\n        __m128i luma_packed   = _mm_mullo_epi16(luma_values, luma_mult);\n        __m128i chroma_packed = _mm_mullo_epi16(chroma_values, chroma_mult);\n\n        luma_packed   = _mm_shuffle_epi8(luma_packed, luma_shuf);\n        chroma_packed = _mm_shuffle_epi8(chroma_packed, chroma_shuf);\n\n        auto res = _mm_or_si128(luma_packed, chroma_packed);\n        _mm_store_si128((*v210_dest)++, res);\n\n        luma_ptr += 6;\n        chroma_ptr += 6;\n    }\n}\n\ntemplate <typename T = uint16_t>\nstruct ARGBPixel\n{\n    T R;\n    T G;\n    T B;\n    T A;\n};\n\ntemplate <typename T>\nvoid pack_v210(const ARGBPixel<T>* src, const std::vector<int32_t>& color_matrix, uint32_t* dest, int num_pixels)\n{\n    auto write_v210 = [dest, index = 0, shift = 0](uint32_t val) mutable {\n        dest[index] |= ((val & 0x3FF) << shift);\n\n        shift += 10;\n        if (shift >= 30) {\n            index++;\n            shift = 0;\n        }\n    };\n\n    for (int x = 0; x < num_pixels; ++x, ++src) {\n        uint32_t r, g, b;\n        if constexpr (std::is_same<T, uint16_t>()) {\n            r = src->R >> 6;\n            g = src->G >> 6;\n            b = src->B >> 6;\n        } else if constexpr (std::is_same<T, uint8_t>()) {\n            r = src->R << 2;\n            g = src->G << 2;\n            b = src->B << 2;\n        }\n\n        if (x % 2 == 0) {\n            // Compute Cr\n            uint32_t v = 1025 << 19;\n            v += (int32_t)(color_matrix[6] * static_cast<int32_t>(r) + color_matrix[7] * static_cast<int32_t>(g) +\n                           color_matrix[8] * static_cast<int32_t>(b));\n            v >>= 20;\n            write_v210(v);\n        }\n\n        // Compute Y\n        uint32_t luma = 64 << 20;\n        luma += (int32_t)(color_matrix[0] * static_cast<int32_t>(r) + color_matrix[1] * static_cast<int32_t>(g) +\n                          color_matrix[2] * static_cast<int32_t>(b));\n        luma >>= 20;\n        write_v210(luma);\n\n        if (x % 2 == 0) {\n            // Compute Cb\n            uint32_t u = 1025 << 19;\n            u += (int32_t)(color_matrix[3] * static_cast<int32_t>(r) + color_matrix[4] * static_cast<int32_t>(g) +\n                           color_matrix[5] * static_cast<int32_t>(b));\n            u >>= 20;\n            write_v210(u);\n        }\n    }\n}\n\nclass v210_strategy\n    : public format_strategy\n    , std::enable_shared_from_this<v210_strategy>\n{\n    std::vector<float> bt709{0.212639005871510,\n                             0.715168678767756,\n                             0.072192315360734,\n                             -0.114592177555732,\n                             -0.385407822444268,\n                             0.5,\n                             0.5,\n                             -0.454155517037873,\n                             -0.045844482962127};\n    std::vector<float> bt2020{0.262700212011267,\n                              0.677998071518871,\n                              0.059301716469862,\n                              -0.139630430187157,\n                              -0.360369569812843,\n                              0.5,\n                              0.5,\n                              -0.459784529009814,\n                              -0.040215470990186};\n\n    std::vector<int32_t> color_matrix;\n    __m128i              black_batch;\n    uint8_t              bpc;\n\n  public:\n    explicit v210_strategy(core::color_space color_space, uint8_t bpc)\n        : color_matrix(create_int_matrix(color_space == core::color_space::bt2020 ? bt2020 : bt709))\n        , bpc(bpc)\n    {\n        // setup black batch (6 pixels of black, encoded as v210)\n        ARGBPixel<> black[6];\n        memset(black, 0, sizeof(black));\n        memset(&black_batch, 0, sizeof(__m128i));\n        pack_v210(black, color_matrix, reinterpret_cast<uint32_t*>(&black_batch), 6);\n    }\n\n    BMDPixelFormat get_pixel_format() override { return bmdFormat10BitYUV; }\n\n    int get_row_bytes(int width) override { return ((width + 47) / 48) * 128; }\n\n    std::shared_ptr<void> allocate_frame_data(const core::video_format_desc& format_desc) override\n    {\n        auto size = get_row_bytes(format_desc.width) * format_desc.height;\n        return create_aligned_buffer(size, 128);\n    }\n    std::shared_ptr<void> convert_frame_for_port(const core::video_format_desc& channel_format_desc,\n                                                 const core::video_format_desc& decklink_format_desc,\n                                                 const port_configuration&      config,\n                                                 const core::const_frame&       frame1,\n                                                 const core::const_frame&       frame2,\n                                                 BMDFieldDominance              field_dominance) override\n    {\n        return bpc == 1 ? do_convert_frame_for_port<uint8_t>(\n                              channel_format_desc, decklink_format_desc, config, frame1, frame2, field_dominance)\n                        : do_convert_frame_for_port<uint16_t>(\n                              channel_format_desc, decklink_format_desc, config, frame1, frame2, field_dominance);\n    }\n\n  private:\n    // Fill count 6-pixel groups with black\n    inline void fill_black_groups(__m128i*& dest, int count) const\n    {\n        for (int i = 0; i < count; ++i) {\n            _mm_storeu_si128(dest++, black_batch);\n        }\n    }\n\n    // Convert 48 pixels using AVX2 SIMD\n    template <typename T>\n    inline void convert_48_pixels_avx2(const ARGBPixel<T>*& src, __m128i*& dest) const\n    {\n        const __m256i* pixeldata = reinterpret_cast<const __m256i*>(src);\n\n        __m256i luma[6];\n        __m256i chroma[6];\n        __m256i zero = _mm256_setzero_si256();\n\n        for (int packet_index = 0; packet_index < 6; packet_index++) {\n            __m256i p0123, p4567;\n            if constexpr (std::is_same<T, uint16_t>()) {\n                p0123 = _mm256_loadu_si256(pixeldata + packet_index * 2);\n                p4567 = _mm256_loadu_si256(pixeldata + packet_index * 2 + 1);\n\n                p0123 = _mm256_srli_epi16(p0123, 6);\n                p4567 = _mm256_srli_epi16(p4567, 6);\n            } else if constexpr (std::is_same<T, uint8_t>()) {\n                auto p01234567 = _mm256_loadu_si256(pixeldata + packet_index);\n                auto p01452367 = _mm256_permute4x64_epi64(p01234567, 0b11011000);\n\n                p0123 = _mm256_unpacklo_epi8(p01452367, zero);\n                p4567 = _mm256_unpackhi_epi8(p01452367, zero);\n\n                p0123 = _mm256_slli_epi16(p0123, 2);\n                p4567 = _mm256_slli_epi16(p4567, 2);\n            } else {\n                static_assert(!std::is_same<T, T>(), \"Unsupported template type for v210 conversion\");\n            }\n\n            __m256i pixel_pairs[4];\n            pixel_pairs[0] = _mm256_unpacklo_epi16(p0123, zero);\n            pixel_pairs[1] = _mm256_unpackhi_epi16(p0123, zero);\n            pixel_pairs[2] = _mm256_unpacklo_epi16(p4567, zero);\n            pixel_pairs[3] = _mm256_unpackhi_epi16(p4567, zero);\n\n            rgb_to_yuv_avx2(pixel_pairs, color_matrix, &luma[packet_index], &chroma[packet_index]);\n        }\n\n        pack_v210_avx2(luma, chroma, &dest);\n        src += 48;\n    }\n\n    // Convert remaining pixels (less than 48) using scalar code\n    template <typename T>\n    inline void convert_remaining_pixels(const ARGBPixel<T>*& src, __m128i*& dest, int pixel_count) const\n    {\n        int full_6pixel_groups = pixel_count / 6;\n        memset(dest, 0, sizeof(__m128i) * ((pixel_count + 5) / 6));\n\n        if (full_6pixel_groups > 0) {\n            int pixels_in_groups = full_6pixel_groups * 6;\n            pack_v210(src, color_matrix, reinterpret_cast<uint32_t*>(dest), pixels_in_groups);\n            dest += full_6pixel_groups;\n            src += pixels_in_groups;\n            pixel_count -= pixels_in_groups;\n        }\n\n        // Handle final partial packet (pad with black)\n        if (pixel_count > 0) {\n            ARGBPixel<T> pixels[6];\n            memset(pixels, 0, sizeof(pixels));\n            memcpy(pixels, src, pixel_count * sizeof(ARGBPixel<T>));\n            pack_v210(pixels, color_matrix, reinterpret_cast<uint32_t*>(dest), 6);\n            dest++;\n            src += pixel_count;\n        }\n    }\n\n    template <typename T>\n    std::shared_ptr<void> do_convert_frame_for_port(const core::video_format_desc& channel_format_desc,\n                                                    const core::video_format_desc& decklink_format_desc,\n                                                    const port_configuration&      config,\n                                                    const core::const_frame&       frame1,\n                                                    const core::const_frame&       frame2,\n                                                    BMDFieldDominance              field_dominance)\n    {\n        std::shared_ptr<void> image_data = allocate_frame_data(decklink_format_desc);\n\n        if (field_dominance != bmdProgressiveFrame) {\n            convert_frame<T>(channel_format_desc,\n                             decklink_format_desc,\n                             config,\n                             image_data,\n                             field_dominance == bmdUpperFieldFirst,\n                             frame1);\n\n            convert_frame<T>(channel_format_desc,\n                             decklink_format_desc,\n                             config,\n                             image_data,\n                             field_dominance != bmdUpperFieldFirst,\n                             frame2);\n\n        } else {\n            convert_frame<T>(channel_format_desc, decklink_format_desc, config, image_data, true, frame1);\n        }\n\n        if (config.key_only) {\n            // TODO: Add support for hdr frames\n        }\n\n        return image_data;\n    }\n\n    template <typename T>\n    void convert_frame(const core::video_format_desc& channel_format_desc,\n                       const core::video_format_desc& decklink_format_desc,\n                       const port_configuration&      config,\n                       std::shared_ptr<void>&         image_data,\n                       bool                           topField,\n                       const core::const_frame&       frame)\n    {\n        if (!frame)\n            return;\n\n        int    firstLine            = topField ? 0 : 1;\n        size_t dest_line_bytes      = get_row_bytes(decklink_format_desc.width);\n        int    black_groups_per_row = static_cast<int>(dest_line_bytes / sizeof(__m128i));\n\n        // Calculate effective region dimensions\n        int region_w = config.region_w > 0 ? config.region_w : channel_format_desc.width - config.src_x;\n        int region_h = config.region_h > 0 ? config.region_h : channel_format_desc.height - config.src_y;\n\n        // Clamp to available source pixels\n        region_w = std::min(region_w, channel_format_desc.width - config.src_x);\n        region_h = std::min(region_h, channel_format_desc.height - config.src_y);\n\n        // Clamp to destination dimensions\n        int pixels_to_copy = std::min(region_w, decklink_format_desc.width - config.dest_x);\n        int lines_to_copy  = std::min(region_h, decklink_format_desc.height - config.dest_y);\n\n        int max_y_content = config.dest_y + lines_to_copy;\n\n        // Calculate dest_x alignment for v210 (6 pixels per group)\n        int black_groups_start   = config.dest_x / 6;\n        int partial_black_pixels = config.dest_x - black_groups_start * 6;\n\n        const int NUM_THREADS     = 6;\n        auto      rows_per_thread = decklink_format_desc.height / NUM_THREADS;\n\n        tbb::parallel_for(0, NUM_THREADS, [&](int thread_index) {\n            auto start_y = firstLine + thread_index * rows_per_thread;\n            auto end_y   = (thread_index + 1) * rows_per_thread;\n\n            for (uint64_t y = start_y; y < end_y; y += decklink_format_desc.field_count) {\n                auto     dest_row  = reinterpret_cast<uint8_t*>(image_data.get()) + y * dest_line_bytes;\n                __m128i* v210_dest = reinterpret_cast<__m128i*>(dest_row);\n\n                // Check if this row is outside the content region\n                if (y < config.dest_y || y >= max_y_content) {\n                    fill_black_groups(v210_dest, black_groups_per_row);\n                    continue;\n                }\n\n                const uint64_t src_y = y - config.dest_y + config.src_y;\n\n                // Fill the start of the row with black (complete 6-pixel groups)\n                fill_black_groups(v210_dest, black_groups_start);\n\n                int content_pixels_written = 0;\n\n                // Handle partial black group at start (if dest_x is not aligned to 6 pixels)\n                if (partial_black_pixels > 0) {\n                    ARGBPixel<T> pixels[6];\n                    memset(pixels, 0, sizeof(pixels));\n                    memset(v210_dest, 0, sizeof(__m128i));\n\n                    int content_in_packet = std::min(6 - partial_black_pixels, pixels_to_copy);\n\n                    auto src = reinterpret_cast<const ARGBPixel<T>*>(frame.image_data(0).data()) +\n                               (src_y * channel_format_desc.width + config.src_x);\n\n                    for (int i = 0; i < content_in_packet; ++i) {\n                        pixels[partial_black_pixels + i] = src[i];\n                    }\n\n                    pack_v210(pixels, color_matrix, reinterpret_cast<uint32_t*>(v210_dest), 6);\n                    v210_dest++;\n                    content_pixels_written = content_in_packet;\n                }\n\n                // Pack the main content pixels\n                int remaining_content = pixels_to_copy - content_pixels_written;\n                if (remaining_content > 0) {\n                    auto src = reinterpret_cast<const ARGBPixel<T>*>(frame.image_data(0).data()) +\n                               (src_y * channel_format_desc.width + config.src_x + content_pixels_written);\n\n                    // Process 48-pixel batches with AVX2\n                    int fullspeed_batches = remaining_content / 48;\n                    for (int batch = 0; batch < fullspeed_batches; ++batch) {\n                        convert_48_pixels_avx2(src, v210_dest);\n                    }\n\n                    // Process remaining content pixels (less than 48)\n                    int rest_content = remaining_content - fullspeed_batches * 48;\n                    if (rest_content > 0) {\n                        convert_remaining_pixels(src, v210_dest, rest_content);\n                    }\n                }\n\n                // Fill the rest of the row with black\n                auto bytes_written  = reinterpret_cast<uint8_t*>(v210_dest) - dest_row;\n                auto padding_bytes  = dest_line_bytes - bytes_written;\n                auto padding_groups = static_cast<int>(padding_bytes / sizeof(black_batch));\n                fill_black_groups(v210_dest, padding_groups);\n            }\n        });\n    }\n};\n\nspl::shared_ptr<format_strategy> create_sdr_v210_strategy(core::color_space color_space)\n{\n    return spl::make_shared<format_strategy, v210_strategy>(color_space, static_cast<uint8_t>(1));\n}\n\nspl::shared_ptr<format_strategy> create_hdr_v210_strategy(core::color_space color_space)\n{\n    return spl::make_shared<format_strategy, v210_strategy>(color_space, static_cast<uint8_t>(2));\n}\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/vanc.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas.andersson@nxtedition.com\n */\n\n#include \"vanc.h\"\n#include <boost/lexical_cast.hpp>\n\nnamespace caspar { namespace decklink {\n\nclass decklink_vanc_packet : public IDeckLinkAncillaryPacket\n{\n    std::atomic<int> ref_count_{0};\n    vanc_packet      pkt_;\n\n  public:\n    explicit decklink_vanc_packet(vanc_packet pkt)\n        : pkt_(pkt)\n    {\n    }\n\n    // IUnknown\n    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) override { return E_NOINTERFACE; }\n    ULONG STDMETHODCALLTYPE   AddRef() override { return ++ref_count_; }\n    ULONG STDMETHODCALLTYPE   Release() override\n    {\n        if (--ref_count_ == 0) {\n            delete this;\n\n            return 0;\n        }\n\n        return ref_count_;\n    }\n\n    // IDeckLinkAncillaryPacket\n    HRESULT STDMETHODCALLTYPE GetBytes(BMDAncillaryPacketFormat format, const void** data, unsigned int* size) override\n    {\n        if (format == bmdAncillaryPacketFormatUInt8) {\n            if (data) {\n                *data = pkt_.data.data();\n            }\n            *size = static_cast<unsigned int>(pkt_.data.size());\n            return S_OK;\n        }\n\n        return E_NOTIMPL;\n    }\n    unsigned char STDMETHODCALLTYPE GetDID(void) override { return pkt_.did; }\n    unsigned char STDMETHODCALLTYPE GetSDID(void) override { return pkt_.sdid; }\n    unsigned int STDMETHODCALLTYPE  GetLineNumber(void) override { return pkt_.line_number; }\n    unsigned char STDMETHODCALLTYPE GetDataStreamIndex(void) override { return 0; }\n};\n\ndecklink_vanc::decklink_vanc(const vanc_configuration& config)\n{\n    if (config.enable_scte104) {\n        strategies_.push_back(create_scte104_strategy(config.scte104_line));\n    }\n    if (config.enable_op47) {\n        strategies_.push_back(create_op47_strategy(\n            config.op47_line, config.op47_line_field2, config.op42_sd_line, config.op47_dummy_header));\n    }\n}\n\nstd::vector<caspar::decklink::com_ptr<IDeckLinkAncillaryPacket>> decklink_vanc::pop_packets(bool field2)\n{\n    std::vector<caspar::decklink::com_ptr<IDeckLinkAncillaryPacket>> packets;\n    for (auto& strategy : strategies_) {\n        if (strategy->has_data()) {\n            try {\n                auto packet =\n                    wrap_raw<com_ptr, IDeckLinkAncillaryPacket>(new decklink_vanc_packet(strategy->pop_packet(field2)));\n                if (packet->GetDID() != 0)\n                    packets.push_back(packet);\n            } catch (const std::exception& e) {\n                CASPAR_LOG(error) << \"Failed to pop \" << strategy->get_name() << \" VANC packet: \" << e.what();\n            } catch (...) {\n                CASPAR_LOG(error) << \"Failed to pop \" << strategy->get_name() << \" VANC packet.\";\n            }\n        }\n    }\n    return packets;\n}\n\nbool decklink_vanc::has_data() const\n{\n    return std::any_of(strategies_.begin(), strategies_.end(), [](auto& strategy) { return strategy->has_data(); });\n}\n\nbool decklink_vanc::try_push_data(const std::vector<std::wstring>& params)\n{\n    if (params.size() < 2) {\n        CASPAR_LOG(error) << \" Not enough parameters to apply VANC data.\";\n        return false;\n    }\n\n    for (auto& strategy : strategies_) {\n        if (boost::iequals(params.at(0), strategy->get_name())) {\n            return strategy->try_push_data(params);\n        }\n    }\n    return false;\n}\n\nstd::shared_ptr<decklink_vanc> create_vanc(const vanc_configuration& config)\n{\n    return std::make_shared<decklink_vanc>(config);\n}\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/vanc.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Niklas Andersson, niklas.andersson@nxtedition.com\n */\n\n#pragma once\n#include \"../decklink_api.h\"\n#include \"config.h\"\n#include <common/memory.h>\n\nnamespace caspar { namespace decklink {\n\nstruct vanc_packet\n{\n    uint8_t              did;\n    uint8_t              sdid;\n    uint32_t             line_number;\n    std::vector<uint8_t> data;\n};\n\nclass decklink_vanc_strategy\n{\n  public:\n    virtual ~decklink_vanc_strategy() noexcept = default;\n\n    virtual bool                has_data() const                                       = 0;\n    virtual vanc_packet         pop_packet(bool field2)                                = 0;\n    virtual bool                try_push_data(const std::vector<std::wstring>& params) = 0;\n    virtual const std::wstring& get_name() const                                       = 0;\n};\n\nclass decklink_vanc\n{\n    std::vector<std::shared_ptr<decklink_vanc_strategy>> strategies_;\n\n  public:\n    explicit decklink_vanc(const vanc_configuration& config);\n    bool                                                             has_data() const;\n    std::vector<caspar::decklink::com_ptr<IDeckLinkAncillaryPacket>> pop_packets(bool field2 = false);\n    bool try_push_data(const std::vector<std::wstring>& params);\n};\n\nstd::shared_ptr<decklink_vanc_strategy>\ncreate_op47_strategy(uint32_t line_number, uint32_t line_number_2, uint32_t sd_line, const std::wstring& dummy_header);\nstd::shared_ptr<decklink_vanc_strategy> create_scte104_strategy(uint32_t line_number);\n\nstd::shared_ptr<decklink_vanc> create_vanc(const vanc_configuration& config);\n}} // namespace caspar::decklink"
  },
  {
    "path": "src/modules/decklink/consumer/vanc_op47_strategy.cpp",
    "content": "#include \"vanc.h\"\n\n#include <locale>\n\n#include <boost/lexical_cast.hpp>\n#include <common/base64.h>\n#include <common/param.h>\n#include <common/ptree.h>\n#include <mutex>\n#include <numeric>\n#include <queue>\n#include <vector>\n\nnamespace caspar { namespace decklink {\n\nconst uint8_t OP47_DID  = 0x43;\nconst uint8_t OP47_SDID = 0x02;\n\nclass vanc_op47_strategy : public decklink_vanc_strategy\n{\n  private:\n    static const std::wstring Name;\n\n    mutable std::mutex mutex_;\n    uint32_t           line_number_;\n    uint32_t           line_number_2_;\n    uint8_t            sd_line_;\n    uint16_t           counter_;\n\n    std::vector<uint8_t>             dummy_header_;\n    std::queue<std::vector<uint8_t>> packets_;\n\n  public:\n    vanc_op47_strategy(uint32_t line_number, uint32_t line_number_2, uint32_t sd_line, const std::wstring& dummy_header)\n        : line_number_(line_number)\n        , line_number_2_(line_number_2)\n        , sd_line_(static_cast<uint8_t>(sd_line & 0xFF))\n        , counter_(1)\n        , dummy_header_(dummy_header.empty() ? std::vector<uint8_t>() : base64_decode(dummy_header))\n    {\n    }\n\n    virtual bool has_data() const override\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n        return !packets_.empty() || !dummy_header_.empty();\n    }\n    virtual vanc_packet pop_packet(bool field2) override\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        if (field2 && line_number_2_ == 0) {\n            return {0, 0, 0, {}};\n        }\n\n        if (packets_.empty()) {\n            return {OP47_DID, OP47_SDID, field2 ? line_number_2_ : line_number_, sdp_encode(dummy_header_, field2)};\n        }\n        auto packet = packets_.front();\n        packets_.pop();\n\n        return {OP47_DID, OP47_SDID, field2 ? line_number_2_ : line_number_, sdp_encode(packet, field2)};\n    }\n\n    virtual bool try_push_data(const std::vector<std::wstring>& params) override\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        try {\n            for (size_t index = 1; index < params.size(); ++index) {\n                packets_.push(base64_decode(params.at(index)));\n            }\n        } catch (const boost::bad_lexical_cast& e) {\n            CASPAR_LOG(error) << \"Failed to parse OP47 parameters: \" << e.what();\n            return false;\n        }\n\n        return true;\n    }\n\n    virtual const std::wstring& get_name() const override { return vanc_op47_strategy::Name; }\n\n  private:\n    std::vector<uint8_t> sdp_encode(const std::vector<uint8_t>& packet, bool field2)\n    {\n        if (packet.size() != 45) {\n            throw std::runtime_error(\"Invalid packet size for OP47: \" + std::to_string(packet.size()));\n        }\n\n        // The following is based on the specification \"Free TV Australia Operational Practice OP- 47\"\n\n        std::vector<uint8_t> result(58);\n        result[0] = 0x51;                                // identifier\n        result[1] = 0x15;                                // identifier\n        result[2] = static_cast<uint8_t>(result.size()); // size of the packet\n        result[3] = 0x02;                                // format-code\n\n        result[4] = (sd_line_ & 0x1F) | (field2 ? 0x00 : 0x80); // VBI packet descriptor (odd field)\n        result[5] = 0;                                          // VBI packet descriptor (not used)\n        result[6] = 0;                                          // VBI packet descriptor (not used)\n        result[7] = 0;                                          // VBI packet descriptor (not used)\n        result[8] = 0;                                          // VBI packet descriptor (not used)\n\n        memcpy(result.data() + 9, packet.data(), packet.size());\n        result[54] = 0x74;                     // footer id\n        result[55] = (counter_ & 0xFF00) >> 8; // footer sequence counter\n        result[56] = counter_ & 0x00FF;        // footer sequence counter\n        result[57] = 0x0;                      // SPD checksum, will be set when calculated\n\n        auto sum   = accumulate(result.begin(), result.end(), (uint8_t)0);\n        result[57] = ~sum + 1;\n\n        counter_++; // this is rolling over at 65535 by design\n\n        return result;\n    }\n\n    std::vector<uint8_t> base64_decode(const std::wstring& encoded)\n    {\n        std::vector<char> buffer(encoded.size());\n        std::use_facet<std::ctype<wchar_t>>(std::locale())\n            .narrow(encoded.data(), encoded.data() + encoded.size(), '?', buffer.data());\n        auto str = std::string(buffer.data(), buffer.size());\n        return caspar::from_base64(str);\n    }\n};\n\nconst std::wstring vanc_op47_strategy::Name = L\"OP47\";\n\nstd::shared_ptr<decklink_vanc_strategy>\ncreate_op47_strategy(uint32_t line_number, uint32_t line_number_2, uint32_t sd_line, const std::wstring& dummy_header)\n{\n    return std::make_shared<vanc_op47_strategy>(line_number, line_number_2, sd_line, dummy_header);\n}\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/consumer/vanc_scte104_strategy.cpp",
    "content": "#include \"vanc.h\"\n\n#include <common/base64.h>\n#include <mutex>\n\nnamespace caspar { namespace decklink {\n\nconst uint8_t SCTE104_DID  = 0x41;\nconst uint8_t SCTE104_SDID = 0x07;\n\nclass vanc_scte104_strategy : public decklink_vanc_strategy\n{\n    static const std::wstring Name;\n\n    mutable std::mutex mutex_;\n    uint32_t           line_number_;\n\n    std::vector<uint8_t> payload_ = {};\n\n  public:\n    explicit vanc_scte104_strategy(uint32_t line_number)\n        : line_number_(line_number)\n    {\n    }\n\n    virtual bool has_data() const override\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n        return !payload_.empty();\n    }\n\n    virtual vanc_packet pop_packet(bool field2) override\n    {\n        if (field2) {\n            // If field2 is requested, we do not return any data.\n            return {0, 0, 0, {}};\n        }\n\n        {\n            std::lock_guard<std::mutex> lock(mutex_);\n\n            // If we have a payload, return it as a vanc_packet.\n            if (payload_.size() > 0) {\n                auto        data = std::vector<uint8_t>(payload_.begin(), payload_.end());\n                vanc_packet pkt{SCTE104_DID, SCTE104_SDID, line_number_, data};\n                payload_.clear();\n                return pkt;\n            }\n        }\n\n        // If we have no data, return an empty vanc_packet.\n        return {0, 0, 0, {}};\n    }\n\n    virtual bool try_push_data(const std::vector<std::wstring>& params) override\n    {\n        try {\n            if (params.size() == 2) {\n                std::lock_guard<std::mutex> lock(mutex_);\n\n                // try to parse the payload as a base64 encoded raw SCTE-104 packet.\n                auto base64_payload = params.at(1);\n                payload_            = base64_decode(base64_payload);\n            }\n        } catch (const std::exception& e) {\n            CASPAR_LOG(error) << \"Failed to parse SCTE 104 parameters: \" << e.what();\n            return false;\n        }\n\n        return true;\n    }\n\n    virtual const std::wstring& get_name() const override { return vanc_scte104_strategy::Name; }\n\n  private:\n    std::vector<uint8_t> base64_decode(const std::wstring& encoded)\n    {\n        std::vector<char> buffer(encoded.size());\n        std::use_facet<std::ctype<wchar_t>>(std::locale())\n            .narrow(encoded.data(), encoded.data() + encoded.size(), '?', buffer.data());\n        auto str = std::string(buffer.data(), buffer.size());\n        return caspar::from_base64(str);\n    }\n};\n\nconst std::wstring vanc_scte104_strategy::Name = L\"SCTE104\";\n\nstd::shared_ptr<decklink_vanc_strategy> create_scte104_strategy(uint32_t line_number)\n{\n    return std::make_shared<vanc_scte104_strategy>(line_number);\n}\n\n}} // namespace caspar::decklink"
  },
  {
    "path": "src/modules/decklink/decklink.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"StdAfx.h\"\n\n#include \"decklink.h\"\n#include \"util/util.h\"\n\n#include \"consumer/decklink_consumer.h\"\n#include \"producer/decklink_producer.h\"\n\n#include <core/consumer/frame_consumer.h>\n#include <core/producer/frame_producer.h>\n\n#include \"decklink_api.h\"\n\nnamespace caspar { namespace decklink {\n\nstd::wstring get_version()\n{\n    std::wstring ver = L\"Not found\";\n\n    struct co_init init;\n\n    try {\n        ver = decklink::version(create_iterator());\n    } catch (...) {\n    }\n\n    return ver;\n}\n\nstd::vector<std::wstring> device_list()\n{\n    std::vector<std::wstring> devices;\n\n    struct co_init init;\n\n    try {\n        auto       pDecklinkIterator = create_iterator();\n        IDeckLink* decklink;\n        for (int n = 1; pDecklinkIterator->Next(&decklink) == S_OK; ++n) {\n            auto decklink_com = wrap_raw<com_ptr>(decklink);\n            auto attributes   = iface_cast<IDeckLinkProfileAttributes>(decklink_com);\n\n            int64_t id = 0;\n            attributes->GetInt(BMDDeckLinkPersistentID, &id);\n\n            devices.push_back(get_model_name(decklink) + L\" [\" + std::to_wstring(n) + L\"] (\" + std::to_wstring(id) +\n                              L\")\");\n            decklink->Release();\n        }\n    } catch (...) {\n    }\n\n    return devices;\n}\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    dependencies.consumer_registry->register_consumer_factory(L\"Decklink Consumer\", create_consumer);\n    dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"decklink\", create_preconfigured_consumer);\n    dependencies.producer_registry->register_producer_factory(L\"Decklink Producer\", create_producer);\n\n    auto devices = device_list();\n    if (!devices.empty()) {\n        CASPAR_LOG(info) << L\"Decklink devices found:\";\n        for (const auto& device : devices) {\n            CASPAR_LOG(info) << L\" - \" << device;\n        }\n    }\n}\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/decklink.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace decklink {\n\nstd::wstring get_version();\nvoid         init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/decklink_api.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <common/except.h>\n\n#if defined(_MSC_VER)\n\n#include <comutil.h>\n\n#include \"interop/DeckLinkAPI.h\"\n\n#include <atlbase.h>\n\nnamespace caspar { namespace decklink {\n\nusing String = BSTR;\nusing UINT32 = unsigned int;\n\nstatic std::wstring to_string(String bstr_string)\n{\n    return static_cast<const wchar_t*>(bstr_t(bstr_string, false));\n}\n\nstatic void com_initialize() { ::CoInitialize(nullptr); }\n\nstatic void com_uninitialize() { ::CoUninitialize(); }\n\nstruct co_init\n{\n    co_init() { ::CoInitialize(nullptr); }\n    ~co_init() { ::CoUninitialize(); }\n};\n\ntemplate <typename T>\nusing com_ptr = CComPtr<T>;\n\ntemplate <typename T>\nusing com_iface_ptr = CComQIPtr<T>;\n\ntemplate <template <typename> class P, typename T>\nstatic P<T> wrap_raw(T* ptr, bool already_referenced = false)\n{\n    if (already_referenced) {\n        P<T> p;\n        p.Attach(ptr);\n        return p;\n    }\n    return P<T>(ptr);\n}\n\nstatic com_ptr<IDeckLinkIterator> create_iterator()\n{\n    CComPtr<IDeckLinkIterator> pDecklinkIterator;\n    if (FAILED(pDecklinkIterator.CoCreateInstance(CLSID_CDeckLinkIterator)))\n        CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\"Decklink drivers not found.\"));\n    return pDecklinkIterator;\n}\n\nstatic com_ptr<IDeckLinkVideoFrameAncillaryPackets> create_ancillary_packets()\n{\n    CComPtr<IDeckLinkVideoFrameAncillaryPackets> pDecklinkAncillaryPackets;\n    if (FAILED(pDecklinkAncillaryPackets.CoCreateInstance(CLSID_CDeckLinkVideoFrameAncillaryPackets)))\n        CASPAR_THROW_EXCEPTION(not_supported()\n                               << msg_info(\"Could not create IDeckLinkVideoFrameAncillaryPackets instance.\"));\n    return pDecklinkAncillaryPackets;\n}\n\ntemplate <typename I, typename T>\nstatic com_iface_ptr<I> iface_cast(const com_ptr<T>& ptr, bool optional = false)\n{\n    com_iface_ptr<I> result{ptr.p};\n\n    if (!optional && !result)\n        CASPAR_THROW_EXCEPTION(not_supported()\n                               << msg_info(std::string(\"Could not cast from \") + typeid(T).name() + \" to \" +\n                                           typeid(I).name() + \". This is probably due to old Decklink drivers.\"));\n\n    return result;\n}\n\ntemplate <typename T>\nT* get_raw(const CComPtr<T>& ptr)\n{\n    return ptr;\n}\n\n}} // namespace caspar::decklink\n\n#else\n\n#include \"linux_interop/DeckLinkAPI.h\"\n#include \"linux_interop/DeckLinkAPIConfiguration.h\"\n#include \"linux_interop/DeckLinkAPIConfiguration_v10_11.h\"\n#include \"linux_interop/DeckLinkAPI_v10_11.h\"\n#include <memory>\n#include <typeinfo>\n\nnamespace caspar { namespace decklink {\n\nusing String   = const char*;\nusing BOOL     = bool;\n#define TRUE true\n#define FALSE false\nusing UINT32   = uint32_t;\nusing LONGLONG = int64_t;\n\nstatic std::wstring to_string(String utf16_string) { return u16(utf16_string); }\n\nstatic void com_initialize() {}\n\nstatic void com_uninitialize() {}\n\nstruct co_init\n{\n    co_init() {}\n    ~co_init() {}\n};\n\ntemplate <typename T>\nusing com_ptr = std::shared_ptr<T>;\n\ntemplate <typename T>\nusing com_iface_ptr = std::shared_ptr<T>;\n\ntemplate <template <typename> class P, typename T>\nstatic P<T> wrap_raw(T* ptr, bool already_referenced = false)\n{\n    if (!already_referenced && ptr)\n        ptr->AddRef();\n\n    return P<T>(ptr, [](T* p) {\n        if (p) {\n            auto remaining_refs = p->Release();\n\n            // CASPAR_LOG(debug) << \"Remaining references for \" << typeid(p).name() << \" = \" << remaining_refs;\n        }\n    });\n}\n\nstatic com_ptr<IDeckLinkIterator> create_iterator()\n{\n    IDeckLinkIterator* iterator = CreateDeckLinkIteratorInstance();\n\n    if (iterator == nullptr)\n        CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\"Decklink drivers not found.\"));\n\n    return wrap_raw<com_ptr>(iterator, true);\n}\n\nstatic com_ptr<IDeckLinkVideoFrameAncillaryPackets> create_ancillary_packets()\n{\n    IDeckLinkVideoFrameAncillaryPackets* ancillaryPackets = CreateVideoFrameAncillaryPacketsInstance();\n\n    if (ancillaryPackets == nullptr)\n        CASPAR_THROW_EXCEPTION(not_supported()\n                               << msg_info(\"Could not create IDeckLinkVideoFrameAncillaryPackets instance.\"));\n\n    return wrap_raw<com_ptr>(ancillaryPackets, true);\n}\n\ntemplate <typename T>\nstatic REFIID iface_id()\n{\n    return T::REFID;\n}\ntemplate <>\nREFIID iface_id<IDeckLink>()\n{\n    return IID_IDeckLink;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkOutput>()\n{\n    return IID_IDeckLinkOutput;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkAPIInformation>()\n{\n    return IID_IDeckLinkAPIInformation;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkConfiguration>()\n{\n    return IID_IDeckLinkConfiguration;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkKeyer>()\n{\n    return IID_IDeckLinkKeyer;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkProfileAttributes>()\n{\n    return IID_IDeckLinkProfileAttributes;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkInput>()\n{\n    return IID_IDeckLinkInput;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkAttributes_v10_11>()\n{\n    return IID_IDeckLinkAttributes_v10_11;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkConfiguration_v10_11>()\n{\n    return IID_IDeckLinkConfiguration_v10_11;\n}\ntemplate <>\nREFIID iface_id<IDeckLinkVideoFrameAncillaryPackets>()\n{\n    return IID_IDeckLinkVideoFrameAncillaryPackets;\n}\n\ntemplate <typename I, typename T>\nstatic com_iface_ptr<I> iface_cast(com_ptr<T> ptr, bool optional = false)\n{\n    I* iface;\n    ptr->QueryInterface(iface_id<I>(), reinterpret_cast<void**>(&iface));\n\n    return wrap_raw<com_iface_ptr>(iface, true);\n}\n\ntemplate <typename T>\nT* get_raw(const std::shared_ptr<T>& ptr)\n{\n    return ptr.get();\n}\n\n}} // namespace caspar::decklink\n\n#endif\n"
  },
  {
    "path": "src/modules/decklink/interop/DeckLinkAPIVersion.h",
    "content": "/* -LICENSE-START-\n * ** Copyright (c) 2014 Blackmagic Design\n * **  \n * ** Permission is hereby granted, free of charge, to any person or organization \n * ** obtaining a copy of the software and accompanying documentation (the \n * ** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n * ** and transmit the Software, and to prepare derivative works of the Software, \n * ** and to permit third-parties to whom the Software is furnished to do so, in \n * ** accordance with:\n * ** \n * ** (1) if the Software is obtained from Blackmagic Design, the End User License \n * ** Agreement for the Software Development Kit (“EULA”) available at \n * ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n * ** \n * ** (2) if the Software is obtained from any third party, such licensing terms \n * ** as notified by that third party,\n * ** \n * ** and all subject to the following:\n * ** \n * ** (3) the copyright notices in the Software and this entire statement, \n * ** including the above license grant, this restriction and the following \n * ** disclaimer, must be included in all copies of the Software, in whole or in \n * ** part, and all derivative works of the Software, unless such copies or \n * ** derivative works are solely in the form of machine-executable object code \n * ** generated by a source language processor.\n * ** \n * ** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n * ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * ** DEALINGS IN THE SOFTWARE.\n * ** \n * ** A copy of the Software is available free of charge at \n * ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n * ** \n * ** -LICENSE-END-\n * */\n\n/* DeckLinkAPIVersion.h */\n\n#ifndef __DeckLink_API_Version_h__\n#define __DeckLink_API_Version_h__\n\n#define BLACKMAGIC_DECKLINK_API_VERSION\t\t\t\t\t0x0c030100\n#define BLACKMAGIC_DECKLINK_API_VERSION_STRING\t\t\t\"12.3.1\"\n\n#endif\t// __DeckLink_API_Version_h__\n\n"
  },
  {
    "path": "src/modules/decklink/interop/DeckLinkAPI_i.c",
    "content": "\r\n\r\n/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */\r\n\r\n/* link this file in with the server and any clients */\r\n\r\n\r\n /* File created by MIDL compiler version 8.01.0628 */\r\n/* at Tue Jan 19 04:14:07 2038\r\n */\r\n/* Compiler settings for ..\\..\\Win\\include\\DeckLinkAPI.idl:\r\n    Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0628 \r\n    protocol : all , ms_ext, c_ext, robust\r\n    error checks: allocation ref bounds_check enum stub_data \r\n    VC __declspec() decoration level: \r\n         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r\n         DECLSPEC_UUID(), MIDL_INTERFACE()\r\n*/\r\n/* @@MIDL_FILE_HEADING(  ) */\r\n\r\n\r\n\r\n#ifdef __cplusplus\r\nextern \"C\"{\r\n#endif \r\n\r\n\r\n#include <rpc.h>\r\n#include <rpcndr.h>\r\n\r\n#ifdef _MIDL_USE_GUIDDEF_\r\n\r\n#ifndef INITGUID\r\n#define INITGUID\r\n#include <guiddef.h>\r\n#undef INITGUID\r\n#else\r\n#include <guiddef.h>\r\n#endif\r\n\r\n#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\r\n        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\r\n\r\n#else // !_MIDL_USE_GUIDDEF_\r\n\r\n#ifndef __IID_DEFINED__\r\n#define __IID_DEFINED__\r\n\r\ntypedef struct _IID\r\n{\r\n    unsigned long x;\r\n    unsigned short s1;\r\n    unsigned short s2;\r\n    unsigned char  c[8];\r\n} IID;\r\n\r\n#endif // __IID_DEFINED__\r\n\r\n#ifndef CLSID_DEFINED\r\n#define CLSID_DEFINED\r\ntypedef IID CLSID;\r\n#endif // CLSID_DEFINED\r\n\r\n#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\r\n        EXTERN_C __declspec(selectany) const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\r\n\r\n#endif // !_MIDL_USE_GUIDDEF_\r\n\r\nMIDL_DEFINE_GUID(IID, LIBID_DeckLinkAPI,0xD864517A,0xEDD5,0x466D,0x86,0x7D,0xC8,0x19,0xF1,0xC0,0x52,0xBB);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkTimecode,0xBC6CFBD3,0x8317,0x4325,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayModeIterator,0x9C88499F,0xF601,0x4021,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayMode,0x3EB2C1AB,0x0A3D,0x4523,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLink,0xC418FBDD,0x0587,0x48ED,0x8F,0xE5,0x64,0x0F,0x0A,0x14,0xAF,0x91);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration,0x912F634B,0x2D4E,0x40A4,0x8A,0xAB,0x8D,0x80,0xB7,0x3F,0x12,0x89);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderConfiguration,0x138050E5,0xC60A,0x4552,0xBF,0x3F,0x0F,0x35,0x80,0x49,0x32,0x7E);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControlStatusCallback,0x53436FFB,0xB434,0x4906,0xBA,0xDC,0xAE,0x30,0x60,0xFF,0xE8,0xEF);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControl,0x8E1C3ACE,0x19C7,0x4E00,0x8B,0x92,0xD8,0x04,0x31,0xD9,0x58,0xBE);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingDeviceNotificationCallback,0xF9531D64,0x3305,0x4B29,0xA3,0x87,0x7F,0x74,0xBB,0x0D,0x0E,0x84);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingH264InputCallback,0x823C475F,0x55AE,0x46F9,0x89,0x0C,0x53,0x7C,0xC5,0xCE,0xDC,0xCA);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingDiscovery,0x2C837444,0xF989,0x4D87,0x90,0x1A,0x47,0xC8,0xA3,0x6D,0x09,0x6D);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingVideoEncodingMode,0x1AB8035B,0xCD13,0x458D,0xB6,0xDF,0x5E,0x8F,0x7C,0x21,0x41,0xD9);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingMutableVideoEncodingMode,0x19BF7D90,0x1E0A,0x400D,0xB2,0xC6,0xFF,0xC4,0xE7,0x8A,0xD4,0x9D);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingVideoEncodingModePresetIterator,0x7AC731A3,0xC950,0x4AD0,0x80,0x4A,0x83,0x77,0xAA,0x51,0xC6,0xC4);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingDeviceInput,0x24B6B6EC,0x1727,0x44BB,0x98,0x18,0x34,0xFF,0x08,0x6A,0xCF,0x98);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingH264NALPacket,0xE260E955,0x14BE,0x4395,0x97,0x75,0x9F,0x02,0xCC,0x0A,0x9D,0x89);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingAudioPacket,0xD9EB5902,0x1AD2,0x43F4,0x9E,0x2C,0x3C,0xFA,0x50,0xB5,0xEE,0x19);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingMPEG2TSPacket,0x91810D1C,0x4FB3,0x4AAA,0xAE,0x56,0xFA,0x30,0x1D,0x3D,0xFA,0x4C);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IBMDStreamingH264NALParser,0x5867F18C,0x5BFA,0x4CCC,0xB2,0xA7,0x9D,0xFD,0x14,0x04,0x17,0xD2);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CBMDStreamingDiscovery,0x23A4EDF5,0xA0E5,0x432C,0x94,0xEF,0x3B,0xAB,0xB5,0xF8,0x1C,0x82);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CBMDStreamingH264NALParser,0x7753EFBD,0x951C,0x407C,0x97,0xA5,0x23,0xC7,0x37,0xB7,0x3B,0x52);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoOutputCallback,0x20AA5225,0x1958,0x47CB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback,0xC6FCE4C9,0xC4E4,0x4047,0x82,0xFB,0x5D,0x23,0x82,0x32,0xA9,0x02);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderInputCallback,0xACF13E61,0xF4A0,0x4974,0xA6,0xA7,0x59,0xAF,0xF6,0x26,0x8B,0x31);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkMemoryAllocator,0xB36EB6E7,0x9D29,0x4AA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAudioOutputCallback,0x403C681B,0x7F46,0x4A12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkIterator,0x50FB36CD,0x3063,0x4B73,0xBD,0xBB,0x95,0x80,0x87,0xF2,0xD8,0xBA);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAPIInformation,0x7BEA3C68,0x730D,0x4322,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput,0xBE2D9020,0x461E,0x442F,0x84,0xB7,0xE9,0x49,0xCB,0x95,0x3B,0x9D);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput,0xC21CDB6E,0xF414,0x46E4,0xA6,0x36,0x80,0xA5,0x66,0xE0,0xED,0x37);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkHDMIInputEDID,0xABBBACBC,0x45BC,0x4665,0x9D,0x92,0xAC,0xE6,0xE5,0xA9,0x79,0x02);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderInput,0xF222551D,0x13DF,0x4FD8,0xB5,0x87,0x9D,0x4F,0x19,0xEC,0x12,0xC9);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame,0x3F716FE0,0xF023,0x4111,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkMutableVideoFrame,0x69E2639F,0x40DA,0x4E19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame3DExtensions,0xDA0F7E4A,0xEDC7,0x48A8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrameMetadataExtensions,0xE232A5B7,0x4DB4,0x44C9,0x91,0x52,0xF4,0x7C,0x12,0xE5,0xF0,0x51);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame,0x05CFE374,0x537C,0x4094,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAncillaryPacket,0xCC5BBF7E,0x029C,0x4D3B,0x91,0x58,0x60,0x00,0xEF,0x5E,0x36,0x70);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAncillaryPacketIterator,0x3FC8994B,0x88FB,0x4C17,0x96,0x8F,0x9A,0xAB,0x69,0xD9,0x64,0xA7);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrameAncillaryPackets,0x6C186C0F,0x459E,0x41D8,0xAE,0xE2,0x48,0x12,0xD8,0x1A,0xEE,0x68);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrameAncillary,0x732E723C,0xD1A4,0x4E29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderPacket,0xB693F36C,0x316E,0x4AF1,0xB6,0xC2,0xF3,0x89,0xA4,0xBC,0xA6,0x20);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderVideoPacket,0x4E7FD944,0xE8C7,0x4EAC,0xB8,0xC0,0x7B,0x77,0xF8,0x0F,0x5A,0xE0);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderAudioPacket,0x49E8EDC8,0x693B,0x4E14,0x8E,0xF6,0x12,0xC6,0x58,0xF5,0xA0,0x7A);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkH265NALPacket,0x639C8E0B,0x68D5,0x4BDE,0xA6,0xD4,0x95,0xF3,0xAE,0xAF,0xF2,0xE7);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAudioInputPacket,0xE43D5870,0x2894,0x11DE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkScreenPreviewCallback,0xB1D3F49A,0x85FE,0x4C5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkGLScreenPreviewHelper,0x504E2209,0xCAC7,0x4C1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDX9ScreenPreviewHelper,0x2094B522,0xD1A1,0x40C0,0x9A,0xC7,0x1C,0x01,0x22,0x18,0xEF,0x02);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkWPFDX9ScreenPreviewHelper,0xAD8EC84A,0x7DDE,0x11E9,0x8F,0x9E,0x2A,0x86,0xE4,0x08,0x5A,0x59);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkNotificationCallback,0xb002a1ec,0x070d,0x4288,0x82,0x89,0xbd,0x5d,0x36,0xe5,0xff,0x0d);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkNotification,0xb85df4c8,0xbdf5,0x47c1,0x80,0x64,0x28,0x16,0x2e,0xbd,0xd4,0xeb);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkProfileAttributes,0x17D4BF8E,0x4911,0x473A,0x80,0xA0,0x73,0x1C,0xF6,0xFF,0x34,0x5B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkProfileIterator,0x29E5A8C0,0x8BE4,0x46EB,0x93,0xAC,0x31,0xDA,0xAB,0x5B,0x7B,0xF2);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkProfile,0x16093466,0x674A,0x432B,0x9D,0xA0,0x1A,0xC2,0xC5,0xA8,0x24,0x1C);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkProfileCallback,0xA4F9341E,0x97AA,0x4E04,0x89,0x35,0x15,0xF8,0x09,0x89,0x8C,0xEA);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkProfileManager,0x30D41429,0x3998,0x4B6D,0x84,0xF8,0x78,0xC9,0x4A,0x79,0x7C,0x6E);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkStatus,0x5F558200,0x4028,0x49BC,0xBE,0xAC,0xDB,0x3F,0xA4,0xA9,0x6E,0x46);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkKeyer,0x89AFCAF5,0x65F8,0x421E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoConversion,0x3BBCB8A2,0xDA2C,0x42D9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDeviceNotificationCallback,0x4997053B,0x0ADF,0x4CC8,0xAC,0x70,0x7A,0x50,0xC4,0xBE,0x72,0x8F);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDiscovery,0xCDBF631C,0xBC76,0x45FA,0xB4,0x4D,0xC5,0x50,0x59,0xBC,0x61,0x01);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkIterator,0xBA6C6F44,0x6DA5,0x4DCE,0x94,0xAA,0xEE,0x2D,0x13,0x72,0xA6,0x76);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkAPIInformation,0x263CA19F,0xED09,0x482E,0x9F,0x9D,0x84,0x00,0x57,0x83,0xA2,0x37);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkGLScreenPreviewHelper,0xF63E77C7,0xB655,0x4A4A,0x9A,0xD0,0x3C,0xA8,0x5D,0x39,0x43,0x43);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkGL3ScreenPreviewHelper,0x00696A71,0xEBC7,0x491F,0xAC,0x02,0x18,0xD3,0x39,0x3F,0x33,0xF0);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkDX9ScreenPreviewHelper,0xCC010023,0xE01D,0x4525,0x9D,0x59,0x80,0xC8,0xAB,0x3D,0xC7,0xA0);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkWPFDX9ScreenPreviewHelper,0xEF2A8478,0x7DDF,0x11E9,0x8F,0x9E,0x2A,0x86,0xE4,0x08,0x5A,0x59);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkVideoConversion,0x7DBBBB11,0x5B7B,0x467D,0xAE,0xA4,0xCE,0xA4,0x68,0xFD,0x36,0x8C);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkDiscovery,0x22FBFC33,0x8D07,0x495C,0xA5,0xBF,0xDA,0xB5,0xEA,0x9B,0x82,0xDB);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkVideoFrameAncillaryPackets,0xF891AD29,0xD0C2,0x46E9,0xA9,0x26,0x4E,0x2D,0x0D,0xD8,0xCF,0xAD);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v11_5_1,0xDD04E5EC,0x7415,0x42AB,0xAE,0x4A,0xE8,0x0C,0x4D,0xFC,0x04,0x4A);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v11_5_1,0x9434C6E4,0xB15D,0x4B1C,0x97,0x9E,0x66,0x1E,0x3D,0xDC,0xB4,0xB9);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v10_11,0xEF90380B,0x4AE5,0x4346,0x90,0x77,0xE2,0x88,0xE1,0x49,0xF1,0x29);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAttributes_v10_11,0xABC11843,0xD966,0x44CB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkNotification_v10_11,0x0A1FB207,0xE215,0x441B,0x9B,0x19,0x6F,0xA1,0x57,0x59,0x46,0xC5);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v10_11,0xCC5C8A6E,0x3F2F,0x4B3A,0x87,0xEA,0xFD,0x78,0xAF,0x30,0x05,0x64);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v10_11,0xAF22762B,0xDFAC,0x4846,0xAA,0x79,0xFA,0x88,0x83,0x56,0x09,0x95);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderInput_v10_11,0x270587DA,0x6B7D,0x42E7,0xA1,0xF0,0x6D,0x85,0x3F,0x58,0x11,0x85);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkIterator_v10_11,0x87D2693F,0x8D4A,0x45C7,0xB4,0x3F,0x10,0xAC,0xBA,0x25,0xE6,0x8F);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkDiscovery_v10_11,0x652615D4,0x26CD,0x4514,0xB1,0x61,0x2F,0xD5,0x07,0x2E,0xD0,0x08);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v10_9,0xCB71734A,0xFE37,0x4E8D,0x8E,0x13,0x80,0x21,0x33,0xA1,0xC3,0xF2);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CBMDStreamingDiscovery_v10_8,0x0CAA31F6,0x8A26,0x40B0,0x86,0xA4,0xBF,0x58,0xDC,0xCA,0x71,0x0C);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v10_4,0x1E69FCF6,0x4203,0x4936,0x80,0x76,0x2A,0x9F,0x4C,0xFD,0x50,0xCB);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v10_2,0xC679A35B,0x610C,0x4D09,0xB7,0x48,0x1D,0x04,0x78,0x10,0x0F,0xC0);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrameMetadataExtensions_v11_5,0xD5973DC9,0x6432,0x46D0,0x8F,0x0B,0x24,0x96,0xF8,0xA1,0x23,0x8F);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v11_4,0x065A0F6C,0xC508,0x4D0D,0xB9,0x19,0xF5,0xEB,0x0E,0xBF,0xC9,0x6B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v11_4,0x2A88CF76,0xF494,0x4216,0xA7,0xEF,0xDC,0x74,0xEE,0xB8,0x38,0x82);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkIterator_v10_8,0x1F2E109A,0x8F4F,0x49E4,0x92,0x03,0x13,0x55,0x95,0xCB,0x6F,0xA5);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkDiscovery_v10_8,0x1073A05C,0xD885,0x47E9,0xB3,0xC6,0x12,0x9B,0x3F,0x9F,0x64,0x8B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkEncoderConfiguration_v10_5,0x67455668,0x0848,0x45DF,0x8D,0x8E,0x35,0x0A,0x77,0xC9,0xA0,0x28);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v9_9,0xA3EF0963,0x0862,0x44ED,0x92,0xA9,0xEE,0x89,0xAB,0xF4,0x31,0xC7);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v9_2,0x6D40EF78,0x28B9,0x4E21,0x99,0x0D,0x95,0xBB,0x77,0x50,0xA0,0x4F);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControlStatusCallback_v8_1,0xE5F693C1,0x4283,0x4716,0xB1,0x8F,0xC1,0x43,0x15,0x21,0x95,0x5B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControl_v8_1,0x522A9E39,0x0F3C,0x4742,0x94,0xEE,0xD8,0x0D,0xE3,0x35,0xDA,0x1D);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLink_v8_0,0x62BFF75D,0x6569,0x4E55,0x8D,0x4D,0x66,0xAA,0x03,0x82,0x9A,0xBC);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkIterator_v8_0,0x74E936FC,0xCC28,0x4A67,0x81,0xA0,0x1E,0x94,0xE5,0x2D,0x4E,0x69);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkIterator_v8_0,0xD9EDA3B3,0x2887,0x41FA,0xB7,0x24,0x01,0x7C,0xF1,0xEB,0x1D,0x37);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDeckControl_v7_9,0xA4D81043,0x0619,0x42B7,0x8E,0xD6,0x60,0x2D,0x29,0x04,0x1D,0xF7);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayModeIterator_v7_6,0x455D741F,0x1779,0x4800,0x86,0xF5,0x0B,0x5D,0x13,0xD7,0x97,0x51);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayMode_v7_6,0x87451E84,0x2B7E,0x439E,0xA6,0x29,0x43,0x93,0xEA,0x4A,0x85,0x50);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v7_6,0x29228142,0xEB8C,0x4141,0xA6,0x21,0xF7,0x40,0x26,0x45,0x09,0x55);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v7_6,0x300C135A,0x9F43,0x48E2,0x99,0x06,0x6D,0x79,0x11,0xD9,0x3C,0xF1);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkTimecode_v7_6,0xEFB9BCA6,0xA521,0x44F7,0xBD,0x69,0x23,0x32,0xF2,0x4D,0x9E,0xE6);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame_v7_6,0xA8D8238E,0x6B18,0x4196,0x99,0xE1,0x5A,0xF7,0x17,0xB8,0x3D,0x32);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkMutableVideoFrame_v7_6,0x46FCEE00,0xB4E6,0x43D0,0x91,0xC0,0x02,0x3A,0x7F,0xCE,0xB3,0x4F);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame_v7_6,0x9A74FA41,0xAE9F,0x47AC,0x8C,0xF4,0x01,0xF4,0x2D,0xD5,0x99,0x65);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkScreenPreviewCallback_v7_6,0x373F499D,0x4B4D,0x4518,0xAD,0x22,0x63,0x54,0xE5,0xA5,0x82,0x5E);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkGLScreenPreviewHelper_v7_6,0xBA575CD9,0xA15E,0x497B,0xB2,0xC2,0xF9,0xAF,0xE7,0xBE,0x4E,0xBA);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoConversion_v7_6,0x3EB504C9,0xF97D,0x40FE,0xA1,0x58,0xD4,0x07,0xD4,0x8C,0xB5,0x3B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkConfiguration_v7_6,0xB8EAD569,0xB764,0x47F0,0xA7,0x3F,0xAE,0x40,0xDF,0x6C,0xBF,0x10);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoOutputCallback_v7_6,0xE763A626,0x4A3C,0x49D1,0xBF,0x13,0xE7,0xAD,0x36,0x92,0xAE,0x52);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v7_6,0x31D28EE7,0x88B6,0x4CB1,0x89,0x7A,0xCD,0xBF,0x79,0xA2,0x64,0x14);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkGLScreenPreviewHelper_v7_6,0xD398CEE7,0x4434,0x4CA3,0x9B,0xA6,0x5A,0xE3,0x45,0x56,0xB9,0x05);\r\n\r\n\r\nMIDL_DEFINE_GUID(CLSID, CLSID_CDeckLinkVideoConversion_v7_6,0xFFA84F77,0x73BE,0x4FB7,0xB0,0x3E,0xB5,0xE4,0x4B,0x9F,0x75,0x9B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v7_3,0xFD6F311D,0x4D00,0x444B,0x9E,0xD4,0x1F,0x25,0xB5,0x73,0x0A,0xD0);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v7_3,0x271C65E3,0xC323,0x4344,0xA3,0x0F,0xD9,0x08,0xBC,0xB2,0x0A,0xA3);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v7_3,0x4973F012,0x9925,0x458C,0x87,0x1C,0x18,0x77,0x4C,0xDB,0xBE,0xCB);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame_v7_3,0xCF317790,0x2894,0x11DE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayModeIterator_v7_1,0xB28131B6,0x59AC,0x4857,0xB5,0xAC,0xCD,0x75,0xD5,0x88,0x3E,0x2F);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkDisplayMode_v7_1,0xAF0CD6D5,0x8376,0x435E,0x84,0x33,0x54,0xF9,0xDD,0x53,0x0A,0xC3);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoFrame_v7_1,0x333F3A10,0x8C2D,0x43CF,0xB7,0x9D,0x46,0x56,0x0F,0xEE,0xA1,0xCE);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoInputFrame_v7_1,0xC8B41D95,0x8848,0x40EE,0x9B,0x37,0x6E,0x34,0x17,0xFB,0x11,0x4B);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkAudioInputPacket_v7_1,0xC86DE4F6,0xA29F,0x42E3,0xAB,0x3A,0x13,0x63,0xE2,0x9F,0x07,0x88);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkVideoOutputCallback_v7_1,0xEBD01AFA,0xE4B0,0x49C6,0xA0,0x1D,0xED,0xB9,0xD1,0xB5,0x5F,0xD9);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInputCallback_v7_1,0x7F94F328,0x5ED4,0x4E9F,0x97,0x29,0x76,0xA8,0x6B,0xDC,0x99,0xCC);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkOutput_v7_1,0xAE5B3E9B,0x4E1E,0x4535,0xB6,0xE8,0x48,0x0F,0xF5,0x2F,0x6C,0xE5);\r\n\r\n\r\nMIDL_DEFINE_GUID(IID, IID_IDeckLinkInput_v7_1,0x2B54EDEF,0x5B32,0x429F,0xBA,0x11,0xBB,0x99,0x05,0x96,0xEA,0xCD);\r\n\r\n#undef MIDL_DEFINE_GUID\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n\r\n\r\n"
  },
  {
    "path": "src/modules/decklink/interop/DecklinkAPI.h",
    "content": "\r\n\r\n/* this ALWAYS GENERATED file contains the definitions for the interfaces */\r\n\r\n\r\n /* File created by MIDL compiler version 8.01.0628 */\r\n/* at Tue Jan 19 04:14:07 2038\r\n */\r\n/* Compiler settings for ..\\..\\Win\\include\\DeckLinkAPI.idl:\r\n    Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0628 \r\n    protocol : all , ms_ext, c_ext, robust\r\n    error checks: allocation ref bounds_check enum stub_data \r\n    VC __declspec() decoration level: \r\n         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\r\n         DECLSPEC_UUID(), MIDL_INTERFACE()\r\n*/\r\n/* @@MIDL_FILE_HEADING(  ) */\r\n\r\n\r\n\r\n/* verify that the <rpcndr.h> version is high enough to compile this file*/\r\n#ifndef __REQUIRED_RPCNDR_H_VERSION__\r\n#define __REQUIRED_RPCNDR_H_VERSION__ 500\r\n#endif\r\n\r\n#include \"rpc.h\"\r\n#include \"rpcndr.h\"\r\n\r\n#ifndef __RPCNDR_H_VERSION__\r\n#error this stub requires an updated version of <rpcndr.h>\r\n#endif /* __RPCNDR_H_VERSION__ */\r\n\r\n\r\n#ifndef __DeckLinkAPI_h_h__\r\n#define __DeckLinkAPI_h_h__\r\n\r\n#if defined(_MSC_VER) && (_MSC_VER >= 1020)\r\n#pragma once\r\n#endif\r\n\r\n#ifndef DECLSPEC_XFGVIRT\r\n#if defined(_CONTROL_FLOW_GUARD_XFG)\r\n#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func))\r\n#else\r\n#define DECLSPEC_XFGVIRT(base, func)\r\n#endif\r\n#endif\r\n\r\n/* Forward Declarations */ \r\n\r\n#ifndef __IDeckLinkTimecode_FWD_DEFINED__\r\n#define __IDeckLinkTimecode_FWD_DEFINED__\r\ntypedef interface IDeckLinkTimecode IDeckLinkTimecode;\r\n\r\n#endif \t/* __IDeckLinkTimecode_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayModeIterator_FWD_DEFINED__\r\n#define __IDeckLinkDisplayModeIterator_FWD_DEFINED__\r\ntypedef interface IDeckLinkDisplayModeIterator IDeckLinkDisplayModeIterator;\r\n\r\n#endif \t/* __IDeckLinkDisplayModeIterator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayMode_FWD_DEFINED__\r\n#define __IDeckLinkDisplayMode_FWD_DEFINED__\r\ntypedef interface IDeckLinkDisplayMode IDeckLinkDisplayMode;\r\n\r\n#endif \t/* __IDeckLinkDisplayMode_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLink_FWD_DEFINED__\r\n#define __IDeckLink_FWD_DEFINED__\r\ntypedef interface IDeckLink IDeckLink;\r\n\r\n#endif \t/* __IDeckLink_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_FWD_DEFINED__\r\n#define __IDeckLinkConfiguration_FWD_DEFINED__\r\ntypedef interface IDeckLinkConfiguration IDeckLinkConfiguration;\r\n\r\n#endif \t/* __IDeckLinkConfiguration_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderConfiguration_FWD_DEFINED__\r\n#define __IDeckLinkEncoderConfiguration_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderConfiguration IDeckLinkEncoderConfiguration;\r\n\r\n#endif \t/* __IDeckLinkEncoderConfiguration_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControlStatusCallback_FWD_DEFINED__\r\n#define __IDeckLinkDeckControlStatusCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkDeckControlStatusCallback IDeckLinkDeckControlStatusCallback;\r\n\r\n#endif \t/* __IDeckLinkDeckControlStatusCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControl_FWD_DEFINED__\r\n#define __IDeckLinkDeckControl_FWD_DEFINED__\r\ntypedef interface IDeckLinkDeckControl IDeckLinkDeckControl;\r\n\r\n#endif \t/* __IDeckLinkDeckControl_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingDeviceNotificationCallback_FWD_DEFINED__\r\n#define __IBMDStreamingDeviceNotificationCallback_FWD_DEFINED__\r\ntypedef interface IBMDStreamingDeviceNotificationCallback IBMDStreamingDeviceNotificationCallback;\r\n\r\n#endif \t/* __IBMDStreamingDeviceNotificationCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingH264InputCallback_FWD_DEFINED__\r\n#define __IBMDStreamingH264InputCallback_FWD_DEFINED__\r\ntypedef interface IBMDStreamingH264InputCallback IBMDStreamingH264InputCallback;\r\n\r\n#endif \t/* __IBMDStreamingH264InputCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingDiscovery_FWD_DEFINED__\r\n#define __IBMDStreamingDiscovery_FWD_DEFINED__\r\ntypedef interface IBMDStreamingDiscovery IBMDStreamingDiscovery;\r\n\r\n#endif \t/* __IBMDStreamingDiscovery_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingVideoEncodingMode_FWD_DEFINED__\r\n#define __IBMDStreamingVideoEncodingMode_FWD_DEFINED__\r\ntypedef interface IBMDStreamingVideoEncodingMode IBMDStreamingVideoEncodingMode;\r\n\r\n#endif \t/* __IBMDStreamingVideoEncodingMode_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingMutableVideoEncodingMode_FWD_DEFINED__\r\n#define __IBMDStreamingMutableVideoEncodingMode_FWD_DEFINED__\r\ntypedef interface IBMDStreamingMutableVideoEncodingMode IBMDStreamingMutableVideoEncodingMode;\r\n\r\n#endif \t/* __IBMDStreamingMutableVideoEncodingMode_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingVideoEncodingModePresetIterator_FWD_DEFINED__\r\n#define __IBMDStreamingVideoEncodingModePresetIterator_FWD_DEFINED__\r\ntypedef interface IBMDStreamingVideoEncodingModePresetIterator IBMDStreamingVideoEncodingModePresetIterator;\r\n\r\n#endif \t/* __IBMDStreamingVideoEncodingModePresetIterator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingDeviceInput_FWD_DEFINED__\r\n#define __IBMDStreamingDeviceInput_FWD_DEFINED__\r\ntypedef interface IBMDStreamingDeviceInput IBMDStreamingDeviceInput;\r\n\r\n#endif \t/* __IBMDStreamingDeviceInput_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingH264NALPacket_FWD_DEFINED__\r\n#define __IBMDStreamingH264NALPacket_FWD_DEFINED__\r\ntypedef interface IBMDStreamingH264NALPacket IBMDStreamingH264NALPacket;\r\n\r\n#endif \t/* __IBMDStreamingH264NALPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingAudioPacket_FWD_DEFINED__\r\n#define __IBMDStreamingAudioPacket_FWD_DEFINED__\r\ntypedef interface IBMDStreamingAudioPacket IBMDStreamingAudioPacket;\r\n\r\n#endif \t/* __IBMDStreamingAudioPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingMPEG2TSPacket_FWD_DEFINED__\r\n#define __IBMDStreamingMPEG2TSPacket_FWD_DEFINED__\r\ntypedef interface IBMDStreamingMPEG2TSPacket IBMDStreamingMPEG2TSPacket;\r\n\r\n#endif \t/* __IBMDStreamingMPEG2TSPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingH264NALParser_FWD_DEFINED__\r\n#define __IBMDStreamingH264NALParser_FWD_DEFINED__\r\ntypedef interface IBMDStreamingH264NALParser IBMDStreamingH264NALParser;\r\n\r\n#endif \t/* __IBMDStreamingH264NALParser_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CBMDStreamingDiscovery_FWD_DEFINED__\r\n#define __CBMDStreamingDiscovery_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CBMDStreamingDiscovery CBMDStreamingDiscovery;\r\n#else\r\ntypedef struct CBMDStreamingDiscovery CBMDStreamingDiscovery;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CBMDStreamingDiscovery_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CBMDStreamingH264NALParser_FWD_DEFINED__\r\n#define __CBMDStreamingH264NALParser_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CBMDStreamingH264NALParser CBMDStreamingH264NALParser;\r\n#else\r\ntypedef struct CBMDStreamingH264NALParser CBMDStreamingH264NALParser;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CBMDStreamingH264NALParser_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoOutputCallback_FWD_DEFINED__\r\n#define __IDeckLinkVideoOutputCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoOutputCallback IDeckLinkVideoOutputCallback;\r\n\r\n#endif \t/* __IDeckLinkVideoOutputCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_FWD_DEFINED__\r\n#define __IDeckLinkInputCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkInputCallback IDeckLinkInputCallback;\r\n\r\n#endif \t/* __IDeckLinkInputCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderInputCallback_FWD_DEFINED__\r\n#define __IDeckLinkEncoderInputCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderInputCallback IDeckLinkEncoderInputCallback;\r\n\r\n#endif \t/* __IDeckLinkEncoderInputCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkMemoryAllocator_FWD_DEFINED__\r\n#define __IDeckLinkMemoryAllocator_FWD_DEFINED__\r\ntypedef interface IDeckLinkMemoryAllocator IDeckLinkMemoryAllocator;\r\n\r\n#endif \t/* __IDeckLinkMemoryAllocator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAudioOutputCallback_FWD_DEFINED__\r\n#define __IDeckLinkAudioOutputCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkAudioOutputCallback IDeckLinkAudioOutputCallback;\r\n\r\n#endif \t/* __IDeckLinkAudioOutputCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkIterator_FWD_DEFINED__\r\n#define __IDeckLinkIterator_FWD_DEFINED__\r\ntypedef interface IDeckLinkIterator IDeckLinkIterator;\r\n\r\n#endif \t/* __IDeckLinkIterator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAPIInformation_FWD_DEFINED__\r\n#define __IDeckLinkAPIInformation_FWD_DEFINED__\r\ntypedef interface IDeckLinkAPIInformation IDeckLinkAPIInformation;\r\n\r\n#endif \t/* __IDeckLinkAPIInformation_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_FWD_DEFINED__\r\n#define __IDeckLinkOutput_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput IDeckLinkOutput;\r\n\r\n#endif \t/* __IDeckLinkOutput_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_FWD_DEFINED__\r\n#define __IDeckLinkInput_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput IDeckLinkInput;\r\n\r\n#endif \t/* __IDeckLinkInput_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkHDMIInputEDID_FWD_DEFINED__\r\n#define __IDeckLinkHDMIInputEDID_FWD_DEFINED__\r\ntypedef interface IDeckLinkHDMIInputEDID IDeckLinkHDMIInputEDID;\r\n\r\n#endif \t/* __IDeckLinkHDMIInputEDID_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderInput_FWD_DEFINED__\r\n#define __IDeckLinkEncoderInput_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderInput IDeckLinkEncoderInput;\r\n\r\n#endif \t/* __IDeckLinkEncoderInput_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrame_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrame IDeckLinkVideoFrame;\r\n\r\n#endif \t/* __IDeckLinkVideoFrame_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkMutableVideoFrame_FWD_DEFINED__\r\n#define __IDeckLinkMutableVideoFrame_FWD_DEFINED__\r\ntypedef interface IDeckLinkMutableVideoFrame IDeckLinkMutableVideoFrame;\r\n\r\n#endif \t/* __IDeckLinkMutableVideoFrame_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame3DExtensions_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrame3DExtensions_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrame3DExtensions IDeckLinkVideoFrame3DExtensions;\r\n\r\n#endif \t/* __IDeckLinkVideoFrame3DExtensions_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameMetadataExtensions_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrameMetadataExtensions_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrameMetadataExtensions IDeckLinkVideoFrameMetadataExtensions;\r\n\r\n#endif \t/* __IDeckLinkVideoFrameMetadataExtensions_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_FWD_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoInputFrame IDeckLinkVideoInputFrame;\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAncillaryPacket_FWD_DEFINED__\r\n#define __IDeckLinkAncillaryPacket_FWD_DEFINED__\r\ntypedef interface IDeckLinkAncillaryPacket IDeckLinkAncillaryPacket;\r\n\r\n#endif \t/* __IDeckLinkAncillaryPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAncillaryPacketIterator_FWD_DEFINED__\r\n#define __IDeckLinkAncillaryPacketIterator_FWD_DEFINED__\r\ntypedef interface IDeckLinkAncillaryPacketIterator IDeckLinkAncillaryPacketIterator;\r\n\r\n#endif \t/* __IDeckLinkAncillaryPacketIterator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameAncillaryPackets_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrameAncillaryPackets_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrameAncillaryPackets IDeckLinkVideoFrameAncillaryPackets;\r\n\r\n#endif \t/* __IDeckLinkVideoFrameAncillaryPackets_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameAncillary_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrameAncillary_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrameAncillary IDeckLinkVideoFrameAncillary;\r\n\r\n#endif \t/* __IDeckLinkVideoFrameAncillary_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderPacket_FWD_DEFINED__\r\n#define __IDeckLinkEncoderPacket_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderPacket IDeckLinkEncoderPacket;\r\n\r\n#endif \t/* __IDeckLinkEncoderPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderVideoPacket_FWD_DEFINED__\r\n#define __IDeckLinkEncoderVideoPacket_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderVideoPacket IDeckLinkEncoderVideoPacket;\r\n\r\n#endif \t/* __IDeckLinkEncoderVideoPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderAudioPacket_FWD_DEFINED__\r\n#define __IDeckLinkEncoderAudioPacket_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderAudioPacket IDeckLinkEncoderAudioPacket;\r\n\r\n#endif \t/* __IDeckLinkEncoderAudioPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkH265NALPacket_FWD_DEFINED__\r\n#define __IDeckLinkH265NALPacket_FWD_DEFINED__\r\ntypedef interface IDeckLinkH265NALPacket IDeckLinkH265NALPacket;\r\n\r\n#endif \t/* __IDeckLinkH265NALPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAudioInputPacket_FWD_DEFINED__\r\n#define __IDeckLinkAudioInputPacket_FWD_DEFINED__\r\ntypedef interface IDeckLinkAudioInputPacket IDeckLinkAudioInputPacket;\r\n\r\n#endif \t/* __IDeckLinkAudioInputPacket_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkScreenPreviewCallback_FWD_DEFINED__\r\n#define __IDeckLinkScreenPreviewCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkScreenPreviewCallback IDeckLinkScreenPreviewCallback;\r\n\r\n#endif \t/* __IDeckLinkScreenPreviewCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkGLScreenPreviewHelper_FWD_DEFINED__\r\n#define __IDeckLinkGLScreenPreviewHelper_FWD_DEFINED__\r\ntypedef interface IDeckLinkGLScreenPreviewHelper IDeckLinkGLScreenPreviewHelper;\r\n\r\n#endif \t/* __IDeckLinkGLScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__\r\n#define __IDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__\r\ntypedef interface IDeckLinkDX9ScreenPreviewHelper IDeckLinkDX9ScreenPreviewHelper;\r\n\r\n#endif \t/* __IDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkWPFDX9ScreenPreviewHelper_FWD_DEFINED__\r\n#define __IDeckLinkWPFDX9ScreenPreviewHelper_FWD_DEFINED__\r\ntypedef interface IDeckLinkWPFDX9ScreenPreviewHelper IDeckLinkWPFDX9ScreenPreviewHelper;\r\n\r\n#endif \t/* __IDeckLinkWPFDX9ScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkNotificationCallback_FWD_DEFINED__\r\n#define __IDeckLinkNotificationCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkNotificationCallback IDeckLinkNotificationCallback;\r\n\r\n#endif \t/* __IDeckLinkNotificationCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkNotification_FWD_DEFINED__\r\n#define __IDeckLinkNotification_FWD_DEFINED__\r\ntypedef interface IDeckLinkNotification IDeckLinkNotification;\r\n\r\n#endif \t/* __IDeckLinkNotification_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileAttributes_FWD_DEFINED__\r\n#define __IDeckLinkProfileAttributes_FWD_DEFINED__\r\ntypedef interface IDeckLinkProfileAttributes IDeckLinkProfileAttributes;\r\n\r\n#endif \t/* __IDeckLinkProfileAttributes_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileIterator_FWD_DEFINED__\r\n#define __IDeckLinkProfileIterator_FWD_DEFINED__\r\ntypedef interface IDeckLinkProfileIterator IDeckLinkProfileIterator;\r\n\r\n#endif \t/* __IDeckLinkProfileIterator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfile_FWD_DEFINED__\r\n#define __IDeckLinkProfile_FWD_DEFINED__\r\ntypedef interface IDeckLinkProfile IDeckLinkProfile;\r\n\r\n#endif \t/* __IDeckLinkProfile_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileCallback_FWD_DEFINED__\r\n#define __IDeckLinkProfileCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkProfileCallback IDeckLinkProfileCallback;\r\n\r\n#endif \t/* __IDeckLinkProfileCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileManager_FWD_DEFINED__\r\n#define __IDeckLinkProfileManager_FWD_DEFINED__\r\ntypedef interface IDeckLinkProfileManager IDeckLinkProfileManager;\r\n\r\n#endif \t/* __IDeckLinkProfileManager_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkStatus_FWD_DEFINED__\r\n#define __IDeckLinkStatus_FWD_DEFINED__\r\ntypedef interface IDeckLinkStatus IDeckLinkStatus;\r\n\r\n#endif \t/* __IDeckLinkStatus_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkKeyer_FWD_DEFINED__\r\n#define __IDeckLinkKeyer_FWD_DEFINED__\r\ntypedef interface IDeckLinkKeyer IDeckLinkKeyer;\r\n\r\n#endif \t/* __IDeckLinkKeyer_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoConversion_FWD_DEFINED__\r\n#define __IDeckLinkVideoConversion_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoConversion IDeckLinkVideoConversion;\r\n\r\n#endif \t/* __IDeckLinkVideoConversion_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeviceNotificationCallback_FWD_DEFINED__\r\n#define __IDeckLinkDeviceNotificationCallback_FWD_DEFINED__\r\ntypedef interface IDeckLinkDeviceNotificationCallback IDeckLinkDeviceNotificationCallback;\r\n\r\n#endif \t/* __IDeckLinkDeviceNotificationCallback_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDiscovery_FWD_DEFINED__\r\n#define __IDeckLinkDiscovery_FWD_DEFINED__\r\ntypedef interface IDeckLinkDiscovery IDeckLinkDiscovery;\r\n\r\n#endif \t/* __IDeckLinkDiscovery_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkIterator_FWD_DEFINED__\r\n#define __CDeckLinkIterator_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkIterator CDeckLinkIterator;\r\n#else\r\ntypedef struct CDeckLinkIterator CDeckLinkIterator;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkIterator_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkAPIInformation_FWD_DEFINED__\r\n#define __CDeckLinkAPIInformation_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkAPIInformation CDeckLinkAPIInformation;\r\n#else\r\ntypedef struct CDeckLinkAPIInformation CDeckLinkAPIInformation;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkAPIInformation_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkGLScreenPreviewHelper_FWD_DEFINED__\r\n#define __CDeckLinkGLScreenPreviewHelper_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkGLScreenPreviewHelper CDeckLinkGLScreenPreviewHelper;\r\n#else\r\ntypedef struct CDeckLinkGLScreenPreviewHelper CDeckLinkGLScreenPreviewHelper;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkGLScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkGL3ScreenPreviewHelper_FWD_DEFINED__\r\n#define __CDeckLinkGL3ScreenPreviewHelper_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkGL3ScreenPreviewHelper CDeckLinkGL3ScreenPreviewHelper;\r\n#else\r\ntypedef struct CDeckLinkGL3ScreenPreviewHelper CDeckLinkGL3ScreenPreviewHelper;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkGL3ScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__\r\n#define __CDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkDX9ScreenPreviewHelper CDeckLinkDX9ScreenPreviewHelper;\r\n#else\r\ntypedef struct CDeckLinkDX9ScreenPreviewHelper CDeckLinkDX9ScreenPreviewHelper;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkDX9ScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkWPFDX9ScreenPreviewHelper_FWD_DEFINED__\r\n#define __CDeckLinkWPFDX9ScreenPreviewHelper_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkWPFDX9ScreenPreviewHelper CDeckLinkWPFDX9ScreenPreviewHelper;\r\n#else\r\ntypedef struct CDeckLinkWPFDX9ScreenPreviewHelper CDeckLinkWPFDX9ScreenPreviewHelper;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkWPFDX9ScreenPreviewHelper_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkVideoConversion_FWD_DEFINED__\r\n#define __CDeckLinkVideoConversion_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkVideoConversion CDeckLinkVideoConversion;\r\n#else\r\ntypedef struct CDeckLinkVideoConversion CDeckLinkVideoConversion;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkVideoConversion_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkDiscovery_FWD_DEFINED__\r\n#define __CDeckLinkDiscovery_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkDiscovery CDeckLinkDiscovery;\r\n#else\r\ntypedef struct CDeckLinkDiscovery CDeckLinkDiscovery;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkDiscovery_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkVideoFrameAncillaryPackets_FWD_DEFINED__\r\n#define __CDeckLinkVideoFrameAncillaryPackets_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkVideoFrameAncillaryPackets CDeckLinkVideoFrameAncillaryPackets;\r\n#else\r\ntypedef struct CDeckLinkVideoFrameAncillaryPackets CDeckLinkVideoFrameAncillaryPackets;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkVideoFrameAncillaryPackets_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_v11_5_1_FWD_DEFINED__\r\n#define __IDeckLinkInputCallback_v11_5_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkInputCallback_v11_5_1 IDeckLinkInputCallback_v11_5_1;\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v11_5_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v11_5_1_FWD_DEFINED__\r\n#define __IDeckLinkInput_v11_5_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v11_5_1 IDeckLinkInput_v11_5_1;\r\n\r\n#endif \t/* __IDeckLinkInput_v11_5_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_11_FWD_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_11_FWD_DEFINED__\r\ntypedef interface IDeckLinkConfiguration_v10_11 IDeckLinkConfiguration_v10_11;\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAttributes_v10_11_FWD_DEFINED__\r\n#define __IDeckLinkAttributes_v10_11_FWD_DEFINED__\r\ntypedef interface IDeckLinkAttributes_v10_11 IDeckLinkAttributes_v10_11;\r\n\r\n#endif \t/* __IDeckLinkAttributes_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkNotification_v10_11_FWD_DEFINED__\r\n#define __IDeckLinkNotification_v10_11_FWD_DEFINED__\r\ntypedef interface IDeckLinkNotification_v10_11 IDeckLinkNotification_v10_11;\r\n\r\n#endif \t/* __IDeckLinkNotification_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v10_11_FWD_DEFINED__\r\n#define __IDeckLinkOutput_v10_11_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput_v10_11 IDeckLinkOutput_v10_11;\r\n\r\n#endif \t/* __IDeckLinkOutput_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v10_11_FWD_DEFINED__\r\n#define __IDeckLinkInput_v10_11_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v10_11 IDeckLinkInput_v10_11;\r\n\r\n#endif \t/* __IDeckLinkInput_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderInput_v10_11_FWD_DEFINED__\r\n#define __IDeckLinkEncoderInput_v10_11_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderInput_v10_11 IDeckLinkEncoderInput_v10_11;\r\n\r\n#endif \t/* __IDeckLinkEncoderInput_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkIterator_v10_11_FWD_DEFINED__\r\n#define __CDeckLinkIterator_v10_11_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkIterator_v10_11 CDeckLinkIterator_v10_11;\r\n#else\r\ntypedef struct CDeckLinkIterator_v10_11 CDeckLinkIterator_v10_11;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkIterator_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkDiscovery_v10_11_FWD_DEFINED__\r\n#define __CDeckLinkDiscovery_v10_11_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkDiscovery_v10_11 CDeckLinkDiscovery_v10_11;\r\n#else\r\ntypedef struct CDeckLinkDiscovery_v10_11 CDeckLinkDiscovery_v10_11;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkDiscovery_v10_11_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_9_FWD_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_9_FWD_DEFINED__\r\ntypedef interface IDeckLinkConfiguration_v10_9 IDeckLinkConfiguration_v10_9;\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_9_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CBMDStreamingDiscovery_v10_8_FWD_DEFINED__\r\n#define __CBMDStreamingDiscovery_v10_8_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CBMDStreamingDiscovery_v10_8 CBMDStreamingDiscovery_v10_8;\r\n#else\r\ntypedef struct CBMDStreamingDiscovery_v10_8 CBMDStreamingDiscovery_v10_8;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CBMDStreamingDiscovery_v10_8_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_4_FWD_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_4_FWD_DEFINED__\r\ntypedef interface IDeckLinkConfiguration_v10_4 IDeckLinkConfiguration_v10_4;\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_4_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_2_FWD_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_2_FWD_DEFINED__\r\ntypedef interface IDeckLinkConfiguration_v10_2 IDeckLinkConfiguration_v10_2;\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_2_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameMetadataExtensions_v11_5_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrameMetadataExtensions_v11_5_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrameMetadataExtensions_v11_5 IDeckLinkVideoFrameMetadataExtensions_v11_5;\r\n\r\n#endif \t/* __IDeckLinkVideoFrameMetadataExtensions_v11_5_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v11_4_FWD_DEFINED__\r\n#define __IDeckLinkOutput_v11_4_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput_v11_4 IDeckLinkOutput_v11_4;\r\n\r\n#endif \t/* __IDeckLinkOutput_v11_4_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v11_4_FWD_DEFINED__\r\n#define __IDeckLinkInput_v11_4_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v11_4 IDeckLinkInput_v11_4;\r\n\r\n#endif \t/* __IDeckLinkInput_v11_4_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkIterator_v10_8_FWD_DEFINED__\r\n#define __CDeckLinkIterator_v10_8_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkIterator_v10_8 CDeckLinkIterator_v10_8;\r\n#else\r\ntypedef struct CDeckLinkIterator_v10_8 CDeckLinkIterator_v10_8;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkIterator_v10_8_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkDiscovery_v10_8_FWD_DEFINED__\r\n#define __CDeckLinkDiscovery_v10_8_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkDiscovery_v10_8 CDeckLinkDiscovery_v10_8;\r\n#else\r\ntypedef struct CDeckLinkDiscovery_v10_8 CDeckLinkDiscovery_v10_8;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkDiscovery_v10_8_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderConfiguration_v10_5_FWD_DEFINED__\r\n#define __IDeckLinkEncoderConfiguration_v10_5_FWD_DEFINED__\r\ntypedef interface IDeckLinkEncoderConfiguration_v10_5 IDeckLinkEncoderConfiguration_v10_5;\r\n\r\n#endif \t/* __IDeckLinkEncoderConfiguration_v10_5_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v9_9_FWD_DEFINED__\r\n#define __IDeckLinkOutput_v9_9_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput_v9_9 IDeckLinkOutput_v9_9;\r\n\r\n#endif \t/* __IDeckLinkOutput_v9_9_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v9_2_FWD_DEFINED__\r\n#define __IDeckLinkInput_v9_2_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v9_2 IDeckLinkInput_v9_2;\r\n\r\n#endif \t/* __IDeckLinkInput_v9_2_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControlStatusCallback_v8_1_FWD_DEFINED__\r\n#define __IDeckLinkDeckControlStatusCallback_v8_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkDeckControlStatusCallback_v8_1 IDeckLinkDeckControlStatusCallback_v8_1;\r\n\r\n#endif \t/* __IDeckLinkDeckControlStatusCallback_v8_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControl_v8_1_FWD_DEFINED__\r\n#define __IDeckLinkDeckControl_v8_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkDeckControl_v8_1 IDeckLinkDeckControl_v8_1;\r\n\r\n#endif \t/* __IDeckLinkDeckControl_v8_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLink_v8_0_FWD_DEFINED__\r\n#define __IDeckLink_v8_0_FWD_DEFINED__\r\ntypedef interface IDeckLink_v8_0 IDeckLink_v8_0;\r\n\r\n#endif \t/* __IDeckLink_v8_0_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkIterator_v8_0_FWD_DEFINED__\r\n#define __IDeckLinkIterator_v8_0_FWD_DEFINED__\r\ntypedef interface IDeckLinkIterator_v8_0 IDeckLinkIterator_v8_0;\r\n\r\n#endif \t/* __IDeckLinkIterator_v8_0_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkIterator_v8_0_FWD_DEFINED__\r\n#define __CDeckLinkIterator_v8_0_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkIterator_v8_0 CDeckLinkIterator_v8_0;\r\n#else\r\ntypedef struct CDeckLinkIterator_v8_0 CDeckLinkIterator_v8_0;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkIterator_v8_0_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControl_v7_9_FWD_DEFINED__\r\n#define __IDeckLinkDeckControl_v7_9_FWD_DEFINED__\r\ntypedef interface IDeckLinkDeckControl_v7_9 IDeckLinkDeckControl_v7_9;\r\n\r\n#endif \t/* __IDeckLinkDeckControl_v7_9_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayModeIterator_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkDisplayModeIterator_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkDisplayModeIterator_v7_6 IDeckLinkDisplayModeIterator_v7_6;\r\n\r\n#endif \t/* __IDeckLinkDisplayModeIterator_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayMode_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkDisplayMode_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkDisplayMode_v7_6 IDeckLinkDisplayMode_v7_6;\r\n\r\n#endif \t/* __IDeckLinkDisplayMode_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkOutput_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput_v7_6 IDeckLinkOutput_v7_6;\r\n\r\n#endif \t/* __IDeckLinkOutput_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkInput_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v7_6 IDeckLinkInput_v7_6;\r\n\r\n#endif \t/* __IDeckLinkInput_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkTimecode_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkTimecode_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkTimecode_v7_6 IDeckLinkTimecode_v7_6;\r\n\r\n#endif \t/* __IDeckLinkTimecode_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrame_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrame_v7_6 IDeckLinkVideoFrame_v7_6;\r\n\r\n#endif \t/* __IDeckLinkVideoFrame_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkMutableVideoFrame_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkMutableVideoFrame_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkMutableVideoFrame_v7_6 IDeckLinkMutableVideoFrame_v7_6;\r\n\r\n#endif \t/* __IDeckLinkMutableVideoFrame_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoInputFrame_v7_6 IDeckLinkVideoInputFrame_v7_6;\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkScreenPreviewCallback_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkScreenPreviewCallback_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkScreenPreviewCallback_v7_6 IDeckLinkScreenPreviewCallback_v7_6;\r\n\r\n#endif \t/* __IDeckLinkScreenPreviewCallback_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkGLScreenPreviewHelper_v7_6 IDeckLinkGLScreenPreviewHelper_v7_6;\r\n\r\n#endif \t/* __IDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoConversion_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkVideoConversion_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoConversion_v7_6 IDeckLinkVideoConversion_v7_6;\r\n\r\n#endif \t/* __IDeckLinkVideoConversion_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkConfiguration_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkConfiguration_v7_6 IDeckLinkConfiguration_v7_6;\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoOutputCallback_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkVideoOutputCallback_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoOutputCallback_v7_6 IDeckLinkVideoOutputCallback_v7_6;\r\n\r\n#endif \t/* __IDeckLinkVideoOutputCallback_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_v7_6_FWD_DEFINED__\r\n#define __IDeckLinkInputCallback_v7_6_FWD_DEFINED__\r\ntypedef interface IDeckLinkInputCallback_v7_6 IDeckLinkInputCallback_v7_6;\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__\r\n#define __CDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkGLScreenPreviewHelper_v7_6 CDeckLinkGLScreenPreviewHelper_v7_6;\r\n#else\r\ntypedef struct CDeckLinkGLScreenPreviewHelper_v7_6 CDeckLinkGLScreenPreviewHelper_v7_6;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkGLScreenPreviewHelper_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __CDeckLinkVideoConversion_v7_6_FWD_DEFINED__\r\n#define __CDeckLinkVideoConversion_v7_6_FWD_DEFINED__\r\n\r\n#ifdef __cplusplus\r\ntypedef class CDeckLinkVideoConversion_v7_6 CDeckLinkVideoConversion_v7_6;\r\n#else\r\ntypedef struct CDeckLinkVideoConversion_v7_6 CDeckLinkVideoConversion_v7_6;\r\n#endif /* __cplusplus */\r\n\r\n#endif \t/* __CDeckLinkVideoConversion_v7_6_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_v7_3_FWD_DEFINED__\r\n#define __IDeckLinkInputCallback_v7_3_FWD_DEFINED__\r\ntypedef interface IDeckLinkInputCallback_v7_3 IDeckLinkInputCallback_v7_3;\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v7_3_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v7_3_FWD_DEFINED__\r\n#define __IDeckLinkOutput_v7_3_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput_v7_3 IDeckLinkOutput_v7_3;\r\n\r\n#endif \t/* __IDeckLinkOutput_v7_3_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v7_3_FWD_DEFINED__\r\n#define __IDeckLinkInput_v7_3_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v7_3 IDeckLinkInput_v7_3;\r\n\r\n#endif \t/* __IDeckLinkInput_v7_3_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_v7_3_FWD_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_v7_3_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoInputFrame_v7_3 IDeckLinkVideoInputFrame_v7_3;\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_v7_3_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayModeIterator_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkDisplayModeIterator_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkDisplayModeIterator_v7_1 IDeckLinkDisplayModeIterator_v7_1;\r\n\r\n#endif \t/* __IDeckLinkDisplayModeIterator_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayMode_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkDisplayMode_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkDisplayMode_v7_1 IDeckLinkDisplayMode_v7_1;\r\n\r\n#endif \t/* __IDeckLinkDisplayMode_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkVideoFrame_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoFrame_v7_1 IDeckLinkVideoFrame_v7_1;\r\n\r\n#endif \t/* __IDeckLinkVideoFrame_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoInputFrame_v7_1 IDeckLinkVideoInputFrame_v7_1;\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAudioInputPacket_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkAudioInputPacket_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkAudioInputPacket_v7_1 IDeckLinkAudioInputPacket_v7_1;\r\n\r\n#endif \t/* __IDeckLinkAudioInputPacket_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoOutputCallback_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkVideoOutputCallback_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkVideoOutputCallback_v7_1 IDeckLinkVideoOutputCallback_v7_1;\r\n\r\n#endif \t/* __IDeckLinkVideoOutputCallback_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkInputCallback_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkInputCallback_v7_1 IDeckLinkInputCallback_v7_1;\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkOutput_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkOutput_v7_1 IDeckLinkOutput_v7_1;\r\n\r\n#endif \t/* __IDeckLinkOutput_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v7_1_FWD_DEFINED__\r\n#define __IDeckLinkInput_v7_1_FWD_DEFINED__\r\ntypedef interface IDeckLinkInput_v7_1 IDeckLinkInput_v7_1;\r\n\r\n#endif \t/* __IDeckLinkInput_v7_1_FWD_DEFINED__ */\r\n\r\n\r\n/* header files for imported files */\r\n#include \"unknwn.h\"\r\n\r\n#ifdef __cplusplus\r\nextern \"C\"{\r\n#endif \r\n\r\n\r\n\r\n#ifndef __DeckLinkAPI_LIBRARY_DEFINED__\r\n#define __DeckLinkAPI_LIBRARY_DEFINED__\r\n\r\n/* library DeckLinkAPI */\r\n/* [helpstring][version][uuid] */ \r\n\r\ntypedef LONGLONG BMDTimeValue;\r\n\r\ntypedef LONGLONG BMDTimeScale;\r\n\r\ntypedef unsigned int BMDTimecodeBCD;\r\n\r\ntypedef unsigned int BMDTimecodeUserBits;\r\n\r\ntypedef unsigned int BMDTimecodeFlags;\r\n#if 0\r\ntypedef enum _BMDTimecodeFlags BMDTimecodeFlags;\r\n\r\n#endif\r\n/* [v1_enum] */ \r\nenum _BMDTimecodeFlags\r\n    {\r\n        bmdTimecodeFlagDefault\t= 0,\r\n        bmdTimecodeIsDropFrame\t= ( 1 << 0 ) ,\r\n        bmdTimecodeFieldMark\t= ( 1 << 1 ) ,\r\n        bmdTimecodeColorFrame\t= ( 1 << 2 ) ,\r\n        bmdTimecodeEmbedRecordingTrigger\t= ( 1 << 3 ) ,\r\n        bmdTimecodeRecordingTriggered\t= ( 1 << 4 ) \r\n    } ;\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoConnection\r\n    {\r\n        bmdVideoConnectionUnspecified\t= 0,\r\n        bmdVideoConnectionSDI\t= ( 1 << 0 ) ,\r\n        bmdVideoConnectionHDMI\t= ( 1 << 1 ) ,\r\n        bmdVideoConnectionOpticalSDI\t= ( 1 << 2 ) ,\r\n        bmdVideoConnectionComponent\t= ( 1 << 3 ) ,\r\n        bmdVideoConnectionComposite\t= ( 1 << 4 ) ,\r\n        bmdVideoConnectionSVideo\t= ( 1 << 5 ) \r\n    } \tBMDVideoConnection;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioConnection\r\n    {\r\n        bmdAudioConnectionEmbedded\t= ( 1 << 0 ) ,\r\n        bmdAudioConnectionAESEBU\t= ( 1 << 1 ) ,\r\n        bmdAudioConnectionAnalog\t= ( 1 << 2 ) ,\r\n        bmdAudioConnectionAnalogXLR\t= ( 1 << 3 ) ,\r\n        bmdAudioConnectionAnalogRCA\t= ( 1 << 4 ) ,\r\n        bmdAudioConnectionMicrophone\t= ( 1 << 5 ) ,\r\n        bmdAudioConnectionHeadphones\t= ( 1 << 6 ) \r\n    } \tBMDAudioConnection;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckControlConnection\r\n    {\r\n        bmdDeckControlConnectionRS422Remote1\t= ( 1 << 0 ) ,\r\n        bmdDeckControlConnectionRS422Remote2\t= ( 1 << 1 ) \r\n    } \tBMDDeckControlConnection;\r\n\r\n\r\ntypedef unsigned int BMDDisplayModeFlags;\r\n#if 0\r\ntypedef enum _BMDDisplayModeFlags BMDDisplayModeFlags;\r\n\r\n#endif\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDisplayMode\r\n    {\r\n        bmdModeNTSC\t= 0x6e747363,\r\n        bmdModeNTSC2398\t= 0x6e743233,\r\n        bmdModePAL\t= 0x70616c20,\r\n        bmdModeNTSCp\t= 0x6e747370,\r\n        bmdModePALp\t= 0x70616c70,\r\n        bmdModeHD1080p2398\t= 0x32337073,\r\n        bmdModeHD1080p24\t= 0x32347073,\r\n        bmdModeHD1080p25\t= 0x48703235,\r\n        bmdModeHD1080p2997\t= 0x48703239,\r\n        bmdModeHD1080p30\t= 0x48703330,\r\n        bmdModeHD1080p4795\t= 0x48703437,\r\n        bmdModeHD1080p48\t= 0x48703438,\r\n        bmdModeHD1080p50\t= 0x48703530,\r\n        bmdModeHD1080p5994\t= 0x48703539,\r\n        bmdModeHD1080p6000\t= 0x48703630,\r\n        bmdModeHD1080p9590\t= 0x48703935,\r\n        bmdModeHD1080p96\t= 0x48703936,\r\n        bmdModeHD1080p100\t= 0x48703130,\r\n        bmdModeHD1080p11988\t= 0x48703131,\r\n        bmdModeHD1080p120\t= 0x48703132,\r\n        bmdModeHD1080i50\t= 0x48693530,\r\n        bmdModeHD1080i5994\t= 0x48693539,\r\n        bmdModeHD1080i6000\t= 0x48693630,\r\n        bmdModeHD720p50\t= 0x68703530,\r\n        bmdModeHD720p5994\t= 0x68703539,\r\n        bmdModeHD720p60\t= 0x68703630,\r\n        bmdMode2k2398\t= 0x326b3233,\r\n        bmdMode2k24\t= 0x326b3234,\r\n        bmdMode2k25\t= 0x326b3235,\r\n        bmdMode2kDCI2398\t= 0x32643233,\r\n        bmdMode2kDCI24\t= 0x32643234,\r\n        bmdMode2kDCI25\t= 0x32643235,\r\n        bmdMode2kDCI2997\t= 0x32643239,\r\n        bmdMode2kDCI30\t= 0x32643330,\r\n        bmdMode2kDCI4795\t= 0x32643437,\r\n        bmdMode2kDCI48\t= 0x32643438,\r\n        bmdMode2kDCI50\t= 0x32643530,\r\n        bmdMode2kDCI5994\t= 0x32643539,\r\n        bmdMode2kDCI60\t= 0x32643630,\r\n        bmdMode2kDCI9590\t= 0x32643935,\r\n        bmdMode2kDCI96\t= 0x32643936,\r\n        bmdMode2kDCI100\t= 0x32643130,\r\n        bmdMode2kDCI11988\t= 0x32643131,\r\n        bmdMode2kDCI120\t= 0x32643132,\r\n        bmdMode4K2160p2398\t= 0x346b3233,\r\n        bmdMode4K2160p24\t= 0x346b3234,\r\n        bmdMode4K2160p25\t= 0x346b3235,\r\n        bmdMode4K2160p2997\t= 0x346b3239,\r\n        bmdMode4K2160p30\t= 0x346b3330,\r\n        bmdMode4K2160p4795\t= 0x346b3437,\r\n        bmdMode4K2160p48\t= 0x346b3438,\r\n        bmdMode4K2160p50\t= 0x346b3530,\r\n        bmdMode4K2160p5994\t= 0x346b3539,\r\n        bmdMode4K2160p60\t= 0x346b3630,\r\n        bmdMode4K2160p9590\t= 0x346b3935,\r\n        bmdMode4K2160p96\t= 0x346b3936,\r\n        bmdMode4K2160p100\t= 0x346b3130,\r\n        bmdMode4K2160p11988\t= 0x346b3131,\r\n        bmdMode4K2160p120\t= 0x346b3132,\r\n        bmdMode4kDCI2398\t= 0x34643233,\r\n        bmdMode4kDCI24\t= 0x34643234,\r\n        bmdMode4kDCI25\t= 0x34643235,\r\n        bmdMode4kDCI2997\t= 0x34643239,\r\n        bmdMode4kDCI30\t= 0x34643330,\r\n        bmdMode4kDCI4795\t= 0x34643437,\r\n        bmdMode4kDCI48\t= 0x34643438,\r\n        bmdMode4kDCI50\t= 0x34643530,\r\n        bmdMode4kDCI5994\t= 0x34643539,\r\n        bmdMode4kDCI60\t= 0x34643630,\r\n        bmdMode4kDCI9590\t= 0x34643935,\r\n        bmdMode4kDCI96\t= 0x34643936,\r\n        bmdMode4kDCI100\t= 0x34643130,\r\n        bmdMode4kDCI11988\t= 0x34643131,\r\n        bmdMode4kDCI120\t= 0x34643132,\r\n        bmdMode8K4320p2398\t= 0x386b3233,\r\n        bmdMode8K4320p24\t= 0x386b3234,\r\n        bmdMode8K4320p25\t= 0x386b3235,\r\n        bmdMode8K4320p2997\t= 0x386b3239,\r\n        bmdMode8K4320p30\t= 0x386b3330,\r\n        bmdMode8K4320p4795\t= 0x386b3437,\r\n        bmdMode8K4320p48\t= 0x386b3438,\r\n        bmdMode8K4320p50\t= 0x386b3530,\r\n        bmdMode8K4320p5994\t= 0x386b3539,\r\n        bmdMode8K4320p60\t= 0x386b3630,\r\n        bmdMode8kDCI2398\t= 0x38643233,\r\n        bmdMode8kDCI24\t= 0x38643234,\r\n        bmdMode8kDCI25\t= 0x38643235,\r\n        bmdMode8kDCI2997\t= 0x38643239,\r\n        bmdMode8kDCI30\t= 0x38643330,\r\n        bmdMode8kDCI4795\t= 0x38643437,\r\n        bmdMode8kDCI48\t= 0x38643438,\r\n        bmdMode8kDCI50\t= 0x38643530,\r\n        bmdMode8kDCI5994\t= 0x38643539,\r\n        bmdMode8kDCI60\t= 0x38643630,\r\n        bmdMode640x480p60\t= 0x76676136,\r\n        bmdMode800x600p60\t= 0x73766736,\r\n        bmdMode1440x900p50\t= 0x77786735,\r\n        bmdMode1440x900p60\t= 0x77786736,\r\n        bmdMode1440x1080p50\t= 0x73786735,\r\n        bmdMode1440x1080p60\t= 0x73786736,\r\n        bmdMode1600x1200p50\t= 0x75786735,\r\n        bmdMode1600x1200p60\t= 0x75786736,\r\n        bmdMode1920x1200p50\t= 0x77757835,\r\n        bmdMode1920x1200p60\t= 0x77757836,\r\n        bmdMode1920x1440p50\t= 0x31393435,\r\n        bmdMode1920x1440p60\t= 0x31393436,\r\n        bmdMode2560x1440p50\t= 0x77716835,\r\n        bmdMode2560x1440p60\t= 0x77716836,\r\n        bmdMode2560x1600p50\t= 0x77717835,\r\n        bmdMode2560x1600p60\t= 0x77717836,\r\n        bmdModeUnknown\t= 0x69756e6b\r\n    } \tBMDDisplayMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDFieldDominance\r\n    {\r\n        bmdUnknownFieldDominance\t= 0,\r\n        bmdLowerFieldFirst\t= 0x6c6f7772,\r\n        bmdUpperFieldFirst\t= 0x75707072,\r\n        bmdProgressiveFrame\t= 0x70726f67,\r\n        bmdProgressiveSegmentedFrame\t= 0x70736620\r\n    } \tBMDFieldDominance;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDPixelFormat\r\n    {\r\n        bmdFormatUnspecified\t= 0,\r\n        bmdFormat8BitYUV\t= 0x32767579,\r\n        bmdFormat10BitYUV\t= 0x76323130,\r\n        bmdFormat8BitARGB\t= 32,\r\n        bmdFormat8BitBGRA\t= 0x42475241,\r\n        bmdFormat10BitRGB\t= 0x72323130,\r\n        bmdFormat12BitRGB\t= 0x52313242,\r\n        bmdFormat12BitRGBLE\t= 0x5231324c,\r\n        bmdFormat10BitRGBXLE\t= 0x5231306c,\r\n        bmdFormat10BitRGBX\t= 0x52313062,\r\n        bmdFormatH265\t= 0x68657631,\r\n        bmdFormatDNxHR\t= 0x41566468\r\n    } \tBMDPixelFormat;\r\n\r\n/* [v1_enum] */ \r\nenum _BMDDisplayModeFlags\r\n    {\r\n        bmdDisplayModeSupports3D\t= ( 1 << 0 ) ,\r\n        bmdDisplayModeColorspaceRec601\t= ( 1 << 1 ) ,\r\n        bmdDisplayModeColorspaceRec709\t= ( 1 << 2 ) ,\r\n        bmdDisplayModeColorspaceRec2020\t= ( 1 << 3 ) \r\n    } ;\r\n\r\n\r\n#if 0\r\n#endif\r\n\r\n#if 0\r\n#endif\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkConfigurationID\r\n    {\r\n        bmdDeckLinkConfigSwapSerialRxTx\t= 0x73737274,\r\n        bmdDeckLinkConfigHDMI3DPackingFormat\t= 0x33647066,\r\n        bmdDeckLinkConfigBypass\t= 0x62797073,\r\n        bmdDeckLinkConfigClockTimingAdjustment\t= 0x63746164,\r\n        bmdDeckLinkConfigAnalogAudioConsumerLevels\t= 0x6161636c,\r\n        bmdDeckLinkConfigSwapHDMICh3AndCh4OnInput\t= 0x68693334,\r\n        bmdDeckLinkConfigSwapHDMICh3AndCh4OnOutput\t= 0x686f3334,\r\n        bmdDeckLinkConfigFieldFlickerRemoval\t= 0x66646672,\r\n        bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion\t= 0x746f3539,\r\n        bmdDeckLinkConfig444SDIVideoOutput\t= 0x3434346f,\r\n        bmdDeckLinkConfigBlackVideoOutputDuringCapture\t= 0x62766f63,\r\n        bmdDeckLinkConfigLowLatencyVideoOutput\t= 0x6c6c766f,\r\n        bmdDeckLinkConfigDownConversionOnAllAnalogOutput\t= 0x6361616f,\r\n        bmdDeckLinkConfigSMPTELevelAOutput\t= 0x736d7461,\r\n        bmdDeckLinkConfigRec2020Output\t= 0x72656332,\r\n        bmdDeckLinkConfigQuadLinkSDIVideoOutputSquareDivisionSplit\t= 0x53445153,\r\n        bmdDeckLinkConfigOutput1080pAsPsF\t= 0x70667072,\r\n        bmdDeckLinkConfigVideoOutputConnection\t= 0x766f636e,\r\n        bmdDeckLinkConfigVideoOutputConversionMode\t= 0x766f636d,\r\n        bmdDeckLinkConfigAnalogVideoOutputFlags\t= 0x61766f66,\r\n        bmdDeckLinkConfigReferenceInputTimingOffset\t= 0x676c6f74,\r\n        bmdDeckLinkConfigVideoOutputIdleOperation\t= 0x766f696f,\r\n        bmdDeckLinkConfigDefaultVideoOutputMode\t= 0x64766f6d,\r\n        bmdDeckLinkConfigDefaultVideoOutputModeFlags\t= 0x64766f66,\r\n        bmdDeckLinkConfigSDIOutputLinkConfiguration\t= 0x736f6c63,\r\n        bmdDeckLinkConfigHDMITimecodePacking\t= 0x6874706b,\r\n        bmdDeckLinkConfigPlaybackGroup\t= 0x706c6772,\r\n        bmdDeckLinkConfigVideoOutputComponentLumaGain\t= 0x6f636c67,\r\n        bmdDeckLinkConfigVideoOutputComponentChromaBlueGain\t= 0x6f636362,\r\n        bmdDeckLinkConfigVideoOutputComponentChromaRedGain\t= 0x6f636372,\r\n        bmdDeckLinkConfigVideoOutputCompositeLumaGain\t= 0x6f696c67,\r\n        bmdDeckLinkConfigVideoOutputCompositeChromaGain\t= 0x6f696367,\r\n        bmdDeckLinkConfigVideoOutputSVideoLumaGain\t= 0x6f736c67,\r\n        bmdDeckLinkConfigVideoOutputSVideoChromaGain\t= 0x6f736367,\r\n        bmdDeckLinkConfigVideoInputScanning\t= 0x76697363,\r\n        bmdDeckLinkConfigUseDedicatedLTCInput\t= 0x646c7463,\r\n        bmdDeckLinkConfigSDIInput3DPayloadOverride\t= 0x33646473,\r\n        bmdDeckLinkConfigCapture1080pAsPsF\t= 0x63667072,\r\n        bmdDeckLinkConfigVideoInputConnection\t= 0x7669636e,\r\n        bmdDeckLinkConfigAnalogVideoInputFlags\t= 0x61766966,\r\n        bmdDeckLinkConfigVideoInputConversionMode\t= 0x7669636d,\r\n        bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame\t= 0x70646966,\r\n        bmdDeckLinkConfigVANCSourceLine1Mapping\t= 0x76736c31,\r\n        bmdDeckLinkConfigVANCSourceLine2Mapping\t= 0x76736c32,\r\n        bmdDeckLinkConfigVANCSourceLine3Mapping\t= 0x76736c33,\r\n        bmdDeckLinkConfigCapturePassThroughMode\t= 0x6370746d,\r\n        bmdDeckLinkConfigCaptureGroup\t= 0x63706772,\r\n        bmdDeckLinkConfigVideoInputComponentLumaGain\t= 0x69636c67,\r\n        bmdDeckLinkConfigVideoInputComponentChromaBlueGain\t= 0x69636362,\r\n        bmdDeckLinkConfigVideoInputComponentChromaRedGain\t= 0x69636372,\r\n        bmdDeckLinkConfigVideoInputCompositeLumaGain\t= 0x69696c67,\r\n        bmdDeckLinkConfigVideoInputCompositeChromaGain\t= 0x69696367,\r\n        bmdDeckLinkConfigVideoInputSVideoLumaGain\t= 0x69736c67,\r\n        bmdDeckLinkConfigVideoInputSVideoChromaGain\t= 0x69736367,\r\n        bmdDeckLinkConfigInternalKeyingAncillaryDataSource\t= 0x696b6173,\r\n        bmdDeckLinkConfigMicrophonePhantomPower\t= 0x6d706870,\r\n        bmdDeckLinkConfigAudioInputConnection\t= 0x6169636e,\r\n        bmdDeckLinkConfigAnalogAudioInputScaleChannel1\t= 0x61697331,\r\n        bmdDeckLinkConfigAnalogAudioInputScaleChannel2\t= 0x61697332,\r\n        bmdDeckLinkConfigAnalogAudioInputScaleChannel3\t= 0x61697333,\r\n        bmdDeckLinkConfigAnalogAudioInputScaleChannel4\t= 0x61697334,\r\n        bmdDeckLinkConfigDigitalAudioInputScale\t= 0x64616973,\r\n        bmdDeckLinkConfigMicrophoneInputGain\t= 0x6d696367,\r\n        bmdDeckLinkConfigAudioOutputAESAnalogSwitch\t= 0x616f6161,\r\n        bmdDeckLinkConfigAnalogAudioOutputScaleChannel1\t= 0x616f7331,\r\n        bmdDeckLinkConfigAnalogAudioOutputScaleChannel2\t= 0x616f7332,\r\n        bmdDeckLinkConfigAnalogAudioOutputScaleChannel3\t= 0x616f7333,\r\n        bmdDeckLinkConfigAnalogAudioOutputScaleChannel4\t= 0x616f7334,\r\n        bmdDeckLinkConfigDigitalAudioOutputScale\t= 0x64616f73,\r\n        bmdDeckLinkConfigHeadphoneVolume\t= 0x68766f6c,\r\n        bmdDeckLinkConfigDeviceInformationLabel\t= 0x64696c61,\r\n        bmdDeckLinkConfigDeviceInformationSerialNumber\t= 0x6469736e,\r\n        bmdDeckLinkConfigDeviceInformationCompany\t= 0x6469636f,\r\n        bmdDeckLinkConfigDeviceInformationPhone\t= 0x64697068,\r\n        bmdDeckLinkConfigDeviceInformationEmail\t= 0x6469656d,\r\n        bmdDeckLinkConfigDeviceInformationDate\t= 0x64696461,\r\n        bmdDeckLinkConfigDeckControlConnection\t= 0x6463636f\r\n    } \tBMDDeckLinkConfigurationID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkEncoderConfigurationID\r\n    {\r\n        bmdDeckLinkEncoderConfigPreferredBitDepth\t= 0x65706272,\r\n        bmdDeckLinkEncoderConfigFrameCodingMode\t= 0x6566636d,\r\n        bmdDeckLinkEncoderConfigH265TargetBitrate\t= 0x68746272,\r\n        bmdDeckLinkEncoderConfigDNxHRCompressionID\t= 0x64636964,\r\n        bmdDeckLinkEncoderConfigDNxHRLevel\t= 0x646c6576,\r\n        bmdDeckLinkEncoderConfigMPEG4SampleDescription\t= 0x73747345,\r\n        bmdDeckLinkEncoderConfigMPEG4CodecSpecificDesc\t= 0x65736473\r\n    } \tBMDDeckLinkEncoderConfigurationID;\r\n\r\n\r\n\r\ntypedef unsigned int BMDDeckControlStatusFlags;\r\ntypedef unsigned int BMDDeckControlExportModeOpsFlags;\r\n#if 0\r\ntypedef enum _BMDDeckControlStatusFlags BMDDeckControlStatusFlags;\r\n\r\ntypedef enum _BMDDeckControlExportModeOpsFlags BMDDeckControlExportModeOpsFlags;\r\n\r\n#endif\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckControlMode\r\n    {\r\n        bmdDeckControlNotOpened\t= 0x6e746f70,\r\n        bmdDeckControlVTRControlMode\t= 0x76747263,\r\n        bmdDeckControlExportMode\t= 0x6578706d,\r\n        bmdDeckControlCaptureMode\t= 0x6361706d\r\n    } \tBMDDeckControlMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckControlEvent\r\n    {\r\n        bmdDeckControlAbortedEvent\t= 0x61627465,\r\n        bmdDeckControlPrepareForExportEvent\t= 0x70666565,\r\n        bmdDeckControlExportCompleteEvent\t= 0x65786365,\r\n        bmdDeckControlPrepareForCaptureEvent\t= 0x70666365,\r\n        bmdDeckControlCaptureCompleteEvent\t= 0x63636576\r\n    } \tBMDDeckControlEvent;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckControlVTRControlState\r\n    {\r\n        bmdDeckControlNotInVTRControlMode\t= 0x6e76636d,\r\n        bmdDeckControlVTRControlPlaying\t= 0x76747270,\r\n        bmdDeckControlVTRControlRecording\t= 0x76747272,\r\n        bmdDeckControlVTRControlStill\t= 0x76747261,\r\n        bmdDeckControlVTRControlShuttleForward\t= 0x76747366,\r\n        bmdDeckControlVTRControlShuttleReverse\t= 0x76747372,\r\n        bmdDeckControlVTRControlJogForward\t= 0x76746a66,\r\n        bmdDeckControlVTRControlJogReverse\t= 0x76746a72,\r\n        bmdDeckControlVTRControlStopped\t= 0x7674726f\r\n    } \tBMDDeckControlVTRControlState;\r\n\r\n/* [v1_enum] */ \r\nenum _BMDDeckControlStatusFlags\r\n    {\r\n        bmdDeckControlStatusDeckConnected\t= ( 1 << 0 ) ,\r\n        bmdDeckControlStatusRemoteMode\t= ( 1 << 1 ) ,\r\n        bmdDeckControlStatusRecordInhibited\t= ( 1 << 2 ) ,\r\n        bmdDeckControlStatusCassetteOut\t= ( 1 << 3 ) \r\n    } ;\r\n/* [v1_enum] */ \r\nenum _BMDDeckControlExportModeOpsFlags\r\n    {\r\n        bmdDeckControlExportModeInsertVideo\t= ( 1 << 0 ) ,\r\n        bmdDeckControlExportModeInsertAudio1\t= ( 1 << 1 ) ,\r\n        bmdDeckControlExportModeInsertAudio2\t= ( 1 << 2 ) ,\r\n        bmdDeckControlExportModeInsertAudio3\t= ( 1 << 3 ) ,\r\n        bmdDeckControlExportModeInsertAudio4\t= ( 1 << 4 ) ,\r\n        bmdDeckControlExportModeInsertAudio5\t= ( 1 << 5 ) ,\r\n        bmdDeckControlExportModeInsertAudio6\t= ( 1 << 6 ) ,\r\n        bmdDeckControlExportModeInsertAudio7\t= ( 1 << 7 ) ,\r\n        bmdDeckControlExportModeInsertAudio8\t= ( 1 << 8 ) ,\r\n        bmdDeckControlExportModeInsertAudio9\t= ( 1 << 9 ) ,\r\n        bmdDeckControlExportModeInsertAudio10\t= ( 1 << 10 ) ,\r\n        bmdDeckControlExportModeInsertAudio11\t= ( 1 << 11 ) ,\r\n        bmdDeckControlExportModeInsertAudio12\t= ( 1 << 12 ) ,\r\n        bmdDeckControlExportModeInsertTimeCode\t= ( 1 << 13 ) ,\r\n        bmdDeckControlExportModeInsertAssemble\t= ( 1 << 14 ) ,\r\n        bmdDeckControlExportModeInsertPreview\t= ( 1 << 15 ) ,\r\n        bmdDeckControlUseManualExport\t= ( 1 << 16 ) \r\n    } ;\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckControlError\r\n    {\r\n        bmdDeckControlNoError\t= 0x6e6f6572,\r\n        bmdDeckControlModeError\t= 0x6d6f6572,\r\n        bmdDeckControlMissedInPointError\t= 0x6d696572,\r\n        bmdDeckControlDeckTimeoutError\t= 0x64746572,\r\n        bmdDeckControlCommandFailedError\t= 0x63666572,\r\n        bmdDeckControlDeviceAlreadyOpenedError\t= 0x64616c6f,\r\n        bmdDeckControlFailedToOpenDeviceError\t= 0x66646572,\r\n        bmdDeckControlInLocalModeError\t= 0x6c6d6572,\r\n        bmdDeckControlEndOfTapeError\t= 0x65746572,\r\n        bmdDeckControlUserAbortError\t= 0x75616572,\r\n        bmdDeckControlNoTapeInDeckError\t= 0x6e746572,\r\n        bmdDeckControlNoVideoFromCardError\t= 0x6e766663,\r\n        bmdDeckControlNoCommunicationError\t= 0x6e636f6d,\r\n        bmdDeckControlBufferTooSmallError\t= 0x6274736d,\r\n        bmdDeckControlBadChecksumError\t= 0x63686b73,\r\n        bmdDeckControlUnknownError\t= 0x756e6572\r\n    } \tBMDDeckControlError;\r\n\r\n\r\n\r\n#if 0\r\n#endif\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingDeviceMode\r\n    {\r\n        bmdStreamingDeviceIdle\t= 0x69646c65,\r\n        bmdStreamingDeviceEncoding\t= 0x656e636f,\r\n        bmdStreamingDeviceStopping\t= 0x73746f70,\r\n        bmdStreamingDeviceUnknown\t= 0x6d756e6b\r\n    } \tBMDStreamingDeviceMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingEncodingFrameRate\r\n    {\r\n        bmdStreamingEncodedFrameRate50i\t= 0x65353069,\r\n        bmdStreamingEncodedFrameRate5994i\t= 0x65353969,\r\n        bmdStreamingEncodedFrameRate60i\t= 0x65363069,\r\n        bmdStreamingEncodedFrameRate2398p\t= 0x65323370,\r\n        bmdStreamingEncodedFrameRate24p\t= 0x65323470,\r\n        bmdStreamingEncodedFrameRate25p\t= 0x65323570,\r\n        bmdStreamingEncodedFrameRate2997p\t= 0x65323970,\r\n        bmdStreamingEncodedFrameRate30p\t= 0x65333070,\r\n        bmdStreamingEncodedFrameRate50p\t= 0x65353070,\r\n        bmdStreamingEncodedFrameRate5994p\t= 0x65353970,\r\n        bmdStreamingEncodedFrameRate60p\t= 0x65363070\r\n    } \tBMDStreamingEncodingFrameRate;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingEncodingSupport\r\n    {\r\n        bmdStreamingEncodingModeNotSupported\t= 0,\r\n        bmdStreamingEncodingModeSupported\t= ( bmdStreamingEncodingModeNotSupported + 1 ) ,\r\n        bmdStreamingEncodingModeSupportedWithChanges\t= ( bmdStreamingEncodingModeSupported + 1 ) \r\n    } \tBMDStreamingEncodingSupport;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingVideoCodec\r\n    {\r\n        bmdStreamingVideoCodecH264\t= 0x48323634\r\n    } \tBMDStreamingVideoCodec;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingH264Profile\r\n    {\r\n        bmdStreamingH264ProfileHigh\t= 0x68696768,\r\n        bmdStreamingH264ProfileMain\t= 0x6d61696e,\r\n        bmdStreamingH264ProfileBaseline\t= 0x62617365\r\n    } \tBMDStreamingH264Profile;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingH264Level\r\n    {\r\n        bmdStreamingH264Level12\t= 0x6c763132,\r\n        bmdStreamingH264Level13\t= 0x6c763133,\r\n        bmdStreamingH264Level2\t= 0x6c763220,\r\n        bmdStreamingH264Level21\t= 0x6c763231,\r\n        bmdStreamingH264Level22\t= 0x6c763232,\r\n        bmdStreamingH264Level3\t= 0x6c763320,\r\n        bmdStreamingH264Level31\t= 0x6c763331,\r\n        bmdStreamingH264Level32\t= 0x6c763332,\r\n        bmdStreamingH264Level4\t= 0x6c763420,\r\n        bmdStreamingH264Level41\t= 0x6c763431,\r\n        bmdStreamingH264Level42\t= 0x6c763432\r\n    } \tBMDStreamingH264Level;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingH264EntropyCoding\r\n    {\r\n        bmdStreamingH264EntropyCodingCAVLC\t= 0x45564c43,\r\n        bmdStreamingH264EntropyCodingCABAC\t= 0x45424143\r\n    } \tBMDStreamingH264EntropyCoding;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingAudioCodec\r\n    {\r\n        bmdStreamingAudioCodecAAC\t= 0x41414320\r\n    } \tBMDStreamingAudioCodec;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDStreamingEncodingModePropertyID\r\n    {\r\n        bmdStreamingEncodingPropertyVideoFrameRate\t= 0x76667274,\r\n        bmdStreamingEncodingPropertyVideoBitRateKbps\t= 0x76627274,\r\n        bmdStreamingEncodingPropertyH264Profile\t= 0x68707266,\r\n        bmdStreamingEncodingPropertyH264Level\t= 0x686c766c,\r\n        bmdStreamingEncodingPropertyH264EntropyCoding\t= 0x68656e74,\r\n        bmdStreamingEncodingPropertyH264HasBFrames\t= 0x68426672,\r\n        bmdStreamingEncodingPropertyAudioCodec\t= 0x61636463,\r\n        bmdStreamingEncodingPropertyAudioSampleRate\t= 0x61737274,\r\n        bmdStreamingEncodingPropertyAudioChannelCount\t= 0x61636863,\r\n        bmdStreamingEncodingPropertyAudioBitRateKbps\t= 0x61627274\r\n    } \tBMDStreamingEncodingModePropertyID;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\ntypedef unsigned int BMDFrameFlags;\r\ntypedef unsigned int BMDVideoInputFlags;\r\ntypedef unsigned int BMDVideoInputFormatChangedEvents;\r\ntypedef unsigned int BMDDetectedVideoInputFormatFlags;\r\ntypedef unsigned int BMDDeckLinkCapturePassthroughMode;\r\ntypedef unsigned int BMDAnalogVideoFlags;\r\ntypedef unsigned int BMDDeviceBusyState;\r\n#if 0\r\ntypedef enum _BMDFrameFlags BMDFrameFlags;\r\n\r\ntypedef enum _BMDVideoInputFlags BMDVideoInputFlags;\r\n\r\ntypedef enum _BMDVideoInputFormatChangedEvents BMDVideoInputFormatChangedEvents;\r\n\r\ntypedef enum _BMDDetectedVideoInputFormatFlags BMDDetectedVideoInputFormatFlags;\r\n\r\ntypedef enum _BMDDeckLinkCapturePassthroughMode BMDDeckLinkCapturePassthroughMode;\r\n\r\ntypedef enum _BMDAnalogVideoFlags BMDAnalogVideoFlags;\r\n\r\ntypedef enum _BMDDeviceBusyState BMDDeviceBusyState;\r\n\r\n#endif\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoOutputFlags\r\n    {\r\n        bmdVideoOutputFlagDefault\t= 0,\r\n        bmdVideoOutputVANC\t= ( 1 << 0 ) ,\r\n        bmdVideoOutputVITC\t= ( 1 << 1 ) ,\r\n        bmdVideoOutputRP188\t= ( 1 << 2 ) ,\r\n        bmdVideoOutputDualStream3D\t= ( 1 << 4 ) ,\r\n        bmdVideoOutputSynchronizeToPlaybackGroup\t= ( 1 << 6 ) \r\n    } \tBMDVideoOutputFlags;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDSupportedVideoModeFlags\r\n    {\r\n        bmdSupportedVideoModeDefault\t= 0,\r\n        bmdSupportedVideoModeKeying\t= ( 1 << 0 ) ,\r\n        bmdSupportedVideoModeDualStream3D\t= ( 1 << 1 ) ,\r\n        bmdSupportedVideoModeSDISingleLink\t= ( 1 << 2 ) ,\r\n        bmdSupportedVideoModeSDIDualLink\t= ( 1 << 3 ) ,\r\n        bmdSupportedVideoModeSDIQuadLink\t= ( 1 << 4 ) ,\r\n        bmdSupportedVideoModeInAnyProfile\t= ( 1 << 5 ) \r\n    } \tBMDSupportedVideoModeFlags;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDPacketType\r\n    {\r\n        bmdPacketTypeStreamInterruptedMarker\t= 0x73696e74,\r\n        bmdPacketTypeStreamData\t= 0x73646174\r\n    } \tBMDPacketType;\r\n\r\n/* [v1_enum] */ \r\nenum _BMDFrameFlags\r\n    {\r\n        bmdFrameFlagDefault\t= 0,\r\n        bmdFrameFlagFlipVertical\t= ( 1 << 0 ) ,\r\n        bmdFrameContainsHDRMetadata\t= ( 1 << 1 ) ,\r\n        bmdFrameCapturedAsPsF\t= ( 1 << 30 ) ,\r\n        bmdFrameHasNoInputSource\t= ( 1 << 31 ) \r\n    } ;\r\n/* [v1_enum] */ \r\nenum _BMDVideoInputFlags\r\n    {\r\n        bmdVideoInputFlagDefault\t= 0,\r\n        bmdVideoInputEnableFormatDetection\t= ( 1 << 0 ) ,\r\n        bmdVideoInputDualStream3D\t= ( 1 << 1 ) ,\r\n        bmdVideoInputSynchronizeToCaptureGroup\t= ( 1 << 2 ) \r\n    } ;\r\n/* [v1_enum] */ \r\nenum _BMDVideoInputFormatChangedEvents\r\n    {\r\n        bmdVideoInputDisplayModeChanged\t= ( 1 << 0 ) ,\r\n        bmdVideoInputFieldDominanceChanged\t= ( 1 << 1 ) ,\r\n        bmdVideoInputColorspaceChanged\t= ( 1 << 2 ) \r\n    } ;\r\n/* [v1_enum] */ \r\nenum _BMDDetectedVideoInputFormatFlags\r\n    {\r\n        bmdDetectedVideoInputYCbCr422\t= ( 1 << 0 ) ,\r\n        bmdDetectedVideoInputRGB444\t= ( 1 << 1 ) ,\r\n        bmdDetectedVideoInputDualStream3D\t= ( 1 << 2 ) ,\r\n        bmdDetectedVideoInput12BitDepth\t= ( 1 << 3 ) ,\r\n        bmdDetectedVideoInput10BitDepth\t= ( 1 << 4 ) ,\r\n        bmdDetectedVideoInput8BitDepth\t= ( 1 << 5 ) \r\n    } ;\r\n/* [v1_enum] */ \r\nenum _BMDDeckLinkCapturePassthroughMode\r\n    {\r\n        bmdDeckLinkCapturePassthroughModeDisabled\t= 0x70646973,\r\n        bmdDeckLinkCapturePassthroughModeDirect\t= 0x70646972,\r\n        bmdDeckLinkCapturePassthroughModeCleanSwitch\t= 0x70636c6e\r\n    } ;\r\ntypedef /* [v1_enum] */ \r\nenum _BMDOutputFrameCompletionResult\r\n    {\r\n        bmdOutputFrameCompleted\t= 0,\r\n        bmdOutputFrameDisplayedLate\t= ( bmdOutputFrameCompleted + 1 ) ,\r\n        bmdOutputFrameDropped\t= ( bmdOutputFrameDisplayedLate + 1 ) ,\r\n        bmdOutputFrameFlushed\t= ( bmdOutputFrameDropped + 1 ) \r\n    } \tBMDOutputFrameCompletionResult;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDReferenceStatus\r\n    {\r\n        bmdReferenceUnlocked\t= 0,\r\n        bmdReferenceNotSupportedByHardware\t= ( 1 << 0 ) ,\r\n        bmdReferenceLocked\t= ( 1 << 1 ) \r\n    } \tBMDReferenceStatus;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioFormat\r\n    {\r\n        bmdAudioFormatPCM\t= 0x6c70636d\r\n    } \tBMDAudioFormat;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioSampleRate\r\n    {\r\n        bmdAudioSampleRate48kHz\t= 48000\r\n    } \tBMDAudioSampleRate;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioSampleType\r\n    {\r\n        bmdAudioSampleType16bitInteger\t= 16,\r\n        bmdAudioSampleType32bitInteger\t= 32\r\n    } \tBMDAudioSampleType;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioOutputStreamType\r\n    {\r\n        bmdAudioOutputStreamContinuous\t= 0,\r\n        bmdAudioOutputStreamContinuousDontResample\t= ( bmdAudioOutputStreamContinuous + 1 ) ,\r\n        bmdAudioOutputStreamTimestamped\t= ( bmdAudioOutputStreamContinuousDontResample + 1 ) \r\n    } \tBMDAudioOutputStreamType;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAncillaryPacketFormat\r\n    {\r\n        bmdAncillaryPacketFormatUInt8\t= 0x75693038,\r\n        bmdAncillaryPacketFormatUInt16\t= 0x75693136,\r\n        bmdAncillaryPacketFormatYCbCr10\t= 0x76323130\r\n    } \tBMDAncillaryPacketFormat;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDTimecodeFormat\r\n    {\r\n        bmdTimecodeRP188VITC1\t= 0x72707631,\r\n        bmdTimecodeRP188VITC2\t= 0x72703132,\r\n        bmdTimecodeRP188LTC\t= 0x72706c74,\r\n        bmdTimecodeRP188HighFrameRate\t= 0x72706872,\r\n        bmdTimecodeRP188Any\t= 0x72703138,\r\n        bmdTimecodeVITC\t= 0x76697463,\r\n        bmdTimecodeVITCField2\t= 0x76697432,\r\n        bmdTimecodeSerial\t= 0x73657269\r\n    } \tBMDTimecodeFormat;\r\n\r\n/* [v1_enum] */ \r\nenum _BMDAnalogVideoFlags\r\n    {\r\n        bmdAnalogVideoFlagCompositeSetup75\t= ( 1 << 0 ) ,\r\n        bmdAnalogVideoFlagComponentBetacamLevels\t= ( 1 << 1 ) \r\n    } ;\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioOutputAnalogAESSwitch\r\n    {\r\n        bmdAudioOutputSwitchAESEBU\t= 0x61657320,\r\n        bmdAudioOutputSwitchAnalog\t= 0x616e6c67\r\n    } \tBMDAudioOutputAnalogAESSwitch;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoOutputConversionMode\r\n    {\r\n        bmdNoVideoOutputConversion\t= 0x6e6f6e65,\r\n        bmdVideoOutputLetterboxDownconversion\t= 0x6c746278,\r\n        bmdVideoOutputAnamorphicDownconversion\t= 0x616d7068,\r\n        bmdVideoOutputHD720toHD1080Conversion\t= 0x37323063,\r\n        bmdVideoOutputHardwareLetterboxDownconversion\t= 0x48576c62,\r\n        bmdVideoOutputHardwareAnamorphicDownconversion\t= 0x4857616d,\r\n        bmdVideoOutputHardwareCenterCutDownconversion\t= 0x48576363,\r\n        bmdVideoOutputHardware720p1080pCrossconversion\t= 0x78636170,\r\n        bmdVideoOutputHardwareAnamorphic720pUpconversion\t= 0x75613770,\r\n        bmdVideoOutputHardwareAnamorphic1080iUpconversion\t= 0x75613169,\r\n        bmdVideoOutputHardwareAnamorphic149To720pUpconversion\t= 0x75343770,\r\n        bmdVideoOutputHardwareAnamorphic149To1080iUpconversion\t= 0x75343169,\r\n        bmdVideoOutputHardwarePillarbox720pUpconversion\t= 0x75703770,\r\n        bmdVideoOutputHardwarePillarbox1080iUpconversion\t= 0x75703169\r\n    } \tBMDVideoOutputConversionMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoInputConversionMode\r\n    {\r\n        bmdNoVideoInputConversion\t= 0x6e6f6e65,\r\n        bmdVideoInputLetterboxDownconversionFromHD1080\t= 0x31306c62,\r\n        bmdVideoInputAnamorphicDownconversionFromHD1080\t= 0x3130616d,\r\n        bmdVideoInputLetterboxDownconversionFromHD720\t= 0x37326c62,\r\n        bmdVideoInputAnamorphicDownconversionFromHD720\t= 0x3732616d,\r\n        bmdVideoInputLetterboxUpconversion\t= 0x6c627570,\r\n        bmdVideoInputAnamorphicUpconversion\t= 0x616d7570\r\n    } \tBMDVideoInputConversionMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideo3DPackingFormat\r\n    {\r\n        bmdVideo3DPackingSidebySideHalf\t= 0x73627368,\r\n        bmdVideo3DPackingLinebyLine\t= 0x6c62796c,\r\n        bmdVideo3DPackingTopAndBottom\t= 0x7461626f,\r\n        bmdVideo3DPackingFramePacking\t= 0x6672706b,\r\n        bmdVideo3DPackingLeftOnly\t= 0x6c656674,\r\n        bmdVideo3DPackingRightOnly\t= 0x72696768\r\n    } \tBMDVideo3DPackingFormat;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDIdleVideoOutputOperation\r\n    {\r\n        bmdIdleVideoOutputBlack\t= 0x626c6163,\r\n        bmdIdleVideoOutputLastFrame\t= 0x6c616661\r\n    } \tBMDIdleVideoOutputOperation;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoEncoderFrameCodingMode\r\n    {\r\n        bmdVideoEncoderFrameCodingModeInter\t= 0x696e7465,\r\n        bmdVideoEncoderFrameCodingModeIntra\t= 0x696e7472\r\n    } \tBMDVideoEncoderFrameCodingMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDNxHRLevel\r\n    {\r\n        bmdDNxHRLevelSQ\t= 0x646e7371,\r\n        bmdDNxHRLevelLB\t= 0x646e6c62,\r\n        bmdDNxHRLevelHQ\t= 0x646e6871,\r\n        bmdDNxHRLevelHQX\t= 0x64687178,\r\n        bmdDNxHRLevel444\t= 0x64343434\r\n    } \tBMDDNxHRLevel;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDLinkConfiguration\r\n    {\r\n        bmdLinkConfigurationSingleLink\t= 0x6c63736c,\r\n        bmdLinkConfigurationDualLink\t= 0x6c63646c,\r\n        bmdLinkConfigurationQuadLink\t= 0x6c63716c\r\n    } \tBMDLinkConfiguration;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeviceInterface\r\n    {\r\n        bmdDeviceInterfacePCI\t= 0x70636920,\r\n        bmdDeviceInterfaceUSB\t= 0x75736220,\r\n        bmdDeviceInterfaceThunderbolt\t= 0x7468756e\r\n    } \tBMDDeviceInterface;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDColorspace\r\n    {\r\n        bmdColorspaceRec601\t= 0x72363031,\r\n        bmdColorspaceRec709\t= 0x72373039,\r\n        bmdColorspaceRec2020\t= 0x32303230\r\n    } \tBMDColorspace;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDynamicRange\r\n    {\r\n        bmdDynamicRangeSDR\t= 0,\r\n        bmdDynamicRangeHDRStaticPQ\t= ( 1 << 29 ) ,\r\n        bmdDynamicRangeHDRStaticHLG\t= ( 1 << 30 ) \r\n    } \tBMDDynamicRange;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkHDMIInputEDIDID\r\n    {\r\n        bmdDeckLinkHDMIInputEDIDDynamicRange\t= 0x48494479\r\n    } \tBMDDeckLinkHDMIInputEDIDID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkFrameMetadataID\r\n    {\r\n        bmdDeckLinkFrameMetadataColorspace\t= 0x63737063,\r\n        bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc\t= 0x656f7466,\r\n        bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX\t= 0x68647278,\r\n        bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY\t= 0x68647279,\r\n        bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX\t= 0x68646778,\r\n        bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY\t= 0x68646779,\r\n        bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX\t= 0x68646278,\r\n        bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY\t= 0x68646279,\r\n        bmdDeckLinkFrameMetadataHDRWhitePointX\t= 0x68647778,\r\n        bmdDeckLinkFrameMetadataHDRWhitePointY\t= 0x68647779,\r\n        bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance\t= 0x68646d6c,\r\n        bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance\t= 0x686d696c,\r\n        bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel\t= 0x6d636c6c,\r\n        bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel\t= 0x66616c6c\r\n    } \tBMDDeckLinkFrameMetadataID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDProfileID\r\n    {\r\n        bmdProfileOneSubDeviceFullDuplex\t= 0x31646664,\r\n        bmdProfileOneSubDeviceHalfDuplex\t= 0x31646864,\r\n        bmdProfileTwoSubDevicesFullDuplex\t= 0x32646664,\r\n        bmdProfileTwoSubDevicesHalfDuplex\t= 0x32646864,\r\n        bmdProfileFourSubDevicesHalfDuplex\t= 0x34646864\r\n    } \tBMDProfileID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDHDMITimecodePacking\r\n    {\r\n        bmdHDMITimecodePackingIEEEOUI000085\t= 0x8500,\r\n        bmdHDMITimecodePackingIEEEOUI080046\t= 0x8004601,\r\n        bmdHDMITimecodePackingIEEEOUI5CF9F0\t= 0x5cf9f003\r\n    } \tBMDHDMITimecodePacking;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDInternalKeyingAncillaryDataSource\r\n    {\r\n        bmdInternalKeyingUsesAncillaryDataFromInputSignal\t= 0x696b6169,\r\n        bmdInternalKeyingUsesAncillaryDataFromKeyFrame\t= 0x696b616b\r\n    } \tBMDInternalKeyingAncillaryDataSource;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkAttributeID\r\n    {\r\n        BMDDeckLinkSupportsInternalKeying\t= 0x6b657969,\r\n        BMDDeckLinkSupportsExternalKeying\t= 0x6b657965,\r\n        BMDDeckLinkSupportsInputFormatDetection\t= 0x696e6664,\r\n        BMDDeckLinkHasReferenceInput\t= 0x6872696e,\r\n        BMDDeckLinkHasSerialPort\t= 0x68737074,\r\n        BMDDeckLinkHasAnalogVideoOutputGain\t= 0x61766f67,\r\n        BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain\t= 0x6f766f67,\r\n        BMDDeckLinkHasVideoInputAntiAliasingFilter\t= 0x6161666c,\r\n        BMDDeckLinkHasBypass\t= 0x62797073,\r\n        BMDDeckLinkSupportsClockTimingAdjustment\t= 0x63746164,\r\n        BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset\t= 0x6672696e,\r\n        BMDDeckLinkSupportsSMPTELevelAOutput\t= 0x6c766c61,\r\n        BMDDeckLinkSupportsAutoSwitchingPPsFOnInput\t= 0x61707366,\r\n        BMDDeckLinkSupportsDualLinkSDI\t= 0x73646c73,\r\n        BMDDeckLinkSupportsQuadLinkSDI\t= 0x73716c73,\r\n        BMDDeckLinkSupportsIdleOutput\t= 0x69646f75,\r\n        BMDDeckLinkVANCRequires10BitYUVVideoFrames\t= 0x76696f59,\r\n        BMDDeckLinkHasLTCTimecodeInput\t= 0x686c7463,\r\n        BMDDeckLinkSupportsHDRMetadata\t= 0x6864726d,\r\n        BMDDeckLinkSupportsColorspaceMetadata\t= 0x636d6574,\r\n        BMDDeckLinkSupportsHDMITimecode\t= 0x6874696d,\r\n        BMDDeckLinkSupportsHighFrameRateTimecode\t= 0x48465254,\r\n        BMDDeckLinkSupportsSynchronizeToCaptureGroup\t= 0x73746367,\r\n        BMDDeckLinkSupportsSynchronizeToPlaybackGroup\t= 0x73747067,\r\n        BMDDeckLinkMaximumAudioChannels\t= 0x6d616368,\r\n        BMDDeckLinkMaximumAnalogAudioInputChannels\t= 0x69616368,\r\n        BMDDeckLinkMaximumAnalogAudioOutputChannels\t= 0x61616368,\r\n        BMDDeckLinkNumberOfSubDevices\t= 0x6e736264,\r\n        BMDDeckLinkSubDeviceIndex\t= 0x73756269,\r\n        BMDDeckLinkPersistentID\t= 0x70656964,\r\n        BMDDeckLinkDeviceGroupID\t= 0x64676964,\r\n        BMDDeckLinkTopologicalID\t= 0x746f6964,\r\n        BMDDeckLinkVideoOutputConnections\t= 0x766f636e,\r\n        BMDDeckLinkVideoInputConnections\t= 0x7669636e,\r\n        BMDDeckLinkAudioOutputConnections\t= 0x616f636e,\r\n        BMDDeckLinkAudioInputConnections\t= 0x6169636e,\r\n        BMDDeckLinkVideoIOSupport\t= 0x76696f73,\r\n        BMDDeckLinkDeckControlConnections\t= 0x6463636e,\r\n        BMDDeckLinkDeviceInterface\t= 0x64627573,\r\n        BMDDeckLinkAudioInputRCAChannelCount\t= 0x61697263,\r\n        BMDDeckLinkAudioInputXLRChannelCount\t= 0x61697863,\r\n        BMDDeckLinkAudioOutputRCAChannelCount\t= 0x616f7263,\r\n        BMDDeckLinkAudioOutputXLRChannelCount\t= 0x616f7863,\r\n        BMDDeckLinkProfileID\t= 0x70726964,\r\n        BMDDeckLinkDuplex\t= 0x64757078,\r\n        BMDDeckLinkMinimumPrerollFrames\t= 0x6d707266,\r\n        BMDDeckLinkSupportedDynamicRange\t= 0x73756472,\r\n        BMDDeckLinkVideoInputGainMinimum\t= 0x7669676d,\r\n        BMDDeckLinkVideoInputGainMaximum\t= 0x76696778,\r\n        BMDDeckLinkVideoOutputGainMinimum\t= 0x766f676d,\r\n        BMDDeckLinkVideoOutputGainMaximum\t= 0x766f6778,\r\n        BMDDeckLinkMicrophoneInputGainMinimum\t= 0x6d69676d,\r\n        BMDDeckLinkMicrophoneInputGainMaximum\t= 0x6d696778,\r\n        BMDDeckLinkSerialPortDeviceName\t= 0x736c706e,\r\n        BMDDeckLinkVendorName\t= 0x766e6472,\r\n        BMDDeckLinkDisplayName\t= 0x6473706e,\r\n        BMDDeckLinkModelName\t= 0x6d646c6e,\r\n        BMDDeckLinkDeviceHandle\t= 0x64657668\r\n    } \tBMDDeckLinkAttributeID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkAPIInformationID\r\n    {\r\n        BMDDeckLinkAPIVersion\t= 0x76657273\r\n    } \tBMDDeckLinkAPIInformationID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkStatusID\r\n    {\r\n        bmdDeckLinkStatusDetectedVideoInputMode\t= 0x6476696d,\r\n        bmdDeckLinkStatusDetectedVideoInputFormatFlags\t= 0x64766666,\r\n        bmdDeckLinkStatusDetectedVideoInputFieldDominance\t= 0x64766664,\r\n        bmdDeckLinkStatusDetectedVideoInputColorspace\t= 0x6473636c,\r\n        bmdDeckLinkStatusDetectedVideoInputDynamicRange\t= 0x64736472,\r\n        bmdDeckLinkStatusDetectedSDILinkConfiguration\t= 0x64736c63,\r\n        bmdDeckLinkStatusCurrentVideoInputMode\t= 0x6376696d,\r\n        bmdDeckLinkStatusCurrentVideoInputPixelFormat\t= 0x63766970,\r\n        bmdDeckLinkStatusCurrentVideoInputFlags\t= 0x63766966,\r\n        bmdDeckLinkStatusCurrentVideoOutputMode\t= 0x63766f6d,\r\n        bmdDeckLinkStatusCurrentVideoOutputFlags\t= 0x63766f66,\r\n        bmdDeckLinkStatusPCIExpressLinkWidth\t= 0x70776964,\r\n        bmdDeckLinkStatusPCIExpressLinkSpeed\t= 0x706c6e6b,\r\n        bmdDeckLinkStatusLastVideoOutputPixelFormat\t= 0x6f706978,\r\n        bmdDeckLinkStatusReferenceSignalMode\t= 0x7265666d,\r\n        bmdDeckLinkStatusReferenceSignalFlags\t= 0x72656666,\r\n        bmdDeckLinkStatusBusy\t= 0x62757379,\r\n        bmdDeckLinkStatusInterchangeablePanelType\t= 0x69637074,\r\n        bmdDeckLinkStatusDeviceTemperature\t= 0x64746d70,\r\n        bmdDeckLinkStatusVideoInputSignalLocked\t= 0x7669736c,\r\n        bmdDeckLinkStatusReferenceSignalLocked\t= 0x7265666c,\r\n        bmdDeckLinkStatusReceivedEDID\t= 0x65646964\r\n    } \tBMDDeckLinkStatusID;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkVideoStatusFlags\r\n    {\r\n        bmdDeckLinkVideoStatusPsF\t= ( 1 << 0 ) ,\r\n        bmdDeckLinkVideoStatusDualStream3D\t= ( 1 << 1 ) \r\n    } \tBMDDeckLinkVideoStatusFlags;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDuplexMode\r\n    {\r\n        bmdDuplexFull\t= 0x64786675,\r\n        bmdDuplexHalf\t= 0x64786861,\r\n        bmdDuplexSimplex\t= 0x64787370,\r\n        bmdDuplexInactive\t= 0x6478696e\r\n    } \tBMDDuplexMode;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDPanelType\r\n    {\r\n        bmdPanelNotDetected\t= 0x6e706e6c,\r\n        bmdPanelTeranexMiniSmartPanel\t= 0x746d736d\r\n    } \tBMDPanelType;\r\n\r\n/* [v1_enum] */ \r\nenum _BMDDeviceBusyState\r\n    {\r\n        bmdDeviceCaptureBusy\t= ( 1 << 0 ) ,\r\n        bmdDevicePlaybackBusy\t= ( 1 << 1 ) ,\r\n        bmdDeviceSerialPortBusy\t= ( 1 << 2 ) \r\n    } ;\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoIOSupport\r\n    {\r\n        bmdDeviceSupportsCapture\t= ( 1 << 0 ) ,\r\n        bmdDeviceSupportsPlayback\t= ( 1 << 1 ) \r\n    } \tBMDVideoIOSupport;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMD3DPreviewFormat\r\n    {\r\n        bmd3DPreviewFormatDefault\t= 0x64656661,\r\n        bmd3DPreviewFormatLeftOnly\t= 0x6c656674,\r\n        bmd3DPreviewFormatRightOnly\t= 0x72696768,\r\n        bmd3DPreviewFormatSideBySide\t= 0x73696465,\r\n        bmd3DPreviewFormatTopBottom\t= 0x746f7062\r\n    } \tBMD3DPreviewFormat;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDNotifications\r\n    {\r\n        bmdPreferencesChanged\t= 0x70726566,\r\n        bmdStatusChanged\t= 0x73746174\r\n    } \tBMDNotifications;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkStatusID_v11_5_1\r\n    {\r\n        bmdDeckLinkStatusDetectedVideoInputFlags_v11_5_1\t= 0x64766966\r\n    } \tBMDDeckLinkStatusID_v11_5_1;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDisplayModeSupport_v10_11\r\n    {\r\n        bmdDisplayModeNotSupported_v10_11\t= 0,\r\n        bmdDisplayModeSupported_v10_11\t= ( bmdDisplayModeNotSupported_v10_11 + 1 ) ,\r\n        bmdDisplayModeSupportedWithConversion_v10_11\t= ( bmdDisplayModeSupported_v10_11 + 1 ) \r\n    } \tBMDDisplayModeSupport_v10_11;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDuplexMode_v10_11\r\n    {\r\n        bmdDuplexModeFull_v10_11\t= 0x66647570,\r\n        bmdDuplexModeHalf_v10_11\t= 0x68647570\r\n    } \tBMDDuplexMode_v10_11;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkConfigurationID_v10_11\r\n    {\r\n        bmdDeckLinkConfigDuplexMode_v10_11\t= 0x64757078\r\n    } \tBMDDeckLinkConfigurationID_v10_11;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkAttributeID_v10_11\r\n    {\r\n        BMDDeckLinkSupportsDuplexModeConfiguration_v10_11\t= 0x64757078,\r\n        BMDDeckLinkSupportsHDKeying_v10_11\t= 0x6b657968,\r\n        BMDDeckLinkPairedDevicePersistentID_v10_11\t= 0x70706964,\r\n        BMDDeckLinkSupportsFullDuplex_v10_11\t= 0x66647570\r\n    } \tBMDDeckLinkAttributeID_v10_11;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkStatusID_v10_11\r\n    {\r\n        bmdDeckLinkStatusDuplexMode_v10_11\t= 0x64757078\r\n    } \tBMDDeckLinkStatusID_v10_11;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDuplexStatus_v10_11\r\n    {\r\n        bmdDuplexFullDuplex_v10_11\t= 0x66647570,\r\n        bmdDuplexHalfDuplex_v10_11\t= 0x68647570,\r\n        bmdDuplexSimplex_v10_11\t= 0x73706c78,\r\n        bmdDuplexInactive_v10_11\t= 0x696e6163\r\n    } \tBMDDuplexStatus_v10_11;\r\n\r\n\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkConfigurationID_v10_9\r\n    {\r\n        bmdDeckLinkConfig1080pNotPsF_v10_9\t= 0x6670726f\r\n    } \tBMDDeckLinkConfigurationID_v10_9;\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkConfigurationID_v10_4\r\n    {\r\n        bmdDeckLinkConfigSingleLinkVideoOutput_v10_4\t= 0x73676c6f\r\n    } \tBMDDeckLinkConfigurationID_v10_4;\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkConfigurationID_v10_2\r\n    {\r\n        bmdDeckLinkConfig3GBpsVideoOutput_v10_2\t= 0x33676273\r\n    } \tBMDDeckLinkConfigurationID_v10_2;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDAudioConnection_v10_2\r\n    {\r\n        bmdAudioConnectionEmbedded_v10_2\t= 0x656d6264,\r\n        bmdAudioConnectionAESEBU_v10_2\t= 0x61657320,\r\n        bmdAudioConnectionAnalog_v10_2\t= 0x616e6c67,\r\n        bmdAudioConnectionAnalogXLR_v10_2\t= 0x61786c72,\r\n        bmdAudioConnectionAnalogRCA_v10_2\t= 0x61726361\r\n    } \tBMDAudioConnection_v10_2;\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkFrameMetadataID_v11_5\r\n    {\r\n        bmdDeckLinkFrameMetadataCintelFilmType_v11_5\t= 0x63667479,\r\n        bmdDeckLinkFrameMetadataCintelFilmGauge_v11_5\t= 0x63666761,\r\n        bmdDeckLinkFrameMetadataCintelKeykodeLow_v11_5\t= 0x636b6b6c,\r\n        bmdDeckLinkFrameMetadataCintelKeykodeHigh_v11_5\t= 0x636b6b68,\r\n        bmdDeckLinkFrameMetadataCintelTile1Size_v11_5\t= 0x63743173,\r\n        bmdDeckLinkFrameMetadataCintelTile2Size_v11_5\t= 0x63743273,\r\n        bmdDeckLinkFrameMetadataCintelTile3Size_v11_5\t= 0x63743373,\r\n        bmdDeckLinkFrameMetadataCintelTile4Size_v11_5\t= 0x63743473,\r\n        bmdDeckLinkFrameMetadataCintelImageWidth_v11_5\t= 0x49575078,\r\n        bmdDeckLinkFrameMetadataCintelImageHeight_v11_5\t= 0x49485078,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingRedInRed_v11_5\t= 0x6d726972,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInRed_v11_5\t= 0x6d676972,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInRed_v11_5\t= 0x6d626972,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingRedInGreen_v11_5\t= 0x6d726967,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInGreen_v11_5\t= 0x6d676967,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInGreen_v11_5\t= 0x6d626967,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingRedInBlue_v11_5\t= 0x6d726962,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInBlue_v11_5\t= 0x6d676962,\r\n        bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInBlue_v11_5\t= 0x6d626962,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingRedInRed_v11_5\t= 0x6d6c7272,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingGreenInRed_v11_5\t= 0x6d6c6772,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingBlueInRed_v11_5\t= 0x6d6c6272,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingRedInGreen_v11_5\t= 0x6d6c7267,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingGreenInGreen_v11_5\t= 0x6d6c6767,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingBlueInGreen_v11_5\t= 0x6d6c6267,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingRedInBlue_v11_5\t= 0x6d6c7262,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingGreenInBlue_v11_5\t= 0x6d6c6762,\r\n        bmdDeckLinkFrameMetadataCintelLogMaskingBlueInBlue_v11_5\t= 0x6d6c6262,\r\n        bmdDeckLinkFrameMetadataCintelFilmFrameRate_v11_5\t= 0x63666672,\r\n        bmdDeckLinkFrameMetadataCintelOffsetToApplyHorizontal_v11_5\t= 0x6f746168,\r\n        bmdDeckLinkFrameMetadataCintelOffsetToApplyVertical_v11_5\t= 0x6f746176,\r\n        bmdDeckLinkFrameMetadataCintelGainRed_v11_5\t= 0x4c665264,\r\n        bmdDeckLinkFrameMetadataCintelGainGreen_v11_5\t= 0x4c664772,\r\n        bmdDeckLinkFrameMetadataCintelGainBlue_v11_5\t= 0x4c66426c,\r\n        bmdDeckLinkFrameMetadataCintelLiftRed_v11_5\t= 0x476e5264,\r\n        bmdDeckLinkFrameMetadataCintelLiftGreen_v11_5\t= 0x476e4772,\r\n        bmdDeckLinkFrameMetadataCintelLiftBlue_v11_5\t= 0x476e426c,\r\n        bmdDeckLinkFrameMetadataCintelHDRGainRed_v11_5\t= 0x48475264,\r\n        bmdDeckLinkFrameMetadataCintelHDRGainGreen_v11_5\t= 0x48474772,\r\n        bmdDeckLinkFrameMetadataCintelHDRGainBlue_v11_5\t= 0x4847426c,\r\n        bmdDeckLinkFrameMetadataCintel16mmCropRequired_v11_5\t= 0x63313663,\r\n        bmdDeckLinkFrameMetadataCintelInversionRequired_v11_5\t= 0x63696e76,\r\n        bmdDeckLinkFrameMetadataCintelFlipRequired_v11_5\t= 0x63666c72,\r\n        bmdDeckLinkFrameMetadataCintelFocusAssistEnabled_v11_5\t= 0x63666165,\r\n        bmdDeckLinkFrameMetadataCintelKeykodeIsInterpolated_v11_5\t= 0x6b6b6969\r\n    } \tBMDDeckLinkFrameMetadataID_v11_5;\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkAttributeID_v10_6\r\n    {\r\n        BMDDeckLinkSupportsDesktopDisplay_v10_6\t= 0x65787464\r\n    } \tBMDDeckLinkAttributeID_v10_6;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDIdleVideoOutputOperation_v10_6\r\n    {\r\n        bmdIdleVideoOutputDesktop_v10_6\t= 0x6465736b\r\n    } \tBMDIdleVideoOutputOperation_v10_6;\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckLinkAttributeID_v10_5\r\n    {\r\n        BMDDeckLinkDeviceBusyState_v10_5\t= 0x64627374\r\n    } \tBMDDeckLinkAttributeID_v10_5;\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDDeckControlVTRControlState_v8_1\r\n    {\r\n        bmdDeckControlNotInVTRControlMode_v8_1\t= 0x6e76636d,\r\n        bmdDeckControlVTRControlPlaying_v8_1\t= 0x76747270,\r\n        bmdDeckControlVTRControlRecording_v8_1\t= 0x76747272,\r\n        bmdDeckControlVTRControlStill_v8_1\t= 0x76747261,\r\n        bmdDeckControlVTRControlSeeking_v8_1\t= 0x76747273,\r\n        bmdDeckControlVTRControlStopped_v8_1\t= 0x7674726f\r\n    } \tBMDDeckControlVTRControlState_v8_1;\r\n\r\n\r\n\r\ntypedef /* [v1_enum] */ \r\nenum _BMDVideoConnection_v7_6\r\n    {\r\n        bmdVideoConnectionSDI_v7_6\t= 0x73646920,\r\n        bmdVideoConnectionHDMI_v7_6\t= 0x68646d69,\r\n        bmdVideoConnectionOpticalSDI_v7_6\t= 0x6f707469,\r\n        bmdVideoConnectionComponent_v7_6\t= 0x63706e74,\r\n        bmdVideoConnectionComposite_v7_6\t= 0x636d7374,\r\n        bmdVideoConnectionSVideo_v7_6\t= 0x73766964\r\n    } \tBMDVideoConnection_v7_6;\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\nEXTERN_C const IID LIBID_DeckLinkAPI;\r\n\r\n#ifndef __IDeckLinkTimecode_INTERFACE_DEFINED__\r\n#define __IDeckLinkTimecode_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkTimecode */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkTimecode;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"BC6CFBD3-8317-4325-AC1C-1216391E9340\")\r\n    IDeckLinkTimecode : public IUnknown\r\n    {\r\n    public:\r\n        virtual BMDTimecodeBCD STDMETHODCALLTYPE GetBCD( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetComponents( \r\n            /* [out] */ unsigned char *hours,\r\n            /* [out] */ unsigned char *minutes,\r\n            /* [out] */ unsigned char *seconds,\r\n            /* [out] */ unsigned char *frames) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [out] */ BSTR *timecode) = 0;\r\n        \r\n        virtual BMDTimecodeFlags STDMETHODCALLTYPE GetFlags( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeUserBits( \r\n            /* [out] */ BMDTimecodeUserBits *userBits) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkTimecodeVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkTimecode * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkTimecode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkTimecode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode, GetBCD)\r\n        BMDTimecodeBCD ( STDMETHODCALLTYPE *GetBCD )( \r\n            IDeckLinkTimecode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode, GetComponents)\r\n        HRESULT ( STDMETHODCALLTYPE *GetComponents )( \r\n            IDeckLinkTimecode * This,\r\n            /* [out] */ unsigned char *hours,\r\n            /* [out] */ unsigned char *minutes,\r\n            /* [out] */ unsigned char *seconds,\r\n            /* [out] */ unsigned char *frames);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkTimecode * This,\r\n            /* [out] */ BSTR *timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode, GetFlags)\r\n        BMDTimecodeFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkTimecode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode, GetTimecodeUserBits)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeUserBits )( \r\n            IDeckLinkTimecode * This,\r\n            /* [out] */ BMDTimecodeUserBits *userBits);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkTimecodeVtbl;\r\n\r\n    interface IDeckLinkTimecode\r\n    {\r\n        CONST_VTBL struct IDeckLinkTimecodeVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkTimecode_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkTimecode_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkTimecode_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkTimecode_GetBCD(This)\t\\\r\n    ( (This)->lpVtbl -> GetBCD(This) ) \r\n\r\n#define IDeckLinkTimecode_GetComponents(This,hours,minutes,seconds,frames)\t\\\r\n    ( (This)->lpVtbl -> GetComponents(This,hours,minutes,seconds,frames) ) \r\n\r\n#define IDeckLinkTimecode_GetString(This,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,timecode) ) \r\n\r\n#define IDeckLinkTimecode_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkTimecode_GetTimecodeUserBits(This,userBits)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeUserBits(This,userBits) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkTimecode_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayModeIterator_INTERFACE_DEFINED__\r\n#define __IDeckLinkDisplayModeIterator_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDisplayModeIterator */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDisplayModeIterator;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"9C88499F-F601-4021-B80B-032E4EB41C35\")\r\n    IDeckLinkDisplayModeIterator : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLinkDisplayMode **deckLinkDisplayMode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDisplayModeIteratorVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDisplayModeIterator * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDisplayModeIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDisplayModeIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayModeIterator, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkDisplayModeIterator * This,\r\n            /* [out] */ IDeckLinkDisplayMode **deckLinkDisplayMode);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDisplayModeIteratorVtbl;\r\n\r\n    interface IDeckLinkDisplayModeIterator\r\n    {\r\n        CONST_VTBL struct IDeckLinkDisplayModeIteratorVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDisplayModeIterator_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDisplayModeIterator_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDisplayModeIterator_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDisplayModeIterator_Next(This,deckLinkDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> Next(This,deckLinkDisplayMode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDisplayModeIterator_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayMode_INTERFACE_DEFINED__\r\n#define __IDeckLinkDisplayMode_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDisplayMode */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDisplayMode;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78\")\r\n    IDeckLinkDisplayMode : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetName( \r\n            /* [out] */ BSTR *name) = 0;\r\n        \r\n        virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetWidth( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetHeight( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameRate( \r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [out] */ BMDTimeScale *timeScale) = 0;\r\n        \r\n        virtual BMDFieldDominance STDMETHODCALLTYPE GetFieldDominance( void) = 0;\r\n        \r\n        virtual BMDDisplayModeFlags STDMETHODCALLTYPE GetFlags( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDisplayModeVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDisplayMode * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetName )( \r\n            IDeckLinkDisplayMode * This,\r\n            /* [out] */ BSTR *name);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetDisplayMode)\r\n        BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetFrameRate)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameRate )( \r\n            IDeckLinkDisplayMode * This,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [out] */ BMDTimeScale *timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetFieldDominance)\r\n        BMDFieldDominance ( STDMETHODCALLTYPE *GetFieldDominance )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode, GetFlags)\r\n        BMDDisplayModeFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkDisplayMode * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDisplayModeVtbl;\r\n\r\n    interface IDeckLinkDisplayMode\r\n    {\r\n        CONST_VTBL struct IDeckLinkDisplayModeVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDisplayMode_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDisplayMode_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDisplayMode_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDisplayMode_GetName(This,name)\t\\\r\n    ( (This)->lpVtbl -> GetName(This,name) ) \r\n\r\n#define IDeckLinkDisplayMode_GetDisplayMode(This)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This) ) \r\n\r\n#define IDeckLinkDisplayMode_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkDisplayMode_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkDisplayMode_GetFrameRate(This,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetFrameRate(This,frameDuration,timeScale) ) \r\n\r\n#define IDeckLinkDisplayMode_GetFieldDominance(This)\t\\\r\n    ( (This)->lpVtbl -> GetFieldDominance(This) ) \r\n\r\n#define IDeckLinkDisplayMode_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDisplayMode_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLink_INTERFACE_DEFINED__\r\n#define __IDeckLink_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLink */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLink;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"C418FBDD-0587-48ED-8FE5-640F0A14AF91\")\r\n    IDeckLink : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetModelName( \r\n            /* [out] */ BSTR *modelName) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayName( \r\n            /* [out] */ BSTR *displayName) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLink * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLink * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLink * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLink, GetModelName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetModelName )( \r\n            IDeckLink * This,\r\n            /* [out] */ BSTR *modelName);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLink, GetDisplayName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayName )( \r\n            IDeckLink * This,\r\n            /* [out] */ BSTR *displayName);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVtbl;\r\n\r\n    interface IDeckLink\r\n    {\r\n        CONST_VTBL struct IDeckLinkVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLink_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLink_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLink_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLink_GetModelName(This,modelName)\t\\\r\n    ( (This)->lpVtbl -> GetModelName(This,modelName) ) \r\n\r\n#define IDeckLink_GetDisplayName(This,displayName)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayName(This,displayName) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLink_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_INTERFACE_DEFINED__\r\n#define __IDeckLinkConfiguration_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkConfiguration */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkConfiguration;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"912F634B-2D4E-40A4-8AAB-8D80B73F1289\")\r\n    IDeckLinkConfiguration : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkConfigurationVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkConfiguration * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkConfiguration * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkConfiguration * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration, WriteConfigurationToPreferences)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )( \r\n            IDeckLinkConfiguration * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkConfigurationVtbl;\r\n\r\n    interface IDeckLinkConfiguration\r\n    {\r\n        CONST_VTBL struct IDeckLinkConfigurationVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkConfiguration_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkConfiguration_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkConfiguration_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkConfiguration_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_WriteConfigurationToPreferences(This)\t\\\r\n    ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkConfiguration_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderConfiguration_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderConfiguration_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderConfiguration */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderConfiguration;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"138050E5-C60A-4552-BF3F-0F358049327E\")\r\n    IDeckLinkEncoderConfiguration : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ void *buffer,\r\n            /* [out][in] */ unsigned int *bufferSize) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderConfigurationVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderConfiguration * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderConfiguration * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkEncoderConfiguration * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ void *buffer,\r\n            /* [out][in] */ unsigned int *bufferSize);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderConfigurationVtbl;\r\n\r\n    interface IDeckLinkEncoderConfiguration\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderConfigurationVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderConfiguration_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderConfiguration_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_GetBytes(This,cfgID,buffer,bufferSize)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,cfgID,buffer,bufferSize) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderConfiguration_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControlStatusCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkDeckControlStatusCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDeckControlStatusCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDeckControlStatusCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"53436FFB-B434-4906-BADC-AE3060FFE8EF\")\r\n    IDeckLinkDeckControlStatusCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE TimecodeUpdate( \r\n            /* [in] */ BMDTimecodeBCD currentTimecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VTRControlStateChanged( \r\n            /* [in] */ BMDDeckControlVTRControlState newState,\r\n            /* [in] */ BMDDeckControlError error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DeckControlEventReceived( \r\n            /* [in] */ BMDDeckControlEvent event,\r\n            /* [in] */ BMDDeckControlError error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DeckControlStatusChanged( \r\n            /* [in] */ BMDDeckControlStatusFlags flags,\r\n            /* [in] */ unsigned int mask) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDeckControlStatusCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDeckControlStatusCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDeckControlStatusCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDeckControlStatusCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback, TimecodeUpdate)\r\n        HRESULT ( STDMETHODCALLTYPE *TimecodeUpdate )( \r\n            IDeckLinkDeckControlStatusCallback * This,\r\n            /* [in] */ BMDTimecodeBCD currentTimecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback, VTRControlStateChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VTRControlStateChanged )( \r\n            IDeckLinkDeckControlStatusCallback * This,\r\n            /* [in] */ BMDDeckControlVTRControlState newState,\r\n            /* [in] */ BMDDeckControlError error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback, DeckControlEventReceived)\r\n        HRESULT ( STDMETHODCALLTYPE *DeckControlEventReceived )( \r\n            IDeckLinkDeckControlStatusCallback * This,\r\n            /* [in] */ BMDDeckControlEvent event,\r\n            /* [in] */ BMDDeckControlError error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback, DeckControlStatusChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *DeckControlStatusChanged )( \r\n            IDeckLinkDeckControlStatusCallback * This,\r\n            /* [in] */ BMDDeckControlStatusFlags flags,\r\n            /* [in] */ unsigned int mask);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDeckControlStatusCallbackVtbl;\r\n\r\n    interface IDeckLinkDeckControlStatusCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkDeckControlStatusCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDeckControlStatusCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDeckControlStatusCallback_TimecodeUpdate(This,currentTimecode)\t\\\r\n    ( (This)->lpVtbl -> TimecodeUpdate(This,currentTimecode) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_VTRControlStateChanged(This,newState,error)\t\\\r\n    ( (This)->lpVtbl -> VTRControlStateChanged(This,newState,error) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_DeckControlEventReceived(This,event,error)\t\\\r\n    ( (This)->lpVtbl -> DeckControlEventReceived(This,event,error) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_DeckControlStatusChanged(This,flags,mask)\t\\\r\n    ( (This)->lpVtbl -> DeckControlStatusChanged(This,flags,mask) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDeckControlStatusCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControl_INTERFACE_DEFINED__\r\n#define __IDeckLinkDeckControl_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDeckControl */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDeckControl;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"8E1C3ACE-19C7-4E00-8B92-D80431D958BE\")\r\n    IDeckLinkDeckControl : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Open( \r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ BMDTimeValue timeValue,\r\n            /* [in] */ BOOL timecodeIsDropFrame,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Close( \r\n            /* [in] */ BOOL standbyOn) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCurrentState( \r\n            /* [out] */ BMDDeckControlMode *mode,\r\n            /* [out] */ BMDDeckControlVTRControlState *vtrControlState,\r\n            /* [out] */ BMDDeckControlStatusFlags *flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetStandby( \r\n            /* [in] */ BOOL standbyOn) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SendCommand( \r\n            /* [in] */ unsigned char *inBuffer,\r\n            /* [in] */ unsigned int inBufferSize,\r\n            /* [out] */ unsigned char *outBuffer,\r\n            /* [out] */ unsigned int *outDataSize,\r\n            /* [in] */ unsigned int outBufferSize,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Play( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Stop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE TogglePlayStop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Eject( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GoToTimecode( \r\n            /* [in] */ BMDTimecodeBCD timecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FastForward( \r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Rewind( \r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StepForward( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StepBack( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Jog( \r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Shuttle( \r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeString( \r\n            /* [out] */ BSTR *currentTimeCode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecode( \r\n            /* [out] */ IDeckLinkTimecode **currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeBCD( \r\n            /* [out] */ BMDTimecodeBCD *currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetPreroll( \r\n            /* [in] */ unsigned int prerollSeconds) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPreroll( \r\n            /* [out] */ unsigned int *prerollSeconds) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetExportOffset( \r\n            /* [in] */ int exportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetExportOffset( \r\n            /* [out] */ int *exportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetManualExportOffset( \r\n            /* [out] */ int *deckManualExportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCaptureOffset( \r\n            /* [in] */ int captureOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCaptureOffset( \r\n            /* [out] */ int *captureOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartExport( \r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartCapture( \r\n            /* [in] */ BOOL useVITC,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDeviceID( \r\n            /* [out] */ unsigned short *deviceId,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CrashRecordStart( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CrashRecordStop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkDeckControlStatusCallback *callback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDeckControlVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDeckControl * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDeckControl * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Open)\r\n        HRESULT ( STDMETHODCALLTYPE *Open )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ BMDTimeValue timeValue,\r\n            /* [in] */ BOOL timecodeIsDropFrame,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Close)\r\n        HRESULT ( STDMETHODCALLTYPE *Close )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BOOL standbyOn);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetCurrentState)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCurrentState )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlMode *mode,\r\n            /* [out] */ BMDDeckControlVTRControlState *vtrControlState,\r\n            /* [out] */ BMDDeckControlStatusFlags *flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, SetStandby)\r\n        HRESULT ( STDMETHODCALLTYPE *SetStandby )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BOOL standbyOn);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, SendCommand)\r\n        HRESULT ( STDMETHODCALLTYPE *SendCommand )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ unsigned char *inBuffer,\r\n            /* [in] */ unsigned int inBufferSize,\r\n            /* [out] */ unsigned char *outBuffer,\r\n            /* [out] */ unsigned int *outDataSize,\r\n            /* [in] */ unsigned int outBufferSize,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Play)\r\n        HRESULT ( STDMETHODCALLTYPE *Play )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Stop)\r\n        HRESULT ( STDMETHODCALLTYPE *Stop )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, TogglePlayStop)\r\n        HRESULT ( STDMETHODCALLTYPE *TogglePlayStop )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Eject)\r\n        HRESULT ( STDMETHODCALLTYPE *Eject )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GoToTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GoToTimecode )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BMDTimecodeBCD timecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, FastForward)\r\n        HRESULT ( STDMETHODCALLTYPE *FastForward )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Rewind)\r\n        HRESULT ( STDMETHODCALLTYPE *Rewind )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, StepForward)\r\n        HRESULT ( STDMETHODCALLTYPE *StepForward )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, StepBack)\r\n        HRESULT ( STDMETHODCALLTYPE *StepBack )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Jog)\r\n        HRESULT ( STDMETHODCALLTYPE *Jog )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Shuttle)\r\n        HRESULT ( STDMETHODCALLTYPE *Shuttle )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetTimecodeString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeString )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BSTR *currentTimeCode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ IDeckLinkTimecode **currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetTimecodeBCD)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeBCD )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDTimecodeBCD *currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, SetPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *SetPreroll )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ unsigned int prerollSeconds);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPreroll )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ unsigned int *prerollSeconds);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, SetExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *SetExportOffset )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ int exportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetExportOffset )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ int *exportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetManualExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetManualExportOffset )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ int *deckManualExportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, SetCaptureOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCaptureOffset )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ int captureOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetCaptureOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCaptureOffset )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ int *captureOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, StartExport)\r\n        HRESULT ( STDMETHODCALLTYPE *StartExport )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, StartCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *StartCapture )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ BOOL useVITC,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, GetDeviceID)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDeviceID )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ unsigned short *deviceId,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, Abort)\r\n        HRESULT ( STDMETHODCALLTYPE *Abort )( \r\n            IDeckLinkDeckControl * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, CrashRecordStart)\r\n        HRESULT ( STDMETHODCALLTYPE *CrashRecordStart )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, CrashRecordStop)\r\n        HRESULT ( STDMETHODCALLTYPE *CrashRecordStop )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkDeckControl * This,\r\n            /* [in] */ IDeckLinkDeckControlStatusCallback *callback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDeckControlVtbl;\r\n\r\n    interface IDeckLinkDeckControl\r\n    {\r\n        CONST_VTBL struct IDeckLinkDeckControlVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDeckControl_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDeckControl_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDeckControl_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDeckControl_Open(This,timeScale,timeValue,timecodeIsDropFrame,error)\t\\\r\n    ( (This)->lpVtbl -> Open(This,timeScale,timeValue,timecodeIsDropFrame,error) ) \r\n\r\n#define IDeckLinkDeckControl_Close(This,standbyOn)\t\\\r\n    ( (This)->lpVtbl -> Close(This,standbyOn) ) \r\n\r\n#define IDeckLinkDeckControl_GetCurrentState(This,mode,vtrControlState,flags)\t\\\r\n    ( (This)->lpVtbl -> GetCurrentState(This,mode,vtrControlState,flags) ) \r\n\r\n#define IDeckLinkDeckControl_SetStandby(This,standbyOn)\t\\\r\n    ( (This)->lpVtbl -> SetStandby(This,standbyOn) ) \r\n\r\n#define IDeckLinkDeckControl_SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error)\t\\\r\n    ( (This)->lpVtbl -> SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error) ) \r\n\r\n#define IDeckLinkDeckControl_Play(This,error)\t\\\r\n    ( (This)->lpVtbl -> Play(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_Stop(This,error)\t\\\r\n    ( (This)->lpVtbl -> Stop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_TogglePlayStop(This,error)\t\\\r\n    ( (This)->lpVtbl -> TogglePlayStop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_Eject(This,error)\t\\\r\n    ( (This)->lpVtbl -> Eject(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_GoToTimecode(This,timecode,error)\t\\\r\n    ( (This)->lpVtbl -> GoToTimecode(This,timecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_FastForward(This,viewTape,error)\t\\\r\n    ( (This)->lpVtbl -> FastForward(This,viewTape,error) ) \r\n\r\n#define IDeckLinkDeckControl_Rewind(This,viewTape,error)\t\\\r\n    ( (This)->lpVtbl -> Rewind(This,viewTape,error) ) \r\n\r\n#define IDeckLinkDeckControl_StepForward(This,error)\t\\\r\n    ( (This)->lpVtbl -> StepForward(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_StepBack(This,error)\t\\\r\n    ( (This)->lpVtbl -> StepBack(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_Jog(This,rate,error)\t\\\r\n    ( (This)->lpVtbl -> Jog(This,rate,error) ) \r\n\r\n#define IDeckLinkDeckControl_Shuttle(This,rate,error)\t\\\r\n    ( (This)->lpVtbl -> Shuttle(This,rate,error) ) \r\n\r\n#define IDeckLinkDeckControl_GetTimecodeString(This,currentTimeCode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeString(This,currentTimeCode,error) ) \r\n\r\n#define IDeckLinkDeckControl_GetTimecode(This,currentTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,currentTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_GetTimecodeBCD(This,currentTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeBCD(This,currentTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_SetPreroll(This,prerollSeconds)\t\\\r\n    ( (This)->lpVtbl -> SetPreroll(This,prerollSeconds) ) \r\n\r\n#define IDeckLinkDeckControl_GetPreroll(This,prerollSeconds)\t\\\r\n    ( (This)->lpVtbl -> GetPreroll(This,prerollSeconds) ) \r\n\r\n#define IDeckLinkDeckControl_SetExportOffset(This,exportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> SetExportOffset(This,exportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_GetExportOffset(This,exportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetExportOffset(This,exportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_GetManualExportOffset(This,deckManualExportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetManualExportOffset(This,deckManualExportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_SetCaptureOffset(This,captureOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> SetCaptureOffset(This,captureOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_GetCaptureOffset(This,captureOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetCaptureOffset(This,captureOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_StartExport(This,inTimecode,outTimecode,exportModeOps,error)\t\\\r\n    ( (This)->lpVtbl -> StartExport(This,inTimecode,outTimecode,exportModeOps,error) ) \r\n\r\n#define IDeckLinkDeckControl_StartCapture(This,useVITC,inTimecode,outTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> StartCapture(This,useVITC,inTimecode,outTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_GetDeviceID(This,deviceId,error)\t\\\r\n    ( (This)->lpVtbl -> GetDeviceID(This,deviceId,error) ) \r\n\r\n#define IDeckLinkDeckControl_Abort(This)\t\\\r\n    ( (This)->lpVtbl -> Abort(This) ) \r\n\r\n#define IDeckLinkDeckControl_CrashRecordStart(This,error)\t\\\r\n    ( (This)->lpVtbl -> CrashRecordStart(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_CrashRecordStop(This,error)\t\\\r\n    ( (This)->lpVtbl -> CrashRecordStop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_SetCallback(This,callback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,callback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDeckControl_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingDeviceNotificationCallback_INTERFACE_DEFINED__\r\n#define __IBMDStreamingDeviceNotificationCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingDeviceNotificationCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingDeviceNotificationCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"F9531D64-3305-4B29-A387-7F74BB0D0E84\")\r\n    IBMDStreamingDeviceNotificationCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE StreamingDeviceArrived( \r\n            /* [in] */ IDeckLink *device) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StreamingDeviceRemoved( \r\n            /* [in] */ IDeckLink *device) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StreamingDeviceModeChanged( \r\n            /* [in] */ IDeckLink *device,\r\n            /* [in] */ BMDStreamingDeviceMode mode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingDeviceNotificationCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingDeviceNotificationCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingDeviceNotificationCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingDeviceNotificationCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceNotificationCallback, StreamingDeviceArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *StreamingDeviceArrived )( \r\n            IBMDStreamingDeviceNotificationCallback * This,\r\n            /* [in] */ IDeckLink *device);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceNotificationCallback, StreamingDeviceRemoved)\r\n        HRESULT ( STDMETHODCALLTYPE *StreamingDeviceRemoved )( \r\n            IBMDStreamingDeviceNotificationCallback * This,\r\n            /* [in] */ IDeckLink *device);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceNotificationCallback, StreamingDeviceModeChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *StreamingDeviceModeChanged )( \r\n            IBMDStreamingDeviceNotificationCallback * This,\r\n            /* [in] */ IDeckLink *device,\r\n            /* [in] */ BMDStreamingDeviceMode mode);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingDeviceNotificationCallbackVtbl;\r\n\r\n    interface IBMDStreamingDeviceNotificationCallback\r\n    {\r\n        CONST_VTBL struct IBMDStreamingDeviceNotificationCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingDeviceNotificationCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingDeviceNotificationCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingDeviceNotificationCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingDeviceNotificationCallback_StreamingDeviceArrived(This,device)\t\\\r\n    ( (This)->lpVtbl -> StreamingDeviceArrived(This,device) ) \r\n\r\n#define IBMDStreamingDeviceNotificationCallback_StreamingDeviceRemoved(This,device)\t\\\r\n    ( (This)->lpVtbl -> StreamingDeviceRemoved(This,device) ) \r\n\r\n#define IBMDStreamingDeviceNotificationCallback_StreamingDeviceModeChanged(This,device,mode)\t\\\r\n    ( (This)->lpVtbl -> StreamingDeviceModeChanged(This,device,mode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingDeviceNotificationCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingH264InputCallback_INTERFACE_DEFINED__\r\n#define __IBMDStreamingH264InputCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingH264InputCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingH264InputCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"823C475F-55AE-46F9-890C-537CC5CEDCCA\")\r\n    IBMDStreamingH264InputCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE H264NALPacketArrived( \r\n            /* [in] */ IBMDStreamingH264NALPacket *nalPacket) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE H264AudioPacketArrived( \r\n            /* [in] */ IBMDStreamingAudioPacket *audioPacket) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE MPEG2TSPacketArrived( \r\n            /* [in] */ IBMDStreamingMPEG2TSPacket *tsPacket) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE H264VideoInputConnectorScanningChanged( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE H264VideoInputConnectorChanged( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE H264VideoInputModeChanged( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingH264InputCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingH264InputCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingH264InputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingH264InputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264InputCallback, H264NALPacketArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *H264NALPacketArrived )( \r\n            IBMDStreamingH264InputCallback * This,\r\n            /* [in] */ IBMDStreamingH264NALPacket *nalPacket);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264InputCallback, H264AudioPacketArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *H264AudioPacketArrived )( \r\n            IBMDStreamingH264InputCallback * This,\r\n            /* [in] */ IBMDStreamingAudioPacket *audioPacket);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264InputCallback, MPEG2TSPacketArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *MPEG2TSPacketArrived )( \r\n            IBMDStreamingH264InputCallback * This,\r\n            /* [in] */ IBMDStreamingMPEG2TSPacket *tsPacket);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264InputCallback, H264VideoInputConnectorScanningChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *H264VideoInputConnectorScanningChanged )( \r\n            IBMDStreamingH264InputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264InputCallback, H264VideoInputConnectorChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *H264VideoInputConnectorChanged )( \r\n            IBMDStreamingH264InputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264InputCallback, H264VideoInputModeChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *H264VideoInputModeChanged )( \r\n            IBMDStreamingH264InputCallback * This);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingH264InputCallbackVtbl;\r\n\r\n    interface IBMDStreamingH264InputCallback\r\n    {\r\n        CONST_VTBL struct IBMDStreamingH264InputCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingH264InputCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingH264InputCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingH264InputCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingH264InputCallback_H264NALPacketArrived(This,nalPacket)\t\\\r\n    ( (This)->lpVtbl -> H264NALPacketArrived(This,nalPacket) ) \r\n\r\n#define IBMDStreamingH264InputCallback_H264AudioPacketArrived(This,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> H264AudioPacketArrived(This,audioPacket) ) \r\n\r\n#define IBMDStreamingH264InputCallback_MPEG2TSPacketArrived(This,tsPacket)\t\\\r\n    ( (This)->lpVtbl -> MPEG2TSPacketArrived(This,tsPacket) ) \r\n\r\n#define IBMDStreamingH264InputCallback_H264VideoInputConnectorScanningChanged(This)\t\\\r\n    ( (This)->lpVtbl -> H264VideoInputConnectorScanningChanged(This) ) \r\n\r\n#define IBMDStreamingH264InputCallback_H264VideoInputConnectorChanged(This)\t\\\r\n    ( (This)->lpVtbl -> H264VideoInputConnectorChanged(This) ) \r\n\r\n#define IBMDStreamingH264InputCallback_H264VideoInputModeChanged(This)\t\\\r\n    ( (This)->lpVtbl -> H264VideoInputModeChanged(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingH264InputCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingDiscovery_INTERFACE_DEFINED__\r\n#define __IBMDStreamingDiscovery_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingDiscovery */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingDiscovery;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"2C837444-F989-4D87-901A-47C8A36D096D\")\r\n    IBMDStreamingDiscovery : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE InstallDeviceNotifications( \r\n            /* [in] */ IBMDStreamingDeviceNotificationCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE UninstallDeviceNotifications( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingDiscoveryVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingDiscovery * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingDiscovery * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingDiscovery * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDiscovery, InstallDeviceNotifications)\r\n        HRESULT ( STDMETHODCALLTYPE *InstallDeviceNotifications )( \r\n            IBMDStreamingDiscovery * This,\r\n            /* [in] */ IBMDStreamingDeviceNotificationCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDiscovery, UninstallDeviceNotifications)\r\n        HRESULT ( STDMETHODCALLTYPE *UninstallDeviceNotifications )( \r\n            IBMDStreamingDiscovery * This);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingDiscoveryVtbl;\r\n\r\n    interface IBMDStreamingDiscovery\r\n    {\r\n        CONST_VTBL struct IBMDStreamingDiscoveryVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingDiscovery_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingDiscovery_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingDiscovery_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingDiscovery_InstallDeviceNotifications(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> InstallDeviceNotifications(This,theCallback) ) \r\n\r\n#define IBMDStreamingDiscovery_UninstallDeviceNotifications(This)\t\\\r\n    ( (This)->lpVtbl -> UninstallDeviceNotifications(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingDiscovery_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingVideoEncodingMode_INTERFACE_DEFINED__\r\n#define __IBMDStreamingVideoEncodingMode_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingVideoEncodingMode */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingVideoEncodingMode;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"1AB8035B-CD13-458D-B6DF-5E8F7C2141D9\")\r\n    IBMDStreamingVideoEncodingMode : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetName( \r\n            /* [out] */ BSTR *name) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetPresetID( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetSourcePositionX( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetSourcePositionY( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetSourceWidth( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetSourceHeight( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetDestWidth( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetDestHeight( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateMutableVideoEncodingMode( \r\n            /* [out] */ IBMDStreamingMutableVideoEncodingMode **newEncodingMode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingVideoEncodingModeVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetName )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [out] */ BSTR *name);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetPresetID)\r\n        unsigned int ( STDMETHODCALLTYPE *GetPresetID )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourcePositionX)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourcePositionX )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourcePositionY)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourcePositionY )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourceWidth)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourceWidth )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourceHeight)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourceHeight )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetDestWidth)\r\n        unsigned int ( STDMETHODCALLTYPE *GetDestWidth )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetDestHeight)\r\n        unsigned int ( STDMETHODCALLTYPE *GetDestHeight )( \r\n            IBMDStreamingVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, CreateMutableVideoEncodingMode)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateMutableVideoEncodingMode )( \r\n            IBMDStreamingVideoEncodingMode * This,\r\n            /* [out] */ IBMDStreamingMutableVideoEncodingMode **newEncodingMode);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingVideoEncodingModeVtbl;\r\n\r\n    interface IBMDStreamingVideoEncodingMode\r\n    {\r\n        CONST_VTBL struct IBMDStreamingVideoEncodingModeVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingVideoEncodingMode_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingVideoEncodingMode_GetName(This,name)\t\\\r\n    ( (This)->lpVtbl -> GetName(This,name) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetPresetID(This)\t\\\r\n    ( (This)->lpVtbl -> GetPresetID(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetSourcePositionX(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourcePositionX(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetSourcePositionY(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourcePositionY(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetSourceWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourceWidth(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetSourceHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourceHeight(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetDestWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetDestWidth(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetDestHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetDestHeight(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingVideoEncodingMode_CreateMutableVideoEncodingMode(This,newEncodingMode)\t\\\r\n    ( (This)->lpVtbl -> CreateMutableVideoEncodingMode(This,newEncodingMode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingVideoEncodingMode_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingMutableVideoEncodingMode_INTERFACE_DEFINED__\r\n#define __IBMDStreamingMutableVideoEncodingMode_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingMutableVideoEncodingMode */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingMutableVideoEncodingMode;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"19BF7D90-1E0A-400D-B2C6-FFC4E78AD49D\")\r\n    IBMDStreamingMutableVideoEncodingMode : public IBMDStreamingVideoEncodingMode\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetSourceRect( \r\n            /* [in] */ unsigned int posX,\r\n            /* [in] */ unsigned int posY,\r\n            /* [in] */ unsigned int width,\r\n            /* [in] */ unsigned int height) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetDestSize( \r\n            /* [in] */ unsigned int width,\r\n            /* [in] */ unsigned int height) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingMutableVideoEncodingModeVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetName )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [out] */ BSTR *name);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetPresetID)\r\n        unsigned int ( STDMETHODCALLTYPE *GetPresetID )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourcePositionX)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourcePositionX )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourcePositionY)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourcePositionY )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourceWidth)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourceWidth )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetSourceHeight)\r\n        unsigned int ( STDMETHODCALLTYPE *GetSourceHeight )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetDestWidth)\r\n        unsigned int ( STDMETHODCALLTYPE *GetDestWidth )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetDestHeight)\r\n        unsigned int ( STDMETHODCALLTYPE *GetDestHeight )( \r\n            IBMDStreamingMutableVideoEncodingMode * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingMode, CreateMutableVideoEncodingMode)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateMutableVideoEncodingMode )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [out] */ IBMDStreamingMutableVideoEncodingMode **newEncodingMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMutableVideoEncodingMode, SetSourceRect)\r\n        HRESULT ( STDMETHODCALLTYPE *SetSourceRect )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ unsigned int posX,\r\n            /* [in] */ unsigned int posY,\r\n            /* [in] */ unsigned int width,\r\n            /* [in] */ unsigned int height);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMutableVideoEncodingMode, SetDestSize)\r\n        HRESULT ( STDMETHODCALLTYPE *SetDestSize )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ unsigned int width,\r\n            /* [in] */ unsigned int height);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMutableVideoEncodingMode, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMutableVideoEncodingMode, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMutableVideoEncodingMode, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMutableVideoEncodingMode, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IBMDStreamingMutableVideoEncodingMode * This,\r\n            /* [in] */ BMDStreamingEncodingModePropertyID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingMutableVideoEncodingModeVtbl;\r\n\r\n    interface IBMDStreamingMutableVideoEncodingMode\r\n    {\r\n        CONST_VTBL struct IBMDStreamingMutableVideoEncodingModeVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetName(This,name)\t\\\r\n    ( (This)->lpVtbl -> GetName(This,name) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetPresetID(This)\t\\\r\n    ( (This)->lpVtbl -> GetPresetID(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetSourcePositionX(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourcePositionX(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetSourcePositionY(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourcePositionY(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetSourceWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourceWidth(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetSourceHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetSourceHeight(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetDestWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetDestWidth(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetDestHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetDestHeight(This) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_CreateMutableVideoEncodingMode(This,newEncodingMode)\t\\\r\n    ( (This)->lpVtbl -> CreateMutableVideoEncodingMode(This,newEncodingMode) ) \r\n\r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_SetSourceRect(This,posX,posY,width,height)\t\\\r\n    ( (This)->lpVtbl -> SetSourceRect(This,posX,posY,width,height) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_SetDestSize(This,width,height)\t\\\r\n    ( (This)->lpVtbl -> SetDestSize(This,width,height) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IBMDStreamingMutableVideoEncodingMode_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingMutableVideoEncodingMode_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingVideoEncodingModePresetIterator_INTERFACE_DEFINED__\r\n#define __IBMDStreamingVideoEncodingModePresetIterator_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingVideoEncodingModePresetIterator */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingVideoEncodingModePresetIterator;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"7AC731A3-C950-4AD0-804A-8377AA51C6C4\")\r\n    IBMDStreamingVideoEncodingModePresetIterator : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IBMDStreamingVideoEncodingMode **videoEncodingMode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingVideoEncodingModePresetIteratorVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingVideoEncodingModePresetIterator * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingVideoEncodingModePresetIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingVideoEncodingModePresetIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingVideoEncodingModePresetIterator, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IBMDStreamingVideoEncodingModePresetIterator * This,\r\n            /* [out] */ IBMDStreamingVideoEncodingMode **videoEncodingMode);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingVideoEncodingModePresetIteratorVtbl;\r\n\r\n    interface IBMDStreamingVideoEncodingModePresetIterator\r\n    {\r\n        CONST_VTBL struct IBMDStreamingVideoEncodingModePresetIteratorVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingVideoEncodingModePresetIterator_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingVideoEncodingModePresetIterator_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingVideoEncodingModePresetIterator_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingVideoEncodingModePresetIterator_Next(This,videoEncodingMode)\t\\\r\n    ( (This)->lpVtbl -> Next(This,videoEncodingMode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingVideoEncodingModePresetIterator_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingDeviceInput_INTERFACE_DEFINED__\r\n#define __IBMDStreamingDeviceInput_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingDeviceInput */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingDeviceInput;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"24B6B6EC-1727-44BB-9818-34FF086ACF98\")\r\n    IBMDStreamingDeviceInput : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoInputMode( \r\n            /* [in] */ BMDDisplayMode inputMode,\r\n            /* [out] */ BOOL *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVideoInputModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputMode( \r\n            /* [in] */ BMDDisplayMode inputMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCurrentDetectedVideoInputMode( \r\n            /* [out] */ BMDDisplayMode *detectedMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVideoEncodingMode( \r\n            /* [out] */ IBMDStreamingVideoEncodingMode **encodingMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVideoEncodingModePresetIterator( \r\n            /* [in] */ BMDDisplayMode inputMode,\r\n            /* [out] */ IBMDStreamingVideoEncodingModePresetIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoEncodingMode( \r\n            /* [in] */ BMDDisplayMode inputMode,\r\n            /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode,\r\n            /* [out] */ BMDStreamingEncodingSupport *result,\r\n            /* [out] */ IBMDStreamingVideoEncodingMode **changedEncodingMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoEncodingMode( \r\n            /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartCapture( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopCapture( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IUnknown *theCallback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingDeviceInputVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingDeviceInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingDeviceInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, DoesSupportVideoInputMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoInputMode )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ BMDDisplayMode inputMode,\r\n            /* [out] */ BOOL *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, GetVideoInputModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVideoInputModeIterator )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, SetVideoInputMode)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputMode )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ BMDDisplayMode inputMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, GetCurrentDetectedVideoInputMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCurrentDetectedVideoInputMode )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [out] */ BMDDisplayMode *detectedMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, GetVideoEncodingMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVideoEncodingMode )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [out] */ IBMDStreamingVideoEncodingMode **encodingMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, GetVideoEncodingModePresetIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVideoEncodingModePresetIterator )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ BMDDisplayMode inputMode,\r\n            /* [out] */ IBMDStreamingVideoEncodingModePresetIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, DoesSupportVideoEncodingMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoEncodingMode )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ BMDDisplayMode inputMode,\r\n            /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode,\r\n            /* [out] */ BMDStreamingEncodingSupport *result,\r\n            /* [out] */ IBMDStreamingVideoEncodingMode **changedEncodingMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, SetVideoEncodingMode)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoEncodingMode )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ IBMDStreamingVideoEncodingMode *encodingMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, StartCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *StartCapture )( \r\n            IBMDStreamingDeviceInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, StopCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *StopCapture )( \r\n            IBMDStreamingDeviceInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingDeviceInput, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IBMDStreamingDeviceInput * This,\r\n            /* [in] */ IUnknown *theCallback);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingDeviceInputVtbl;\r\n\r\n    interface IBMDStreamingDeviceInput\r\n    {\r\n        CONST_VTBL struct IBMDStreamingDeviceInputVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingDeviceInput_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingDeviceInput_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingDeviceInput_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingDeviceInput_DoesSupportVideoInputMode(This,inputMode,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoInputMode(This,inputMode,result) ) \r\n\r\n#define IBMDStreamingDeviceInput_GetVideoInputModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetVideoInputModeIterator(This,iterator) ) \r\n\r\n#define IBMDStreamingDeviceInput_SetVideoInputMode(This,inputMode)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputMode(This,inputMode) ) \r\n\r\n#define IBMDStreamingDeviceInput_GetCurrentDetectedVideoInputMode(This,detectedMode)\t\\\r\n    ( (This)->lpVtbl -> GetCurrentDetectedVideoInputMode(This,detectedMode) ) \r\n\r\n#define IBMDStreamingDeviceInput_GetVideoEncodingMode(This,encodingMode)\t\\\r\n    ( (This)->lpVtbl -> GetVideoEncodingMode(This,encodingMode) ) \r\n\r\n#define IBMDStreamingDeviceInput_GetVideoEncodingModePresetIterator(This,inputMode,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetVideoEncodingModePresetIterator(This,inputMode,iterator) ) \r\n\r\n#define IBMDStreamingDeviceInput_DoesSupportVideoEncodingMode(This,inputMode,encodingMode,result,changedEncodingMode)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoEncodingMode(This,inputMode,encodingMode,result,changedEncodingMode) ) \r\n\r\n#define IBMDStreamingDeviceInput_SetVideoEncodingMode(This,encodingMode)\t\\\r\n    ( (This)->lpVtbl -> SetVideoEncodingMode(This,encodingMode) ) \r\n\r\n#define IBMDStreamingDeviceInput_StartCapture(This)\t\\\r\n    ( (This)->lpVtbl -> StartCapture(This) ) \r\n\r\n#define IBMDStreamingDeviceInput_StopCapture(This)\t\\\r\n    ( (This)->lpVtbl -> StopCapture(This) ) \r\n\r\n#define IBMDStreamingDeviceInput_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingDeviceInput_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingH264NALPacket_INTERFACE_DEFINED__\r\n#define __IBMDStreamingH264NALPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingH264NALPacket */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingH264NALPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"E260E955-14BE-4395-9775-9F02CC0A9D89\")\r\n    IBMDStreamingH264NALPacket : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetPayloadSize( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytesWithSizePrefix( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayTime( \r\n            /* [in] */ ULONGLONG requestedTimeScale,\r\n            /* [out] */ ULONGLONG *displayTime) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPacketIndex( \r\n            /* [out] */ unsigned int *packetIndex) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingH264NALPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingH264NALPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingH264NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingH264NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALPacket, GetPayloadSize)\r\n        long ( STDMETHODCALLTYPE *GetPayloadSize )( \r\n            IBMDStreamingH264NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IBMDStreamingH264NALPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALPacket, GetBytesWithSizePrefix)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytesWithSizePrefix )( \r\n            IBMDStreamingH264NALPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALPacket, GetDisplayTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayTime )( \r\n            IBMDStreamingH264NALPacket * This,\r\n            /* [in] */ ULONGLONG requestedTimeScale,\r\n            /* [out] */ ULONGLONG *displayTime);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALPacket, GetPacketIndex)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPacketIndex )( \r\n            IBMDStreamingH264NALPacket * This,\r\n            /* [out] */ unsigned int *packetIndex);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingH264NALPacketVtbl;\r\n\r\n    interface IBMDStreamingH264NALPacket\r\n    {\r\n        CONST_VTBL struct IBMDStreamingH264NALPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingH264NALPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingH264NALPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingH264NALPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingH264NALPacket_GetPayloadSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetPayloadSize(This) ) \r\n\r\n#define IBMDStreamingH264NALPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IBMDStreamingH264NALPacket_GetBytesWithSizePrefix(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytesWithSizePrefix(This,buffer) ) \r\n\r\n#define IBMDStreamingH264NALPacket_GetDisplayTime(This,requestedTimeScale,displayTime)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayTime(This,requestedTimeScale,displayTime) ) \r\n\r\n#define IBMDStreamingH264NALPacket_GetPacketIndex(This,packetIndex)\t\\\r\n    ( (This)->lpVtbl -> GetPacketIndex(This,packetIndex) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingH264NALPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingAudioPacket_INTERFACE_DEFINED__\r\n#define __IBMDStreamingAudioPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingAudioPacket */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingAudioPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"D9EB5902-1AD2-43F4-9E2C-3CFA50B5EE19\")\r\n    IBMDStreamingAudioPacket : public IUnknown\r\n    {\r\n    public:\r\n        virtual BMDStreamingAudioCodec STDMETHODCALLTYPE GetCodec( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetPayloadSize( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPlayTime( \r\n            /* [in] */ ULONGLONG requestedTimeScale,\r\n            /* [out] */ ULONGLONG *playTime) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPacketIndex( \r\n            /* [out] */ unsigned int *packetIndex) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingAudioPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingAudioPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingAudioPacket, GetCodec)\r\n        BMDStreamingAudioCodec ( STDMETHODCALLTYPE *GetCodec )( \r\n            IBMDStreamingAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingAudioPacket, GetPayloadSize)\r\n        long ( STDMETHODCALLTYPE *GetPayloadSize )( \r\n            IBMDStreamingAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingAudioPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IBMDStreamingAudioPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingAudioPacket, GetPlayTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPlayTime )( \r\n            IBMDStreamingAudioPacket * This,\r\n            /* [in] */ ULONGLONG requestedTimeScale,\r\n            /* [out] */ ULONGLONG *playTime);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingAudioPacket, GetPacketIndex)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPacketIndex )( \r\n            IBMDStreamingAudioPacket * This,\r\n            /* [out] */ unsigned int *packetIndex);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingAudioPacketVtbl;\r\n\r\n    interface IBMDStreamingAudioPacket\r\n    {\r\n        CONST_VTBL struct IBMDStreamingAudioPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingAudioPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingAudioPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingAudioPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingAudioPacket_GetCodec(This)\t\\\r\n    ( (This)->lpVtbl -> GetCodec(This) ) \r\n\r\n#define IBMDStreamingAudioPacket_GetPayloadSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetPayloadSize(This) ) \r\n\r\n#define IBMDStreamingAudioPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IBMDStreamingAudioPacket_GetPlayTime(This,requestedTimeScale,playTime)\t\\\r\n    ( (This)->lpVtbl -> GetPlayTime(This,requestedTimeScale,playTime) ) \r\n\r\n#define IBMDStreamingAudioPacket_GetPacketIndex(This,packetIndex)\t\\\r\n    ( (This)->lpVtbl -> GetPacketIndex(This,packetIndex) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingAudioPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingMPEG2TSPacket_INTERFACE_DEFINED__\r\n#define __IBMDStreamingMPEG2TSPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingMPEG2TSPacket */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingMPEG2TSPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"91810D1C-4FB3-4AAA-AE56-FA301D3DFA4C\")\r\n    IBMDStreamingMPEG2TSPacket : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetPayloadSize( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingMPEG2TSPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingMPEG2TSPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingMPEG2TSPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingMPEG2TSPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMPEG2TSPacket, GetPayloadSize)\r\n        long ( STDMETHODCALLTYPE *GetPayloadSize )( \r\n            IBMDStreamingMPEG2TSPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingMPEG2TSPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IBMDStreamingMPEG2TSPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingMPEG2TSPacketVtbl;\r\n\r\n    interface IBMDStreamingMPEG2TSPacket\r\n    {\r\n        CONST_VTBL struct IBMDStreamingMPEG2TSPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingMPEG2TSPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingMPEG2TSPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingMPEG2TSPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingMPEG2TSPacket_GetPayloadSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetPayloadSize(This) ) \r\n\r\n#define IBMDStreamingMPEG2TSPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingMPEG2TSPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IBMDStreamingH264NALParser_INTERFACE_DEFINED__\r\n#define __IBMDStreamingH264NALParser_INTERFACE_DEFINED__\r\n\r\n/* interface IBMDStreamingH264NALParser */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IBMDStreamingH264NALParser;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"5867F18C-5BFA-4CCC-B2A7-9DFD140417D2\")\r\n    IBMDStreamingH264NALParser : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE IsNALSequenceParameterSet( \r\n            /* [in] */ IBMDStreamingH264NALPacket *nal) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsNALPictureParameterSet( \r\n            /* [in] */ IBMDStreamingH264NALPacket *nal) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetProfileAndLevelFromSPS( \r\n            /* [in] */ IBMDStreamingH264NALPacket *nal,\r\n            /* [out] */ unsigned int *profileIdc,\r\n            /* [out] */ unsigned int *profileCompatability,\r\n            /* [out] */ unsigned int *levelIdc) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IBMDStreamingH264NALParserVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IBMDStreamingH264NALParser * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IBMDStreamingH264NALParser * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IBMDStreamingH264NALParser * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALParser, IsNALSequenceParameterSet)\r\n        HRESULT ( STDMETHODCALLTYPE *IsNALSequenceParameterSet )( \r\n            IBMDStreamingH264NALParser * This,\r\n            /* [in] */ IBMDStreamingH264NALPacket *nal);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALParser, IsNALPictureParameterSet)\r\n        HRESULT ( STDMETHODCALLTYPE *IsNALPictureParameterSet )( \r\n            IBMDStreamingH264NALParser * This,\r\n            /* [in] */ IBMDStreamingH264NALPacket *nal);\r\n        \r\n        DECLSPEC_XFGVIRT(IBMDStreamingH264NALParser, GetProfileAndLevelFromSPS)\r\n        HRESULT ( STDMETHODCALLTYPE *GetProfileAndLevelFromSPS )( \r\n            IBMDStreamingH264NALParser * This,\r\n            /* [in] */ IBMDStreamingH264NALPacket *nal,\r\n            /* [out] */ unsigned int *profileIdc,\r\n            /* [out] */ unsigned int *profileCompatability,\r\n            /* [out] */ unsigned int *levelIdc);\r\n        \r\n        END_INTERFACE\r\n    } IBMDStreamingH264NALParserVtbl;\r\n\r\n    interface IBMDStreamingH264NALParser\r\n    {\r\n        CONST_VTBL struct IBMDStreamingH264NALParserVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IBMDStreamingH264NALParser_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IBMDStreamingH264NALParser_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IBMDStreamingH264NALParser_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IBMDStreamingH264NALParser_IsNALSequenceParameterSet(This,nal)\t\\\r\n    ( (This)->lpVtbl -> IsNALSequenceParameterSet(This,nal) ) \r\n\r\n#define IBMDStreamingH264NALParser_IsNALPictureParameterSet(This,nal)\t\\\r\n    ( (This)->lpVtbl -> IsNALPictureParameterSet(This,nal) ) \r\n\r\n#define IBMDStreamingH264NALParser_GetProfileAndLevelFromSPS(This,nal,profileIdc,profileCompatability,levelIdc)\t\\\r\n    ( (This)->lpVtbl -> GetProfileAndLevelFromSPS(This,nal,profileIdc,profileCompatability,levelIdc) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IBMDStreamingH264NALParser_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CBMDStreamingDiscovery;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"23A4EDF5-A0E5-432C-94EF-3BABB5F81C82\")\r\nCBMDStreamingDiscovery;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CBMDStreamingH264NALParser;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"7753EFBD-951C-407C-97A5-23C737B73B52\")\r\nCBMDStreamingH264NALParser;\r\n#endif\r\n\r\n#ifndef __IDeckLinkVideoOutputCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoOutputCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoOutputCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoOutputCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"20AA5225-1958-47CB-820B-80A8D521A6EE\")\r\n    IDeckLinkVideoOutputCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted( \r\n            /* [in] */ IDeckLinkVideoFrame *completedFrame,\r\n            /* [in] */ BMDOutputFrameCompletionResult result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoOutputCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoOutputCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoOutputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoOutputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoOutputCallback, ScheduledFrameCompleted)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduledFrameCompleted )( \r\n            IDeckLinkVideoOutputCallback * This,\r\n            /* [in] */ IDeckLinkVideoFrame *completedFrame,\r\n            /* [in] */ BMDOutputFrameCompletionResult result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoOutputCallback, ScheduledPlaybackHasStopped)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduledPlaybackHasStopped )( \r\n            IDeckLinkVideoOutputCallback * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoOutputCallbackVtbl;\r\n\r\n    interface IDeckLinkVideoOutputCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoOutputCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoOutputCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoOutputCallback_ScheduledFrameCompleted(This,completedFrame,result)\t\\\r\n    ( (This)->lpVtbl -> ScheduledFrameCompleted(This,completedFrame,result) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_ScheduledPlaybackHasStopped(This)\t\\\r\n    ( (This)->lpVtbl -> ScheduledPlaybackHasStopped(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoOutputCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkInputCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInputCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInputCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"C6FCE4C9-C4E4-4047-82FB-5D238232A902\")\r\n    IDeckLinkInputCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged( \r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived( \r\n            /* [in] */ IDeckLinkVideoInputFrame *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInputCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInputCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback, VideoInputFormatChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )( \r\n            IDeckLinkInputCallback * This,\r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback, VideoInputFrameArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )( \r\n            IDeckLinkInputCallback * This,\r\n            /* [in] */ IDeckLinkVideoInputFrame *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInputCallbackVtbl;\r\n\r\n    interface IDeckLinkInputCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkInputCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInputCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInputCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInputCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInputCallback_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) ) \r\n\r\n#define IDeckLinkInputCallback_VideoInputFrameArrived(This,videoFrame,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInputCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderInputCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderInputCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderInputCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderInputCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"ACF13E61-F4A0-4974-A6A7-59AFF6268B31\")\r\n    IDeckLinkEncoderInputCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputSignalChanged( \r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VideoPacketArrived( \r\n            /* [in] */ IDeckLinkEncoderVideoPacket *videoPacket) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE AudioPacketArrived( \r\n            /* [in] */ IDeckLinkEncoderAudioPacket *audioPacket) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderInputCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderInputCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderInputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderInputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInputCallback, VideoInputSignalChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputSignalChanged )( \r\n            IDeckLinkEncoderInputCallback * This,\r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInputCallback, VideoPacketArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoPacketArrived )( \r\n            IDeckLinkEncoderInputCallback * This,\r\n            /* [in] */ IDeckLinkEncoderVideoPacket *videoPacket);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInputCallback, AudioPacketArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *AudioPacketArrived )( \r\n            IDeckLinkEncoderInputCallback * This,\r\n            /* [in] */ IDeckLinkEncoderAudioPacket *audioPacket);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderInputCallbackVtbl;\r\n\r\n    interface IDeckLinkEncoderInputCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderInputCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderInputCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderInputCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderInputCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderInputCallback_VideoInputSignalChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags)\t\\\r\n    ( (This)->lpVtbl -> VideoInputSignalChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) ) \r\n\r\n#define IDeckLinkEncoderInputCallback_VideoPacketArrived(This,videoPacket)\t\\\r\n    ( (This)->lpVtbl -> VideoPacketArrived(This,videoPacket) ) \r\n\r\n#define IDeckLinkEncoderInputCallback_AudioPacketArrived(This,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> AudioPacketArrived(This,audioPacket) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderInputCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkMemoryAllocator_INTERFACE_DEFINED__\r\n#define __IDeckLinkMemoryAllocator_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkMemoryAllocator */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkMemoryAllocator;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"B36EB6E7-9D29-4AA8-92EF-843B87A289E8\")\r\n    IDeckLinkMemoryAllocator : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE AllocateBuffer( \r\n            /* [in] */ unsigned int bufferSize,\r\n            /* [out] */ void **allocatedBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ReleaseBuffer( \r\n            /* [in] */ void *buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Commit( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Decommit( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkMemoryAllocatorVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkMemoryAllocator * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkMemoryAllocator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkMemoryAllocator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMemoryAllocator, AllocateBuffer)\r\n        HRESULT ( STDMETHODCALLTYPE *AllocateBuffer )( \r\n            IDeckLinkMemoryAllocator * This,\r\n            /* [in] */ unsigned int bufferSize,\r\n            /* [out] */ void **allocatedBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMemoryAllocator, ReleaseBuffer)\r\n        HRESULT ( STDMETHODCALLTYPE *ReleaseBuffer )( \r\n            IDeckLinkMemoryAllocator * This,\r\n            /* [in] */ void *buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMemoryAllocator, Commit)\r\n        HRESULT ( STDMETHODCALLTYPE *Commit )( \r\n            IDeckLinkMemoryAllocator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMemoryAllocator, Decommit)\r\n        HRESULT ( STDMETHODCALLTYPE *Decommit )( \r\n            IDeckLinkMemoryAllocator * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkMemoryAllocatorVtbl;\r\n\r\n    interface IDeckLinkMemoryAllocator\r\n    {\r\n        CONST_VTBL struct IDeckLinkMemoryAllocatorVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkMemoryAllocator_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkMemoryAllocator_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkMemoryAllocator_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkMemoryAllocator_AllocateBuffer(This,bufferSize,allocatedBuffer)\t\\\r\n    ( (This)->lpVtbl -> AllocateBuffer(This,bufferSize,allocatedBuffer) ) \r\n\r\n#define IDeckLinkMemoryAllocator_ReleaseBuffer(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> ReleaseBuffer(This,buffer) ) \r\n\r\n#define IDeckLinkMemoryAllocator_Commit(This)\t\\\r\n    ( (This)->lpVtbl -> Commit(This) ) \r\n\r\n#define IDeckLinkMemoryAllocator_Decommit(This)\t\\\r\n    ( (This)->lpVtbl -> Decommit(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkMemoryAllocator_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAudioOutputCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkAudioOutputCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAudioOutputCallback */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAudioOutputCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"403C681B-7F46-4A12-B993-2BB127084EE6\")\r\n    IDeckLinkAudioOutputCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE RenderAudioSamples( \r\n            /* [in] */ BOOL preroll) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAudioOutputCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAudioOutputCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAudioOutputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAudioOutputCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioOutputCallback, RenderAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *RenderAudioSamples )( \r\n            IDeckLinkAudioOutputCallback * This,\r\n            /* [in] */ BOOL preroll);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAudioOutputCallbackVtbl;\r\n\r\n    interface IDeckLinkAudioOutputCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkAudioOutputCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAudioOutputCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAudioOutputCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAudioOutputCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAudioOutputCallback_RenderAudioSamples(This,preroll)\t\\\r\n    ( (This)->lpVtbl -> RenderAudioSamples(This,preroll) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAudioOutputCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkIterator_INTERFACE_DEFINED__\r\n#define __IDeckLinkIterator_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkIterator */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkIterator;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"50FB36CD-3063-4B73-BDBB-958087F2D8BA\")\r\n    IDeckLinkIterator : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLink **deckLinkInstance) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkIteratorVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkIterator * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkIterator, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkIterator * This,\r\n            /* [out] */ IDeckLink **deckLinkInstance);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkIteratorVtbl;\r\n\r\n    interface IDeckLinkIterator\r\n    {\r\n        CONST_VTBL struct IDeckLinkIteratorVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkIterator_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkIterator_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkIterator_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkIterator_Next(This,deckLinkInstance)\t\\\r\n    ( (This)->lpVtbl -> Next(This,deckLinkInstance) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkIterator_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAPIInformation_INTERFACE_DEFINED__\r\n#define __IDeckLinkAPIInformation_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAPIInformation */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAPIInformation;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"7BEA3C68-730D-4322-AF34-8A7152B532A4\")\r\n    IDeckLinkAPIInformation : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAPIInformationVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAPIInformation * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAPIInformation * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAPIInformation * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAPIInformation, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkAPIInformation * This,\r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAPIInformation, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkAPIInformation * This,\r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAPIInformation, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkAPIInformation * This,\r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAPIInformation, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkAPIInformation * This,\r\n            /* [in] */ BMDDeckLinkAPIInformationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAPIInformationVtbl;\r\n\r\n    interface IDeckLinkAPIInformation\r\n    {\r\n        CONST_VTBL struct IDeckLinkAPIInformationVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAPIInformation_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAPIInformation_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAPIInformation_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAPIInformation_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkAPIInformation_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkAPIInformation_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkAPIInformation_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAPIInformation_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"BE2D9020-461E-442F-84B7-E949CB953B9D\")\r\n    IDeckLinkOutput : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDVideoOutputConversionMode conversionMode,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData( \r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount( \r\n            /* [out] */ unsigned int *bufferedFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning( \r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetReferenceStatus( \r\n            /* [out] */ BMDReferenceStatus *referenceStatus) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameCompletionReferenceTimestamp( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *frameCompletionTimestamp) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutputVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDVideoOutputConversionMode conversionMode,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetDisplayMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, CreateAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetBufferedVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )( \r\n            IDeckLinkOutput * This,\r\n            /* [out] */ unsigned int *bufferedFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput * This,\r\n            /* [out] */ unsigned int *bufferedSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, IsScheduledPlaybackRunning)\r\n        HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )( \r\n            IDeckLinkOutput * This,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetScheduledStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetReferenceStatus)\r\n        HRESULT ( STDMETHODCALLTYPE *GetReferenceStatus )( \r\n            IDeckLinkOutput * This,\r\n            /* [out] */ BMDReferenceStatus *referenceStatus);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput, GetFrameCompletionReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameCompletionReferenceTimestamp )( \r\n            IDeckLinkOutput * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *frameCompletionTimestamp);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutputVtbl;\r\n\r\n    interface IDeckLinkOutput\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutputVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,conversionMode,flags,actualMode,supported)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,conversionMode,flags,actualMode,supported) ) \r\n\r\n#define IDeckLinkOutput_GetDisplayMode(This,displayMode,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This,displayMode,resultDisplayMode) ) \r\n\r\n#define IDeckLinkOutput_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkOutput_EnableVideoOutput(This,displayMode,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) ) \r\n\r\n#define IDeckLinkOutput_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_CreateAncillaryData(This,pixelFormat,outBuffer)\t\\\r\n    ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) ) \r\n\r\n#define IDeckLinkOutput_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_GetBufferedVideoFrameCount(This,bufferedFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) ) \r\n\r\n#define IDeckLinkOutput_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) ) \r\n\r\n#define IDeckLinkOutput_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) ) \r\n\r\n#define IDeckLinkOutput_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_IsScheduledPlaybackRunning(This,active)\t\\\r\n    ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) ) \r\n\r\n#define IDeckLinkOutput_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_GetReferenceStatus(This,referenceStatus)\t\\\r\n    ( (This)->lpVtbl -> GetReferenceStatus(This,referenceStatus) ) \r\n\r\n#define IDeckLinkOutput_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#define IDeckLinkOutput_GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp)\t\\\r\n    ( (This)->lpVtbl -> GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"C21CDB6E-F414-46E4-A636-80A566E0ED37\")\r\n    IDeckLinkInput : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDVideoInputConversionMode conversionMode,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInputVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDVideoInputConversionMode conversionMode,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, GetDisplayMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, SetVideoInputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputFrameMemoryAllocator )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ IDeckLinkInputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkInput * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInputVtbl;\r\n\r\n    interface IDeckLinkInput\r\n    {\r\n        CONST_VTBL struct IDeckLinkInputVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,conversionMode,flags,actualMode,supported)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,conversionMode,flags,actualMode,supported) ) \r\n\r\n#define IDeckLinkInput_GetDisplayMode(This,displayMode,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This,displayMode,resultDisplayMode) ) \r\n\r\n#define IDeckLinkInput_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_SetVideoInputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkInput_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkInput_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkHDMIInputEDID_INTERFACE_DEFINED__\r\n#define __IDeckLinkHDMIInputEDID_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkHDMIInputEDID */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkHDMIInputEDID;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"ABBBACBC-45BC-4665-9D92-ACE6E5A97902\")\r\n    IDeckLinkHDMIInputEDID : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkHDMIInputEDIDID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkHDMIInputEDIDID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteToEDID( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkHDMIInputEDIDVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkHDMIInputEDID * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkHDMIInputEDID * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkHDMIInputEDID * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkHDMIInputEDID, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkHDMIInputEDID * This,\r\n            /* [in] */ BMDDeckLinkHDMIInputEDIDID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkHDMIInputEDID, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkHDMIInputEDID * This,\r\n            /* [in] */ BMDDeckLinkHDMIInputEDIDID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkHDMIInputEDID, WriteToEDID)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteToEDID )( \r\n            IDeckLinkHDMIInputEDID * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkHDMIInputEDIDVtbl;\r\n\r\n    interface IDeckLinkHDMIInputEDID\r\n    {\r\n        CONST_VTBL struct IDeckLinkHDMIInputEDIDVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkHDMIInputEDID_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkHDMIInputEDID_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkHDMIInputEDID_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkHDMIInputEDID_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkHDMIInputEDID_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkHDMIInputEDID_WriteToEDID(This)\t\\\r\n    ( (This)->lpVtbl -> WriteToEDID(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkHDMIInputEDID_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderInput_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderInput_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderInput */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderInput;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"F222551D-13DF-4FD8-B587-9D4F19EC12C9\")\r\n    IDeckLinkEncoderInput : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedCodec,\r\n            /* [in] */ unsigned int requestedCodecProfile,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BOOL *supported) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailablePacketsCount( \r\n            /* [out] */ unsigned int *availablePacketsCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioFormat audioFormat,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkEncoderInputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderInputVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedCodec,\r\n            /* [in] */ unsigned int requestedCodecProfile,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BOOL *supported);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, GetDisplayMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, GetAvailablePacketsCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailablePacketsCount )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [out] */ unsigned int *availablePacketsCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, SetMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetMemoryAllocator )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ BMDAudioFormat audioFormat,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkEncoderInput * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ IDeckLinkEncoderInputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkEncoderInput * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderInputVtbl;\r\n\r\n    interface IDeckLinkEncoderInput\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderInputVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderInput_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderInput_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderInput_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderInput_DoesSupportVideoMode(This,connection,requestedMode,requestedCodec,requestedCodecProfile,flags,supported)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,connection,requestedMode,requestedCodec,requestedCodecProfile,flags,supported) ) \r\n\r\n#define IDeckLinkEncoderInput_GetDisplayMode(This,displayMode,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This,displayMode,resultDisplayMode) ) \r\n\r\n#define IDeckLinkEncoderInput_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkEncoderInput_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkEncoderInput_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkEncoderInput_GetAvailablePacketsCount(This,availablePacketsCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailablePacketsCount(This,availablePacketsCount) ) \r\n\r\n#define IDeckLinkEncoderInput_SetMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkEncoderInput_EnableAudioInput(This,audioFormat,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,audioFormat,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkEncoderInput_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkEncoderInput_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkEncoderInput_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkEncoderInput_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderInput_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrame_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrame */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrame;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"3F716FE0-F023-4111-BE5D-EF4414C05B17\")\r\n    IDeckLinkVideoFrame : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetWidth( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetHeight( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetRowBytes( void) = 0;\r\n        \r\n        virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;\r\n        \r\n        virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecode( \r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAncillaryData( \r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrameVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrame * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoFrame * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkVideoFrame * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkVideoFrame * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrameVtbl;\r\n\r\n    interface IDeckLinkVideoFrame\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrameVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrame_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrame_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrame_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrame_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoFrame_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoFrame_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoFrame_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoFrame_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoFrame_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkVideoFrame_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkVideoFrame_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrame_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkMutableVideoFrame_INTERFACE_DEFINED__\r\n#define __IDeckLinkMutableVideoFrame_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkMutableVideoFrame */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkMutableVideoFrame;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"69E2639F-40DA-4E19-B6F2-20ACE815C390\")\r\n    IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlags( \r\n            /* [in] */ BMDFrameFlags newFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetTimecode( \r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [in] */ IDeckLinkTimecode *timecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetTimecodeFromComponents( \r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [in] */ unsigned char hours,\r\n            /* [in] */ unsigned char minutes,\r\n            /* [in] */ unsigned char seconds,\r\n            /* [in] */ unsigned char frames,\r\n            /* [in] */ BMDTimecodeFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAncillaryData( \r\n            /* [in] */ IDeckLinkVideoFrameAncillary *ancillary) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetTimecodeUserBits( \r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [in] */ BMDTimecodeUserBits userBits) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkMutableVideoFrameVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkMutableVideoFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame, SetFlags)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlags )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ BMDFrameFlags newFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame, SetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *SetTimecode )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [in] */ IDeckLinkTimecode *timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame, SetTimecodeFromComponents)\r\n        HRESULT ( STDMETHODCALLTYPE *SetTimecodeFromComponents )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [in] */ unsigned char hours,\r\n            /* [in] */ unsigned char minutes,\r\n            /* [in] */ unsigned char seconds,\r\n            /* [in] */ unsigned char frames,\r\n            /* [in] */ BMDTimecodeFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame, SetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAncillaryData )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ IDeckLinkVideoFrameAncillary *ancillary);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame, SetTimecodeUserBits)\r\n        HRESULT ( STDMETHODCALLTYPE *SetTimecodeUserBits )( \r\n            IDeckLinkMutableVideoFrame * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [in] */ BMDTimecodeUserBits userBits);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkMutableVideoFrameVtbl;\r\n\r\n    interface IDeckLinkMutableVideoFrame\r\n    {\r\n        CONST_VTBL struct IDeckLinkMutableVideoFrameVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkMutableVideoFrame_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkMutableVideoFrame_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n\r\n#define IDeckLinkMutableVideoFrame_SetFlags(This,newFlags)\t\\\r\n    ( (This)->lpVtbl -> SetFlags(This,newFlags) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_SetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> SetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags)\t\\\r\n    ( (This)->lpVtbl -> SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_SetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> SetAncillaryData(This,ancillary) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_SetTimecodeUserBits(This,format,userBits)\t\\\r\n    ( (This)->lpVtbl -> SetTimecodeUserBits(This,format,userBits) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkMutableVideoFrame_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame3DExtensions_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrame3DExtensions_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrame3DExtensions */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrame3DExtensions;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7\")\r\n    IDeckLinkVideoFrame3DExtensions : public IUnknown\r\n    {\r\n    public:\r\n        virtual BMDVideo3DPackingFormat STDMETHODCALLTYPE Get3DPackingFormat( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameForRightEye( \r\n            /* [out] */ IDeckLinkVideoFrame **rightEyeFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrame3DExtensionsVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrame3DExtensions * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrame3DExtensions * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrame3DExtensions * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame3DExtensions, Get3DPackingFormat)\r\n        BMDVideo3DPackingFormat ( STDMETHODCALLTYPE *Get3DPackingFormat )( \r\n            IDeckLinkVideoFrame3DExtensions * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame3DExtensions, GetFrameForRightEye)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameForRightEye )( \r\n            IDeckLinkVideoFrame3DExtensions * This,\r\n            /* [out] */ IDeckLinkVideoFrame **rightEyeFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrame3DExtensionsVtbl;\r\n\r\n    interface IDeckLinkVideoFrame3DExtensions\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrame3DExtensionsVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrame3DExtensions_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrame3DExtensions_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrame3DExtensions_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrame3DExtensions_Get3DPackingFormat(This)\t\\\r\n    ( (This)->lpVtbl -> Get3DPackingFormat(This) ) \r\n\r\n#define IDeckLinkVideoFrame3DExtensions_GetFrameForRightEye(This,rightEyeFrame)\t\\\r\n    ( (This)->lpVtbl -> GetFrameForRightEye(This,rightEyeFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrame3DExtensions_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameMetadataExtensions_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrameMetadataExtensions_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrameMetadataExtensions */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrameMetadataExtensions;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"E232A5B7-4DB4-44C9-9152-F47C12E5F051\")\r\n    IDeckLinkVideoFrameMetadataExtensions : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ void *buffer,\r\n            /* [out][in] */ unsigned int *bufferSize) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrameMetadataExtensionsVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoFrameMetadataExtensions * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID metadataID,\r\n            /* [out] */ void *buffer,\r\n            /* [out][in] */ unsigned int *bufferSize);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrameMetadataExtensionsVtbl;\r\n\r\n    interface IDeckLinkVideoFrameMetadataExtensions\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrameMetadataExtensionsVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_GetInt(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_GetFloat(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_GetFlag(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_GetString(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_GetBytes(This,metadataID,buffer,bufferSize)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,metadataID,buffer,bufferSize) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrameMetadataExtensions_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoInputFrame */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoInputFrame;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"05CFE374-537C-4094-9A57-680525118F44\")\r\n    IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetStreamTime( \r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceTimestamp( \r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoInputFrameVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoInputFrame * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoInputFrame * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoInputFrame * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkVideoInputFrame * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkVideoInputFrame * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoInputFrame, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkVideoInputFrame * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoInputFrame, GetHardwareReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceTimestamp )( \r\n            IDeckLinkVideoInputFrame * This,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoInputFrameVtbl;\r\n\r\n    interface IDeckLinkVideoInputFrame\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoInputFrameVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoInputFrame_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoInputFrame_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_GetStreamTime(This,frameTime,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,frameDuration,timeScale) ) \r\n\r\n#define IDeckLinkVideoInputFrame_GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAncillaryPacket_INTERFACE_DEFINED__\r\n#define __IDeckLinkAncillaryPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAncillaryPacket */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAncillaryPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"CC5BBF7E-029C-4D3B-9158-6000EF5E3670\")\r\n    IDeckLinkAncillaryPacket : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [in] */ BMDAncillaryPacketFormat format,\r\n            /* [out] */ const void **data,\r\n            /* [out] */ unsigned int *size) = 0;\r\n        \r\n        virtual unsigned char STDMETHODCALLTYPE GetDID( void) = 0;\r\n        \r\n        virtual unsigned char STDMETHODCALLTYPE GetSDID( void) = 0;\r\n        \r\n        virtual unsigned int STDMETHODCALLTYPE GetLineNumber( void) = 0;\r\n        \r\n        virtual unsigned char STDMETHODCALLTYPE GetDataStreamIndex( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAncillaryPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAncillaryPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAncillaryPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAncillaryPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAncillaryPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkAncillaryPacket * This,\r\n            /* [in] */ BMDAncillaryPacketFormat format,\r\n            /* [out] */ const void **data,\r\n            /* [out] */ unsigned int *size);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAncillaryPacket, GetDID)\r\n        unsigned char ( STDMETHODCALLTYPE *GetDID )( \r\n            IDeckLinkAncillaryPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAncillaryPacket, GetSDID)\r\n        unsigned char ( STDMETHODCALLTYPE *GetSDID )( \r\n            IDeckLinkAncillaryPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAncillaryPacket, GetLineNumber)\r\n        unsigned int ( STDMETHODCALLTYPE *GetLineNumber )( \r\n            IDeckLinkAncillaryPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAncillaryPacket, GetDataStreamIndex)\r\n        unsigned char ( STDMETHODCALLTYPE *GetDataStreamIndex )( \r\n            IDeckLinkAncillaryPacket * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAncillaryPacketVtbl;\r\n\r\n    interface IDeckLinkAncillaryPacket\r\n    {\r\n        CONST_VTBL struct IDeckLinkAncillaryPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAncillaryPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAncillaryPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAncillaryPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAncillaryPacket_GetBytes(This,format,data,size)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,format,data,size) ) \r\n\r\n#define IDeckLinkAncillaryPacket_GetDID(This)\t\\\r\n    ( (This)->lpVtbl -> GetDID(This) ) \r\n\r\n#define IDeckLinkAncillaryPacket_GetSDID(This)\t\\\r\n    ( (This)->lpVtbl -> GetSDID(This) ) \r\n\r\n#define IDeckLinkAncillaryPacket_GetLineNumber(This)\t\\\r\n    ( (This)->lpVtbl -> GetLineNumber(This) ) \r\n\r\n#define IDeckLinkAncillaryPacket_GetDataStreamIndex(This)\t\\\r\n    ( (This)->lpVtbl -> GetDataStreamIndex(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAncillaryPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAncillaryPacketIterator_INTERFACE_DEFINED__\r\n#define __IDeckLinkAncillaryPacketIterator_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAncillaryPacketIterator */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAncillaryPacketIterator;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"3FC8994B-88FB-4C17-968F-9AAB69D964A7\")\r\n    IDeckLinkAncillaryPacketIterator : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLinkAncillaryPacket **packet) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAncillaryPacketIteratorVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAncillaryPacketIterator * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAncillaryPacketIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAncillaryPacketIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAncillaryPacketIterator, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkAncillaryPacketIterator * This,\r\n            /* [out] */ IDeckLinkAncillaryPacket **packet);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAncillaryPacketIteratorVtbl;\r\n\r\n    interface IDeckLinkAncillaryPacketIterator\r\n    {\r\n        CONST_VTBL struct IDeckLinkAncillaryPacketIteratorVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAncillaryPacketIterator_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAncillaryPacketIterator_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAncillaryPacketIterator_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAncillaryPacketIterator_Next(This,packet)\t\\\r\n    ( (This)->lpVtbl -> Next(This,packet) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAncillaryPacketIterator_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameAncillaryPackets_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrameAncillaryPackets_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrameAncillaryPackets */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrameAncillaryPackets;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"6C186C0F-459E-41D8-AEE2-4812D81AEE68\")\r\n    IDeckLinkVideoFrameAncillaryPackets : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetPacketIterator( \r\n            /* [out] */ IDeckLinkAncillaryPacketIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFirstPacketByID( \r\n            /* [in] */ unsigned char DID,\r\n            /* [in] */ unsigned char SDID,\r\n            /* [out] */ IDeckLinkAncillaryPacket **packet) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE AttachPacket( \r\n            /* [in] */ IDeckLinkAncillaryPacket *packet) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DetachPacket( \r\n            /* [in] */ IDeckLinkAncillaryPacket *packet) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DetachAllPackets( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrameAncillaryPacketsVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillaryPackets, GetPacketIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPacketIterator )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This,\r\n            /* [out] */ IDeckLinkAncillaryPacketIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillaryPackets, GetFirstPacketByID)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFirstPacketByID )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This,\r\n            /* [in] */ unsigned char DID,\r\n            /* [in] */ unsigned char SDID,\r\n            /* [out] */ IDeckLinkAncillaryPacket **packet);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillaryPackets, AttachPacket)\r\n        HRESULT ( STDMETHODCALLTYPE *AttachPacket )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This,\r\n            /* [in] */ IDeckLinkAncillaryPacket *packet);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillaryPackets, DetachPacket)\r\n        HRESULT ( STDMETHODCALLTYPE *DetachPacket )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This,\r\n            /* [in] */ IDeckLinkAncillaryPacket *packet);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillaryPackets, DetachAllPackets)\r\n        HRESULT ( STDMETHODCALLTYPE *DetachAllPackets )( \r\n            IDeckLinkVideoFrameAncillaryPackets * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrameAncillaryPacketsVtbl;\r\n\r\n    interface IDeckLinkVideoFrameAncillaryPackets\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrameAncillaryPacketsVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_GetPacketIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetPacketIterator(This,iterator) ) \r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_GetFirstPacketByID(This,DID,SDID,packet)\t\\\r\n    ( (This)->lpVtbl -> GetFirstPacketByID(This,DID,SDID,packet) ) \r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_AttachPacket(This,packet)\t\\\r\n    ( (This)->lpVtbl -> AttachPacket(This,packet) ) \r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_DetachPacket(This,packet)\t\\\r\n    ( (This)->lpVtbl -> DetachPacket(This,packet) ) \r\n\r\n#define IDeckLinkVideoFrameAncillaryPackets_DetachAllPackets(This)\t\\\r\n    ( (This)->lpVtbl -> DetachAllPackets(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrameAncillaryPackets_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameAncillary_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrameAncillary_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrameAncillary */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrameAncillary;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"732E723C-D1A4-4E29-9E8E-4A88797A0004\")\r\n    IDeckLinkVideoFrameAncillary : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferForVerticalBlankingLine( \r\n            /* [in] */ unsigned int lineNumber,\r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;\r\n        \r\n        virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrameAncillaryVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrameAncillary * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrameAncillary * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrameAncillary * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillary, GetBufferForVerticalBlankingLine)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferForVerticalBlankingLine )( \r\n            IDeckLinkVideoFrameAncillary * This,\r\n            /* [in] */ unsigned int lineNumber,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillary, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoFrameAncillary * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameAncillary, GetDisplayMode)\r\n        BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkVideoFrameAncillary * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrameAncillaryVtbl;\r\n\r\n    interface IDeckLinkVideoFrameAncillary\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrameAncillaryVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrameAncillary_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrameAncillary_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrameAncillary_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrameAncillary_GetBufferForVerticalBlankingLine(This,lineNumber,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBufferForVerticalBlankingLine(This,lineNumber,buffer) ) \r\n\r\n#define IDeckLinkVideoFrameAncillary_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoFrameAncillary_GetDisplayMode(This)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrameAncillary_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderPacket_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderPacket */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"B693F36C-316E-4AF1-B6C2-F389A4BCA620\")\r\n    IDeckLinkEncoderPacket : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetSize( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetStreamTime( \r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual BMDPacketType STDMETHODCALLTYPE GetPacketType( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkEncoderPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetSize)\r\n        long ( STDMETHODCALLTYPE *GetSize )( \r\n            IDeckLinkEncoderPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkEncoderPacket * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetPacketType)\r\n        BMDPacketType ( STDMETHODCALLTYPE *GetPacketType )( \r\n            IDeckLinkEncoderPacket * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderPacketVtbl;\r\n\r\n    interface IDeckLinkEncoderPacket\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkEncoderPacket_GetSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetSize(This) ) \r\n\r\n#define IDeckLinkEncoderPacket_GetStreamTime(This,frameTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,timeScale) ) \r\n\r\n#define IDeckLinkEncoderPacket_GetPacketType(This)\t\\\r\n    ( (This)->lpVtbl -> GetPacketType(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderVideoPacket_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderVideoPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderVideoPacket */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderVideoPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"4E7FD944-E8C7-4EAC-B8C0-7B77F80F5AE0\")\r\n    IDeckLinkEncoderVideoPacket : public IDeckLinkEncoderPacket\r\n    {\r\n    public:\r\n        virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceTimestamp( \r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecode( \r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderVideoPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderVideoPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderVideoPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderVideoPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkEncoderVideoPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetSize)\r\n        long ( STDMETHODCALLTYPE *GetSize )( \r\n            IDeckLinkEncoderVideoPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkEncoderVideoPacket * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetPacketType)\r\n        BMDPacketType ( STDMETHODCALLTYPE *GetPacketType )( \r\n            IDeckLinkEncoderVideoPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderVideoPacket, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkEncoderVideoPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderVideoPacket, GetHardwareReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceTimestamp )( \r\n            IDeckLinkEncoderVideoPacket * This,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderVideoPacket, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkEncoderVideoPacket * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderVideoPacketVtbl;\r\n\r\n    interface IDeckLinkEncoderVideoPacket\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderVideoPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderVideoPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderVideoPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_GetSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetSize(This) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_GetStreamTime(This,frameTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,timeScale) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_GetPacketType(This)\t\\\r\n    ( (This)->lpVtbl -> GetPacketType(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderVideoPacket_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) ) \r\n\r\n#define IDeckLinkEncoderVideoPacket_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderVideoPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderAudioPacket_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderAudioPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderAudioPacket */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderAudioPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"49E8EDC8-693B-4E14-8EF6-12C658F5A07A\")\r\n    IDeckLinkEncoderAudioPacket : public IDeckLinkEncoderPacket\r\n    {\r\n    public:\r\n        virtual BMDAudioFormat STDMETHODCALLTYPE GetAudioFormat( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderAudioPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderAudioPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkEncoderAudioPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetSize)\r\n        long ( STDMETHODCALLTYPE *GetSize )( \r\n            IDeckLinkEncoderAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkEncoderAudioPacket * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetPacketType)\r\n        BMDPacketType ( STDMETHODCALLTYPE *GetPacketType )( \r\n            IDeckLinkEncoderAudioPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderAudioPacket, GetAudioFormat)\r\n        BMDAudioFormat ( STDMETHODCALLTYPE *GetAudioFormat )( \r\n            IDeckLinkEncoderAudioPacket * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderAudioPacketVtbl;\r\n\r\n    interface IDeckLinkEncoderAudioPacket\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderAudioPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderAudioPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderAudioPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderAudioPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderAudioPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkEncoderAudioPacket_GetSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetSize(This) ) \r\n\r\n#define IDeckLinkEncoderAudioPacket_GetStreamTime(This,frameTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,timeScale) ) \r\n\r\n#define IDeckLinkEncoderAudioPacket_GetPacketType(This)\t\\\r\n    ( (This)->lpVtbl -> GetPacketType(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderAudioPacket_GetAudioFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetAudioFormat(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderAudioPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkH265NALPacket_INTERFACE_DEFINED__\r\n#define __IDeckLinkH265NALPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkH265NALPacket */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkH265NALPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"639C8E0B-68D5-4BDE-A6D4-95F3AEAFF2E7\")\r\n    IDeckLinkH265NALPacket : public IDeckLinkEncoderVideoPacket\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetUnitType( \r\n            /* [out] */ unsigned char *unitType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytesNoPrefix( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetSizeNoPrefix( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkH265NALPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkH265NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkH265NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetSize)\r\n        long ( STDMETHODCALLTYPE *GetSize )( \r\n            IDeckLinkH265NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderPacket, GetPacketType)\r\n        BMDPacketType ( STDMETHODCALLTYPE *GetPacketType )( \r\n            IDeckLinkH265NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderVideoPacket, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkH265NALPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderVideoPacket, GetHardwareReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceTimestamp )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderVideoPacket, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [in] */ BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkH265NALPacket, GetUnitType)\r\n        HRESULT ( STDMETHODCALLTYPE *GetUnitType )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [out] */ unsigned char *unitType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkH265NALPacket, GetBytesNoPrefix)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytesNoPrefix )( \r\n            IDeckLinkH265NALPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkH265NALPacket, GetSizeNoPrefix)\r\n        long ( STDMETHODCALLTYPE *GetSizeNoPrefix )( \r\n            IDeckLinkH265NALPacket * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkH265NALPacketVtbl;\r\n\r\n    interface IDeckLinkH265NALPacket\r\n    {\r\n        CONST_VTBL struct IDeckLinkH265NALPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkH265NALPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkH265NALPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkH265NALPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkH265NALPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetSize(This)\t\\\r\n    ( (This)->lpVtbl -> GetSize(This) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetStreamTime(This,frameTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,timeScale) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetPacketType(This)\t\\\r\n    ( (This)->lpVtbl -> GetPacketType(This) ) \r\n\r\n\r\n#define IDeckLinkH265NALPacket_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n\r\n#define IDeckLinkH265NALPacket_GetUnitType(This,unitType)\t\\\r\n    ( (This)->lpVtbl -> GetUnitType(This,unitType) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetBytesNoPrefix(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytesNoPrefix(This,buffer) ) \r\n\r\n#define IDeckLinkH265NALPacket_GetSizeNoPrefix(This)\t\\\r\n    ( (This)->lpVtbl -> GetSizeNoPrefix(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkH265NALPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAudioInputPacket_INTERFACE_DEFINED__\r\n#define __IDeckLinkAudioInputPacket_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAudioInputPacket */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAudioInputPacket;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"E43D5870-2894-11DE-8C30-0800200C9A66\")\r\n    IDeckLinkAudioInputPacket : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetSampleFrameCount( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPacketTime( \r\n            /* [out] */ BMDTimeValue *packetTime,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAudioInputPacketVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAudioInputPacket * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAudioInputPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAudioInputPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioInputPacket, GetSampleFrameCount)\r\n        long ( STDMETHODCALLTYPE *GetSampleFrameCount )( \r\n            IDeckLinkAudioInputPacket * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioInputPacket, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkAudioInputPacket * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioInputPacket, GetPacketTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPacketTime )( \r\n            IDeckLinkAudioInputPacket * This,\r\n            /* [out] */ BMDTimeValue *packetTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAudioInputPacketVtbl;\r\n\r\n    interface IDeckLinkAudioInputPacket\r\n    {\r\n        CONST_VTBL struct IDeckLinkAudioInputPacketVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAudioInputPacket_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAudioInputPacket_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAudioInputPacket_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAudioInputPacket_GetSampleFrameCount(This)\t\\\r\n    ( (This)->lpVtbl -> GetSampleFrameCount(This) ) \r\n\r\n#define IDeckLinkAudioInputPacket_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkAudioInputPacket_GetPacketTime(This,packetTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetPacketTime(This,packetTime,timeScale) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAudioInputPacket_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkScreenPreviewCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkScreenPreviewCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkScreenPreviewCallback */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkScreenPreviewCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438\")\r\n    IDeckLinkScreenPreviewCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DrawFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkScreenPreviewCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkScreenPreviewCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkScreenPreviewCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkScreenPreviewCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkScreenPreviewCallback, DrawFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *DrawFrame )( \r\n            IDeckLinkScreenPreviewCallback * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkScreenPreviewCallbackVtbl;\r\n\r\n    interface IDeckLinkScreenPreviewCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkScreenPreviewCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkScreenPreviewCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkScreenPreviewCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkScreenPreviewCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkScreenPreviewCallback_DrawFrame(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DrawFrame(This,theFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkScreenPreviewCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkGLScreenPreviewHelper_INTERFACE_DEFINED__\r\n#define __IDeckLinkGLScreenPreviewHelper_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkGLScreenPreviewHelper */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkGLScreenPreviewHelper;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"504E2209-CAC7-4C1A-9FB4-C5BB6274D22F\")\r\n    IDeckLinkGLScreenPreviewHelper : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE InitializeGL( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PaintGL( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Set3DPreviewFormat( \r\n            /* [in] */ BMD3DPreviewFormat previewFormat) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkGLScreenPreviewHelperVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkGLScreenPreviewHelper * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkGLScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkGLScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper, InitializeGL)\r\n        HRESULT ( STDMETHODCALLTYPE *InitializeGL )( \r\n            IDeckLinkGLScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper, PaintGL)\r\n        HRESULT ( STDMETHODCALLTYPE *PaintGL )( \r\n            IDeckLinkGLScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper, SetFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFrame )( \r\n            IDeckLinkGLScreenPreviewHelper * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper, Set3DPreviewFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *Set3DPreviewFormat )( \r\n            IDeckLinkGLScreenPreviewHelper * This,\r\n            /* [in] */ BMD3DPreviewFormat previewFormat);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkGLScreenPreviewHelperVtbl;\r\n\r\n    interface IDeckLinkGLScreenPreviewHelper\r\n    {\r\n        CONST_VTBL struct IDeckLinkGLScreenPreviewHelperVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkGLScreenPreviewHelper_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkGLScreenPreviewHelper_InitializeGL(This)\t\\\r\n    ( (This)->lpVtbl -> InitializeGL(This) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_PaintGL(This)\t\\\r\n    ( (This)->lpVtbl -> PaintGL(This) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_SetFrame(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> SetFrame(This,theFrame) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_Set3DPreviewFormat(This,previewFormat)\t\\\r\n    ( (This)->lpVtbl -> Set3DPreviewFormat(This,previewFormat) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkGLScreenPreviewHelper_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDX9ScreenPreviewHelper_INTERFACE_DEFINED__\r\n#define __IDeckLinkDX9ScreenPreviewHelper_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDX9ScreenPreviewHelper */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDX9ScreenPreviewHelper;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"2094B522-D1A1-40C0-9AC7-1C012218EF02\")\r\n    IDeckLinkDX9ScreenPreviewHelper : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Initialize( \r\n            /* [in] */ void *device) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Render( \r\n            /* [in] */ RECT *rc) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Set3DPreviewFormat( \r\n            /* [in] */ BMD3DPreviewFormat previewFormat) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDX9ScreenPreviewHelperVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDX9ScreenPreviewHelper, Initialize)\r\n        HRESULT ( STDMETHODCALLTYPE *Initialize )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This,\r\n            /* [in] */ void *device);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDX9ScreenPreviewHelper, Render)\r\n        HRESULT ( STDMETHODCALLTYPE *Render )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This,\r\n            /* [in] */ RECT *rc);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDX9ScreenPreviewHelper, SetFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFrame )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDX9ScreenPreviewHelper, Set3DPreviewFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *Set3DPreviewFormat )( \r\n            IDeckLinkDX9ScreenPreviewHelper * This,\r\n            /* [in] */ BMD3DPreviewFormat previewFormat);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDX9ScreenPreviewHelperVtbl;\r\n\r\n    interface IDeckLinkDX9ScreenPreviewHelper\r\n    {\r\n        CONST_VTBL struct IDeckLinkDX9ScreenPreviewHelperVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_Initialize(This,device)\t\\\r\n    ( (This)->lpVtbl -> Initialize(This,device) ) \r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_Render(This,rc)\t\\\r\n    ( (This)->lpVtbl -> Render(This,rc) ) \r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_SetFrame(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> SetFrame(This,theFrame) ) \r\n\r\n#define IDeckLinkDX9ScreenPreviewHelper_Set3DPreviewFormat(This,previewFormat)\t\\\r\n    ( (This)->lpVtbl -> Set3DPreviewFormat(This,previewFormat) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDX9ScreenPreviewHelper_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkWPFDX9ScreenPreviewHelper_INTERFACE_DEFINED__\r\n#define __IDeckLinkWPFDX9ScreenPreviewHelper_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkWPFDX9ScreenPreviewHelper */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkWPFDX9ScreenPreviewHelper;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"AD8EC84A-7DDE-11E9-8F9E-2A86E4085A59\")\r\n    IDeckLinkWPFDX9ScreenPreviewHelper : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Initialize( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Render( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetSurfaceSize( \r\n            /* [in] */ unsigned int width,\r\n            /* [in] */ unsigned int height) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Set3DPreviewFormat( \r\n            /* [in] */ BMD3DPreviewFormat previewFormat) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBackBuffer( \r\n            /* [out] */ void **backBuffer) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkWPFDX9ScreenPreviewHelperVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkWPFDX9ScreenPreviewHelper, Initialize)\r\n        HRESULT ( STDMETHODCALLTYPE *Initialize )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkWPFDX9ScreenPreviewHelper, Render)\r\n        HRESULT ( STDMETHODCALLTYPE *Render )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkWPFDX9ScreenPreviewHelper, SetSurfaceSize)\r\n        HRESULT ( STDMETHODCALLTYPE *SetSurfaceSize )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This,\r\n            /* [in] */ unsigned int width,\r\n            /* [in] */ unsigned int height);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkWPFDX9ScreenPreviewHelper, SetFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFrame )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkWPFDX9ScreenPreviewHelper, Set3DPreviewFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *Set3DPreviewFormat )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This,\r\n            /* [in] */ BMD3DPreviewFormat previewFormat);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkWPFDX9ScreenPreviewHelper, GetBackBuffer)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBackBuffer )( \r\n            IDeckLinkWPFDX9ScreenPreviewHelper * This,\r\n            /* [out] */ void **backBuffer);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkWPFDX9ScreenPreviewHelperVtbl;\r\n\r\n    interface IDeckLinkWPFDX9ScreenPreviewHelper\r\n    {\r\n        CONST_VTBL struct IDeckLinkWPFDX9ScreenPreviewHelperVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_Initialize(This)\t\\\r\n    ( (This)->lpVtbl -> Initialize(This) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_Render(This)\t\\\r\n    ( (This)->lpVtbl -> Render(This) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_SetSurfaceSize(This,width,height)\t\\\r\n    ( (This)->lpVtbl -> SetSurfaceSize(This,width,height) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_SetFrame(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> SetFrame(This,theFrame) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_Set3DPreviewFormat(This,previewFormat)\t\\\r\n    ( (This)->lpVtbl -> Set3DPreviewFormat(This,previewFormat) ) \r\n\r\n#define IDeckLinkWPFDX9ScreenPreviewHelper_GetBackBuffer(This,backBuffer)\t\\\r\n    ( (This)->lpVtbl -> GetBackBuffer(This,backBuffer) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkWPFDX9ScreenPreviewHelper_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkNotificationCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkNotificationCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkNotificationCallback */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkNotificationCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"b002a1ec-070d-4288-8289-bd5d36e5ff0d\")\r\n    IDeckLinkNotificationCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Notify( \r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ ULONGLONG param1,\r\n            /* [in] */ ULONGLONG param2) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkNotificationCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkNotificationCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkNotificationCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkNotificationCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkNotificationCallback, Notify)\r\n        HRESULT ( STDMETHODCALLTYPE *Notify )( \r\n            IDeckLinkNotificationCallback * This,\r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ ULONGLONG param1,\r\n            /* [in] */ ULONGLONG param2);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkNotificationCallbackVtbl;\r\n\r\n    interface IDeckLinkNotificationCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkNotificationCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkNotificationCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkNotificationCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkNotificationCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkNotificationCallback_Notify(This,topic,param1,param2)\t\\\r\n    ( (This)->lpVtbl -> Notify(This,topic,param1,param2) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkNotificationCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkNotification_INTERFACE_DEFINED__\r\n#define __IDeckLinkNotification_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkNotification */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkNotification;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"b85df4c8-bdf5-47c1-8064-28162ebdd4eb\")\r\n    IDeckLinkNotification : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Subscribe( \r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Unsubscribe( \r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkNotificationVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkNotification * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkNotification * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkNotification * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkNotification, Subscribe)\r\n        HRESULT ( STDMETHODCALLTYPE *Subscribe )( \r\n            IDeckLinkNotification * This,\r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkNotification, Unsubscribe)\r\n        HRESULT ( STDMETHODCALLTYPE *Unsubscribe )( \r\n            IDeckLinkNotification * This,\r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkNotificationVtbl;\r\n\r\n    interface IDeckLinkNotification\r\n    {\r\n        CONST_VTBL struct IDeckLinkNotificationVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkNotification_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkNotification_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkNotification_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkNotification_Subscribe(This,topic,theCallback)\t\\\r\n    ( (This)->lpVtbl -> Subscribe(This,topic,theCallback) ) \r\n\r\n#define IDeckLinkNotification_Unsubscribe(This,topic,theCallback)\t\\\r\n    ( (This)->lpVtbl -> Unsubscribe(This,topic,theCallback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkNotification_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileAttributes_INTERFACE_DEFINED__\r\n#define __IDeckLinkProfileAttributes_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkProfileAttributes */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkProfileAttributes;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"17D4BF8E-4911-473A-80A0-731CF6FF345B\")\r\n    IDeckLinkProfileAttributes : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkProfileAttributesVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkProfileAttributes * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkProfileAttributes * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkProfileAttributes * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileAttributes, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkProfileAttributes * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileAttributes, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkProfileAttributes * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileAttributes, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkProfileAttributes * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileAttributes, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkProfileAttributes * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkProfileAttributesVtbl;\r\n\r\n    interface IDeckLinkProfileAttributes\r\n    {\r\n        CONST_VTBL struct IDeckLinkProfileAttributesVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkProfileAttributes_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkProfileAttributes_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkProfileAttributes_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkProfileAttributes_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkProfileAttributes_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkProfileAttributes_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkProfileAttributes_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkProfileAttributes_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileIterator_INTERFACE_DEFINED__\r\n#define __IDeckLinkProfileIterator_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkProfileIterator */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkProfileIterator;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"29E5A8C0-8BE4-46EB-93AC-31DAAB5B7BF2\")\r\n    IDeckLinkProfileIterator : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLinkProfile **profile) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkProfileIteratorVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkProfileIterator * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkProfileIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkProfileIterator * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileIterator, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkProfileIterator * This,\r\n            /* [out] */ IDeckLinkProfile **profile);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkProfileIteratorVtbl;\r\n\r\n    interface IDeckLinkProfileIterator\r\n    {\r\n        CONST_VTBL struct IDeckLinkProfileIteratorVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkProfileIterator_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkProfileIterator_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkProfileIterator_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkProfileIterator_Next(This,profile)\t\\\r\n    ( (This)->lpVtbl -> Next(This,profile) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkProfileIterator_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfile_INTERFACE_DEFINED__\r\n#define __IDeckLinkProfile_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkProfile */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkProfile;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"16093466-674A-432B-9DA0-1AC2C5A8241C\")\r\n    IDeckLinkProfile : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetDevice( \r\n            /* [out] */ IDeckLink **device) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsActive( \r\n            /* [out] */ BOOL *isActive) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetActive( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPeers( \r\n            /* [out] */ IDeckLinkProfileIterator **profileIterator) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkProfileVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkProfile * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkProfile * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkProfile * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfile, GetDevice)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDevice )( \r\n            IDeckLinkProfile * This,\r\n            /* [out] */ IDeckLink **device);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfile, IsActive)\r\n        HRESULT ( STDMETHODCALLTYPE *IsActive )( \r\n            IDeckLinkProfile * This,\r\n            /* [out] */ BOOL *isActive);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfile, SetActive)\r\n        HRESULT ( STDMETHODCALLTYPE *SetActive )( \r\n            IDeckLinkProfile * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfile, GetPeers)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPeers )( \r\n            IDeckLinkProfile * This,\r\n            /* [out] */ IDeckLinkProfileIterator **profileIterator);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkProfileVtbl;\r\n\r\n    interface IDeckLinkProfile\r\n    {\r\n        CONST_VTBL struct IDeckLinkProfileVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkProfile_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkProfile_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkProfile_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkProfile_GetDevice(This,device)\t\\\r\n    ( (This)->lpVtbl -> GetDevice(This,device) ) \r\n\r\n#define IDeckLinkProfile_IsActive(This,isActive)\t\\\r\n    ( (This)->lpVtbl -> IsActive(This,isActive) ) \r\n\r\n#define IDeckLinkProfile_SetActive(This)\t\\\r\n    ( (This)->lpVtbl -> SetActive(This) ) \r\n\r\n#define IDeckLinkProfile_GetPeers(This,profileIterator)\t\\\r\n    ( (This)->lpVtbl -> GetPeers(This,profileIterator) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkProfile_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkProfileCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkProfileCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkProfileCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"A4F9341E-97AA-4E04-8935-15F809898CEA\")\r\n    IDeckLinkProfileCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE ProfileChanging( \r\n            /* [in] */ IDeckLinkProfile *profileToBeActivated,\r\n            /* [in] */ BOOL streamsWillBeForcedToStop) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ProfileActivated( \r\n            /* [in] */ IDeckLinkProfile *activatedProfile) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkProfileCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkProfileCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkProfileCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkProfileCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileCallback, ProfileChanging)\r\n        HRESULT ( STDMETHODCALLTYPE *ProfileChanging )( \r\n            IDeckLinkProfileCallback * This,\r\n            /* [in] */ IDeckLinkProfile *profileToBeActivated,\r\n            /* [in] */ BOOL streamsWillBeForcedToStop);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileCallback, ProfileActivated)\r\n        HRESULT ( STDMETHODCALLTYPE *ProfileActivated )( \r\n            IDeckLinkProfileCallback * This,\r\n            /* [in] */ IDeckLinkProfile *activatedProfile);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkProfileCallbackVtbl;\r\n\r\n    interface IDeckLinkProfileCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkProfileCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkProfileCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkProfileCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkProfileCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkProfileCallback_ProfileChanging(This,profileToBeActivated,streamsWillBeForcedToStop)\t\\\r\n    ( (This)->lpVtbl -> ProfileChanging(This,profileToBeActivated,streamsWillBeForcedToStop) ) \r\n\r\n#define IDeckLinkProfileCallback_ProfileActivated(This,activatedProfile)\t\\\r\n    ( (This)->lpVtbl -> ProfileActivated(This,activatedProfile) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkProfileCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkProfileManager_INTERFACE_DEFINED__\r\n#define __IDeckLinkProfileManager_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkProfileManager */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkProfileManager;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"30D41429-3998-4B6D-84F8-78C94A797C6E\")\r\n    IDeckLinkProfileManager : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetProfiles( \r\n            /* [out] */ IDeckLinkProfileIterator **profileIterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetProfile( \r\n            /* [in] */ BMDProfileID profileID,\r\n            /* [out] */ IDeckLinkProfile **profile) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkProfileCallback *callback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkProfileManagerVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkProfileManager * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkProfileManager * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkProfileManager * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileManager, GetProfiles)\r\n        HRESULT ( STDMETHODCALLTYPE *GetProfiles )( \r\n            IDeckLinkProfileManager * This,\r\n            /* [out] */ IDeckLinkProfileIterator **profileIterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileManager, GetProfile)\r\n        HRESULT ( STDMETHODCALLTYPE *GetProfile )( \r\n            IDeckLinkProfileManager * This,\r\n            /* [in] */ BMDProfileID profileID,\r\n            /* [out] */ IDeckLinkProfile **profile);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkProfileManager, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkProfileManager * This,\r\n            /* [in] */ IDeckLinkProfileCallback *callback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkProfileManagerVtbl;\r\n\r\n    interface IDeckLinkProfileManager\r\n    {\r\n        CONST_VTBL struct IDeckLinkProfileManagerVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkProfileManager_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkProfileManager_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkProfileManager_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkProfileManager_GetProfiles(This,profileIterator)\t\\\r\n    ( (This)->lpVtbl -> GetProfiles(This,profileIterator) ) \r\n\r\n#define IDeckLinkProfileManager_GetProfile(This,profileID,profile)\t\\\r\n    ( (This)->lpVtbl -> GetProfile(This,profileID,profile) ) \r\n\r\n#define IDeckLinkProfileManager_SetCallback(This,callback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,callback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkProfileManager_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkStatus_INTERFACE_DEFINED__\r\n#define __IDeckLinkStatus_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkStatus */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkStatus;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"5F558200-4028-49BC-BEAC-DB3FA4A96E46\")\r\n    IDeckLinkStatus : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ void *buffer,\r\n            /* [out][in] */ unsigned int *bufferSize) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkStatusVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkStatus * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkStatus * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkStatus * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkStatus, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkStatus * This,\r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkStatus, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkStatus * This,\r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkStatus, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkStatus * This,\r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkStatus, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkStatus * This,\r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkStatus, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkStatus * This,\r\n            /* [in] */ BMDDeckLinkStatusID statusID,\r\n            /* [out] */ void *buffer,\r\n            /* [out][in] */ unsigned int *bufferSize);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkStatusVtbl;\r\n\r\n    interface IDeckLinkStatus\r\n    {\r\n        CONST_VTBL struct IDeckLinkStatusVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkStatus_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkStatus_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkStatus_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkStatus_GetFlag(This,statusID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,statusID,value) ) \r\n\r\n#define IDeckLinkStatus_GetInt(This,statusID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,statusID,value) ) \r\n\r\n#define IDeckLinkStatus_GetFloat(This,statusID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,statusID,value) ) \r\n\r\n#define IDeckLinkStatus_GetString(This,statusID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,statusID,value) ) \r\n\r\n#define IDeckLinkStatus_GetBytes(This,statusID,buffer,bufferSize)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,statusID,buffer,bufferSize) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkStatus_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkKeyer_INTERFACE_DEFINED__\r\n#define __IDeckLinkKeyer_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkKeyer */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkKeyer;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3\")\r\n    IDeckLinkKeyer : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Enable( \r\n            /* [in] */ BOOL isExternal) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetLevel( \r\n            /* [in] */ unsigned char level) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE RampUp( \r\n            /* [in] */ unsigned int numberOfFrames) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE RampDown( \r\n            /* [in] */ unsigned int numberOfFrames) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Disable( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkKeyerVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkKeyer * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkKeyer * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkKeyer * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkKeyer, Enable)\r\n        HRESULT ( STDMETHODCALLTYPE *Enable )( \r\n            IDeckLinkKeyer * This,\r\n            /* [in] */ BOOL isExternal);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkKeyer, SetLevel)\r\n        HRESULT ( STDMETHODCALLTYPE *SetLevel )( \r\n            IDeckLinkKeyer * This,\r\n            /* [in] */ unsigned char level);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkKeyer, RampUp)\r\n        HRESULT ( STDMETHODCALLTYPE *RampUp )( \r\n            IDeckLinkKeyer * This,\r\n            /* [in] */ unsigned int numberOfFrames);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkKeyer, RampDown)\r\n        HRESULT ( STDMETHODCALLTYPE *RampDown )( \r\n            IDeckLinkKeyer * This,\r\n            /* [in] */ unsigned int numberOfFrames);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkKeyer, Disable)\r\n        HRESULT ( STDMETHODCALLTYPE *Disable )( \r\n            IDeckLinkKeyer * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkKeyerVtbl;\r\n\r\n    interface IDeckLinkKeyer\r\n    {\r\n        CONST_VTBL struct IDeckLinkKeyerVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkKeyer_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkKeyer_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkKeyer_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkKeyer_Enable(This,isExternal)\t\\\r\n    ( (This)->lpVtbl -> Enable(This,isExternal) ) \r\n\r\n#define IDeckLinkKeyer_SetLevel(This,level)\t\\\r\n    ( (This)->lpVtbl -> SetLevel(This,level) ) \r\n\r\n#define IDeckLinkKeyer_RampUp(This,numberOfFrames)\t\\\r\n    ( (This)->lpVtbl -> RampUp(This,numberOfFrames) ) \r\n\r\n#define IDeckLinkKeyer_RampDown(This,numberOfFrames)\t\\\r\n    ( (This)->lpVtbl -> RampDown(This,numberOfFrames) ) \r\n\r\n#define IDeckLinkKeyer_Disable(This)\t\\\r\n    ( (This)->lpVtbl -> Disable(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkKeyer_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoConversion_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoConversion_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoConversion */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoConversion;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"3BBCB8A2-DA2C-42D9-B5D8-88083644E99A\")\r\n    IDeckLinkVideoConversion : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE ConvertFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *srcFrame,\r\n            /* [in] */ IDeckLinkVideoFrame *dstFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoConversionVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoConversion * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoConversion * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoConversion * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoConversion, ConvertFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ConvertFrame )( \r\n            IDeckLinkVideoConversion * This,\r\n            /* [in] */ IDeckLinkVideoFrame *srcFrame,\r\n            /* [in] */ IDeckLinkVideoFrame *dstFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoConversionVtbl;\r\n\r\n    interface IDeckLinkVideoConversion\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoConversionVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoConversion_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoConversion_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoConversion_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoConversion_ConvertFrame(This,srcFrame,dstFrame)\t\\\r\n    ( (This)->lpVtbl -> ConvertFrame(This,srcFrame,dstFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoConversion_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeviceNotificationCallback_INTERFACE_DEFINED__\r\n#define __IDeckLinkDeviceNotificationCallback_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDeviceNotificationCallback */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDeviceNotificationCallback;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"4997053B-0ADF-4CC8-AC70-7A50C4BE728F\")\r\n    IDeckLinkDeviceNotificationCallback : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DeckLinkDeviceArrived( \r\n            /* [in] */ IDeckLink *deckLinkDevice) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DeckLinkDeviceRemoved( \r\n            /* [in] */ IDeckLink *deckLinkDevice) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDeviceNotificationCallbackVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDeviceNotificationCallback * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDeviceNotificationCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDeviceNotificationCallback * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeviceNotificationCallback, DeckLinkDeviceArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *DeckLinkDeviceArrived )( \r\n            IDeckLinkDeviceNotificationCallback * This,\r\n            /* [in] */ IDeckLink *deckLinkDevice);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeviceNotificationCallback, DeckLinkDeviceRemoved)\r\n        HRESULT ( STDMETHODCALLTYPE *DeckLinkDeviceRemoved )( \r\n            IDeckLinkDeviceNotificationCallback * This,\r\n            /* [in] */ IDeckLink *deckLinkDevice);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDeviceNotificationCallbackVtbl;\r\n\r\n    interface IDeckLinkDeviceNotificationCallback\r\n    {\r\n        CONST_VTBL struct IDeckLinkDeviceNotificationCallbackVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDeviceNotificationCallback_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDeviceNotificationCallback_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDeviceNotificationCallback_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDeviceNotificationCallback_DeckLinkDeviceArrived(This,deckLinkDevice)\t\\\r\n    ( (This)->lpVtbl -> DeckLinkDeviceArrived(This,deckLinkDevice) ) \r\n\r\n#define IDeckLinkDeviceNotificationCallback_DeckLinkDeviceRemoved(This,deckLinkDevice)\t\\\r\n    ( (This)->lpVtbl -> DeckLinkDeviceRemoved(This,deckLinkDevice) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDeviceNotificationCallback_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDiscovery_INTERFACE_DEFINED__\r\n#define __IDeckLinkDiscovery_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDiscovery */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDiscovery;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"CDBF631C-BC76-45FA-B44D-C55059BC6101\")\r\n    IDeckLinkDiscovery : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE InstallDeviceNotifications( \r\n            /* [in] */ IDeckLinkDeviceNotificationCallback *deviceNotificationCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE UninstallDeviceNotifications( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDiscoveryVtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDiscovery * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDiscovery * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDiscovery * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDiscovery, InstallDeviceNotifications)\r\n        HRESULT ( STDMETHODCALLTYPE *InstallDeviceNotifications )( \r\n            IDeckLinkDiscovery * This,\r\n            /* [in] */ IDeckLinkDeviceNotificationCallback *deviceNotificationCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDiscovery, UninstallDeviceNotifications)\r\n        HRESULT ( STDMETHODCALLTYPE *UninstallDeviceNotifications )( \r\n            IDeckLinkDiscovery * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDiscoveryVtbl;\r\n\r\n    interface IDeckLinkDiscovery\r\n    {\r\n        CONST_VTBL struct IDeckLinkDiscoveryVtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDiscovery_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDiscovery_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDiscovery_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDiscovery_InstallDeviceNotifications(This,deviceNotificationCallback)\t\\\r\n    ( (This)->lpVtbl -> InstallDeviceNotifications(This,deviceNotificationCallback) ) \r\n\r\n#define IDeckLinkDiscovery_UninstallDeviceNotifications(This)\t\\\r\n    ( (This)->lpVtbl -> UninstallDeviceNotifications(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDiscovery_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkIterator;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"BA6C6F44-6DA5-4DCE-94AA-EE2D1372A676\")\r\nCDeckLinkIterator;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkAPIInformation;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"263CA19F-ED09-482E-9F9D-84005783A237\")\r\nCDeckLinkAPIInformation;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkGLScreenPreviewHelper;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"F63E77C7-B655-4A4A-9AD0-3CA85D394343\")\r\nCDeckLinkGLScreenPreviewHelper;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkGL3ScreenPreviewHelper;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"00696A71-EBC7-491F-AC02-18D3393F33F0\")\r\nCDeckLinkGL3ScreenPreviewHelper;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkDX9ScreenPreviewHelper;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"CC010023-E01D-4525-9D59-80C8AB3DC7A0\")\r\nCDeckLinkDX9ScreenPreviewHelper;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkWPFDX9ScreenPreviewHelper;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"EF2A8478-7DDF-11E9-8F9E-2A86E4085A59\")\r\nCDeckLinkWPFDX9ScreenPreviewHelper;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkVideoConversion;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"7DBBBB11-5B7B-467D-AEA4-CEA468FD368C\")\r\nCDeckLinkVideoConversion;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkDiscovery;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"22FBFC33-8D07-495C-A5BF-DAB5EA9B82DB\")\r\nCDeckLinkDiscovery;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkVideoFrameAncillaryPackets;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"F891AD29-D0C2-46E9-A926-4E2D0DD8CFAD\")\r\nCDeckLinkVideoFrameAncillaryPackets;\r\n#endif\r\n\r\n#ifndef __IDeckLinkInputCallback_v11_5_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkInputCallback_v11_5_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInputCallback_v11_5_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInputCallback_v11_5_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"DD04E5EC-7415-42AB-AE4A-E80C4DFC044A\")\r\n    IDeckLinkInputCallback_v11_5_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged( \r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived( \r\n            /* [in] */ IDeckLinkVideoInputFrame *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInputCallback_v11_5_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInputCallback_v11_5_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInputCallback_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInputCallback_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v11_5_1, VideoInputFormatChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )( \r\n            IDeckLinkInputCallback_v11_5_1 * This,\r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v11_5_1, VideoInputFrameArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )( \r\n            IDeckLinkInputCallback_v11_5_1 * This,\r\n            /* [in] */ IDeckLinkVideoInputFrame *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInputCallback_v11_5_1Vtbl;\r\n\r\n    interface IDeckLinkInputCallback_v11_5_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkInputCallback_v11_5_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInputCallback_v11_5_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInputCallback_v11_5_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInputCallback_v11_5_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInputCallback_v11_5_1_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) ) \r\n\r\n#define IDeckLinkInputCallback_v11_5_1_VideoInputFrameArrived(This,videoFrame,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v11_5_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v11_5_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v11_5_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v11_5_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v11_5_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"9434C6E4-B15D-4B1C-979E-661E3DDCB4B9\")\r\n    IDeckLinkInput_v11_5_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDVideoInputConversionMode conversionMode,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v11_5_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDVideoInputConversionMode conversionMode,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, GetDisplayMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, SetVideoInputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputFrameMemoryAllocator )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput_v11_5_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_5_1, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkInput_v11_5_1 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v11_5_1Vtbl;\r\n\r\n    interface IDeckLinkInput_v11_5_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v11_5_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v11_5_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v11_5_1_DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,conversionMode,flags,actualMode,supported)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,conversionMode,flags,actualMode,supported) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_GetDisplayMode(This,displayMode,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This,displayMode,resultDisplayMode) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_SetVideoInputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkInput_v11_5_1_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v11_5_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_11_INTERFACE_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_11_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkConfiguration_v10_11 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkConfiguration_v10_11;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"EF90380B-4AE5-4346-9077-E288E149F129\")\r\n    IDeckLinkConfiguration_v10_11 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkConfiguration_v10_11Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkConfiguration_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkConfiguration_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkConfiguration_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_11, WriteConfigurationToPreferences)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )( \r\n            IDeckLinkConfiguration_v10_11 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkConfiguration_v10_11Vtbl;\r\n\r\n    interface IDeckLinkConfiguration_v10_11\r\n    {\r\n        CONST_VTBL struct IDeckLinkConfiguration_v10_11Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkConfiguration_v10_11_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkConfiguration_v10_11_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_11_WriteConfigurationToPreferences(This)\t\\\r\n    ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_11_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAttributes_v10_11_INTERFACE_DEFINED__\r\n#define __IDeckLinkAttributes_v10_11_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAttributes_v10_11 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAttributes_v10_11;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"ABC11843-D966-44CB-96E2-A1CB5D3135C4\")\r\n    IDeckLinkAttributes_v10_11 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAttributes_v10_11Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAttributes_v10_11 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAttributes_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAttributes_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAttributes_v10_11, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkAttributes_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAttributes_v10_11, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkAttributes_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAttributes_v10_11, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkAttributes_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAttributes_v10_11, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkAttributes_v10_11 * This,\r\n            /* [in] */ BMDDeckLinkAttributeID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAttributes_v10_11Vtbl;\r\n\r\n    interface IDeckLinkAttributes_v10_11\r\n    {\r\n        CONST_VTBL struct IDeckLinkAttributes_v10_11Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAttributes_v10_11_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAttributes_v10_11_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAttributes_v10_11_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAttributes_v10_11_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkAttributes_v10_11_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkAttributes_v10_11_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkAttributes_v10_11_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAttributes_v10_11_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkNotification_v10_11_INTERFACE_DEFINED__\r\n#define __IDeckLinkNotification_v10_11_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkNotification_v10_11 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkNotification_v10_11;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"0A1FB207-E215-441B-9B19-6FA1575946C5\")\r\n    IDeckLinkNotification_v10_11 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Subscribe( \r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Unsubscribe( \r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkNotification_v10_11Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkNotification_v10_11 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkNotification_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkNotification_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkNotification_v10_11, Subscribe)\r\n        HRESULT ( STDMETHODCALLTYPE *Subscribe )( \r\n            IDeckLinkNotification_v10_11 * This,\r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkNotification_v10_11, Unsubscribe)\r\n        HRESULT ( STDMETHODCALLTYPE *Unsubscribe )( \r\n            IDeckLinkNotification_v10_11 * This,\r\n            /* [in] */ BMDNotifications topic,\r\n            /* [in] */ IDeckLinkNotificationCallback *theCallback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkNotification_v10_11Vtbl;\r\n\r\n    interface IDeckLinkNotification_v10_11\r\n    {\r\n        CONST_VTBL struct IDeckLinkNotification_v10_11Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkNotification_v10_11_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkNotification_v10_11_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkNotification_v10_11_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkNotification_v10_11_Subscribe(This,topic,theCallback)\t\\\r\n    ( (This)->lpVtbl -> Subscribe(This,topic,theCallback) ) \r\n\r\n#define IDeckLinkNotification_v10_11_Unsubscribe(This,topic,theCallback)\t\\\r\n    ( (This)->lpVtbl -> Unsubscribe(This,topic,theCallback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkNotification_v10_11_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v10_11_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_v10_11_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput_v10_11 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput_v10_11;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564\")\r\n    IDeckLinkOutput_v10_11 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoOutputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData( \r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount( \r\n            /* [out] */ unsigned int *bufferedFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning( \r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetReferenceStatus( \r\n            /* [out] */ BMDReferenceStatus *referenceStatus) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameCompletionReferenceTimestamp( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *frameCompletionTimestamp) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutput_v10_11Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoOutputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, CreateAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetBufferedVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [out] */ unsigned int *bufferedFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [out] */ unsigned int *bufferedSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, IsScheduledPlaybackRunning)\r\n        HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetScheduledStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetReferenceStatus)\r\n        HRESULT ( STDMETHODCALLTYPE *GetReferenceStatus )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [out] */ BMDReferenceStatus *referenceStatus);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v10_11, GetFrameCompletionReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameCompletionReferenceTimestamp )( \r\n            IDeckLinkOutput_v10_11 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *frameCompletionTimestamp);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutput_v10_11Vtbl;\r\n\r\n    interface IDeckLinkOutput_v10_11\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutput_v10_11Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_v10_11_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_v10_11_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_v10_11_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_v10_11_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_v10_11_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkOutput_v10_11_EnableVideoOutput(This,displayMode,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) ) \r\n\r\n#define IDeckLinkOutput_v10_11_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v10_11_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_v10_11_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v10_11_CreateAncillaryData(This,pixelFormat,outBuffer)\t\\\r\n    ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) ) \r\n\r\n#define IDeckLinkOutput_v10_11_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_v10_11_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v10_11_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetBufferedVideoFrameCount(This,bufferedFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v10_11_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) ) \r\n\r\n#define IDeckLinkOutput_v10_11_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v10_11_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v10_11_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v10_11_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v10_11_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v10_11_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_v10_11_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v10_11_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v10_11_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v10_11_IsScheduledPlaybackRunning(This,active)\t\\\r\n    ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetReferenceStatus(This,referenceStatus)\t\\\r\n    ( (This)->lpVtbl -> GetReferenceStatus(This,referenceStatus) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#define IDeckLinkOutput_v10_11_GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp)\t\\\r\n    ( (This)->lpVtbl -> GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_v10_11_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v10_11_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v10_11_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v10_11 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v10_11;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"AF22762B-DFAC-4846-AA79-FA8883560995\")\r\n    IDeckLinkInput_v10_11 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v10_11Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, SetVideoInputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputFrameMemoryAllocator )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v10_11, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkInput_v10_11 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v10_11Vtbl;\r\n\r\n    interface IDeckLinkInput_v10_11\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v10_11Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v10_11_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v10_11_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v10_11_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) ) \r\n\r\n#define IDeckLinkInput_v10_11_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v10_11_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_v10_11_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v10_11_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_v10_11_SetVideoInputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkInput_v10_11_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v10_11_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_v10_11_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_v10_11_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkInput_v10_11_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v10_11_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkEncoderInput_v10_11_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderInput_v10_11_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderInput_v10_11 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderInput_v10_11;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"270587DA-6B7D-42E7-A1F0-6D853F581185\")\r\n    IDeckLinkEncoderInput_v10_11 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailablePacketsCount( \r\n            /* [out] */ unsigned int *availablePacketsCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioFormat audioFormat,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkEncoderInputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderInput_v10_11Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, GetAvailablePacketsCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailablePacketsCount )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [out] */ unsigned int *availablePacketsCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, SetMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetMemoryAllocator )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ BMDAudioFormat audioFormat,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkEncoderInput_v10_11 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ IDeckLinkEncoderInputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderInput_v10_11, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkEncoderInput_v10_11 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderInput_v10_11Vtbl;\r\n\r\n    interface IDeckLinkEncoderInput_v10_11\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderInput_v10_11Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderInput_v10_11_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderInput_v10_11_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_GetAvailablePacketsCount(This,availablePacketsCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailablePacketsCount(This,availablePacketsCount) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_SetMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_EnableAudioInput(This,audioFormat,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,audioFormat,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkEncoderInput_v10_11_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderInput_v10_11_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkIterator_v10_11;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"87D2693F-8D4A-45C7-B43F-10ACBA25E68F\")\r\nCDeckLinkIterator_v10_11;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkDiscovery_v10_11;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"652615D4-26CD-4514-B161-2FD5072ED008\")\r\nCDeckLinkDiscovery_v10_11;\r\n#endif\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_9_INTERFACE_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_9_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkConfiguration_v10_9 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkConfiguration_v10_9;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"CB71734A-FE37-4E8D-8E13-802133A1C3F2\")\r\n    IDeckLinkConfiguration_v10_9 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkConfiguration_v10_9Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkConfiguration_v10_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkConfiguration_v10_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkConfiguration_v10_9 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_9, WriteConfigurationToPreferences)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )( \r\n            IDeckLinkConfiguration_v10_9 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkConfiguration_v10_9Vtbl;\r\n\r\n    interface IDeckLinkConfiguration_v10_9\r\n    {\r\n        CONST_VTBL struct IDeckLinkConfiguration_v10_9Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkConfiguration_v10_9_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkConfiguration_v10_9_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_9_WriteConfigurationToPreferences(This)\t\\\r\n    ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_9_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CBMDStreamingDiscovery_v10_8;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"0CAA31F6-8A26-40B0-86A4-BF58DCCA710C\")\r\nCBMDStreamingDiscovery_v10_8;\r\n#endif\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_4_INTERFACE_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_4_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkConfiguration_v10_4 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkConfiguration_v10_4;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"1E69FCF6-4203-4936-8076-2A9F4CFD50CB\")\r\n    IDeckLinkConfiguration_v10_4 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkConfiguration_v10_4Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkConfiguration_v10_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkConfiguration_v10_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkConfiguration_v10_4 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_4, WriteConfigurationToPreferences)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )( \r\n            IDeckLinkConfiguration_v10_4 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkConfiguration_v10_4Vtbl;\r\n\r\n    interface IDeckLinkConfiguration_v10_4\r\n    {\r\n        CONST_VTBL struct IDeckLinkConfiguration_v10_4Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkConfiguration_v10_4_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkConfiguration_v10_4_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_4_WriteConfigurationToPreferences(This)\t\\\r\n    ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_4_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v10_2_INTERFACE_DEFINED__\r\n#define __IDeckLinkConfiguration_v10_2_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkConfiguration_v10_2 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkConfiguration_v10_2;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"C679A35B-610C-4D09-B748-1D0478100FC0\")\r\n    IDeckLinkConfiguration_v10_2 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkConfiguration_v10_2Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkConfiguration_v10_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkConfiguration_v10_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkConfiguration_v10_2 * This,\r\n            /* [in] */ BMDDeckLinkConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v10_2, WriteConfigurationToPreferences)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )( \r\n            IDeckLinkConfiguration_v10_2 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkConfiguration_v10_2Vtbl;\r\n\r\n    interface IDeckLinkConfiguration_v10_2\r\n    {\r\n        CONST_VTBL struct IDeckLinkConfiguration_v10_2Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkConfiguration_v10_2_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkConfiguration_v10_2_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkConfiguration_v10_2_WriteConfigurationToPreferences(This)\t\\\r\n    ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v10_2_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrameMetadataExtensions_v11_5_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrameMetadataExtensions_v11_5_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrameMetadataExtensions_v11_5 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrameMetadataExtensions_v11_5;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"D5973DC9-6432-46D0-8F0B-2496F8A1238F\")\r\n    IDeckLinkVideoFrameMetadataExtensions_v11_5 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrameMetadataExtensions_v11_5Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions_v11_5, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions_v11_5, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions_v11_5, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrameMetadataExtensions_v11_5, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkVideoFrameMetadataExtensions_v11_5 * This,\r\n            /* [in] */ BMDDeckLinkFrameMetadataID_v11_5 metadataID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrameMetadataExtensions_v11_5Vtbl;\r\n\r\n    interface IDeckLinkVideoFrameMetadataExtensions_v11_5\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrameMetadataExtensions_v11_5Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_GetInt(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_GetFloat(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_GetFlag(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,metadataID,value) ) \r\n\r\n#define IDeckLinkVideoFrameMetadataExtensions_v11_5_GetString(This,metadataID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,metadataID,value) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrameMetadataExtensions_v11_5_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v11_4_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_v11_4_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput_v11_4 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput_v11_4;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"065A0F6C-C508-4D0D-B919-F5EB0EBFC96B\")\r\n    IDeckLinkOutput_v11_4 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData( \r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount( \r\n            /* [out] */ unsigned int *bufferedFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning( \r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetReferenceStatus( \r\n            /* [out] */ BMDReferenceStatus *referenceStatus) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameCompletionReferenceTimestamp( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *frameCompletionTimestamp) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutput_v11_4Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BMDDisplayMode *actualMode,\r\n            /* [out] */ BOOL *supported);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetDisplayMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, CreateAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetBufferedVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [out] */ unsigned int *bufferedFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [out] */ unsigned int *bufferedSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, IsScheduledPlaybackRunning)\r\n        HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetScheduledStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetReferenceStatus)\r\n        HRESULT ( STDMETHODCALLTYPE *GetReferenceStatus )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [out] */ BMDReferenceStatus *referenceStatus);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v11_4, GetFrameCompletionReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameCompletionReferenceTimestamp )( \r\n            IDeckLinkOutput_v11_4 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *frameCompletionTimestamp);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutput_v11_4Vtbl;\r\n\r\n    interface IDeckLinkOutput_v11_4\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutput_v11_4Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_v11_4_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_v11_4_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_v11_4_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_v11_4_DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,flags,actualMode,supported)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,flags,actualMode,supported) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetDisplayMode(This,displayMode,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This,displayMode,resultDisplayMode) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_v11_4_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkOutput_v11_4_EnableVideoOutput(This,displayMode,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) ) \r\n\r\n#define IDeckLinkOutput_v11_4_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v11_4_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_v11_4_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v11_4_CreateAncillaryData(This,pixelFormat,outBuffer)\t\\\r\n    ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) ) \r\n\r\n#define IDeckLinkOutput_v11_4_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_v11_4_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v11_4_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetBufferedVideoFrameCount(This,bufferedFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v11_4_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) ) \r\n\r\n#define IDeckLinkOutput_v11_4_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v11_4_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v11_4_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v11_4_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v11_4_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v11_4_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_v11_4_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v11_4_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v11_4_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v11_4_IsScheduledPlaybackRunning(This,active)\t\\\r\n    ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetReferenceStatus(This,referenceStatus)\t\\\r\n    ( (This)->lpVtbl -> GetReferenceStatus(This,referenceStatus) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#define IDeckLinkOutput_v11_4_GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp)\t\\\r\n    ( (This)->lpVtbl -> GetFrameCompletionReferenceTimestamp(This,theFrame,desiredTimeScale,frameCompletionTimestamp) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_v11_4_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v11_4_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v11_4_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v11_4 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v11_4;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"2A88CF76-F494-4216-A7EF-DC74EEB83882\")\r\n    IDeckLinkInput_v11_4 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BOOL *supported) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v11_4Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ BMDVideoConnection connection,\r\n            /* [in] */ BMDDisplayMode requestedMode,\r\n            /* [in] */ BMDPixelFormat requestedPixelFormat,\r\n            /* [in] */ BMDSupportedVideoModeFlags flags,\r\n            /* [out] */ BOOL *supported);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, GetDisplayMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, SetVideoInputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputFrameMemoryAllocator )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput_v11_4 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v11_4, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkInput_v11_4 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v11_4Vtbl;\r\n\r\n    interface IDeckLinkInput_v11_4\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v11_4Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v11_4_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v11_4_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v11_4_DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,flags,supported)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,connection,requestedMode,requestedPixelFormat,flags,supported) ) \r\n\r\n#define IDeckLinkInput_v11_4_GetDisplayMode(This,displayMode,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This,displayMode,resultDisplayMode) ) \r\n\r\n#define IDeckLinkInput_v11_4_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v11_4_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_v11_4_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v11_4_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_v11_4_SetVideoInputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkInput_v11_4_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v11_4_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_v11_4_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_v11_4_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkInput_v11_4_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v11_4_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkIterator_v10_8;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"1F2E109A-8F4F-49E4-9203-135595CB6FA5\")\r\nCDeckLinkIterator_v10_8;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkDiscovery_v10_8;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"1073A05C-D885-47E9-B3C6-129B3F9F648B\")\r\nCDeckLinkDiscovery_v10_8;\r\n#endif\r\n\r\n#ifndef __IDeckLinkEncoderConfiguration_v10_5_INTERFACE_DEFINED__\r\n#define __IDeckLinkEncoderConfiguration_v10_5_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkEncoderConfiguration_v10_5 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkEncoderConfiguration_v10_5;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"67455668-0848-45DF-8D8E-350A77C9A028\")\r\n    IDeckLinkEncoderConfiguration_v10_5 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlag( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BOOL value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFlag( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BOOL *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetInt( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetInt( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFloat( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ double value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFloat( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ double *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetString( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BSTR value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BSTR *value) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDecoderConfigurationInfo( \r\n            /* [out] */ void *buffer,\r\n            /* [in] */ long bufferSize,\r\n            /* [out] */ long *returnedSize) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkEncoderConfiguration_v10_5Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, SetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlag )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BOOL value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, GetFlag)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFlag )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BOOL *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, SetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *SetInt )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ LONGLONG value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, GetInt)\r\n        HRESULT ( STDMETHODCALLTYPE *GetInt )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ LONGLONG *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, SetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFloat )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ double value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, GetFloat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFloat )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ double *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, SetString)\r\n        HRESULT ( STDMETHODCALLTYPE *SetString )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [in] */ BSTR value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [in] */ BMDDeckLinkEncoderConfigurationID cfgID,\r\n            /* [out] */ BSTR *value);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkEncoderConfiguration_v10_5, GetDecoderConfigurationInfo)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDecoderConfigurationInfo )( \r\n            IDeckLinkEncoderConfiguration_v10_5 * This,\r\n            /* [out] */ void *buffer,\r\n            /* [in] */ long bufferSize,\r\n            /* [out] */ long *returnedSize);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkEncoderConfiguration_v10_5Vtbl;\r\n\r\n    interface IDeckLinkEncoderConfiguration_v10_5\r\n    {\r\n        CONST_VTBL struct IDeckLinkEncoderConfiguration_v10_5Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_SetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_GetFlag(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFlag(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_SetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_GetInt(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetInt(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_SetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_GetFloat(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetFloat(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_SetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> SetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_GetString(This,cfgID,value)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,cfgID,value) ) \r\n\r\n#define IDeckLinkEncoderConfiguration_v10_5_GetDecoderConfigurationInfo(This,buffer,bufferSize,returnedSize)\t\\\r\n    ( (This)->lpVtbl -> GetDecoderConfigurationInfo(This,buffer,bufferSize,returnedSize) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkEncoderConfiguration_v10_5_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v9_9_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_v9_9_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput_v9_9 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput_v9_9;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"A3EF0963-0862-44ED-92A9-EE89ABF431C7\")\r\n    IDeckLinkOutput_v9_9 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoOutputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData( \r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount( \r\n            /* [out] */ unsigned int *bufferedFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning( \r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetReferenceStatus( \r\n            /* [out] */ BMDReferenceStatus *referenceStatus) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutput_v9_9Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoOutputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDVideoOutputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ int width,\r\n            /* [in] */ int height,\r\n            /* [in] */ int rowBytes,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, CreateAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ IDeckLinkVideoFrame *theFrame,\r\n            /* [in] */ BMDTimeValue displayTime,\r\n            /* [in] */ BMDTimeValue displayDuration,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, GetBufferedVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [out] */ unsigned int *bufferedFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount,\r\n            /* [in] */ BMDAudioOutputStreamType streamType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ void *buffer,\r\n            /* [in] */ unsigned int sampleFrameCount,\r\n            /* [in] */ BMDTimeValue streamTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [out] */ unsigned int *bufferedSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput_v9_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDTimeValue playbackStartTime,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            /* [in] */ BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, IsScheduledPlaybackRunning)\r\n        HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, GetScheduledStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, GetReferenceStatus)\r\n        HRESULT ( STDMETHODCALLTYPE *GetReferenceStatus )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [out] */ BMDReferenceStatus *referenceStatus);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v9_9, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput_v9_9 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutput_v9_9Vtbl;\r\n\r\n    interface IDeckLinkOutput_v9_9\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutput_v9_9Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_v9_9_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_v9_9_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_v9_9_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_v9_9_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) ) \r\n\r\n#define IDeckLinkOutput_v9_9_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_v9_9_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkOutput_v9_9_EnableVideoOutput(This,displayMode,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) ) \r\n\r\n#define IDeckLinkOutput_v9_9_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v9_9_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_v9_9_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v9_9_CreateAncillaryData(This,pixelFormat,outBuffer)\t\\\r\n    ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) ) \r\n\r\n#define IDeckLinkOutput_v9_9_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_v9_9_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v9_9_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v9_9_GetBufferedVideoFrameCount(This,bufferedFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v9_9_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) ) \r\n\r\n#define IDeckLinkOutput_v9_9_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v9_9_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v9_9_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v9_9_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v9_9_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v9_9_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v9_9_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_v9_9_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v9_9_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v9_9_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v9_9_IsScheduledPlaybackRunning(This,active)\t\\\r\n    ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) ) \r\n\r\n#define IDeckLinkOutput_v9_9_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v9_9_GetReferenceStatus(This,referenceStatus)\t\\\r\n    ( (This)->lpVtbl -> GetReferenceStatus(This,referenceStatus) ) \r\n\r\n#define IDeckLinkOutput_v9_9_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_v9_9_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v9_2_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v9_2_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v9_2 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v9_2;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"6D40EF78-28B9-4E21-990D-95BB7750A04F\")\r\n    IDeckLinkInput_v9_2 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v9_2Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result,\r\n            /* [out] */ IDeckLinkDisplayMode **resultDisplayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ BMDDisplayMode displayMode,\r\n            /* [in] */ BMDPixelFormat pixelFormat,\r\n            /* [in] */ BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ BMDAudioSampleRate sampleRate,\r\n            /* [in] */ BMDAudioSampleType sampleType,\r\n            /* [in] */ unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput_v9_2 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v11_5_1 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v9_2, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkInput_v9_2 * This,\r\n            /* [in] */ BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v9_2Vtbl;\r\n\r\n    interface IDeckLinkInput_v9_2\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v9_2Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v9_2_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v9_2_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v9_2_DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,flags,result,resultDisplayMode) ) \r\n\r\n#define IDeckLinkInput_v9_2_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v9_2_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_v9_2_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v9_2_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_v9_2_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v9_2_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_v9_2_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_v9_2_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkInput_v9_2_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v9_2_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControlStatusCallback_v8_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkDeckControlStatusCallback_v8_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDeckControlStatusCallback_v8_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDeckControlStatusCallback_v8_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"E5F693C1-4283-4716-B18F-C1431521955B\")\r\n    IDeckLinkDeckControlStatusCallback_v8_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE TimecodeUpdate( \r\n            /* [in] */ BMDTimecodeBCD currentTimecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VTRControlStateChanged( \r\n            /* [in] */ BMDDeckControlVTRControlState_v8_1 newState,\r\n            /* [in] */ BMDDeckControlError error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DeckControlEventReceived( \r\n            /* [in] */ BMDDeckControlEvent event,\r\n            /* [in] */ BMDDeckControlError error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DeckControlStatusChanged( \r\n            /* [in] */ BMDDeckControlStatusFlags flags,\r\n            /* [in] */ unsigned int mask) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDeckControlStatusCallback_v8_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback_v8_1, TimecodeUpdate)\r\n        HRESULT ( STDMETHODCALLTYPE *TimecodeUpdate )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This,\r\n            /* [in] */ BMDTimecodeBCD currentTimecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback_v8_1, VTRControlStateChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VTRControlStateChanged )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This,\r\n            /* [in] */ BMDDeckControlVTRControlState_v8_1 newState,\r\n            /* [in] */ BMDDeckControlError error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback_v8_1, DeckControlEventReceived)\r\n        HRESULT ( STDMETHODCALLTYPE *DeckControlEventReceived )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This,\r\n            /* [in] */ BMDDeckControlEvent event,\r\n            /* [in] */ BMDDeckControlError error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControlStatusCallback_v8_1, DeckControlStatusChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *DeckControlStatusChanged )( \r\n            IDeckLinkDeckControlStatusCallback_v8_1 * This,\r\n            /* [in] */ BMDDeckControlStatusFlags flags,\r\n            /* [in] */ unsigned int mask);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDeckControlStatusCallback_v8_1Vtbl;\r\n\r\n    interface IDeckLinkDeckControlStatusCallback_v8_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkDeckControlStatusCallback_v8_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_TimecodeUpdate(This,currentTimecode)\t\\\r\n    ( (This)->lpVtbl -> TimecodeUpdate(This,currentTimecode) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_VTRControlStateChanged(This,newState,error)\t\\\r\n    ( (This)->lpVtbl -> VTRControlStateChanged(This,newState,error) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_DeckControlEventReceived(This,event,error)\t\\\r\n    ( (This)->lpVtbl -> DeckControlEventReceived(This,event,error) ) \r\n\r\n#define IDeckLinkDeckControlStatusCallback_v8_1_DeckControlStatusChanged(This,flags,mask)\t\\\r\n    ( (This)->lpVtbl -> DeckControlStatusChanged(This,flags,mask) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDeckControlStatusCallback_v8_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDeckControl_v8_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkDeckControl_v8_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDeckControl_v8_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDeckControl_v8_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"522A9E39-0F3C-4742-94EE-D80DE335DA1D\")\r\n    IDeckLinkDeckControl_v8_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Open( \r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ BMDTimeValue timeValue,\r\n            /* [in] */ BOOL timecodeIsDropFrame,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Close( \r\n            /* [in] */ BOOL standbyOn) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCurrentState( \r\n            /* [out] */ BMDDeckControlMode *mode,\r\n            /* [out] */ BMDDeckControlVTRControlState_v8_1 *vtrControlState,\r\n            /* [out] */ BMDDeckControlStatusFlags *flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetStandby( \r\n            /* [in] */ BOOL standbyOn) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SendCommand( \r\n            /* [in] */ unsigned char *inBuffer,\r\n            /* [in] */ unsigned int inBufferSize,\r\n            /* [out] */ unsigned char *outBuffer,\r\n            /* [out] */ unsigned int *outDataSize,\r\n            /* [in] */ unsigned int outBufferSize,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Play( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Stop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE TogglePlayStop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Eject( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GoToTimecode( \r\n            /* [in] */ BMDTimecodeBCD timecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FastForward( \r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Rewind( \r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StepForward( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StepBack( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Jog( \r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Shuttle( \r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeString( \r\n            /* [out] */ BSTR *currentTimeCode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecode( \r\n            /* [out] */ IDeckLinkTimecode **currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeBCD( \r\n            /* [out] */ BMDTimecodeBCD *currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetPreroll( \r\n            /* [in] */ unsigned int prerollSeconds) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPreroll( \r\n            /* [out] */ unsigned int *prerollSeconds) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetExportOffset( \r\n            /* [in] */ int exportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetExportOffset( \r\n            /* [out] */ int *exportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetManualExportOffset( \r\n            /* [out] */ int *deckManualExportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCaptureOffset( \r\n            /* [in] */ int captureOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCaptureOffset( \r\n            /* [out] */ int *captureOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartExport( \r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartCapture( \r\n            /* [in] */ BOOL useVITC,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDeviceID( \r\n            /* [out] */ unsigned short *deviceId,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CrashRecordStart( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CrashRecordStop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkDeckControlStatusCallback_v8_1 *callback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDeckControl_v8_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDeckControl_v8_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDeckControl_v8_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Open)\r\n        HRESULT ( STDMETHODCALLTYPE *Open )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ BMDTimeValue timeValue,\r\n            /* [in] */ BOOL timecodeIsDropFrame,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Close)\r\n        HRESULT ( STDMETHODCALLTYPE *Close )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BOOL standbyOn);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetCurrentState)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCurrentState )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlMode *mode,\r\n            /* [out] */ BMDDeckControlVTRControlState_v8_1 *vtrControlState,\r\n            /* [out] */ BMDDeckControlStatusFlags *flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, SetStandby)\r\n        HRESULT ( STDMETHODCALLTYPE *SetStandby )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BOOL standbyOn);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, SendCommand)\r\n        HRESULT ( STDMETHODCALLTYPE *SendCommand )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ unsigned char *inBuffer,\r\n            /* [in] */ unsigned int inBufferSize,\r\n            /* [out] */ unsigned char *outBuffer,\r\n            /* [out] */ unsigned int *outDataSize,\r\n            /* [in] */ unsigned int outBufferSize,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Play)\r\n        HRESULT ( STDMETHODCALLTYPE *Play )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Stop)\r\n        HRESULT ( STDMETHODCALLTYPE *Stop )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, TogglePlayStop)\r\n        HRESULT ( STDMETHODCALLTYPE *TogglePlayStop )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Eject)\r\n        HRESULT ( STDMETHODCALLTYPE *Eject )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GoToTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GoToTimecode )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BMDTimecodeBCD timecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, FastForward)\r\n        HRESULT ( STDMETHODCALLTYPE *FastForward )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Rewind)\r\n        HRESULT ( STDMETHODCALLTYPE *Rewind )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, StepForward)\r\n        HRESULT ( STDMETHODCALLTYPE *StepForward )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, StepBack)\r\n        HRESULT ( STDMETHODCALLTYPE *StepBack )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Jog)\r\n        HRESULT ( STDMETHODCALLTYPE *Jog )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Shuttle)\r\n        HRESULT ( STDMETHODCALLTYPE *Shuttle )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetTimecodeString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeString )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BSTR *currentTimeCode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ IDeckLinkTimecode **currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetTimecodeBCD)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeBCD )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDTimecodeBCD *currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, SetPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *SetPreroll )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ unsigned int prerollSeconds);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPreroll )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ unsigned int *prerollSeconds);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, SetExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *SetExportOffset )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ int exportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetExportOffset )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ int *exportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetManualExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetManualExportOffset )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ int *deckManualExportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, SetCaptureOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCaptureOffset )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ int captureOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetCaptureOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCaptureOffset )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ int *captureOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, StartExport)\r\n        HRESULT ( STDMETHODCALLTYPE *StartExport )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, StartCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *StartCapture )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ BOOL useVITC,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, GetDeviceID)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDeviceID )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ unsigned short *deviceId,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, Abort)\r\n        HRESULT ( STDMETHODCALLTYPE *Abort )( \r\n            IDeckLinkDeckControl_v8_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, CrashRecordStart)\r\n        HRESULT ( STDMETHODCALLTYPE *CrashRecordStart )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, CrashRecordStop)\r\n        HRESULT ( STDMETHODCALLTYPE *CrashRecordStop )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v8_1, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkDeckControl_v8_1 * This,\r\n            /* [in] */ IDeckLinkDeckControlStatusCallback_v8_1 *callback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDeckControl_v8_1Vtbl;\r\n\r\n    interface IDeckLinkDeckControl_v8_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkDeckControl_v8_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDeckControl_v8_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDeckControl_v8_1_Open(This,timeScale,timeValue,timecodeIsDropFrame,error)\t\\\r\n    ( (This)->lpVtbl -> Open(This,timeScale,timeValue,timecodeIsDropFrame,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Close(This,standbyOn)\t\\\r\n    ( (This)->lpVtbl -> Close(This,standbyOn) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetCurrentState(This,mode,vtrControlState,flags)\t\\\r\n    ( (This)->lpVtbl -> GetCurrentState(This,mode,vtrControlState,flags) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_SetStandby(This,standbyOn)\t\\\r\n    ( (This)->lpVtbl -> SetStandby(This,standbyOn) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error)\t\\\r\n    ( (This)->lpVtbl -> SendCommand(This,inBuffer,inBufferSize,outBuffer,outDataSize,outBufferSize,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Play(This,error)\t\\\r\n    ( (This)->lpVtbl -> Play(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Stop(This,error)\t\\\r\n    ( (This)->lpVtbl -> Stop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_TogglePlayStop(This,error)\t\\\r\n    ( (This)->lpVtbl -> TogglePlayStop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Eject(This,error)\t\\\r\n    ( (This)->lpVtbl -> Eject(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GoToTimecode(This,timecode,error)\t\\\r\n    ( (This)->lpVtbl -> GoToTimecode(This,timecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_FastForward(This,viewTape,error)\t\\\r\n    ( (This)->lpVtbl -> FastForward(This,viewTape,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Rewind(This,viewTape,error)\t\\\r\n    ( (This)->lpVtbl -> Rewind(This,viewTape,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_StepForward(This,error)\t\\\r\n    ( (This)->lpVtbl -> StepForward(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_StepBack(This,error)\t\\\r\n    ( (This)->lpVtbl -> StepBack(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Jog(This,rate,error)\t\\\r\n    ( (This)->lpVtbl -> Jog(This,rate,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Shuttle(This,rate,error)\t\\\r\n    ( (This)->lpVtbl -> Shuttle(This,rate,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetTimecodeString(This,currentTimeCode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeString(This,currentTimeCode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetTimecode(This,currentTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,currentTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetTimecodeBCD(This,currentTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeBCD(This,currentTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_SetPreroll(This,prerollSeconds)\t\\\r\n    ( (This)->lpVtbl -> SetPreroll(This,prerollSeconds) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetPreroll(This,prerollSeconds)\t\\\r\n    ( (This)->lpVtbl -> GetPreroll(This,prerollSeconds) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_SetExportOffset(This,exportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> SetExportOffset(This,exportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetExportOffset(This,exportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetExportOffset(This,exportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetManualExportOffset(This,deckManualExportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetManualExportOffset(This,deckManualExportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_SetCaptureOffset(This,captureOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> SetCaptureOffset(This,captureOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetCaptureOffset(This,captureOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetCaptureOffset(This,captureOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_StartExport(This,inTimecode,outTimecode,exportModeOps,error)\t\\\r\n    ( (This)->lpVtbl -> StartExport(This,inTimecode,outTimecode,exportModeOps,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_StartCapture(This,useVITC,inTimecode,outTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> StartCapture(This,useVITC,inTimecode,outTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_GetDeviceID(This,deviceId,error)\t\\\r\n    ( (This)->lpVtbl -> GetDeviceID(This,deviceId,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_Abort(This)\t\\\r\n    ( (This)->lpVtbl -> Abort(This) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_CrashRecordStart(This,error)\t\\\r\n    ( (This)->lpVtbl -> CrashRecordStart(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_CrashRecordStop(This,error)\t\\\r\n    ( (This)->lpVtbl -> CrashRecordStop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v8_1_SetCallback(This,callback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,callback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDeckControl_v8_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLink_v8_0_INTERFACE_DEFINED__\r\n#define __IDeckLink_v8_0_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLink_v8_0 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLink_v8_0;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"62BFF75D-6569-4E55-8D4D-66AA03829ABC\")\r\n    IDeckLink_v8_0 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetModelName( \r\n            /* [out] */ BSTR *modelName) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLink_v8_0Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLink_v8_0 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLink_v8_0 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLink_v8_0 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLink_v8_0, GetModelName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetModelName )( \r\n            IDeckLink_v8_0 * This,\r\n            /* [out] */ BSTR *modelName);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLink_v8_0Vtbl;\r\n\r\n    interface IDeckLink_v8_0\r\n    {\r\n        CONST_VTBL struct IDeckLink_v8_0Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLink_v8_0_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLink_v8_0_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLink_v8_0_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLink_v8_0_GetModelName(This,modelName)\t\\\r\n    ( (This)->lpVtbl -> GetModelName(This,modelName) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLink_v8_0_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkIterator_v8_0_INTERFACE_DEFINED__\r\n#define __IDeckLinkIterator_v8_0_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkIterator_v8_0 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkIterator_v8_0;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"74E936FC-CC28-4A67-81A0-1E94E52D4E69\")\r\n    IDeckLinkIterator_v8_0 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLink_v8_0 **deckLinkInstance) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkIterator_v8_0Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkIterator_v8_0 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkIterator_v8_0 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkIterator_v8_0 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkIterator_v8_0, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkIterator_v8_0 * This,\r\n            /* [out] */ IDeckLink_v8_0 **deckLinkInstance);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkIterator_v8_0Vtbl;\r\n\r\n    interface IDeckLinkIterator_v8_0\r\n    {\r\n        CONST_VTBL struct IDeckLinkIterator_v8_0Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkIterator_v8_0_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkIterator_v8_0_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkIterator_v8_0_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkIterator_v8_0_Next(This,deckLinkInstance)\t\\\r\n    ( (This)->lpVtbl -> Next(This,deckLinkInstance) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkIterator_v8_0_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkIterator_v8_0;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"D9EDA3B3-2887-41FA-B724-017CF1EB1D37\")\r\nCDeckLinkIterator_v8_0;\r\n#endif\r\n\r\n#ifndef __IDeckLinkDeckControl_v7_9_INTERFACE_DEFINED__\r\n#define __IDeckLinkDeckControl_v7_9_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDeckControl_v7_9 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDeckControl_v7_9;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"A4D81043-0619-42B7-8ED6-602D29041DF7\")\r\n    IDeckLinkDeckControl_v7_9 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Open( \r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ BMDTimeValue timeValue,\r\n            /* [in] */ BOOL timecodeIsDropFrame,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Close( \r\n            /* [in] */ BOOL standbyOn) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCurrentState( \r\n            /* [out] */ BMDDeckControlMode *mode,\r\n            /* [out] */ BMDDeckControlVTRControlState *vtrControlState,\r\n            /* [out] */ BMDDeckControlStatusFlags *flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetStandby( \r\n            /* [in] */ BOOL standbyOn) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Play( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Stop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE TogglePlayStop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Eject( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GoToTimecode( \r\n            /* [in] */ BMDTimecodeBCD timecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FastForward( \r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Rewind( \r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StepForward( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StepBack( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Jog( \r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Shuttle( \r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeString( \r\n            /* [out] */ BSTR *currentTimeCode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecode( \r\n            /* [out] */ IDeckLinkTimecode **currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecodeBCD( \r\n            /* [out] */ BMDTimecodeBCD *currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetPreroll( \r\n            /* [in] */ unsigned int prerollSeconds) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetPreroll( \r\n            /* [out] */ unsigned int *prerollSeconds) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetExportOffset( \r\n            /* [in] */ int exportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetExportOffset( \r\n            /* [out] */ int *exportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetManualExportOffset( \r\n            /* [out] */ int *deckManualExportOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCaptureOffset( \r\n            /* [in] */ int captureOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetCaptureOffset( \r\n            /* [out] */ int *captureOffsetFields) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartExport( \r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartCapture( \r\n            /* [in] */ BOOL useVITC,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDeviceID( \r\n            /* [out] */ unsigned short *deviceId,\r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Abort( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CrashRecordStart( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CrashRecordStop( \r\n            /* [out] */ BMDDeckControlError *error) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkDeckControlStatusCallback *callback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDeckControl_v7_9Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDeckControl_v7_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDeckControl_v7_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Open)\r\n        HRESULT ( STDMETHODCALLTYPE *Open )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BMDTimeScale timeScale,\r\n            /* [in] */ BMDTimeValue timeValue,\r\n            /* [in] */ BOOL timecodeIsDropFrame,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Close)\r\n        HRESULT ( STDMETHODCALLTYPE *Close )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BOOL standbyOn);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetCurrentState)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCurrentState )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlMode *mode,\r\n            /* [out] */ BMDDeckControlVTRControlState *vtrControlState,\r\n            /* [out] */ BMDDeckControlStatusFlags *flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, SetStandby)\r\n        HRESULT ( STDMETHODCALLTYPE *SetStandby )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BOOL standbyOn);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Play)\r\n        HRESULT ( STDMETHODCALLTYPE *Play )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Stop)\r\n        HRESULT ( STDMETHODCALLTYPE *Stop )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, TogglePlayStop)\r\n        HRESULT ( STDMETHODCALLTYPE *TogglePlayStop )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Eject)\r\n        HRESULT ( STDMETHODCALLTYPE *Eject )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GoToTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GoToTimecode )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BMDTimecodeBCD timecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, FastForward)\r\n        HRESULT ( STDMETHODCALLTYPE *FastForward )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Rewind)\r\n        HRESULT ( STDMETHODCALLTYPE *Rewind )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BOOL viewTape,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, StepForward)\r\n        HRESULT ( STDMETHODCALLTYPE *StepForward )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, StepBack)\r\n        HRESULT ( STDMETHODCALLTYPE *StepBack )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Jog)\r\n        HRESULT ( STDMETHODCALLTYPE *Jog )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Shuttle)\r\n        HRESULT ( STDMETHODCALLTYPE *Shuttle )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ double rate,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetTimecodeString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeString )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BSTR *currentTimeCode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ IDeckLinkTimecode **currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetTimecodeBCD)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecodeBCD )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDTimecodeBCD *currentTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, SetPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *SetPreroll )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ unsigned int prerollSeconds);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *GetPreroll )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ unsigned int *prerollSeconds);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, SetExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *SetExportOffset )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ int exportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetExportOffset )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ int *exportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetManualExportOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetManualExportOffset )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ int *deckManualExportOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, SetCaptureOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCaptureOffset )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ int captureOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetCaptureOffset)\r\n        HRESULT ( STDMETHODCALLTYPE *GetCaptureOffset )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ int *captureOffsetFields);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, StartExport)\r\n        HRESULT ( STDMETHODCALLTYPE *StartExport )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [in] */ BMDDeckControlExportModeOpsFlags exportModeOps,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, StartCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *StartCapture )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ BOOL useVITC,\r\n            /* [in] */ BMDTimecodeBCD inTimecode,\r\n            /* [in] */ BMDTimecodeBCD outTimecode,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, GetDeviceID)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDeviceID )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ unsigned short *deviceId,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, Abort)\r\n        HRESULT ( STDMETHODCALLTYPE *Abort )( \r\n            IDeckLinkDeckControl_v7_9 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, CrashRecordStart)\r\n        HRESULT ( STDMETHODCALLTYPE *CrashRecordStart )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, CrashRecordStop)\r\n        HRESULT ( STDMETHODCALLTYPE *CrashRecordStop )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [out] */ BMDDeckControlError *error);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDeckControl_v7_9, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkDeckControl_v7_9 * This,\r\n            /* [in] */ IDeckLinkDeckControlStatusCallback *callback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDeckControl_v7_9Vtbl;\r\n\r\n    interface IDeckLinkDeckControl_v7_9\r\n    {\r\n        CONST_VTBL struct IDeckLinkDeckControl_v7_9Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDeckControl_v7_9_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDeckControl_v7_9_Open(This,timeScale,timeValue,timecodeIsDropFrame,error)\t\\\r\n    ( (This)->lpVtbl -> Open(This,timeScale,timeValue,timecodeIsDropFrame,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Close(This,standbyOn)\t\\\r\n    ( (This)->lpVtbl -> Close(This,standbyOn) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetCurrentState(This,mode,vtrControlState,flags)\t\\\r\n    ( (This)->lpVtbl -> GetCurrentState(This,mode,vtrControlState,flags) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_SetStandby(This,standbyOn)\t\\\r\n    ( (This)->lpVtbl -> SetStandby(This,standbyOn) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Play(This,error)\t\\\r\n    ( (This)->lpVtbl -> Play(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Stop(This,error)\t\\\r\n    ( (This)->lpVtbl -> Stop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_TogglePlayStop(This,error)\t\\\r\n    ( (This)->lpVtbl -> TogglePlayStop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Eject(This,error)\t\\\r\n    ( (This)->lpVtbl -> Eject(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GoToTimecode(This,timecode,error)\t\\\r\n    ( (This)->lpVtbl -> GoToTimecode(This,timecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_FastForward(This,viewTape,error)\t\\\r\n    ( (This)->lpVtbl -> FastForward(This,viewTape,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Rewind(This,viewTape,error)\t\\\r\n    ( (This)->lpVtbl -> Rewind(This,viewTape,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_StepForward(This,error)\t\\\r\n    ( (This)->lpVtbl -> StepForward(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_StepBack(This,error)\t\\\r\n    ( (This)->lpVtbl -> StepBack(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Jog(This,rate,error)\t\\\r\n    ( (This)->lpVtbl -> Jog(This,rate,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Shuttle(This,rate,error)\t\\\r\n    ( (This)->lpVtbl -> Shuttle(This,rate,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetTimecodeString(This,currentTimeCode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeString(This,currentTimeCode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetTimecode(This,currentTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,currentTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetTimecodeBCD(This,currentTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> GetTimecodeBCD(This,currentTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_SetPreroll(This,prerollSeconds)\t\\\r\n    ( (This)->lpVtbl -> SetPreroll(This,prerollSeconds) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetPreroll(This,prerollSeconds)\t\\\r\n    ( (This)->lpVtbl -> GetPreroll(This,prerollSeconds) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_SetExportOffset(This,exportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> SetExportOffset(This,exportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetExportOffset(This,exportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetExportOffset(This,exportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetManualExportOffset(This,deckManualExportOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetManualExportOffset(This,deckManualExportOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_SetCaptureOffset(This,captureOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> SetCaptureOffset(This,captureOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetCaptureOffset(This,captureOffsetFields)\t\\\r\n    ( (This)->lpVtbl -> GetCaptureOffset(This,captureOffsetFields) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_StartExport(This,inTimecode,outTimecode,exportModeOps,error)\t\\\r\n    ( (This)->lpVtbl -> StartExport(This,inTimecode,outTimecode,exportModeOps,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_StartCapture(This,useVITC,inTimecode,outTimecode,error)\t\\\r\n    ( (This)->lpVtbl -> StartCapture(This,useVITC,inTimecode,outTimecode,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_GetDeviceID(This,deviceId,error)\t\\\r\n    ( (This)->lpVtbl -> GetDeviceID(This,deviceId,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_Abort(This)\t\\\r\n    ( (This)->lpVtbl -> Abort(This) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_CrashRecordStart(This,error)\t\\\r\n    ( (This)->lpVtbl -> CrashRecordStart(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_CrashRecordStop(This,error)\t\\\r\n    ( (This)->lpVtbl -> CrashRecordStop(This,error) ) \r\n\r\n#define IDeckLinkDeckControl_v7_9_SetCallback(This,callback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,callback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDeckControl_v7_9_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayModeIterator_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkDisplayModeIterator_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDisplayModeIterator_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDisplayModeIterator_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"455D741F-1779-4800-86F5-0B5D13D79751\")\r\n    IDeckLinkDisplayModeIterator_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDisplayModeIterator_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDisplayModeIterator_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDisplayModeIterator_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDisplayModeIterator_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayModeIterator_v7_6, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkDisplayModeIterator_v7_6 * This,\r\n            /* [out] */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDisplayModeIterator_v7_6Vtbl;\r\n\r\n    interface IDeckLinkDisplayModeIterator_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkDisplayModeIterator_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDisplayModeIterator_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDisplayModeIterator_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDisplayModeIterator_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDisplayModeIterator_v7_6_Next(This,deckLinkDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> Next(This,deckLinkDisplayMode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDisplayModeIterator_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayMode_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkDisplayMode_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDisplayMode_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDisplayMode_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"87451E84-2B7E-439E-A629-4393EA4A8550\")\r\n    IDeckLinkDisplayMode_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetName( \r\n            /* [out] */ BSTR *name) = 0;\r\n        \r\n        virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetWidth( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetHeight( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameRate( \r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [out] */ BMDTimeScale *timeScale) = 0;\r\n        \r\n        virtual BMDFieldDominance STDMETHODCALLTYPE GetFieldDominance( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDisplayMode_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDisplayMode_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDisplayMode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDisplayMode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_6, GetName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetName )( \r\n            IDeckLinkDisplayMode_v7_6 * This,\r\n            /* [out] */ BSTR *name);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_6, GetDisplayMode)\r\n        BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkDisplayMode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_6, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkDisplayMode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_6, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkDisplayMode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_6, GetFrameRate)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameRate )( \r\n            IDeckLinkDisplayMode_v7_6 * This,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [out] */ BMDTimeScale *timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_6, GetFieldDominance)\r\n        BMDFieldDominance ( STDMETHODCALLTYPE *GetFieldDominance )( \r\n            IDeckLinkDisplayMode_v7_6 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDisplayMode_v7_6Vtbl;\r\n\r\n    interface IDeckLinkDisplayMode_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkDisplayMode_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDisplayMode_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDisplayMode_v7_6_GetName(This,name)\t\\\r\n    ( (This)->lpVtbl -> GetName(This,name) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_GetDisplayMode(This)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_GetFrameRate(This,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetFrameRate(This,frameDuration,timeScale) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_6_GetFieldDominance(This)\t\\\r\n    ( (This)->lpVtbl -> GetFieldDominance(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDisplayMode_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"29228142-EB8C-4141-A621-F74026450955\")\r\n    IDeckLinkOutput_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            BMDDisplayMode displayMode,\r\n            BMDVideoOutputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData( \r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,\r\n            BMDTimeValue displayTime,\r\n            BMDTimeValue displayDuration,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback_v7_6 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount( \r\n            /* [out] */ unsigned int *bufferedFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount,\r\n            BMDAudioOutputStreamType streamType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            BMDTimeValue streamTime,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            BMDTimeValue playbackStartTime,\r\n            BMDTimeScale timeScale,\r\n            double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning( \r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetScheduledStreamTime( \r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutput_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDVideoOutputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, CreateAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,\r\n            BMDTimeValue displayTime,\r\n            BMDTimeValue displayDuration,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback_v7_6 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, GetBufferedVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [out] */ unsigned int *bufferedFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount,\r\n            BMDAudioOutputStreamType streamType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            BMDTimeValue streamTime,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [out] */ unsigned int *bufferedSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDTimeValue playbackStartTime,\r\n            BMDTimeScale timeScale,\r\n            double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, IsScheduledPlaybackRunning)\r\n        HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, GetScheduledStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetScheduledStreamTime )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *streamTime,\r\n            /* [out] */ double *playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_6, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput_v7_6 * This,\r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutput_v7_6Vtbl;\r\n\r\n    interface IDeckLinkOutput_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutput_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_v7_6_DoesSupportVideoMode(This,displayMode,pixelFormat,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) ) \r\n\r\n#define IDeckLinkOutput_v7_6_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_v7_6_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_6_EnableVideoOutput(This,displayMode,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) ) \r\n\r\n#define IDeckLinkOutput_v7_6_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v7_6_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_v7_6_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_6_CreateAncillaryData(This,pixelFormat,outBuffer)\t\\\r\n    ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) ) \r\n\r\n#define IDeckLinkOutput_v7_6_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_6_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v7_6_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_6_GetBufferedVideoFrameCount(This,bufferedFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v7_6_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) ) \r\n\r\n#define IDeckLinkOutput_v7_6_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v7_6_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v7_6_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v7_6_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v7_6_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v7_6_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v7_6_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_v7_6_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_6_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v7_6_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v7_6_IsScheduledPlaybackRunning(This,active)\t\\\r\n    ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) ) \r\n\r\n#define IDeckLinkOutput_v7_6_GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> GetScheduledStreamTime(This,desiredTimeScale,streamTime,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v7_6_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"300C135A-9F43-48E2-9906-6D7911D93CF1\")\r\n    IDeckLinkInput_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v7_6 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v7_6 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_6, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkInput_v7_6 * This,\r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *hardwareTime,\r\n            /* [out] */ BMDTimeValue *timeInFrame,\r\n            /* [out] */ BMDTimeValue *ticksPerFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v7_6Vtbl;\r\n\r\n    interface IDeckLinkInput_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v7_6_DoesSupportVideoMode(This,displayMode,pixelFormat,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) ) \r\n\r\n#define IDeckLinkInput_v7_6_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v7_6_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_v7_6_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v7_6_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_v7_6_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v7_6_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_v7_6_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_6_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkInput_v7_6_GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,hardwareTime,timeInFrame,ticksPerFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkTimecode_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkTimecode_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkTimecode_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkTimecode_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"EFB9BCA6-A521-44F7-BD69-2332F24D9EE6\")\r\n    IDeckLinkTimecode_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual BMDTimecodeBCD STDMETHODCALLTYPE GetBCD( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetComponents( \r\n            /* [out] */ unsigned char *hours,\r\n            /* [out] */ unsigned char *minutes,\r\n            /* [out] */ unsigned char *seconds,\r\n            /* [out] */ unsigned char *frames) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetString( \r\n            /* [out] */ BSTR *timecode) = 0;\r\n        \r\n        virtual BMDTimecodeFlags STDMETHODCALLTYPE GetFlags( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkTimecode_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkTimecode_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkTimecode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkTimecode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode_v7_6, GetBCD)\r\n        BMDTimecodeBCD ( STDMETHODCALLTYPE *GetBCD )( \r\n            IDeckLinkTimecode_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode_v7_6, GetComponents)\r\n        HRESULT ( STDMETHODCALLTYPE *GetComponents )( \r\n            IDeckLinkTimecode_v7_6 * This,\r\n            /* [out] */ unsigned char *hours,\r\n            /* [out] */ unsigned char *minutes,\r\n            /* [out] */ unsigned char *seconds,\r\n            /* [out] */ unsigned char *frames);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode_v7_6, GetString)\r\n        HRESULT ( STDMETHODCALLTYPE *GetString )( \r\n            IDeckLinkTimecode_v7_6 * This,\r\n            /* [out] */ BSTR *timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkTimecode_v7_6, GetFlags)\r\n        BMDTimecodeFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkTimecode_v7_6 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkTimecode_v7_6Vtbl;\r\n\r\n    interface IDeckLinkTimecode_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkTimecode_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkTimecode_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkTimecode_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkTimecode_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkTimecode_v7_6_GetBCD(This)\t\\\r\n    ( (This)->lpVtbl -> GetBCD(This) ) \r\n\r\n#define IDeckLinkTimecode_v7_6_GetComponents(This,hours,minutes,seconds,frames)\t\\\r\n    ( (This)->lpVtbl -> GetComponents(This,hours,minutes,seconds,frames) ) \r\n\r\n#define IDeckLinkTimecode_v7_6_GetString(This,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetString(This,timecode) ) \r\n\r\n#define IDeckLinkTimecode_v7_6_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkTimecode_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrame_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrame_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrame_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"A8D8238E-6B18-4196-99E1-5AF717B83D32\")\r\n    IDeckLinkVideoFrame_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetWidth( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetHeight( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetRowBytes( void) = 0;\r\n        \r\n        virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;\r\n        \r\n        virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            /* [out] */ void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetTimecode( \r\n            BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode_v7_6 **timecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAncillaryData( \r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrame_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrame_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoFrame_v7_6 * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkVideoFrame_v7_6 * This,\r\n            BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode_v7_6 **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkVideoFrame_v7_6 * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrame_v7_6Vtbl;\r\n\r\n    interface IDeckLinkVideoFrame_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrame_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrame_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_6_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrame_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkMutableVideoFrame_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkMutableVideoFrame_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkMutableVideoFrame_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkMutableVideoFrame_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"46FCEE00-B4E6-43D0-91C0-023A7FCEB34F\")\r\n    IDeckLinkMutableVideoFrame_v7_6 : public IDeckLinkVideoFrame_v7_6\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE SetFlags( \r\n            BMDFrameFlags newFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetTimecode( \r\n            BMDTimecodeFormat format,\r\n            /* [in] */ IDeckLinkTimecode_v7_6 *timecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetTimecodeFromComponents( \r\n            BMDTimecodeFormat format,\r\n            unsigned char hours,\r\n            unsigned char minutes,\r\n            unsigned char seconds,\r\n            unsigned char frames,\r\n            BMDTimecodeFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAncillaryData( \r\n            /* [in] */ IDeckLinkVideoFrameAncillary *ancillary) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkMutableVideoFrame_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode_v7_6 **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame_v7_6, SetFlags)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFlags )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            BMDFrameFlags newFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame_v7_6, SetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *SetTimecode )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            BMDTimecodeFormat format,\r\n            /* [in] */ IDeckLinkTimecode_v7_6 *timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame_v7_6, SetTimecodeFromComponents)\r\n        HRESULT ( STDMETHODCALLTYPE *SetTimecodeFromComponents )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            BMDTimecodeFormat format,\r\n            unsigned char hours,\r\n            unsigned char minutes,\r\n            unsigned char seconds,\r\n            unsigned char frames,\r\n            BMDTimecodeFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkMutableVideoFrame_v7_6, SetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAncillaryData )( \r\n            IDeckLinkMutableVideoFrame_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrameAncillary *ancillary);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkMutableVideoFrame_v7_6Vtbl;\r\n\r\n    interface IDeckLinkMutableVideoFrame_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkMutableVideoFrame_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_SetFlags(This,newFlags)\t\\\r\n    ( (This)->lpVtbl -> SetFlags(This,newFlags) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_SetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> SetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags)\t\\\r\n    ( (This)->lpVtbl -> SetTimecodeFromComponents(This,format,hours,minutes,seconds,frames,flags) ) \r\n\r\n#define IDeckLinkMutableVideoFrame_v7_6_SetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> SetAncillaryData(This,ancillary) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkMutableVideoFrame_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoInputFrame_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoInputFrame_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"9A74FA41-AE9F-47AC-8CF4-01F42DD59965\")\r\n    IDeckLinkVideoInputFrame_v7_6 : public IDeckLinkVideoFrame_v7_6\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetStreamTime( \r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceTimestamp( \r\n            BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoInputFrame_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This,\r\n            BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode_v7_6 **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoInputFrame_v7_6, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoInputFrame_v7_6, GetHardwareReferenceTimestamp)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceTimestamp )( \r\n            IDeckLinkVideoInputFrame_v7_6 * This,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoInputFrame_v7_6Vtbl;\r\n\r\n    interface IDeckLinkVideoInputFrame_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoInputFrame_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetStreamTime(This,frameTime,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,frameDuration,timeScale) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_6_GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceTimestamp(This,timeScale,frameTime,frameDuration) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkScreenPreviewCallback_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkScreenPreviewCallback_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkScreenPreviewCallback_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkScreenPreviewCallback_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"373F499D-4B4D-4518-AD22-6354E5A5825E\")\r\n    IDeckLinkScreenPreviewCallback_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DrawFrame( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkScreenPreviewCallback_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkScreenPreviewCallback_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkScreenPreviewCallback_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkScreenPreviewCallback_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkScreenPreviewCallback_v7_6, DrawFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *DrawFrame )( \r\n            IDeckLinkScreenPreviewCallback_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkScreenPreviewCallback_v7_6Vtbl;\r\n\r\n    interface IDeckLinkScreenPreviewCallback_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkScreenPreviewCallback_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkScreenPreviewCallback_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkScreenPreviewCallback_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkScreenPreviewCallback_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkScreenPreviewCallback_v7_6_DrawFrame(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DrawFrame(This,theFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkScreenPreviewCallback_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkGLScreenPreviewHelper_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkGLScreenPreviewHelper_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkGLScreenPreviewHelper_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkGLScreenPreviewHelper_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA\")\r\n    IDeckLinkGLScreenPreviewHelper_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE InitializeGL( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PaintGL( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetFrame( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkGLScreenPreviewHelper_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkGLScreenPreviewHelper_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkGLScreenPreviewHelper_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkGLScreenPreviewHelper_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper_v7_6, InitializeGL)\r\n        HRESULT ( STDMETHODCALLTYPE *InitializeGL )( \r\n            IDeckLinkGLScreenPreviewHelper_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper_v7_6, PaintGL)\r\n        HRESULT ( STDMETHODCALLTYPE *PaintGL )( \r\n            IDeckLinkGLScreenPreviewHelper_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkGLScreenPreviewHelper_v7_6, SetFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *SetFrame )( \r\n            IDeckLinkGLScreenPreviewHelper_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkGLScreenPreviewHelper_v7_6Vtbl;\r\n\r\n    interface IDeckLinkGLScreenPreviewHelper_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkGLScreenPreviewHelper_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkGLScreenPreviewHelper_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkGLScreenPreviewHelper_v7_6_InitializeGL(This)\t\\\r\n    ( (This)->lpVtbl -> InitializeGL(This) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_v7_6_PaintGL(This)\t\\\r\n    ( (This)->lpVtbl -> PaintGL(This) ) \r\n\r\n#define IDeckLinkGLScreenPreviewHelper_v7_6_SetFrame(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> SetFrame(This,theFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkGLScreenPreviewHelper_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoConversion_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoConversion_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoConversion_v7_6 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoConversion_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"3EB504C9-F97D-40FE-A158-D407D48CB53B\")\r\n    IDeckLinkVideoConversion_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE ConvertFrame( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *srcFrame,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *dstFrame) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoConversion_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoConversion_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoConversion_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoConversion_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoConversion_v7_6, ConvertFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ConvertFrame )( \r\n            IDeckLinkVideoConversion_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *srcFrame,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *dstFrame);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoConversion_v7_6Vtbl;\r\n\r\n    interface IDeckLinkVideoConversion_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoConversion_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoConversion_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoConversion_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoConversion_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoConversion_v7_6_ConvertFrame(This,srcFrame,dstFrame)\t\\\r\n    ( (This)->lpVtbl -> ConvertFrame(This,srcFrame,dstFrame) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoConversion_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkConfiguration_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkConfiguration_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkConfiguration_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkConfiguration_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"B8EAD569-B764-47F0-A73F-AE40DF6CBF10\")\r\n    IDeckLinkConfiguration_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetConfigurationValidator( \r\n            /* [out] */ IDeckLinkConfiguration_v7_6 **configObject) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteConfigurationToPreferences( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFormat( \r\n            /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsVideoOutputActive( \r\n            /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection,\r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAnalogVideoOutputFlags( \r\n            /* [in] */ BMDAnalogVideoFlags analogVideoFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAnalogVideoOutputFlags( \r\n            /* [out] */ BMDAnalogVideoFlags *analogVideoFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableFieldFlickerRemovalWhenPaused( \r\n            /* [in] */ BOOL enable) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsEnabledFieldFlickerRemovalWhenPaused( \r\n            /* [out] */ BOOL *enabled) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Set444And3GBpsVideoOutput( \r\n            /* [in] */ BOOL enable444VideoOutput,\r\n            /* [in] */ BOOL enable3GbsOutput) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Get444And3GBpsVideoOutput( \r\n            /* [out] */ BOOL *is444VideoOutputEnabled,\r\n            /* [out] */ BOOL *threeGbsOutputEnabled) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputConversionMode( \r\n            /* [in] */ BMDVideoOutputConversionMode conversionMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVideoOutputConversionMode( \r\n            /* [out] */ BMDVideoOutputConversionMode *conversionMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Set_HD1080p24_to_HD1080i5994_Conversion( \r\n            /* [in] */ BOOL enable) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Get_HD1080p24_to_HD1080i5994_Conversion( \r\n            /* [out] */ BOOL *enabled) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputFormat( \r\n            /* [in] */ BMDVideoConnection_v7_6 videoInputFormat) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVideoInputFormat( \r\n            /* [out] */ BMDVideoConnection_v7_6 *videoInputFormat) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAnalogVideoInputFlags( \r\n            /* [in] */ BMDAnalogVideoFlags analogVideoFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAnalogVideoInputFlags( \r\n            /* [out] */ BMDAnalogVideoFlags *analogVideoFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoInputConversionMode( \r\n            /* [in] */ BMDVideoInputConversionMode conversionMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVideoInputConversionMode( \r\n            /* [out] */ BMDVideoInputConversionMode *conversionMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetBlackVideoOutputDuringCapture( \r\n            /* [in] */ BOOL blackOutInCapture) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBlackVideoOutputDuringCapture( \r\n            /* [out] */ BOOL *blackOutInCapture) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Set32PulldownSequenceInitialTimecodeFrame( \r\n            /* [in] */ unsigned int aFrameTimecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE Get32PulldownSequenceInitialTimecodeFrame( \r\n            /* [out] */ unsigned int *aFrameTimecode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVancSourceLineMapping( \r\n            /* [in] */ unsigned int activeLine1VANCsource,\r\n            /* [in] */ unsigned int activeLine2VANCsource,\r\n            /* [in] */ unsigned int activeLine3VANCsource) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetVancSourceLineMapping( \r\n            /* [out] */ unsigned int *activeLine1VANCsource,\r\n            /* [out] */ unsigned int *activeLine2VANCsource,\r\n            /* [out] */ unsigned int *activeLine3VANCsource) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioInputFormat( \r\n            /* [in] */ BMDAudioConnection_v10_2 audioInputFormat) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAudioInputFormat( \r\n            /* [out] */ BMDAudioConnection_v10_2 *audioInputFormat) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkConfiguration_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkConfiguration_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkConfiguration_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetConfigurationValidator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetConfigurationValidator )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ IDeckLinkConfiguration_v7_6 **configObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, WriteConfigurationToPreferences)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteConfigurationToPreferences )( \r\n            IDeckLinkConfiguration_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetVideoOutputFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFormat )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, IsVideoOutputActive)\r\n        HRESULT ( STDMETHODCALLTYPE *IsVideoOutputActive )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDVideoConnection_v7_6 videoOutputConnection,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetAnalogVideoOutputFlags)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAnalogVideoOutputFlags )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDAnalogVideoFlags analogVideoFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetAnalogVideoOutputFlags)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAnalogVideoOutputFlags )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BMDAnalogVideoFlags *analogVideoFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, EnableFieldFlickerRemovalWhenPaused)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableFieldFlickerRemovalWhenPaused )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BOOL enable);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, IsEnabledFieldFlickerRemovalWhenPaused)\r\n        HRESULT ( STDMETHODCALLTYPE *IsEnabledFieldFlickerRemovalWhenPaused )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BOOL *enabled);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, Set444And3GBpsVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *Set444And3GBpsVideoOutput )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BOOL enable444VideoOutput,\r\n            /* [in] */ BOOL enable3GbsOutput);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, Get444And3GBpsVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *Get444And3GBpsVideoOutput )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BOOL *is444VideoOutputEnabled,\r\n            /* [out] */ BOOL *threeGbsOutputEnabled);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetVideoOutputConversionMode)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputConversionMode )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDVideoOutputConversionMode conversionMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetVideoOutputConversionMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVideoOutputConversionMode )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BMDVideoOutputConversionMode *conversionMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, Set_HD1080p24_to_HD1080i5994_Conversion)\r\n        HRESULT ( STDMETHODCALLTYPE *Set_HD1080p24_to_HD1080i5994_Conversion )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BOOL enable);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, Get_HD1080p24_to_HD1080i5994_Conversion)\r\n        HRESULT ( STDMETHODCALLTYPE *Get_HD1080p24_to_HD1080i5994_Conversion )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BOOL *enabled);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetVideoInputFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputFormat )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDVideoConnection_v7_6 videoInputFormat);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetVideoInputFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVideoInputFormat )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BMDVideoConnection_v7_6 *videoInputFormat);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetAnalogVideoInputFlags)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAnalogVideoInputFlags )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDAnalogVideoFlags analogVideoFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetAnalogVideoInputFlags)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAnalogVideoInputFlags )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BMDAnalogVideoFlags *analogVideoFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetVideoInputConversionMode)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoInputConversionMode )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDVideoInputConversionMode conversionMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetVideoInputConversionMode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVideoInputConversionMode )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BMDVideoInputConversionMode *conversionMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetBlackVideoOutputDuringCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *SetBlackVideoOutputDuringCapture )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BOOL blackOutInCapture);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetBlackVideoOutputDuringCapture)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBlackVideoOutputDuringCapture )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BOOL *blackOutInCapture);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, Set32PulldownSequenceInitialTimecodeFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *Set32PulldownSequenceInitialTimecodeFrame )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ unsigned int aFrameTimecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, Get32PulldownSequenceInitialTimecodeFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *Get32PulldownSequenceInitialTimecodeFrame )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ unsigned int *aFrameTimecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetVancSourceLineMapping)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVancSourceLineMapping )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ unsigned int activeLine1VANCsource,\r\n            /* [in] */ unsigned int activeLine2VANCsource,\r\n            /* [in] */ unsigned int activeLine3VANCsource);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetVancSourceLineMapping)\r\n        HRESULT ( STDMETHODCALLTYPE *GetVancSourceLineMapping )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ unsigned int *activeLine1VANCsource,\r\n            /* [out] */ unsigned int *activeLine2VANCsource,\r\n            /* [out] */ unsigned int *activeLine3VANCsource);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, SetAudioInputFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioInputFormat )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [in] */ BMDAudioConnection_v10_2 audioInputFormat);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkConfiguration_v7_6, GetAudioInputFormat)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAudioInputFormat )( \r\n            IDeckLinkConfiguration_v7_6 * This,\r\n            /* [out] */ BMDAudioConnection_v10_2 *audioInputFormat);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkConfiguration_v7_6Vtbl;\r\n\r\n    interface IDeckLinkConfiguration_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkConfiguration_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkConfiguration_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkConfiguration_v7_6_GetConfigurationValidator(This,configObject)\t\\\r\n    ( (This)->lpVtbl -> GetConfigurationValidator(This,configObject) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_WriteConfigurationToPreferences(This)\t\\\r\n    ( (This)->lpVtbl -> WriteConfigurationToPreferences(This) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetVideoOutputFormat(This,videoOutputConnection)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFormat(This,videoOutputConnection) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_IsVideoOutputActive(This,videoOutputConnection,active)\t\\\r\n    ( (This)->lpVtbl -> IsVideoOutputActive(This,videoOutputConnection,active) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetAnalogVideoOutputFlags(This,analogVideoFlags)\t\\\r\n    ( (This)->lpVtbl -> SetAnalogVideoOutputFlags(This,analogVideoFlags) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetAnalogVideoOutputFlags(This,analogVideoFlags)\t\\\r\n    ( (This)->lpVtbl -> GetAnalogVideoOutputFlags(This,analogVideoFlags) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_EnableFieldFlickerRemovalWhenPaused(This,enable)\t\\\r\n    ( (This)->lpVtbl -> EnableFieldFlickerRemovalWhenPaused(This,enable) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_IsEnabledFieldFlickerRemovalWhenPaused(This,enabled)\t\\\r\n    ( (This)->lpVtbl -> IsEnabledFieldFlickerRemovalWhenPaused(This,enabled) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Set444And3GBpsVideoOutput(This,enable444VideoOutput,enable3GbsOutput)\t\\\r\n    ( (This)->lpVtbl -> Set444And3GBpsVideoOutput(This,enable444VideoOutput,enable3GbsOutput) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Get444And3GBpsVideoOutput(This,is444VideoOutputEnabled,threeGbsOutputEnabled)\t\\\r\n    ( (This)->lpVtbl -> Get444And3GBpsVideoOutput(This,is444VideoOutputEnabled,threeGbsOutputEnabled) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetVideoOutputConversionMode(This,conversionMode)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputConversionMode(This,conversionMode) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetVideoOutputConversionMode(This,conversionMode)\t\\\r\n    ( (This)->lpVtbl -> GetVideoOutputConversionMode(This,conversionMode) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Set_HD1080p24_to_HD1080i5994_Conversion(This,enable)\t\\\r\n    ( (This)->lpVtbl -> Set_HD1080p24_to_HD1080i5994_Conversion(This,enable) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Get_HD1080p24_to_HD1080i5994_Conversion(This,enabled)\t\\\r\n    ( (This)->lpVtbl -> Get_HD1080p24_to_HD1080i5994_Conversion(This,enabled) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetVideoInputFormat(This,videoInputFormat)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputFormat(This,videoInputFormat) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetVideoInputFormat(This,videoInputFormat)\t\\\r\n    ( (This)->lpVtbl -> GetVideoInputFormat(This,videoInputFormat) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetAnalogVideoInputFlags(This,analogVideoFlags)\t\\\r\n    ( (This)->lpVtbl -> SetAnalogVideoInputFlags(This,analogVideoFlags) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetAnalogVideoInputFlags(This,analogVideoFlags)\t\\\r\n    ( (This)->lpVtbl -> GetAnalogVideoInputFlags(This,analogVideoFlags) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetVideoInputConversionMode(This,conversionMode)\t\\\r\n    ( (This)->lpVtbl -> SetVideoInputConversionMode(This,conversionMode) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetVideoInputConversionMode(This,conversionMode)\t\\\r\n    ( (This)->lpVtbl -> GetVideoInputConversionMode(This,conversionMode) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetBlackVideoOutputDuringCapture(This,blackOutInCapture)\t\\\r\n    ( (This)->lpVtbl -> SetBlackVideoOutputDuringCapture(This,blackOutInCapture) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetBlackVideoOutputDuringCapture(This,blackOutInCapture)\t\\\r\n    ( (This)->lpVtbl -> GetBlackVideoOutputDuringCapture(This,blackOutInCapture) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Set32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode)\t\\\r\n    ( (This)->lpVtbl -> Set32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_Get32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode)\t\\\r\n    ( (This)->lpVtbl -> Get32PulldownSequenceInitialTimecodeFrame(This,aFrameTimecode) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource)\t\\\r\n    ( (This)->lpVtbl -> SetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource)\t\\\r\n    ( (This)->lpVtbl -> GetVancSourceLineMapping(This,activeLine1VANCsource,activeLine2VANCsource,activeLine3VANCsource) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_SetAudioInputFormat(This,audioInputFormat)\t\\\r\n    ( (This)->lpVtbl -> SetAudioInputFormat(This,audioInputFormat) ) \r\n\r\n#define IDeckLinkConfiguration_v7_6_GetAudioInputFormat(This,audioInputFormat)\t\\\r\n    ( (This)->lpVtbl -> GetAudioInputFormat(This,audioInputFormat) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkConfiguration_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoOutputCallback_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoOutputCallback_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoOutputCallback_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoOutputCallback_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"E763A626-4A3C-49D1-BF13-E7AD3692AE52\")\r\n    IDeckLinkVideoOutputCallback_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *completedFrame,\r\n            /* [in] */ BMDOutputFrameCompletionResult result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduledPlaybackHasStopped( void) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoOutputCallback_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoOutputCallback_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoOutputCallback_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoOutputCallback_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoOutputCallback_v7_6, ScheduledFrameCompleted)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduledFrameCompleted )( \r\n            IDeckLinkVideoOutputCallback_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *completedFrame,\r\n            /* [in] */ BMDOutputFrameCompletionResult result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoOutputCallback_v7_6, ScheduledPlaybackHasStopped)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduledPlaybackHasStopped )( \r\n            IDeckLinkVideoOutputCallback_v7_6 * This);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoOutputCallback_v7_6Vtbl;\r\n\r\n    interface IDeckLinkVideoOutputCallback_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoOutputCallback_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoOutputCallback_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoOutputCallback_v7_6_ScheduledFrameCompleted(This,completedFrame,result)\t\\\r\n    ( (This)->lpVtbl -> ScheduledFrameCompleted(This,completedFrame,result) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_v7_6_ScheduledPlaybackHasStopped(This)\t\\\r\n    ( (This)->lpVtbl -> ScheduledPlaybackHasStopped(This) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoOutputCallback_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_v7_6_INTERFACE_DEFINED__\r\n#define __IDeckLinkInputCallback_v7_6_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInputCallback_v7_6 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInputCallback_v7_6;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"31D28EE7-88B6-4CB1-897A-CDBF79A26414\")\r\n    IDeckLinkInputCallback_v7_6 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged( \r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived( \r\n            /* [in] */ IDeckLinkVideoInputFrame_v7_6 *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInputCallback_v7_6Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInputCallback_v7_6 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInputCallback_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInputCallback_v7_6 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v7_6, VideoInputFormatChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )( \r\n            IDeckLinkInputCallback_v7_6 * This,\r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v7_6, VideoInputFrameArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )( \r\n            IDeckLinkInputCallback_v7_6 * This,\r\n            /* [in] */ IDeckLinkVideoInputFrame_v7_6 *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInputCallback_v7_6Vtbl;\r\n\r\n    interface IDeckLinkInputCallback_v7_6\r\n    {\r\n        CONST_VTBL struct IDeckLinkInputCallback_v7_6Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInputCallback_v7_6_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInputCallback_v7_6_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInputCallback_v7_6_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInputCallback_v7_6_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) ) \r\n\r\n#define IDeckLinkInputCallback_v7_6_VideoInputFrameArrived(This,videoFrame,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v7_6_INTERFACE_DEFINED__ */\r\n\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkGLScreenPreviewHelper_v7_6;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"D398CEE7-4434-4CA3-9BA6-5AE34556B905\")\r\nCDeckLinkGLScreenPreviewHelper_v7_6;\r\n#endif\r\n\r\nEXTERN_C const CLSID CLSID_CDeckLinkVideoConversion_v7_6;\r\n\r\n#ifdef __cplusplus\r\n\r\nclass DECLSPEC_UUID(\"FFA84F77-73BE-4FB7-B03E-B5E44B9F759B\")\r\nCDeckLinkVideoConversion_v7_6;\r\n#endif\r\n\r\n#ifndef __IDeckLinkInputCallback_v7_3_INTERFACE_DEFINED__\r\n#define __IDeckLinkInputCallback_v7_3_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInputCallback_v7_3 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInputCallback_v7_3;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"FD6F311D-4D00-444B-9ED4-1F25B5730AD0\")\r\n    IDeckLinkInputCallback_v7_3 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFormatChanged( \r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived( \r\n            /* [in] */ IDeckLinkVideoInputFrame_v7_3 *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInputCallback_v7_3Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInputCallback_v7_3 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInputCallback_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInputCallback_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v7_3, VideoInputFormatChanged)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFormatChanged )( \r\n            IDeckLinkInputCallback_v7_3 * This,\r\n            /* [in] */ BMDVideoInputFormatChangedEvents notificationEvents,\r\n            /* [in] */ IDeckLinkDisplayMode_v7_6 *newDisplayMode,\r\n            /* [in] */ BMDDetectedVideoInputFormatFlags detectedSignalFlags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v7_3, VideoInputFrameArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )( \r\n            IDeckLinkInputCallback_v7_3 * This,\r\n            /* [in] */ IDeckLinkVideoInputFrame_v7_3 *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket *audioPacket);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInputCallback_v7_3Vtbl;\r\n\r\n    interface IDeckLinkInputCallback_v7_3\r\n    {\r\n        CONST_VTBL struct IDeckLinkInputCallback_v7_3Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInputCallback_v7_3_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInputCallback_v7_3_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInputCallback_v7_3_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInputCallback_v7_3_VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFormatChanged(This,notificationEvents,newDisplayMode,detectedSignalFlags) ) \r\n\r\n#define IDeckLinkInputCallback_v7_3_VideoInputFrameArrived(This,videoFrame,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v7_3_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v7_3_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_v7_3_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput_v7_3 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput_v7_3;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"271C65E3-C323-4344-A30F-D908BCB20AA3\")\r\n    IDeckLinkOutput_v7_3 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            BMDDisplayMode displayMode,\r\n            BMDVideoOutputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateAncillaryData( \r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,\r\n            BMDTimeValue displayTime,\r\n            BMDTimeValue displayDuration,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedVideoFrameCount( \r\n            /* [out] */ unsigned int *bufferedFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount,\r\n            BMDAudioOutputStreamType streamType) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            BMDTimeValue streamTime,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            BMDTimeValue playbackStartTime,\r\n            BMDTimeScale timeScale,\r\n            double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE IsScheduledPlaybackRunning( \r\n            /* [out] */ BOOL *active) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutput_v7_3Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDVideoOutputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            /* [out] */ IDeckLinkMutableVideoFrame_v7_6 **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, CreateAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateAncillaryData )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **outBuffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_6 *theFrame,\r\n            BMDTimeValue displayTime,\r\n            BMDTimeValue displayDuration,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, GetBufferedVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedVideoFrameCount )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [out] */ unsigned int *bufferedFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount,\r\n            BMDAudioOutputStreamType streamType);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            BMDTimeValue streamTime,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [out] */ unsigned int *bufferedSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDTimeValue playbackStartTime,\r\n            BMDTimeScale timeScale,\r\n            double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDTimeValue stopPlaybackAtTime,\r\n            /* [out] */ BMDTimeValue *actualStopTime,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, IsScheduledPlaybackRunning)\r\n        HRESULT ( STDMETHODCALLTYPE *IsScheduledPlaybackRunning )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            /* [out] */ BOOL *active);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_3, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput_v7_3 * This,\r\n            BMDTimeScale desiredTimeScale,\r\n            /* [out] */ BMDTimeValue *elapsedTimeSinceSchedulerBegan);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutput_v7_3Vtbl;\r\n\r\n    interface IDeckLinkOutput_v7_3\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutput_v7_3Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_v7_3_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_v7_3_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_v7_3_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_v7_3_DoesSupportVideoMode(This,displayMode,pixelFormat,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) ) \r\n\r\n#define IDeckLinkOutput_v7_3_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_v7_3_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_3_EnableVideoOutput(This,displayMode,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode,flags) ) \r\n\r\n#define IDeckLinkOutput_v7_3_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v7_3_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_v7_3_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_3_CreateAncillaryData(This,pixelFormat,outBuffer)\t\\\r\n    ( (This)->lpVtbl -> CreateAncillaryData(This,pixelFormat,outBuffer) ) \r\n\r\n#define IDeckLinkOutput_v7_3_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_3_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v7_3_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_3_GetBufferedVideoFrameCount(This,bufferedFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedVideoFrameCount(This,bufferedFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v7_3_EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount,streamType) ) \r\n\r\n#define IDeckLinkOutput_v7_3_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v7_3_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v7_3_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v7_3_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v7_3_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v7_3_GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleFrameCount) ) \r\n\r\n#define IDeckLinkOutput_v7_3_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_v7_3_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_3_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v7_3_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v7_3_IsScheduledPlaybackRunning(This,active)\t\\\r\n    ( (This)->lpVtbl -> IsScheduledPlaybackRunning(This,active) ) \r\n\r\n#define IDeckLinkOutput_v7_3_GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_v7_3_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v7_3_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v7_3_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v7_3 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v7_3;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"4973F012-9925-458C-871C-18774CDBBECB\")\r\n    IDeckLinkInput_v7_3 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScreenPreviewCallback( \r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableVideoFrameCount( \r\n            /* [out] */ unsigned int *availableFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAvailableAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *availableSampleFrameCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v7_3 *theCallback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v7_3Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_6 **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, SetScreenPreviewCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScreenPreviewCallback )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            /* [in] */ IDeckLinkScreenPreviewCallback *previewCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, GetAvailableVideoFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableVideoFrameCount )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            /* [out] */ unsigned int *availableFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, GetAvailableAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAvailableAudioSampleFrameCount )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            /* [out] */ unsigned int *availableSampleFrameCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, FlushStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushStreams )( \r\n            IDeckLinkInput_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_3, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v7_3 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v7_3 *theCallback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v7_3Vtbl;\r\n\r\n    interface IDeckLinkInput_v7_3\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v7_3Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v7_3_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v7_3_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v7_3_DoesSupportVideoMode(This,displayMode,pixelFormat,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) ) \r\n\r\n#define IDeckLinkInput_v7_3_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v7_3_SetScreenPreviewCallback(This,previewCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScreenPreviewCallback(This,previewCallback) ) \r\n\r\n#define IDeckLinkInput_v7_3_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v7_3_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_GetAvailableVideoFrameCount(This,availableFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableVideoFrameCount(This,availableFrameCount) ) \r\n\r\n#define IDeckLinkInput_v7_3_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v7_3_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount)\t\\\r\n    ( (This)->lpVtbl -> GetAvailableAudioSampleFrameCount(This,availableSampleFrameCount) ) \r\n\r\n#define IDeckLinkInput_v7_3_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_FlushStreams(This)\t\\\r\n    ( (This)->lpVtbl -> FlushStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_3_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v7_3_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_v7_3_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_v7_3_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoInputFrame_v7_3 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoInputFrame_v7_3;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"CF317790-2894-11DE-8C30-0800200C9A66\")\r\n    IDeckLinkVideoInputFrame_v7_3 : public IDeckLinkVideoFrame_v7_6\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetStreamTime( \r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoInputFrame_v7_3Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This,\r\n            /* [out] */ void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetTimecode)\r\n        HRESULT ( STDMETHODCALLTYPE *GetTimecode )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This,\r\n            BMDTimecodeFormat format,\r\n            /* [out] */ IDeckLinkTimecode_v7_6 **timecode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_6, GetAncillaryData)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAncillaryData )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This,\r\n            /* [out] */ IDeckLinkVideoFrameAncillary **ancillary);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoInputFrame_v7_3, GetStreamTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetStreamTime )( \r\n            IDeckLinkVideoInputFrame_v7_3 * This,\r\n            /* [out] */ BMDTimeValue *frameTime,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            BMDTimeScale timeScale);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoInputFrame_v7_3Vtbl;\r\n\r\n    interface IDeckLinkVideoInputFrame_v7_3\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoInputFrame_v7_3Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetTimecode(This,format,timecode)\t\\\r\n    ( (This)->lpVtbl -> GetTimecode(This,format,timecode) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetAncillaryData(This,ancillary)\t\\\r\n    ( (This)->lpVtbl -> GetAncillaryData(This,ancillary) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_3_GetStreamTime(This,frameTime,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetStreamTime(This,frameTime,frameDuration,timeScale) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_v7_3_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayModeIterator_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkDisplayModeIterator_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDisplayModeIterator_v7_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDisplayModeIterator_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"B28131B6-59AC-4857-B5AC-CD75D5883E2F\")\r\n    IDeckLinkDisplayModeIterator_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE Next( \r\n            /* [out] */ IDeckLinkDisplayMode_v7_1 **deckLinkDisplayMode) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDisplayModeIterator_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDisplayModeIterator_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDisplayModeIterator_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDisplayModeIterator_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayModeIterator_v7_1, Next)\r\n        HRESULT ( STDMETHODCALLTYPE *Next )( \r\n            IDeckLinkDisplayModeIterator_v7_1 * This,\r\n            /* [out] */ IDeckLinkDisplayMode_v7_1 **deckLinkDisplayMode);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDisplayModeIterator_v7_1Vtbl;\r\n\r\n    interface IDeckLinkDisplayModeIterator_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkDisplayModeIterator_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDisplayModeIterator_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDisplayModeIterator_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDisplayModeIterator_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDisplayModeIterator_v7_1_Next(This,deckLinkDisplayMode)\t\\\r\n    ( (This)->lpVtbl -> Next(This,deckLinkDisplayMode) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDisplayModeIterator_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkDisplayMode_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkDisplayMode_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkDisplayMode_v7_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkDisplayMode_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"AF0CD6D5-8376-435E-8433-54F9DD530AC3\")\r\n    IDeckLinkDisplayMode_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetName( \r\n            /* [out] */ BSTR *name) = 0;\r\n        \r\n        virtual BMDDisplayMode STDMETHODCALLTYPE GetDisplayMode( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetWidth( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetHeight( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameRate( \r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [out] */ BMDTimeScale *timeScale) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkDisplayMode_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkDisplayMode_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkDisplayMode_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkDisplayMode_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_1, GetName)\r\n        HRESULT ( STDMETHODCALLTYPE *GetName )( \r\n            IDeckLinkDisplayMode_v7_1 * This,\r\n            /* [out] */ BSTR *name);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_1, GetDisplayMode)\r\n        BMDDisplayMode ( STDMETHODCALLTYPE *GetDisplayMode )( \r\n            IDeckLinkDisplayMode_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_1, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkDisplayMode_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_1, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkDisplayMode_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkDisplayMode_v7_1, GetFrameRate)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameRate )( \r\n            IDeckLinkDisplayMode_v7_1 * This,\r\n            /* [out] */ BMDTimeValue *frameDuration,\r\n            /* [out] */ BMDTimeScale *timeScale);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkDisplayMode_v7_1Vtbl;\r\n\r\n    interface IDeckLinkDisplayMode_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkDisplayMode_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkDisplayMode_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkDisplayMode_v7_1_GetName(This,name)\t\\\r\n    ( (This)->lpVtbl -> GetName(This,name) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_1_GetDisplayMode(This)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayMode(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_1_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_1_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkDisplayMode_v7_1_GetFrameRate(This,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetFrameRate(This,frameDuration,timeScale) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkDisplayMode_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoFrame_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoFrame_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoFrame_v7_1 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoFrame_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"333F3A10-8C2D-43CF-B79D-46560FEEA1CE\")\r\n    IDeckLinkVideoFrame_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetWidth( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetHeight( void) = 0;\r\n        \r\n        virtual long STDMETHODCALLTYPE GetRowBytes( void) = 0;\r\n        \r\n        virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat( void) = 0;\r\n        \r\n        virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            void **buffer) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoFrame_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoFrame_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoFrame_v7_1 * This,\r\n            void **buffer);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoFrame_v7_1Vtbl;\r\n\r\n    interface IDeckLinkVideoFrame_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoFrame_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoFrame_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoFrame_v7_1_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoFrame_v7_1_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoFrame_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoInputFrame_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoInputFrame_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoInputFrame_v7_1 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoInputFrame_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"C8B41D95-8848-40EE-9B37-6E3417FB114B\")\r\n    IDeckLinkVideoInputFrame_v7_1 : public IDeckLinkVideoFrame_v7_1\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE GetFrameTime( \r\n            BMDTimeValue *frameTime,\r\n            BMDTimeValue *frameDuration,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoInputFrame_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetWidth)\r\n        long ( STDMETHODCALLTYPE *GetWidth )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetHeight)\r\n        long ( STDMETHODCALLTYPE *GetHeight )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetRowBytes)\r\n        long ( STDMETHODCALLTYPE *GetRowBytes )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetPixelFormat)\r\n        BMDPixelFormat ( STDMETHODCALLTYPE *GetPixelFormat )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetFlags)\r\n        BMDFrameFlags ( STDMETHODCALLTYPE *GetFlags )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoFrame_v7_1, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This,\r\n            void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoInputFrame_v7_1, GetFrameTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetFrameTime )( \r\n            IDeckLinkVideoInputFrame_v7_1 * This,\r\n            BMDTimeValue *frameTime,\r\n            BMDTimeValue *frameDuration,\r\n            BMDTimeScale timeScale);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoInputFrame_v7_1Vtbl;\r\n\r\n    interface IDeckLinkVideoInputFrame_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoInputFrame_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetWidth(This)\t\\\r\n    ( (This)->lpVtbl -> GetWidth(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetHeight(This)\t\\\r\n    ( (This)->lpVtbl -> GetHeight(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetRowBytes(This)\t\\\r\n    ( (This)->lpVtbl -> GetRowBytes(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetPixelFormat(This)\t\\\r\n    ( (This)->lpVtbl -> GetPixelFormat(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetFlags(This)\t\\\r\n    ( (This)->lpVtbl -> GetFlags(This) ) \r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n\r\n#define IDeckLinkVideoInputFrame_v7_1_GetFrameTime(This,frameTime,frameDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetFrameTime(This,frameTime,frameDuration,timeScale) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoInputFrame_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkAudioInputPacket_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkAudioInputPacket_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkAudioInputPacket_v7_1 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkAudioInputPacket_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"C86DE4F6-A29F-42E3-AB3A-1363E29F0788\")\r\n    IDeckLinkAudioInputPacket_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual long STDMETHODCALLTYPE GetSampleCount( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBytes( \r\n            void **buffer) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetAudioPacketTime( \r\n            BMDTimeValue *packetTime,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkAudioInputPacket_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkAudioInputPacket_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkAudioInputPacket_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkAudioInputPacket_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioInputPacket_v7_1, GetSampleCount)\r\n        long ( STDMETHODCALLTYPE *GetSampleCount )( \r\n            IDeckLinkAudioInputPacket_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioInputPacket_v7_1, GetBytes)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBytes )( \r\n            IDeckLinkAudioInputPacket_v7_1 * This,\r\n            void **buffer);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkAudioInputPacket_v7_1, GetAudioPacketTime)\r\n        HRESULT ( STDMETHODCALLTYPE *GetAudioPacketTime )( \r\n            IDeckLinkAudioInputPacket_v7_1 * This,\r\n            BMDTimeValue *packetTime,\r\n            BMDTimeScale timeScale);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkAudioInputPacket_v7_1Vtbl;\r\n\r\n    interface IDeckLinkAudioInputPacket_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkAudioInputPacket_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkAudioInputPacket_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkAudioInputPacket_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkAudioInputPacket_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkAudioInputPacket_v7_1_GetSampleCount(This)\t\\\r\n    ( (This)->lpVtbl -> GetSampleCount(This) ) \r\n\r\n#define IDeckLinkAudioInputPacket_v7_1_GetBytes(This,buffer)\t\\\r\n    ( (This)->lpVtbl -> GetBytes(This,buffer) ) \r\n\r\n#define IDeckLinkAudioInputPacket_v7_1_GetAudioPacketTime(This,packetTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> GetAudioPacketTime(This,packetTime,timeScale) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkAudioInputPacket_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkVideoOutputCallback_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkVideoOutputCallback_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkVideoOutputCallback_v7_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkVideoOutputCallback_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9\")\r\n    IDeckLinkVideoOutputCallback_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE ScheduledFrameCompleted( \r\n            /* [in] */ IDeckLinkVideoFrame_v7_1 *completedFrame,\r\n            /* [in] */ BMDOutputFrameCompletionResult result) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkVideoOutputCallback_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkVideoOutputCallback_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkVideoOutputCallback_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkVideoOutputCallback_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkVideoOutputCallback_v7_1, ScheduledFrameCompleted)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduledFrameCompleted )( \r\n            IDeckLinkVideoOutputCallback_v7_1 * This,\r\n            /* [in] */ IDeckLinkVideoFrame_v7_1 *completedFrame,\r\n            /* [in] */ BMDOutputFrameCompletionResult result);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkVideoOutputCallback_v7_1Vtbl;\r\n\r\n    interface IDeckLinkVideoOutputCallback_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkVideoOutputCallback_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkVideoOutputCallback_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkVideoOutputCallback_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkVideoOutputCallback_v7_1_ScheduledFrameCompleted(This,completedFrame,result)\t\\\r\n    ( (This)->lpVtbl -> ScheduledFrameCompleted(This,completedFrame,result) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkVideoOutputCallback_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInputCallback_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkInputCallback_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInputCallback_v7_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInputCallback_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"7F94F328-5ED4-4E9F-9729-76A86BDC99CC\")\r\n    IDeckLinkInputCallback_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE VideoInputFrameArrived( \r\n            /* [in] */ IDeckLinkVideoInputFrame_v7_1 *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket_v7_1 *audioPacket) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInputCallback_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInputCallback_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInputCallback_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInputCallback_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInputCallback_v7_1, VideoInputFrameArrived)\r\n        HRESULT ( STDMETHODCALLTYPE *VideoInputFrameArrived )( \r\n            IDeckLinkInputCallback_v7_1 * This,\r\n            /* [in] */ IDeckLinkVideoInputFrame_v7_1 *videoFrame,\r\n            /* [in] */ IDeckLinkAudioInputPacket_v7_1 *audioPacket);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInputCallback_v7_1Vtbl;\r\n\r\n    interface IDeckLinkInputCallback_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkInputCallback_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInputCallback_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInputCallback_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInputCallback_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInputCallback_v7_1_VideoInputFrameArrived(This,videoFrame,audioPacket)\t\\\r\n    ( (This)->lpVtbl -> VideoInputFrameArrived(This,videoFrame,audioPacket) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInputCallback_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkOutput_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkOutput_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkOutput_v7_1 */\r\n/* [helpstring][local][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkOutput_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5\")\r\n    IDeckLinkOutput_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoOutput( \r\n            BMDDisplayMode displayMode) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetVideoOutputFrameMemoryAllocator( \r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrame( \r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            IDeckLinkVideoFrame_v7_1 **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE CreateVideoFrameFromBuffer( \r\n            void *buffer,\r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            IDeckLinkVideoFrame_v7_1 **outFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisplayVideoFrameSync( \r\n            IDeckLinkVideoFrame_v7_1 *theFrame) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleVideoFrame( \r\n            IDeckLinkVideoFrame_v7_1 *theFrame,\r\n            BMDTimeValue displayTime,\r\n            BMDTimeValue displayDuration,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetScheduledFrameCompletionCallback( \r\n            /* [in] */ IDeckLinkVideoOutputCallback_v7_1 *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioOutput( \r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioOutput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE WriteAudioSamplesSync( \r\n            void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE BeginAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EndAudioPreroll( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ScheduleAudioSamples( \r\n            void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            BMDTimeValue streamTime,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE FlushBufferedAudioSamples( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetAudioCallback( \r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartScheduledPlayback( \r\n            BMDTimeValue playbackStartTime,\r\n            BMDTimeScale timeScale,\r\n            double playbackSpeed) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopScheduledPlayback( \r\n            BMDTimeValue stopPlaybackAtTime,\r\n            BMDTimeValue *actualStopTime,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetHardwareReferenceClock( \r\n            BMDTimeScale desiredTimeScale,\r\n            BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkOutput_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, EnableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoOutput )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            BMDDisplayMode displayMode);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, DisableVideoOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoOutput )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, SetVideoOutputFrameMemoryAllocator)\r\n        HRESULT ( STDMETHODCALLTYPE *SetVideoOutputFrameMemoryAllocator )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            /* [in] */ IDeckLinkMemoryAllocator *theAllocator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, CreateVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrame )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            IDeckLinkVideoFrame_v7_1 **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, CreateVideoFrameFromBuffer)\r\n        HRESULT ( STDMETHODCALLTYPE *CreateVideoFrameFromBuffer )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            void *buffer,\r\n            int width,\r\n            int height,\r\n            int rowBytes,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDFrameFlags flags,\r\n            IDeckLinkVideoFrame_v7_1 **outFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, DisplayVideoFrameSync)\r\n        HRESULT ( STDMETHODCALLTYPE *DisplayVideoFrameSync )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            IDeckLinkVideoFrame_v7_1 *theFrame);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, ScheduleVideoFrame)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleVideoFrame )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            IDeckLinkVideoFrame_v7_1 *theFrame,\r\n            BMDTimeValue displayTime,\r\n            BMDTimeValue displayDuration,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, SetScheduledFrameCompletionCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetScheduledFrameCompletionCallback )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            /* [in] */ IDeckLinkVideoOutputCallback_v7_1 *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, EnableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioOutput )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, DisableAudioOutput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioOutput )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, WriteAudioSamplesSync)\r\n        HRESULT ( STDMETHODCALLTYPE *WriteAudioSamplesSync )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, BeginAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *BeginAudioPreroll )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, EndAudioPreroll)\r\n        HRESULT ( STDMETHODCALLTYPE *EndAudioPreroll )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, ScheduleAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ScheduleAudioSamples )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            BMDTimeValue streamTime,\r\n            BMDTimeScale timeScale,\r\n            /* [out] */ unsigned int *sampleFramesWritten);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            /* [out] */ unsigned int *bufferedSampleCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, FlushBufferedAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *FlushBufferedAudioSamples )( \r\n            IDeckLinkOutput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, SetAudioCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetAudioCallback )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            /* [in] */ IDeckLinkAudioOutputCallback *theCallback);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, StartScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StartScheduledPlayback )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            BMDTimeValue playbackStartTime,\r\n            BMDTimeScale timeScale,\r\n            double playbackSpeed);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, StopScheduledPlayback)\r\n        HRESULT ( STDMETHODCALLTYPE *StopScheduledPlayback )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            BMDTimeValue stopPlaybackAtTime,\r\n            BMDTimeValue *actualStopTime,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkOutput_v7_1, GetHardwareReferenceClock)\r\n        HRESULT ( STDMETHODCALLTYPE *GetHardwareReferenceClock )( \r\n            IDeckLinkOutput_v7_1 * This,\r\n            BMDTimeScale desiredTimeScale,\r\n            BMDTimeValue *elapsedTimeSinceSchedulerBegan);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkOutput_v7_1Vtbl;\r\n\r\n    interface IDeckLinkOutput_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkOutput_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkOutput_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkOutput_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkOutput_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkOutput_v7_1_DoesSupportVideoMode(This,displayMode,pixelFormat,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) ) \r\n\r\n#define IDeckLinkOutput_v7_1_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkOutput_v7_1_EnableVideoOutput(This,displayMode)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoOutput(This,displayMode) ) \r\n\r\n#define IDeckLinkOutput_v7_1_DisableVideoOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v7_1_SetVideoOutputFrameMemoryAllocator(This,theAllocator)\t\\\r\n    ( (This)->lpVtbl -> SetVideoOutputFrameMemoryAllocator(This,theAllocator) ) \r\n\r\n#define IDeckLinkOutput_v7_1_CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrame(This,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_1_CreateVideoFrameFromBuffer(This,buffer,width,height,rowBytes,pixelFormat,flags,outFrame)\t\\\r\n    ( (This)->lpVtbl -> CreateVideoFrameFromBuffer(This,buffer,width,height,rowBytes,pixelFormat,flags,outFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_1_DisplayVideoFrameSync(This,theFrame)\t\\\r\n    ( (This)->lpVtbl -> DisplayVideoFrameSync(This,theFrame) ) \r\n\r\n#define IDeckLinkOutput_v7_1_ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ScheduleVideoFrame(This,theFrame,displayTime,displayDuration,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v7_1_SetScheduledFrameCompletionCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetScheduledFrameCompletionCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_1_EnableAudioOutput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioOutput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkOutput_v7_1_DisableAudioOutput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioOutput(This) ) \r\n\r\n#define IDeckLinkOutput_v7_1_WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> WriteAudioSamplesSync(This,buffer,sampleFrameCount,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v7_1_BeginAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> BeginAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v7_1_EndAudioPreroll(This)\t\\\r\n    ( (This)->lpVtbl -> EndAudioPreroll(This) ) \r\n\r\n#define IDeckLinkOutput_v7_1_ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten)\t\\\r\n    ( (This)->lpVtbl -> ScheduleAudioSamples(This,buffer,sampleFrameCount,streamTime,timeScale,sampleFramesWritten) ) \r\n\r\n#define IDeckLinkOutput_v7_1_GetBufferedAudioSampleFrameCount(This,bufferedSampleCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleCount) ) \r\n\r\n#define IDeckLinkOutput_v7_1_FlushBufferedAudioSamples(This)\t\\\r\n    ( (This)->lpVtbl -> FlushBufferedAudioSamples(This) ) \r\n\r\n#define IDeckLinkOutput_v7_1_SetAudioCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetAudioCallback(This,theCallback) ) \r\n\r\n#define IDeckLinkOutput_v7_1_StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed)\t\\\r\n    ( (This)->lpVtbl -> StartScheduledPlayback(This,playbackStartTime,timeScale,playbackSpeed) ) \r\n\r\n#define IDeckLinkOutput_v7_1_StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> StopScheduledPlayback(This,stopPlaybackAtTime,actualStopTime,timeScale) ) \r\n\r\n#define IDeckLinkOutput_v7_1_GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan)\t\\\r\n    ( (This)->lpVtbl -> GetHardwareReferenceClock(This,desiredTimeScale,elapsedTimeSinceSchedulerBegan) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkOutput_v7_1_INTERFACE_DEFINED__ */\r\n\r\n\r\n#ifndef __IDeckLinkInput_v7_1_INTERFACE_DEFINED__\r\n#define __IDeckLinkInput_v7_1_INTERFACE_DEFINED__\r\n\r\n/* interface IDeckLinkInput_v7_1 */\r\n/* [helpstring][uuid][object] */ \r\n\r\n\r\nEXTERN_C const IID IID_IDeckLinkInput_v7_1;\r\n\r\n#if defined(__cplusplus) && !defined(CINTERFACE)\r\n    \r\n    MIDL_INTERFACE(\"2B54EDEF-5B32-429F-BA11-BB990596EACD\")\r\n    IDeckLinkInput_v7_1 : public IUnknown\r\n    {\r\n    public:\r\n        virtual HRESULT STDMETHODCALLTYPE DoesSupportVideoMode( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetDisplayModeIterator( \r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableVideoInput( \r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDVideoInputFlags flags) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableVideoInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE EnableAudioInput( \r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE DisableAudioInput( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE ReadAudioSamples( \r\n            void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesRead,\r\n            /* [out] */ BMDTimeValue *audioPacketTime,\r\n            BMDTimeScale timeScale) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE GetBufferedAudioSampleFrameCount( \r\n            /* [out] */ unsigned int *bufferedSampleCount) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StartStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE StopStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE PauseStreams( void) = 0;\r\n        \r\n        virtual HRESULT STDMETHODCALLTYPE SetCallback( \r\n            /* [in] */ IDeckLinkInputCallback_v7_1 *theCallback) = 0;\r\n        \r\n    };\r\n    \r\n    \r\n#else \t/* C style interface */\r\n\r\n    typedef struct IDeckLinkInput_v7_1Vtbl\r\n    {\r\n        BEGIN_INTERFACE\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, QueryInterface)\r\n        HRESULT ( STDMETHODCALLTYPE *QueryInterface )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            /* [in] */ REFIID riid,\r\n            /* [annotation][iid_is][out] */ \r\n            _COM_Outptr_  void **ppvObject);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, AddRef)\r\n        ULONG ( STDMETHODCALLTYPE *AddRef )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IUnknown, Release)\r\n        ULONG ( STDMETHODCALLTYPE *Release )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, DoesSupportVideoMode)\r\n        HRESULT ( STDMETHODCALLTYPE *DoesSupportVideoMode )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            /* [out] */ BMDDisplayModeSupport_v10_11 *result);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, GetDisplayModeIterator)\r\n        HRESULT ( STDMETHODCALLTYPE *GetDisplayModeIterator )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            /* [out] */ IDeckLinkDisplayModeIterator_v7_1 **iterator);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, EnableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableVideoInput )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            BMDDisplayMode displayMode,\r\n            BMDPixelFormat pixelFormat,\r\n            BMDVideoInputFlags flags);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, DisableVideoInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableVideoInput )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, EnableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *EnableAudioInput )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            BMDAudioSampleRate sampleRate,\r\n            BMDAudioSampleType sampleType,\r\n            unsigned int channelCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, DisableAudioInput)\r\n        HRESULT ( STDMETHODCALLTYPE *DisableAudioInput )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, ReadAudioSamples)\r\n        HRESULT ( STDMETHODCALLTYPE *ReadAudioSamples )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            void *buffer,\r\n            unsigned int sampleFrameCount,\r\n            /* [out] */ unsigned int *sampleFramesRead,\r\n            /* [out] */ BMDTimeValue *audioPacketTime,\r\n            BMDTimeScale timeScale);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, GetBufferedAudioSampleFrameCount)\r\n        HRESULT ( STDMETHODCALLTYPE *GetBufferedAudioSampleFrameCount )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            /* [out] */ unsigned int *bufferedSampleCount);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, StartStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StartStreams )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, StopStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *StopStreams )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, PauseStreams)\r\n        HRESULT ( STDMETHODCALLTYPE *PauseStreams )( \r\n            IDeckLinkInput_v7_1 * This);\r\n        \r\n        DECLSPEC_XFGVIRT(IDeckLinkInput_v7_1, SetCallback)\r\n        HRESULT ( STDMETHODCALLTYPE *SetCallback )( \r\n            IDeckLinkInput_v7_1 * This,\r\n            /* [in] */ IDeckLinkInputCallback_v7_1 *theCallback);\r\n        \r\n        END_INTERFACE\r\n    } IDeckLinkInput_v7_1Vtbl;\r\n\r\n    interface IDeckLinkInput_v7_1\r\n    {\r\n        CONST_VTBL struct IDeckLinkInput_v7_1Vtbl *lpVtbl;\r\n    };\r\n\r\n    \r\n\r\n#ifdef COBJMACROS\r\n\r\n\r\n#define IDeckLinkInput_v7_1_QueryInterface(This,riid,ppvObject)\t\\\r\n    ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) \r\n\r\n#define IDeckLinkInput_v7_1_AddRef(This)\t\\\r\n    ( (This)->lpVtbl -> AddRef(This) ) \r\n\r\n#define IDeckLinkInput_v7_1_Release(This)\t\\\r\n    ( (This)->lpVtbl -> Release(This) ) \r\n\r\n\r\n#define IDeckLinkInput_v7_1_DoesSupportVideoMode(This,displayMode,pixelFormat,result)\t\\\r\n    ( (This)->lpVtbl -> DoesSupportVideoMode(This,displayMode,pixelFormat,result) ) \r\n\r\n#define IDeckLinkInput_v7_1_GetDisplayModeIterator(This,iterator)\t\\\r\n    ( (This)->lpVtbl -> GetDisplayModeIterator(This,iterator) ) \r\n\r\n#define IDeckLinkInput_v7_1_EnableVideoInput(This,displayMode,pixelFormat,flags)\t\\\r\n    ( (This)->lpVtbl -> EnableVideoInput(This,displayMode,pixelFormat,flags) ) \r\n\r\n#define IDeckLinkInput_v7_1_DisableVideoInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableVideoInput(This) ) \r\n\r\n#define IDeckLinkInput_v7_1_EnableAudioInput(This,sampleRate,sampleType,channelCount)\t\\\r\n    ( (This)->lpVtbl -> EnableAudioInput(This,sampleRate,sampleType,channelCount) ) \r\n\r\n#define IDeckLinkInput_v7_1_DisableAudioInput(This)\t\\\r\n    ( (This)->lpVtbl -> DisableAudioInput(This) ) \r\n\r\n#define IDeckLinkInput_v7_1_ReadAudioSamples(This,buffer,sampleFrameCount,sampleFramesRead,audioPacketTime,timeScale)\t\\\r\n    ( (This)->lpVtbl -> ReadAudioSamples(This,buffer,sampleFrameCount,sampleFramesRead,audioPacketTime,timeScale) ) \r\n\r\n#define IDeckLinkInput_v7_1_GetBufferedAudioSampleFrameCount(This,bufferedSampleCount)\t\\\r\n    ( (This)->lpVtbl -> GetBufferedAudioSampleFrameCount(This,bufferedSampleCount) ) \r\n\r\n#define IDeckLinkInput_v7_1_StartStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StartStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_1_StopStreams(This)\t\\\r\n    ( (This)->lpVtbl -> StopStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_1_PauseStreams(This)\t\\\r\n    ( (This)->lpVtbl -> PauseStreams(This) ) \r\n\r\n#define IDeckLinkInput_v7_1_SetCallback(This,theCallback)\t\\\r\n    ( (This)->lpVtbl -> SetCallback(This,theCallback) ) \r\n\r\n#endif /* COBJMACROS */\r\n\r\n\r\n#endif \t/* C style interface */\r\n\r\n\r\n\r\n\r\n#endif \t/* __IDeckLinkInput_v7_1_INTERFACE_DEFINED__ */\r\n\r\n#endif /* __DeckLinkAPI_LIBRARY_DEFINED__ */\r\n\r\n/* Additional Prototypes for ALL interfaces */\r\n\r\n/* end of Additional Prototypes */\r\n\r\n#ifdef __cplusplus\r\n}\r\n#endif\r\n\r\n#endif\r\n\r\n\r\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI.h",
    "content": "/* -LICENSE-START-\n ** Copyright (c) 2022 Blackmagic Design\n **  \n ** Permission is hereby granted, free of charge, to any person or organization \n ** obtaining a copy of the software and accompanying documentation (the \n ** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n ** and transmit the Software, and to prepare derivative works of the Software, \n ** and to permit third-parties to whom the Software is furnished to do so, in \n ** accordance with:\n ** \n ** (1) if the Software is obtained from Blackmagic Design, the End User License \n ** Agreement for the Software Development Kit (\"EULA\") available at \n ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n ** \n ** (2) if the Software is obtained from any third party, such licensing terms \n ** as notified by that third party,\n ** \n ** and all subject to the following:\n ** \n ** (3) the copyright notices in the Software and this entire statement, \n ** including the above license grant, this restriction and the following \n ** disclaimer, must be included in all copies of the Software, in whole or in \n ** part, and all derivative works of the Software, unless such copies or \n ** derivative works are solely in the form of machine-executable object code \n ** generated by a source language processor.\n ** \n ** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n ** DEALINGS IN THE SOFTWARE.\n ** \n ** A copy of the Software is available free of charge at \n ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n ** \n ** -LICENSE-END-\n */\n\n\n#ifndef BMD_DECKLINKAPI_H\n#define BMD_DECKLINKAPI_H\n\n\n#ifndef BMD_CONST\n    #if defined(_MSC_VER)\n        #define BMD_CONST __declspec(selectany) static const\n    #else\n        #define BMD_CONST static const\n    #endif\n#endif\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n/* DeckLink API */\n\n#include <stdint.h>\n#include \"LinuxCOM.h\"\n\n#include \"DeckLinkAPITypes.h\"\n#include \"DeckLinkAPIModes.h\"\n#include \"DeckLinkAPIDiscovery.h\"\n#include \"DeckLinkAPIConfiguration.h\"\n#include \"DeckLinkAPIDeckControl.h\"\n\n#define BLACKMAGIC_DECKLINK_API_MAGIC\t1\n\n// Type Declarations\n\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkVideoOutputCallback                 = /* 20AA5225-1958-47CB-820B-80A8D521A6EE */ { 0x20,0xAA,0x52,0x25,0x19,0x58,0x47,0xCB,0x82,0x0B,0x80,0xA8,0xD5,0x21,0xA6,0xEE };\nBMD_CONST REFIID IID_IDeckLinkInputCallback                       = /* C6FCE4C9-C4E4-4047-82FB-5D238232A902 */ { 0xC6,0xFC,0xE4,0xC9,0xC4,0xE4,0x40,0x47,0x82,0xFB,0x5D,0x23,0x82,0x32,0xA9,0x02 };\nBMD_CONST REFIID IID_IDeckLinkEncoderInputCallback                = /* ACF13E61-F4A0-4974-A6A7-59AFF6268B31 */ { 0xAC,0xF1,0x3E,0x61,0xF4,0xA0,0x49,0x74,0xA6,0xA7,0x59,0xAF,0xF6,0x26,0x8B,0x31 };\nBMD_CONST REFIID IID_IDeckLinkMemoryAllocator                     = /* B36EB6E7-9D29-4AA8-92EF-843B87A289E8 */ { 0xB3,0x6E,0xB6,0xE7,0x9D,0x29,0x4A,0xA8,0x92,0xEF,0x84,0x3B,0x87,0xA2,0x89,0xE8 };\nBMD_CONST REFIID IID_IDeckLinkAudioOutputCallback                 = /* 403C681B-7F46-4A12-B993-2BB127084EE6 */ { 0x40,0x3C,0x68,0x1B,0x7F,0x46,0x4A,0x12,0xB9,0x93,0x2B,0xB1,0x27,0x08,0x4E,0xE6 };\nBMD_CONST REFIID IID_IDeckLinkIterator                            = /* 50FB36CD-3063-4B73-BDBB-958087F2D8BA */ { 0x50,0xFB,0x36,0xCD,0x30,0x63,0x4B,0x73,0xBD,0xBB,0x95,0x80,0x87,0xF2,0xD8,0xBA };\nBMD_CONST REFIID IID_IDeckLinkAPIInformation                      = /* 7BEA3C68-730D-4322-AF34-8A7152B532A4 */ { 0x7B,0xEA,0x3C,0x68,0x73,0x0D,0x43,0x22,0xAF,0x34,0x8A,0x71,0x52,0xB5,0x32,0xA4 };\nBMD_CONST REFIID IID_IDeckLinkOutput                              = /* BE2D9020-461E-442F-84B7-E949CB953B9D */ { 0xBE,0x2D,0x90,0x20,0x46,0x1E,0x44,0x2F,0x84,0xB7,0xE9,0x49,0xCB,0x95,0x3B,0x9D };\nBMD_CONST REFIID IID_IDeckLinkInput                               = /* C21CDB6E-F414-46E4-A636-80A566E0ED37 */ { 0xC2,0x1C,0xDB,0x6E,0xF4,0x14,0x46,0xE4,0xA6,0x36,0x80,0xA5,0x66,0xE0,0xED,0x37 };\nBMD_CONST REFIID IID_IDeckLinkHDMIInputEDID                       = /* ABBBACBC-45BC-4665-9D92-ACE6E5A97902 */ { 0xAB,0xBB,0xAC,0xBC,0x45,0xBC,0x46,0x65,0x9D,0x92,0xAC,0xE6,0xE5,0xA9,0x79,0x02 };\nBMD_CONST REFIID IID_IDeckLinkEncoderInput                        = /* F222551D-13DF-4FD8-B587-9D4F19EC12C9 */ { 0xF2,0x22,0x55,0x1D,0x13,0xDF,0x4F,0xD8,0xB5,0x87,0x9D,0x4F,0x19,0xEC,0x12,0xC9 };\nBMD_CONST REFIID IID_IDeckLinkVideoFrame                          = /* 3F716FE0-F023-4111-BE5D-EF4414C05B17 */ { 0x3F,0x71,0x6F,0xE0,0xF0,0x23,0x41,0x11,0xBE,0x5D,0xEF,0x44,0x14,0xC0,0x5B,0x17 };\nBMD_CONST REFIID IID_IDeckLinkMutableVideoFrame                   = /* 69E2639F-40DA-4E19-B6F2-20ACE815C390 */ { 0x69,0xE2,0x63,0x9F,0x40,0xDA,0x4E,0x19,0xB6,0xF2,0x20,0xAC,0xE8,0x15,0xC3,0x90 };\nBMD_CONST REFIID IID_IDeckLinkVideoFrame3DExtensions              = /* DA0F7E4A-EDC7-48A8-9CDD-2DB51C729CD7 */ { 0xDA,0x0F,0x7E,0x4A,0xED,0xC7,0x48,0xA8,0x9C,0xDD,0x2D,0xB5,0x1C,0x72,0x9C,0xD7 };\nBMD_CONST REFIID IID_IDeckLinkVideoFrameMetadataExtensions        = /* E232A5B7-4DB4-44C9-9152-F47C12E5F051 */ { 0xE2,0x32,0xA5,0xB7,0x4D,0xB4,0x44,0xC9,0x91,0x52,0xF4,0x7C,0x12,0xE5,0xF0,0x51 };\nBMD_CONST REFIID IID_IDeckLinkVideoInputFrame                     = /* 05CFE374-537C-4094-9A57-680525118F44 */ { 0x05,0xCF,0xE3,0x74,0x53,0x7C,0x40,0x94,0x9A,0x57,0x68,0x05,0x25,0x11,0x8F,0x44 };\nBMD_CONST REFIID IID_IDeckLinkAncillaryPacket                     = /* CC5BBF7E-029C-4D3B-9158-6000EF5E3670 */ { 0xCC,0x5B,0xBF,0x7E,0x02,0x9C,0x4D,0x3B,0x91,0x58,0x60,0x00,0xEF,0x5E,0x36,0x70 };\nBMD_CONST REFIID IID_IDeckLinkAncillaryPacketIterator             = /* 3FC8994B-88FB-4C17-968F-9AAB69D964A7 */ { 0x3F,0xC8,0x99,0x4B,0x88,0xFB,0x4C,0x17,0x96,0x8F,0x9A,0xAB,0x69,0xD9,0x64,0xA7 };\nBMD_CONST REFIID IID_IDeckLinkVideoFrameAncillaryPackets          = /* 6C186C0F-459E-41D8-AEE2-4812D81AEE68 */ { 0x6C,0x18,0x6C,0x0F,0x45,0x9E,0x41,0xD8,0xAE,0xE2,0x48,0x12,0xD8,0x1A,0xEE,0x68 };\nBMD_CONST REFIID IID_IDeckLinkVideoFrameAncillary                 = /* 732E723C-D1A4-4E29-9E8E-4A88797A0004 */ { 0x73,0x2E,0x72,0x3C,0xD1,0xA4,0x4E,0x29,0x9E,0x8E,0x4A,0x88,0x79,0x7A,0x00,0x04 };\nBMD_CONST REFIID IID_IDeckLinkEncoderPacket                       = /* B693F36C-316E-4AF1-B6C2-F389A4BCA620 */ { 0xB6,0x93,0xF3,0x6C,0x31,0x6E,0x4A,0xF1,0xB6,0xC2,0xF3,0x89,0xA4,0xBC,0xA6,0x20 };\nBMD_CONST REFIID IID_IDeckLinkEncoderVideoPacket                  = /* 4E7FD944-E8C7-4EAC-B8C0-7B77F80F5AE0 */ { 0x4E,0x7F,0xD9,0x44,0xE8,0xC7,0x4E,0xAC,0xB8,0xC0,0x7B,0x77,0xF8,0x0F,0x5A,0xE0 };\nBMD_CONST REFIID IID_IDeckLinkEncoderAudioPacket                  = /* 49E8EDC8-693B-4E14-8EF6-12C658F5A07A */ { 0x49,0xE8,0xED,0xC8,0x69,0x3B,0x4E,0x14,0x8E,0xF6,0x12,0xC6,0x58,0xF5,0xA0,0x7A };\nBMD_CONST REFIID IID_IDeckLinkH265NALPacket                       = /* 639C8E0B-68D5-4BDE-A6D4-95F3AEAFF2E7 */ { 0x63,0x9C,0x8E,0x0B,0x68,0xD5,0x4B,0xDE,0xA6,0xD4,0x95,0xF3,0xAE,0xAF,0xF2,0xE7 };\nBMD_CONST REFIID IID_IDeckLinkAudioInputPacket                    = /* E43D5870-2894-11DE-8C30-0800200C9A66 */ { 0xE4,0x3D,0x58,0x70,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66 };\nBMD_CONST REFIID IID_IDeckLinkScreenPreviewCallback               = /* B1D3F49A-85FE-4C5D-95C8-0B5D5DCCD438 */ { 0xB1,0xD3,0xF4,0x9A,0x85,0xFE,0x4C,0x5D,0x95,0xC8,0x0B,0x5D,0x5D,0xCC,0xD4,0x38 };\nBMD_CONST REFIID IID_IDeckLinkGLScreenPreviewHelper               = /* 504E2209-CAC7-4C1A-9FB4-C5BB6274D22F */ { 0x50,0x4E,0x22,0x09,0xCA,0xC7,0x4C,0x1A,0x9F,0xB4,0xC5,0xBB,0x62,0x74,0xD2,0x2F };\nBMD_CONST REFIID IID_IDeckLinkNotificationCallback                = /* B002A1EC-070D-4288-8289-BD5D36E5FF0D */ { 0xB0,0x02,0xA1,0xEC,0x07,0x0D,0x42,0x88,0x82,0x89,0xBD,0x5D,0x36,0xE5,0xFF,0x0D };\nBMD_CONST REFIID IID_IDeckLinkNotification                        = /* B85DF4C8-BDF5-47C1-8064-28162EBDD4EB */ { 0xB8,0x5D,0xF4,0xC8,0xBD,0xF5,0x47,0xC1,0x80,0x64,0x28,0x16,0x2E,0xBD,0xD4,0xEB };\nBMD_CONST REFIID IID_IDeckLinkProfileAttributes                   = /* 17D4BF8E-4911-473A-80A0-731CF6FF345B */ { 0x17,0xD4,0xBF,0x8E,0x49,0x11,0x47,0x3A,0x80,0xA0,0x73,0x1C,0xF6,0xFF,0x34,0x5B };\nBMD_CONST REFIID IID_IDeckLinkProfileIterator                     = /* 29E5A8C0-8BE4-46EB-93AC-31DAAB5B7BF2 */ { 0x29,0xE5,0xA8,0xC0,0x8B,0xE4,0x46,0xEB,0x93,0xAC,0x31,0xDA,0xAB,0x5B,0x7B,0xF2 };\nBMD_CONST REFIID IID_IDeckLinkProfile                             = /* 16093466-674A-432B-9DA0-1AC2C5A8241C */ { 0x16,0x09,0x34,0x66,0x67,0x4A,0x43,0x2B,0x9D,0xA0,0x1A,0xC2,0xC5,0xA8,0x24,0x1C };\nBMD_CONST REFIID IID_IDeckLinkProfileCallback                     = /* A4F9341E-97AA-4E04-8935-15F809898CEA */ { 0xA4,0xF9,0x34,0x1E,0x97,0xAA,0x4E,0x04,0x89,0x35,0x15,0xF8,0x09,0x89,0x8C,0xEA };\nBMD_CONST REFIID IID_IDeckLinkProfileManager                      = /* 30D41429-3998-4B6D-84F8-78C94A797C6E */ { 0x30,0xD4,0x14,0x29,0x39,0x98,0x4B,0x6D,0x84,0xF8,0x78,0xC9,0x4A,0x79,0x7C,0x6E };\nBMD_CONST REFIID IID_IDeckLinkStatus                              = /* 5F558200-4028-49BC-BEAC-DB3FA4A96E46 */ { 0x5F,0x55,0x82,0x00,0x40,0x28,0x49,0xBC,0xBE,0xAC,0xDB,0x3F,0xA4,0xA9,0x6E,0x46 };\nBMD_CONST REFIID IID_IDeckLinkKeyer                               = /* 89AFCAF5-65F8-421E-98F7-96FE5F5BFBA3 */ { 0x89,0xAF,0xCA,0xF5,0x65,0xF8,0x42,0x1E,0x98,0xF7,0x96,0xFE,0x5F,0x5B,0xFB,0xA3 };\nBMD_CONST REFIID IID_IDeckLinkVideoConversion                     = /* 3BBCB8A2-DA2C-42D9-B5D8-88083644E99A */ { 0x3B,0xBC,0xB8,0xA2,0xDA,0x2C,0x42,0xD9,0xB5,0xD8,0x88,0x08,0x36,0x44,0xE9,0x9A };\nBMD_CONST REFIID IID_IDeckLinkDeviceNotificationCallback          = /* 4997053B-0ADF-4CC8-AC70-7A50C4BE728F */ { 0x49,0x97,0x05,0x3B,0x0A,0xDF,0x4C,0xC8,0xAC,0x70,0x7A,0x50,0xC4,0xBE,0x72,0x8F };\nBMD_CONST REFIID IID_IDeckLinkDiscovery                           = /* CDBF631C-BC76-45FA-B44D-C55059BC6101 */ { 0xCD,0xBF,0x63,0x1C,0xBC,0x76,0x45,0xFA,0xB4,0x4D,0xC5,0x50,0x59,0xBC,0x61,0x01 };\n\n/* Enum BMDVideoOutputFlags - Flags to control the output of ancillary data along with video. */\n\ntypedef uint32_t BMDVideoOutputFlags;\nenum _BMDVideoOutputFlags {\n    bmdVideoOutputFlagDefault                                    = 0,\n    bmdVideoOutputVANC                                           = 1 << 0,\n    bmdVideoOutputVITC                                           = 1 << 1,\n    bmdVideoOutputRP188                                          = 1 << 2,\n    bmdVideoOutputDualStream3D                                   = 1 << 4,\n    bmdVideoOutputSynchronizeToPlaybackGroup                     = 1 << 6\n};\n\n/* Enum BMDSupportedVideoModeFlags - Flags to describe supported video modes */\n\ntypedef uint32_t BMDSupportedVideoModeFlags;\nenum _BMDSupportedVideoModeFlags {\n    bmdSupportedVideoModeDefault                                 = 0,\n    bmdSupportedVideoModeKeying                                  = 1 << 0,\n    bmdSupportedVideoModeDualStream3D                            = 1 << 1,\n    bmdSupportedVideoModeSDISingleLink                           = 1 << 2,\n    bmdSupportedVideoModeSDIDualLink                             = 1 << 3,\n    bmdSupportedVideoModeSDIQuadLink                             = 1 << 4,\n    bmdSupportedVideoModeInAnyProfile                            = 1 << 5\n};\n\n/* Enum BMDPacketType - Type of packet */\n\ntypedef uint32_t BMDPacketType;\nenum _BMDPacketType {\n    bmdPacketTypeStreamInterruptedMarker                         = /* 'sint' */ 0x73696E74,\t// A packet of this type marks the time when a video stream was interrupted, for example by a disconnected cable\n    bmdPacketTypeStreamData                                      = /* 'sdat' */ 0x73646174\t// Regular stream data\n};\n\n/* Enum BMDFrameFlags - Frame flags */\n\ntypedef uint32_t BMDFrameFlags;\nenum _BMDFrameFlags {\n    bmdFrameFlagDefault                                          = 0,\n    bmdFrameFlagFlipVertical                                     = 1 << 0,\n    bmdFrameContainsHDRMetadata                                  = 1 << 1,\n\n    /* Flags that are applicable only to instances of IDeckLinkVideoInputFrame */\n\n    bmdFrameCapturedAsPsF                                        = 1 << 30,\n    bmdFrameHasNoInputSource                                     = 1 << 31\n};\n\n/* Enum BMDVideoInputFlags - Flags applicable to video input */\n\ntypedef uint32_t BMDVideoInputFlags;\nenum _BMDVideoInputFlags {\n    bmdVideoInputFlagDefault                                     = 0,\n    bmdVideoInputEnableFormatDetection                           = 1 << 0,\n    bmdVideoInputDualStream3D                                    = 1 << 1,\n    bmdVideoInputSynchronizeToCaptureGroup                       = 1 << 2\n};\n\n/* Enum BMDVideoInputFormatChangedEvents - Bitmask passed to the VideoInputFormatChanged notification to identify the properties of the input signal that have changed */\n\ntypedef uint32_t BMDVideoInputFormatChangedEvents;\nenum _BMDVideoInputFormatChangedEvents {\n    bmdVideoInputDisplayModeChanged                              = 1 << 0,\n    bmdVideoInputFieldDominanceChanged                           = 1 << 1,\n    bmdVideoInputColorspaceChanged                               = 1 << 2\n};\n\n/* Enum BMDDetectedVideoInputFormatFlags - Flags passed to the VideoInputFormatChanged notification to describe the detected video input signal */\n\ntypedef uint32_t BMDDetectedVideoInputFormatFlags;\nenum _BMDDetectedVideoInputFormatFlags {\n    bmdDetectedVideoInputYCbCr422                                = 1 << 0,\n    bmdDetectedVideoInputRGB444                                  = 1 << 1,\n    bmdDetectedVideoInputDualStream3D                            = 1 << 2,\n    bmdDetectedVideoInput12BitDepth                              = 1 << 3,\n    bmdDetectedVideoInput10BitDepth                              = 1 << 4,\n    bmdDetectedVideoInput8BitDepth                               = 1 << 5\n};\n\n/* Enum BMDDeckLinkCapturePassthroughMode - Enumerates whether the video output is electrically connected to the video input or if the clean switching mode is enabled */\n\ntypedef uint32_t BMDDeckLinkCapturePassthroughMode;\nenum _BMDDeckLinkCapturePassthroughMode {\n    bmdDeckLinkCapturePassthroughModeDisabled                    = /* 'pdis' */ 0x70646973,\n    bmdDeckLinkCapturePassthroughModeDirect                      = /* 'pdir' */ 0x70646972,\n    bmdDeckLinkCapturePassthroughModeCleanSwitch                 = /* 'pcln' */ 0x70636C6E\n};\n\n/* Enum BMDOutputFrameCompletionResult - Frame Completion Callback */\n\ntypedef uint32_t BMDOutputFrameCompletionResult;\nenum _BMDOutputFrameCompletionResult {\n    bmdOutputFrameCompleted,\n    bmdOutputFrameDisplayedLate,\n    bmdOutputFrameDropped,\n    bmdOutputFrameFlushed\n};\n\n/* Enum BMDReferenceStatus - GenLock input status */\n\ntypedef uint32_t BMDReferenceStatus;\nenum _BMDReferenceStatus {\n    bmdReferenceUnlocked                                         = 0,\n    bmdReferenceNotSupportedByHardware                           = 1 << 0,\n    bmdReferenceLocked                                           = 1 << 1\n};\n\n/* Enum BMDAudioFormat - Audio Format */\n\ntypedef uint32_t BMDAudioFormat;\nenum _BMDAudioFormat {\n    bmdAudioFormatPCM                                            = /* 'lpcm' */ 0x6C70636D\t// Linear signed PCM samples\n};\n\n/* Enum BMDAudioSampleRate - Audio sample rates supported for output/input */\n\ntypedef uint32_t BMDAudioSampleRate;\nenum _BMDAudioSampleRate {\n    bmdAudioSampleRate48kHz                                      = 48000\n};\n\n/* Enum BMDAudioSampleType - Audio sample sizes supported for output/input */\n\ntypedef uint32_t BMDAudioSampleType;\nenum _BMDAudioSampleType {\n    bmdAudioSampleType16bitInteger                               = 16,\n    bmdAudioSampleType32bitInteger                               = 32\n};\n\n/* Enum BMDAudioOutputStreamType - Audio output stream type */\n\ntypedef uint32_t BMDAudioOutputStreamType;\nenum _BMDAudioOutputStreamType {\n    bmdAudioOutputStreamContinuous,\n    bmdAudioOutputStreamContinuousDontResample,\n    bmdAudioOutputStreamTimestamped\n};\n\n/* Enum BMDAncillaryPacketFormat - Ancillary packet format */\n\ntypedef uint32_t BMDAncillaryPacketFormat;\nenum _BMDAncillaryPacketFormat {\n    bmdAncillaryPacketFormatUInt8                                = /* 'ui08' */ 0x75693038,\n    bmdAncillaryPacketFormatUInt16                               = /* 'ui16' */ 0x75693136,\n    bmdAncillaryPacketFormatYCbCr10                              = /* 'v210' */ 0x76323130\n};\n\n/* Enum BMDTimecodeFormat - Timecode formats for frame metadata */\n\ntypedef uint32_t BMDTimecodeFormat;\nenum _BMDTimecodeFormat {\n    bmdTimecodeRP188VITC1                                        = /* 'rpv1' */ 0x72707631,\t// RP188 timecode where DBB1 equals VITC1 (line 9)\n    bmdTimecodeRP188VITC2                                        = /* 'rp12' */ 0x72703132,\t// RP188 timecode where DBB1 equals VITC2 (line 9 for progressive or line 571 for interlaced/PsF)\n    bmdTimecodeRP188LTC                                          = /* 'rplt' */ 0x72706C74,\t// RP188 timecode where DBB1 equals LTC (line 10)\n    bmdTimecodeRP188HighFrameRate                                = /* 'rphr' */ 0x72706872,\t// RP188 timecode where DBB1 is an HFRTC (SMPTE ST 12-3), the only timecode allowing the frame value to go above 30\n    bmdTimecodeRP188Any                                          = /* 'rp18' */ 0x72703138,\t// Convenience for capture, returning the first valid timecode in {HFRTC (if supported), VITC1, LTC, VITC2}\n    bmdTimecodeVITC                                              = /* 'vitc' */ 0x76697463,\n    bmdTimecodeVITCField2                                        = /* 'vit2' */ 0x76697432,\n    bmdTimecodeSerial                                            = /* 'seri' */ 0x73657269\n};\n\n/* Enum BMDAnalogVideoFlags - Analog video display flags */\n\ntypedef uint32_t BMDAnalogVideoFlags;\nenum _BMDAnalogVideoFlags {\n    bmdAnalogVideoFlagCompositeSetup75                           = 1 << 0,\n    bmdAnalogVideoFlagComponentBetacamLevels                     = 1 << 1\n};\n\n/* Enum BMDAudioOutputAnalogAESSwitch - Audio output Analog/AESEBU switch */\n\ntypedef uint32_t BMDAudioOutputAnalogAESSwitch;\nenum _BMDAudioOutputAnalogAESSwitch {\n    bmdAudioOutputSwitchAESEBU                                   = /* 'aes ' */ 0x61657320,\n    bmdAudioOutputSwitchAnalog                                   = /* 'anlg' */ 0x616E6C67\n};\n\n/* Enum BMDVideoOutputConversionMode - Video/audio conversion mode */\n\ntypedef uint32_t BMDVideoOutputConversionMode;\nenum _BMDVideoOutputConversionMode {\n    bmdNoVideoOutputConversion                                   = /* 'none' */ 0x6E6F6E65,\n    bmdVideoOutputLetterboxDownconversion                        = /* 'ltbx' */ 0x6C746278,\n    bmdVideoOutputAnamorphicDownconversion                       = /* 'amph' */ 0x616D7068,\n    bmdVideoOutputHD720toHD1080Conversion                        = /* '720c' */ 0x37323063,\n    bmdVideoOutputHardwareLetterboxDownconversion                = /* 'HWlb' */ 0x48576C62,\n    bmdVideoOutputHardwareAnamorphicDownconversion               = /* 'HWam' */ 0x4857616D,\n    bmdVideoOutputHardwareCenterCutDownconversion                = /* 'HWcc' */ 0x48576363,\n    bmdVideoOutputHardware720p1080pCrossconversion               = /* 'xcap' */ 0x78636170,\n    bmdVideoOutputHardwareAnamorphic720pUpconversion             = /* 'ua7p' */ 0x75613770,\n    bmdVideoOutputHardwareAnamorphic1080iUpconversion            = /* 'ua1i' */ 0x75613169,\n    bmdVideoOutputHardwareAnamorphic149To720pUpconversion        = /* 'u47p' */ 0x75343770,\n    bmdVideoOutputHardwareAnamorphic149To1080iUpconversion       = /* 'u41i' */ 0x75343169,\n    bmdVideoOutputHardwarePillarbox720pUpconversion              = /* 'up7p' */ 0x75703770,\n    bmdVideoOutputHardwarePillarbox1080iUpconversion             = /* 'up1i' */ 0x75703169\n};\n\n/* Enum BMDVideoInputConversionMode - Video input conversion mode */\n\ntypedef uint32_t BMDVideoInputConversionMode;\nenum _BMDVideoInputConversionMode {\n    bmdNoVideoInputConversion                                    = /* 'none' */ 0x6E6F6E65,\n    bmdVideoInputLetterboxDownconversionFromHD1080               = /* '10lb' */ 0x31306C62,\n    bmdVideoInputAnamorphicDownconversionFromHD1080              = /* '10am' */ 0x3130616D,\n    bmdVideoInputLetterboxDownconversionFromHD720                = /* '72lb' */ 0x37326C62,\n    bmdVideoInputAnamorphicDownconversionFromHD720               = /* '72am' */ 0x3732616D,\n    bmdVideoInputLetterboxUpconversion                           = /* 'lbup' */ 0x6C627570,\n    bmdVideoInputAnamorphicUpconversion                          = /* 'amup' */ 0x616D7570\n};\n\n/* Enum BMDVideo3DPackingFormat - Video 3D packing format */\n\ntypedef uint32_t BMDVideo3DPackingFormat;\nenum _BMDVideo3DPackingFormat {\n    bmdVideo3DPackingSidebySideHalf                              = /* 'sbsh' */ 0x73627368,\n    bmdVideo3DPackingLinebyLine                                  = /* 'lbyl' */ 0x6C62796C,\n    bmdVideo3DPackingTopAndBottom                                = /* 'tabo' */ 0x7461626F,\n    bmdVideo3DPackingFramePacking                                = /* 'frpk' */ 0x6672706B,\n    bmdVideo3DPackingLeftOnly                                    = /* 'left' */ 0x6C656674,\n    bmdVideo3DPackingRightOnly                                   = /* 'righ' */ 0x72696768\n};\n\n/* Enum BMDIdleVideoOutputOperation - Video output operation when not playing video */\n\ntypedef uint32_t BMDIdleVideoOutputOperation;\nenum _BMDIdleVideoOutputOperation {\n    bmdIdleVideoOutputBlack                                      = /* 'blac' */ 0x626C6163,\n    bmdIdleVideoOutputLastFrame                                  = /* 'lafa' */ 0x6C616661\n};\n\n/* Enum BMDVideoEncoderFrameCodingMode - Video frame coding mode */\n\ntypedef uint32_t BMDVideoEncoderFrameCodingMode;\nenum _BMDVideoEncoderFrameCodingMode {\n    bmdVideoEncoderFrameCodingModeInter                          = /* 'inte' */ 0x696E7465,\n    bmdVideoEncoderFrameCodingModeIntra                          = /* 'intr' */ 0x696E7472\n};\n\n/* Enum BMDDNxHRLevel - DNxHR Levels */\n\ntypedef uint32_t BMDDNxHRLevel;\nenum _BMDDNxHRLevel {\n    bmdDNxHRLevelSQ                                              = /* 'dnsq' */ 0x646E7371,\n    bmdDNxHRLevelLB                                              = /* 'dnlb' */ 0x646E6C62,\n    bmdDNxHRLevelHQ                                              = /* 'dnhq' */ 0x646E6871,\n    bmdDNxHRLevelHQX                                             = /* 'dhqx' */ 0x64687178,\n    bmdDNxHRLevel444                                             = /* 'd444' */ 0x64343434\n};\n\n/* Enum BMDLinkConfiguration - Video link configuration */\n\ntypedef uint32_t BMDLinkConfiguration;\nenum _BMDLinkConfiguration {\n    bmdLinkConfigurationSingleLink                               = /* 'lcsl' */ 0x6C63736C,\n    bmdLinkConfigurationDualLink                                 = /* 'lcdl' */ 0x6C63646C,\n    bmdLinkConfigurationQuadLink                                 = /* 'lcql' */ 0x6C63716C\n};\n\n/* Enum BMDDeviceInterface - Device interface type */\n\ntypedef uint32_t BMDDeviceInterface;\nenum _BMDDeviceInterface {\n    bmdDeviceInterfacePCI                                        = /* 'pci ' */ 0x70636920,\n    bmdDeviceInterfaceUSB                                        = /* 'usb ' */ 0x75736220,\n    bmdDeviceInterfaceThunderbolt                                = /* 'thun' */ 0x7468756E\n};\n\n/* Enum BMDColorspace - Colorspace */\n\ntypedef uint32_t BMDColorspace;\nenum _BMDColorspace {\n    bmdColorspaceRec601                                          = /* 'r601' */ 0x72363031,\n    bmdColorspaceRec709                                          = /* 'r709' */ 0x72373039,\n    bmdColorspaceRec2020                                         = /* '2020' */ 0x32303230\n};\n\n/* Enum BMDDynamicRange - SDR or HDR */\n\ntypedef uint32_t BMDDynamicRange;\nenum _BMDDynamicRange {\n    bmdDynamicRangeSDR                                           = 0,\t// Standard Dynamic Range in accordance with SMPTE ST 2036-1\n    bmdDynamicRangeHDRStaticPQ                                   = 1 << 29,\t// High Dynamic Range PQ in accordance with SMPTE ST 2084\n    bmdDynamicRangeHDRStaticHLG                                  = 1 << 30\t// High Dynamic Range HLG in accordance with ITU-R BT.2100-0\n};\n\n/* Enum BMDDeckLinkHDMIInputEDIDID - DeckLink HDMI Input EDID ID */\n\ntypedef uint32_t BMDDeckLinkHDMIInputEDIDID;\nenum _BMDDeckLinkHDMIInputEDIDID {\n\n    /* Integers */\n\n    bmdDeckLinkHDMIInputEDIDDynamicRange                         = /* 'HIDy' */ 0x48494479\t// Parameter is of type BMDDynamicRange. Default is (bmdDynamicRangeSDR|bmdDynamicRangeHDRStaticPQ)\n};\n\n/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */\n\ntypedef uint32_t BMDDeckLinkFrameMetadataID;\nenum _BMDDeckLinkFrameMetadataID {\n\n    /* Colorspace Metadata - Integers */\n\n    bmdDeckLinkFrameMetadataColorspace                           = /* 'cspc' */ 0x63737063,\t// Colorspace of video frame (see BMDColorspace)\n\n    /* HDR Metadata - Integers */\n\n    bmdDeckLinkFrameMetadataHDRElectroOpticalTransferFunc        = /* 'eotf' */ 0x656F7466,\t// EOTF in range 0-7 as per CEA 861.3\n\n    /* HDR Metadata - Floats */\n\n    bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedX              = /* 'hdrx' */ 0x68647278,\t// Red display primaries in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRDisplayPrimariesRedY              = /* 'hdry' */ 0x68647279,\t// Red display primaries in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenX            = /* 'hdgx' */ 0x68646778,\t// Green display primaries in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRDisplayPrimariesGreenY            = /* 'hdgy' */ 0x68646779,\t// Green display primaries in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueX             = /* 'hdbx' */ 0x68646278,\t// Blue display primaries in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRDisplayPrimariesBlueY             = /* 'hdby' */ 0x68646279,\t// Blue display primaries in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRWhitePointX                       = /* 'hdwx' */ 0x68647778,\t// White point in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRWhitePointY                       = /* 'hdwy' */ 0x68647779,\t// White point in range 0.0 - 1.0\n    bmdDeckLinkFrameMetadataHDRMaxDisplayMasteringLuminance      = /* 'hdml' */ 0x68646D6C,\t// Max display mastering luminance in range 1 cd/m2 - 65535 cd/m2\n    bmdDeckLinkFrameMetadataHDRMinDisplayMasteringLuminance      = /* 'hmil' */ 0x686D696C,\t// Min display mastering luminance in range 0.0001 cd/m2 - 6.5535 cd/m2\n    bmdDeckLinkFrameMetadataHDRMaximumContentLightLevel          = /* 'mcll' */ 0x6D636C6C,\t// Maximum Content Light Level in range 1 cd/m2 - 65535 cd/m2\n    bmdDeckLinkFrameMetadataHDRMaximumFrameAverageLightLevel     = /* 'fall' */ 0x66616C6C\t// Maximum Frame Average Light Level in range 1 cd/m2 - 65535 cd/m2\n};\n\n/* Enum BMDProfileID - Identifies a profile */\n\ntypedef uint32_t BMDProfileID;\nenum _BMDProfileID {\n    bmdProfileOneSubDeviceFullDuplex                             = /* '1dfd' */ 0x31646664,\n    bmdProfileOneSubDeviceHalfDuplex                             = /* '1dhd' */ 0x31646864,\n    bmdProfileTwoSubDevicesFullDuplex                            = /* '2dfd' */ 0x32646664,\n    bmdProfileTwoSubDevicesHalfDuplex                            = /* '2dhd' */ 0x32646864,\n    bmdProfileFourSubDevicesHalfDuplex                           = /* '4dhd' */ 0x34646864\n};\n\n/* Enum BMDHDMITimecodePacking - Packing form of timecode on HDMI */\n\ntypedef uint32_t BMDHDMITimecodePacking;\nenum _BMDHDMITimecodePacking {\n    bmdHDMITimecodePackingIEEEOUI000085                          = 0x00008500,\n    bmdHDMITimecodePackingIEEEOUI080046                          = 0x08004601,\n    bmdHDMITimecodePackingIEEEOUI5CF9F0                          = 0x5CF9F003\n};\n\n/* Enum BMDInternalKeyingAncillaryDataSource - Source for VANC and timecode data when performing internal keying */\n\ntypedef uint32_t BMDInternalKeyingAncillaryDataSource;\nenum _BMDInternalKeyingAncillaryDataSource {\n    bmdInternalKeyingUsesAncillaryDataFromInputSignal            = /* 'ikai' */ 0x696B6169,\n    bmdInternalKeyingUsesAncillaryDataFromKeyFrame               = /* 'ikak' */ 0x696B616B\n};\n\n/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */\n\ntypedef uint32_t BMDDeckLinkAttributeID;\nenum _BMDDeckLinkAttributeID {\n\n    /* Flags */\n\n    BMDDeckLinkSupportsInternalKeying                            = /* 'keyi' */ 0x6B657969,\n    BMDDeckLinkSupportsExternalKeying                            = /* 'keye' */ 0x6B657965,\n    BMDDeckLinkSupportsInputFormatDetection                      = /* 'infd' */ 0x696E6664,\n    BMDDeckLinkHasReferenceInput                                 = /* 'hrin' */ 0x6872696E,\n    BMDDeckLinkHasSerialPort                                     = /* 'hspt' */ 0x68737074,\n    BMDDeckLinkHasAnalogVideoOutputGain                          = /* 'avog' */ 0x61766F67,\n    BMDDeckLinkCanOnlyAdjustOverallVideoOutputGain               = /* 'ovog' */ 0x6F766F67,\n    BMDDeckLinkHasVideoInputAntiAliasingFilter                   = /* 'aafl' */ 0x6161666C,\n    BMDDeckLinkHasBypass                                         = /* 'byps' */ 0x62797073,\n    BMDDeckLinkSupportsClockTimingAdjustment                     = /* 'ctad' */ 0x63746164,\n    BMDDeckLinkSupportsFullFrameReferenceInputTimingOffset       = /* 'frin' */ 0x6672696E,\n    BMDDeckLinkSupportsSMPTELevelAOutput                         = /* 'lvla' */ 0x6C766C61,\n    BMDDeckLinkSupportsAutoSwitchingPPsFOnInput                  = /* 'apsf' */ 0x61707366,\n    BMDDeckLinkSupportsDualLinkSDI                               = /* 'sdls' */ 0x73646C73,\n    BMDDeckLinkSupportsQuadLinkSDI                               = /* 'sqls' */ 0x73716C73,\n    BMDDeckLinkSupportsIdleOutput                                = /* 'idou' */ 0x69646F75,\n    BMDDeckLinkVANCRequires10BitYUVVideoFrames                   = /* 'vioY' */ 0x76696F59,\t// Legacy product requires v210 active picture for IDeckLinkVideoFrameAncillaryPackets or 10-bit VANC\n    BMDDeckLinkHasLTCTimecodeInput                               = /* 'hltc' */ 0x686C7463,\n    BMDDeckLinkSupportsHDRMetadata                               = /* 'hdrm' */ 0x6864726D,\n    BMDDeckLinkSupportsColorspaceMetadata                        = /* 'cmet' */ 0x636D6574,\n    BMDDeckLinkSupportsHDMITimecode                              = /* 'htim' */ 0x6874696D,\n    BMDDeckLinkSupportsHighFrameRateTimecode                     = /* 'HFRT' */ 0x48465254,\n    BMDDeckLinkSupportsSynchronizeToCaptureGroup                 = /* 'stcg' */ 0x73746367,\n    BMDDeckLinkSupportsSynchronizeToPlaybackGroup                = /* 'stpg' */ 0x73747067,\n\n    /* Integers */\n\n    BMDDeckLinkMaximumAudioChannels                              = /* 'mach' */ 0x6D616368,\n    BMDDeckLinkMaximumAnalogAudioInputChannels                   = /* 'iach' */ 0x69616368,\n    BMDDeckLinkMaximumAnalogAudioOutputChannels                  = /* 'aach' */ 0x61616368,\n    BMDDeckLinkNumberOfSubDevices                                = /* 'nsbd' */ 0x6E736264,\n    BMDDeckLinkSubDeviceIndex                                    = /* 'subi' */ 0x73756269,\n    BMDDeckLinkPersistentID                                      = /* 'peid' */ 0x70656964,\n    BMDDeckLinkDeviceGroupID                                     = /* 'dgid' */ 0x64676964,\n    BMDDeckLinkTopologicalID                                     = /* 'toid' */ 0x746F6964,\n    BMDDeckLinkVideoOutputConnections                            = /* 'vocn' */ 0x766F636E,\t// Returns a BMDVideoConnection bit field\n    BMDDeckLinkVideoInputConnections                             = /* 'vicn' */ 0x7669636E,\t// Returns a BMDVideoConnection bit field\n    BMDDeckLinkAudioOutputConnections                            = /* 'aocn' */ 0x616F636E,\t// Returns a BMDAudioConnection bit field\n    BMDDeckLinkAudioInputConnections                             = /* 'aicn' */ 0x6169636E,\t// Returns a BMDAudioConnection bit field\n    BMDDeckLinkVideoIOSupport                                    = /* 'vios' */ 0x76696F73,\t// Returns a BMDVideoIOSupport bit field\n    BMDDeckLinkDeckControlConnections                            = /* 'dccn' */ 0x6463636E,\t// Returns a BMDDeckControlConnection bit field\n    BMDDeckLinkDeviceInterface                                   = /* 'dbus' */ 0x64627573,\t// Returns a BMDDeviceInterface\n    BMDDeckLinkAudioInputRCAChannelCount                         = /* 'airc' */ 0x61697263,\n    BMDDeckLinkAudioInputXLRChannelCount                         = /* 'aixc' */ 0x61697863,\n    BMDDeckLinkAudioOutputRCAChannelCount                        = /* 'aorc' */ 0x616F7263,\n    BMDDeckLinkAudioOutputXLRChannelCount                        = /* 'aoxc' */ 0x616F7863,\n    BMDDeckLinkProfileID                                         = /* 'prid' */ 0x70726964,\t// Returns a BMDProfileID\n    BMDDeckLinkDuplex                                            = /* 'dupx' */ 0x64757078,\n    BMDDeckLinkMinimumPrerollFrames                              = /* 'mprf' */ 0x6D707266,\n    BMDDeckLinkSupportedDynamicRange                             = /* 'sudr' */ 0x73756472,\n\n    /* Floats */\n\n    BMDDeckLinkVideoInputGainMinimum                             = /* 'vigm' */ 0x7669676D,\n    BMDDeckLinkVideoInputGainMaximum                             = /* 'vigx' */ 0x76696778,\n    BMDDeckLinkVideoOutputGainMinimum                            = /* 'vogm' */ 0x766F676D,\n    BMDDeckLinkVideoOutputGainMaximum                            = /* 'vogx' */ 0x766F6778,\n    BMDDeckLinkMicrophoneInputGainMinimum                        = /* 'migm' */ 0x6D69676D,\n    BMDDeckLinkMicrophoneInputGainMaximum                        = /* 'migx' */ 0x6D696778,\n\n    /* Strings */\n\n    BMDDeckLinkSerialPortDeviceName                              = /* 'slpn' */ 0x736C706E,\n    BMDDeckLinkVendorName                                        = /* 'vndr' */ 0x766E6472,\n    BMDDeckLinkDisplayName                                       = /* 'dspn' */ 0x6473706E,\n    BMDDeckLinkModelName                                         = /* 'mdln' */ 0x6D646C6E,\n    BMDDeckLinkDeviceHandle                                      = /* 'devh' */ 0x64657668\n};\n\n/* Enum BMDDeckLinkAPIInformationID - DeckLinkAPI information ID */\n\ntypedef uint32_t BMDDeckLinkAPIInformationID;\nenum _BMDDeckLinkAPIInformationID {\n\n    /* Integer or String */\n\n    BMDDeckLinkAPIVersion                                        = /* 'vers' */ 0x76657273\n};\n\n/* Enum BMDDeckLinkStatusID - DeckLink Status ID */\n\ntypedef uint32_t BMDDeckLinkStatusID;\nenum _BMDDeckLinkStatusID {\n\n    /* Integers */\n\n    bmdDeckLinkStatusDetectedVideoInputMode                      = /* 'dvim' */ 0x6476696D,\n    bmdDeckLinkStatusDetectedVideoInputFormatFlags               = /* 'dvff' */ 0x64766666,\n    bmdDeckLinkStatusDetectedVideoInputFieldDominance            = /* 'dvfd' */ 0x64766664,\n    bmdDeckLinkStatusDetectedVideoInputColorspace                = /* 'dscl' */ 0x6473636C,\n    bmdDeckLinkStatusDetectedVideoInputDynamicRange              = /* 'dsdr' */ 0x64736472,\n    bmdDeckLinkStatusDetectedSDILinkConfiguration                = /* 'dslc' */ 0x64736C63,\n    bmdDeckLinkStatusCurrentVideoInputMode                       = /* 'cvim' */ 0x6376696D,\n    bmdDeckLinkStatusCurrentVideoInputPixelFormat                = /* 'cvip' */ 0x63766970,\n    bmdDeckLinkStatusCurrentVideoInputFlags                      = /* 'cvif' */ 0x63766966,\n    bmdDeckLinkStatusCurrentVideoOutputMode                      = /* 'cvom' */ 0x63766F6D,\n    bmdDeckLinkStatusCurrentVideoOutputFlags                     = /* 'cvof' */ 0x63766F66,\n    bmdDeckLinkStatusPCIExpressLinkWidth                         = /* 'pwid' */ 0x70776964,\n    bmdDeckLinkStatusPCIExpressLinkSpeed                         = /* 'plnk' */ 0x706C6E6B,\n    bmdDeckLinkStatusLastVideoOutputPixelFormat                  = /* 'opix' */ 0x6F706978,\n    bmdDeckLinkStatusReferenceSignalMode                         = /* 'refm' */ 0x7265666D,\n    bmdDeckLinkStatusReferenceSignalFlags                        = /* 'reff' */ 0x72656666,\n    bmdDeckLinkStatusBusy                                        = /* 'busy' */ 0x62757379,\n    bmdDeckLinkStatusInterchangeablePanelType                    = /* 'icpt' */ 0x69637074,\n    bmdDeckLinkStatusDeviceTemperature                           = /* 'dtmp' */ 0x64746D70,\n\n    /* Flags */\n\n    bmdDeckLinkStatusVideoInputSignalLocked                      = /* 'visl' */ 0x7669736C,\n    bmdDeckLinkStatusReferenceSignalLocked                       = /* 'refl' */ 0x7265666C,\n\n    /* Bytes */\n\n    bmdDeckLinkStatusReceivedEDID                                = /* 'edid' */ 0x65646964\n};\n\n/* Enum BMDDeckLinkVideoStatusFlags -  */\n\ntypedef uint32_t BMDDeckLinkVideoStatusFlags;\nenum _BMDDeckLinkVideoStatusFlags {\n    bmdDeckLinkVideoStatusPsF                                    = 1 << 0,\n    bmdDeckLinkVideoStatusDualStream3D                           = 1 << 1\n};\n\n/* Enum BMDDuplexMode - Duplex of the device */\n\ntypedef uint32_t BMDDuplexMode;\nenum _BMDDuplexMode {\n    bmdDuplexFull                                                = /* 'dxfu' */ 0x64786675,\n    bmdDuplexHalf                                                = /* 'dxha' */ 0x64786861,\n    bmdDuplexSimplex                                             = /* 'dxsp' */ 0x64787370,\n    bmdDuplexInactive                                            = /* 'dxin' */ 0x6478696E\n};\n\n/* Enum BMDPanelType - The type of interchangeable panel */\n\ntypedef uint32_t BMDPanelType;\nenum _BMDPanelType {\n    bmdPanelNotDetected                                          = /* 'npnl' */ 0x6E706E6C,\n    bmdPanelTeranexMiniSmartPanel                                = /* 'tmsm' */ 0x746D736D\n};\n\n/* Enum BMDDeviceBusyState - Current device busy state */\n\ntypedef uint32_t BMDDeviceBusyState;\nenum _BMDDeviceBusyState {\n    bmdDeviceCaptureBusy                                         = 1 << 0,\n    bmdDevicePlaybackBusy                                        = 1 << 1,\n    bmdDeviceSerialPortBusy                                      = 1 << 2\n};\n\n/* Enum BMDVideoIOSupport - Device video input/output support */\n\ntypedef uint32_t BMDVideoIOSupport;\nenum _BMDVideoIOSupport {\n    bmdDeviceSupportsCapture                                     = 1 << 0,\n    bmdDeviceSupportsPlayback                                    = 1 << 1\n};\n\n/* Enum BMD3DPreviewFormat - Linked Frame preview format */\n\ntypedef uint32_t BMD3DPreviewFormat;\nenum _BMD3DPreviewFormat {\n    bmd3DPreviewFormatDefault                                    = /* 'defa' */ 0x64656661,\n    bmd3DPreviewFormatLeftOnly                                   = /* 'left' */ 0x6C656674,\n    bmd3DPreviewFormatRightOnly                                  = /* 'righ' */ 0x72696768,\n    bmd3DPreviewFormatSideBySide                                 = /* 'side' */ 0x73696465,\n    bmd3DPreviewFormatTopBottom                                  = /* 'topb' */ 0x746F7062\n};\n\n/* Enum BMDNotifications - Events that can be subscribed through IDeckLinkNotification */\n\ntypedef uint32_t BMDNotifications;\nenum _BMDNotifications {\n    bmdPreferencesChanged                                        = /* 'pref' */ 0x70726566,\n    bmdStatusChanged                                             = /* 'stat' */ 0x73746174\n};\n\n#if defined(__cplusplus)\n\n// Forward Declarations\n\nclass IDeckLinkVideoOutputCallback;\nclass IDeckLinkInputCallback;\nclass IDeckLinkEncoderInputCallback;\nclass IDeckLinkMemoryAllocator;\nclass IDeckLinkAudioOutputCallback;\nclass IDeckLinkIterator;\nclass IDeckLinkAPIInformation;\nclass IDeckLinkOutput;\nclass IDeckLinkInput;\nclass IDeckLinkHDMIInputEDID;\nclass IDeckLinkEncoderInput;\nclass IDeckLinkVideoFrame;\nclass IDeckLinkMutableVideoFrame;\nclass IDeckLinkVideoFrame3DExtensions;\nclass IDeckLinkVideoFrameMetadataExtensions;\nclass IDeckLinkVideoInputFrame;\nclass IDeckLinkAncillaryPacket;\nclass IDeckLinkAncillaryPacketIterator;\nclass IDeckLinkVideoFrameAncillaryPackets;\nclass IDeckLinkVideoFrameAncillary;\nclass IDeckLinkEncoderPacket;\nclass IDeckLinkEncoderVideoPacket;\nclass IDeckLinkEncoderAudioPacket;\nclass IDeckLinkH265NALPacket;\nclass IDeckLinkAudioInputPacket;\nclass IDeckLinkScreenPreviewCallback;\nclass IDeckLinkGLScreenPreviewHelper;\nclass IDeckLinkNotificationCallback;\nclass IDeckLinkNotification;\nclass IDeckLinkProfileAttributes;\nclass IDeckLinkProfileIterator;\nclass IDeckLinkProfile;\nclass IDeckLinkProfileCallback;\nclass IDeckLinkProfileManager;\nclass IDeckLinkStatus;\nclass IDeckLinkKeyer;\nclass IDeckLinkVideoConversion;\nclass IDeckLinkDeviceNotificationCallback;\nclass IDeckLinkDiscovery;\n\n/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */\n\nclass BMD_PUBLIC IDeckLinkVideoOutputCallback : public IUnknown\n{\npublic:\n    virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame* completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0;\n    virtual HRESULT ScheduledPlaybackHasStopped (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoOutputCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkInputCallback - Frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkInputCallback : public IUnknown\n{\npublic:\n    virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\n    virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0;\n\nprotected:\n    virtual ~IDeckLinkInputCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkEncoderInputCallback - Frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkEncoderInputCallback : public IUnknown\n{\npublic:\n    virtual HRESULT VideoInputSignalChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\n    virtual HRESULT VideoPacketArrived (/* in */ IDeckLinkEncoderVideoPacket* videoPacket) = 0;\n    virtual HRESULT AudioPacketArrived (/* in */ IDeckLinkEncoderAudioPacket* audioPacket) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderInputCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkMemoryAllocator - Memory allocator for video frames. */\n\nclass BMD_PUBLIC IDeckLinkMemoryAllocator : public IUnknown\n{\npublic:\n    virtual HRESULT AllocateBuffer (/* in */ uint32_t bufferSize, /* out */ void** allocatedBuffer) = 0;\n    virtual HRESULT ReleaseBuffer (/* in */ void* buffer) = 0;\n    virtual HRESULT Commit (void) = 0;\n    virtual HRESULT Decommit (void) = 0;\n};\n\n/* Interface IDeckLinkAudioOutputCallback - Optional callback to allow audio samples to be pulled as required. */\n\nclass BMD_PUBLIC IDeckLinkAudioOutputCallback : public IUnknown\n{\npublic:\n    virtual HRESULT RenderAudioSamples (/* in */ bool preroll) = 0;\n};\n\n/* Interface IDeckLinkIterator - Enumerates installed DeckLink hardware */\n\nclass BMD_PUBLIC IDeckLinkIterator : public IUnknown\n{\npublic:\n    virtual HRESULT Next (/* out */ IDeckLink** deckLinkInstance) = 0;\n};\n\n/* Interface IDeckLinkAPIInformation - DeckLinkAPI attribute interface */\n\nclass BMD_PUBLIC IDeckLinkAPIInformation : public IUnknown\n{\npublic:\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ bool* value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ int64_t* value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ double* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkAPIInformationID cfgID, /* out */ const char** value) = 0;\n\nprotected:\n    virtual ~IDeckLinkAPIInformation () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkOutput : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoOutputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0;\n    virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0;\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0;\n\n    /* Video Output */\n\n    virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;\n    virtual HRESULT DisableVideoOutput (void) = 0;\n    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0;\n    virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame** outFrame) = 0;\n    virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary** outBuffer) = 0;\t// Use of IDeckLinkVideoFrameAncillaryPackets is preferred\n    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame* theFrame) = 0;\n    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback* theCallback) = 0;\n    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t* bufferedFrameCount) = 0;\n\n    /* Audio Output */\n\n    virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;\n    virtual HRESULT DisableAudioOutput (void) = 0;\n    virtual HRESULT WriteAudioSamplesSync (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t* sampleFramesWritten) = 0;\n    virtual HRESULT BeginAudioPreroll (void) = 0;\n    virtual HRESULT EndAudioPreroll (void) = 0;\n    virtual HRESULT ScheduleAudioSamples (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t* sampleFramesWritten) = 0;\n    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t* bufferedSampleFrameCount) = 0;\n    virtual HRESULT FlushBufferedAudioSamples (void) = 0;\n    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback* theCallback) = 0;\n\n    /* Output Control */\n\n    virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;\n    virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue* actualStopTime, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool* active) = 0;\n    virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* streamTime, /* out */ double* playbackSpeed) = 0;\n    virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus* referenceStatus) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0;\n    virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* frameCompletionTimestamp) = 0;\n\nprotected:\n    virtual ~IDeckLinkOutput () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkInput : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoInputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0;\n    virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0;\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0;\n    virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback* theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkHDMIInputEDID - Created by QueryInterface from IDeckLink. Releasing all references will restore EDID to default */\n\nclass BMD_PUBLIC IDeckLinkHDMIInputEDID : public IUnknown\n{\npublic:\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkHDMIInputEDIDID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkHDMIInputEDIDID cfgID, /* out */ int64_t* value) = 0;\n    virtual HRESULT WriteToEDID (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkHDMIInputEDID () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkEncoderInput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkEncoderInput : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedCodec, /* in */ uint32_t requestedCodecProfile, /* in */ BMDSupportedVideoModeFlags flags, /* out */ bool* supported) = 0;\n    virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailablePacketsCount (/* out */ uint32_t* availablePacketsCount) = 0;\n    virtual HRESULT SetMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioFormat audioFormat, /* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkEncoderInputCallback* theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderInput () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */\n\nclass BMD_PUBLIC IDeckLinkVideoFrame : public IUnknown\n{\npublic:\n    virtual long GetWidth (void) = 0;\n    virtual long GetHeight (void) = 0;\n    virtual long GetRowBytes (void) = 0;\n    virtual BMDPixelFormat GetPixelFormat (void) = 0;\n    virtual BMDFrameFlags GetFlags (void) = 0;\n    virtual HRESULT GetBytes (/* out */ void** buffer) = 0;\n    virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) = 0;\n    virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary** ancillary) = 0;\t// Use of IDeckLinkVideoFrameAncillaryPackets is preferred\n\nprotected:\n    virtual ~IDeckLinkVideoFrame () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */\n\nclass BMD_PUBLIC IDeckLinkMutableVideoFrame : public IDeckLinkVideoFrame\n{\npublic:\n    virtual HRESULT SetFlags (/* in */ BMDFrameFlags newFlags) = 0;\n    virtual HRESULT SetTimecode (/* in */ BMDTimecodeFormat format, /* in */ IDeckLinkTimecode* timecode) = 0;\n    virtual HRESULT SetTimecodeFromComponents (/* in */ BMDTimecodeFormat format, /* in */ uint8_t hours, /* in */ uint8_t minutes, /* in */ uint8_t seconds, /* in */ uint8_t frames, /* in */ BMDTimecodeFlags flags) = 0;\n    virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary* ancillary) = 0;\n    virtual HRESULT SetTimecodeUserBits (/* in */ BMDTimecodeFormat format, /* in */ BMDTimecodeUserBits userBits) = 0;\n\nprotected:\n    virtual ~IDeckLinkMutableVideoFrame () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoFrame3DExtensions - Optional interface implemented on IDeckLinkVideoFrame to support 3D frames */\n\nclass BMD_PUBLIC IDeckLinkVideoFrame3DExtensions : public IUnknown\n{\npublic:\n    virtual BMDVideo3DPackingFormat Get3DPackingFormat (void) = 0;\n    virtual HRESULT GetFrameForRightEye (/* out */ IDeckLinkVideoFrame** rightEyeFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoFrame3DExtensions () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDR information */\n\nclass BMD_PUBLIC IDeckLinkVideoFrameMetadataExtensions : public IUnknown\n{\npublic:\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ int64_t* value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ double* value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ bool* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ const char** value) = 0;\n    virtual HRESULT GetBytes (/* in */ BMDDeckLinkFrameMetadataID metadataID, /* out */ void* buffer /* optional */, /* in, out */ uint32_t* bufferSize) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoFrameMetadataExtensions () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkVideoInputFrame : public IDeckLinkVideoFrame\n{\npublic:\n    virtual HRESULT GetStreamTime (/* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoInputFrame () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkAncillaryPacket - On output, user needs to implement this interface */\n\nclass BMD_PUBLIC IDeckLinkAncillaryPacket : public IUnknown\n{\npublic:\n    virtual HRESULT GetBytes (/* in */ BMDAncillaryPacketFormat format /* For output, only one format need be offered */, /* out */ const void** data /* Optional */, /* out */ uint32_t* size /* Optional */) = 0;\n    virtual uint8_t GetDID (void) = 0;\n    virtual uint8_t GetSDID (void) = 0;\n    virtual uint32_t GetLineNumber (void) = 0;\t// On output, zero is auto\n    virtual uint8_t GetDataStreamIndex (void) = 0;\t// Usually zero. Can only be 1 if non-SD and the first data stream is completely full\n\nprotected:\n    virtual ~IDeckLinkAncillaryPacket () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkAncillaryPacketIterator - Enumerates ancillary packets */\n\nclass BMD_PUBLIC IDeckLinkAncillaryPacketIterator : public IUnknown\n{\npublic:\n    virtual HRESULT Next (/* out */ IDeckLinkAncillaryPacket** packet) = 0;\n\nprotected:\n    virtual ~IDeckLinkAncillaryPacketIterator () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoFrameAncillaryPackets - Obtained through QueryInterface on an IDeckLinkVideoFrame object. */\n\nclass BMD_PUBLIC IDeckLinkVideoFrameAncillaryPackets : public IUnknown\n{\npublic:\n    virtual HRESULT GetPacketIterator (/* out */ IDeckLinkAncillaryPacketIterator** iterator) = 0;\n    virtual HRESULT GetFirstPacketByID (/* in */ uint8_t DID, /* in */ uint8_t SDID, /* out */ IDeckLinkAncillaryPacket** packet) = 0;\n    virtual HRESULT AttachPacket (/* in */ IDeckLinkAncillaryPacket* packet) = 0;\t// Implement IDeckLinkAncillaryPacket to output your own\n    virtual HRESULT DetachPacket (/* in */ IDeckLinkAncillaryPacket* packet) = 0;\n    virtual HRESULT DetachAllPackets (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoFrameAncillaryPackets () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoFrameAncillary - Use of IDeckLinkVideoFrameAncillaryPackets is preferred. Obtained through QueryInterface on an IDeckLinkVideoFrame object. */\n\nclass BMD_PUBLIC IDeckLinkVideoFrameAncillary : public IUnknown\n{\npublic:\n    virtual HRESULT GetBufferForVerticalBlankingLine (/* in */ uint32_t lineNumber, /* out */ void** buffer) = 0;\t// Pixels/rowbytes is same as display mode, except for above HD where it's 1920 pixels for UHD modes and 2048 pixels for DCI modes\n    virtual BMDPixelFormat GetPixelFormat (void) = 0;\n    virtual BMDDisplayMode GetDisplayMode (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoFrameAncillary () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkEncoderPacket - Interface to encapsulate an encoded packet. */\n\nclass BMD_PUBLIC IDeckLinkEncoderPacket : public IUnknown\n{\npublic:\n    virtual HRESULT GetBytes (/* out */ void** buffer) = 0;\n    virtual long GetSize (void) = 0;\n    virtual HRESULT GetStreamTime (/* out */ BMDTimeValue* frameTime, /* in */ BMDTimeScale timeScale) = 0;\n    virtual BMDPacketType GetPacketType (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderPacket () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkEncoderVideoPacket - Provided by the IDeckLinkEncoderInput video packet arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkEncoderVideoPacket : public IDeckLinkEncoderPacket\n{\npublic:\n    virtual BMDPixelFormat GetPixelFormat (void) = 0;\n    virtual HRESULT GetHardwareReferenceTimestamp (/* in */ BMDTimeScale timeScale, /* out */ BMDTimeValue* frameTime, /* out */ BMDTimeValue* frameDuration) = 0;\n    virtual HRESULT GetTimecode (/* in */ BMDTimecodeFormat format, /* out */ IDeckLinkTimecode** timecode) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderVideoPacket () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkEncoderAudioPacket - Provided by the IDeckLinkEncoderInput audio packet arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkEncoderAudioPacket : public IDeckLinkEncoderPacket\n{\npublic:\n    virtual BMDAudioFormat GetAudioFormat (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderAudioPacket () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkH265NALPacket - Obtained through QueryInterface on an IDeckLinkEncoderVideoPacket object */\n\nclass BMD_PUBLIC IDeckLinkH265NALPacket : public IDeckLinkEncoderVideoPacket\n{\npublic:\n    virtual HRESULT GetUnitType (/* out */ uint8_t* unitType) = 0;\n    virtual HRESULT GetBytesNoPrefix (/* out */ void** buffer) = 0;\n    virtual long GetSizeNoPrefix (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkH265NALPacket () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkAudioInputPacket - Provided by the IDeckLinkInput callback. */\n\nclass BMD_PUBLIC IDeckLinkAudioInputPacket : public IUnknown\n{\npublic:\n    virtual long GetSampleFrameCount (void) = 0;\n    virtual HRESULT GetBytes (/* out */ void** buffer) = 0;\n    virtual HRESULT GetPacketTime (/* out */ BMDTimeValue* packetTime, /* in */ BMDTimeScale timeScale) = 0;\n\nprotected:\n    virtual ~IDeckLinkAudioInputPacket () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */\n\nclass BMD_PUBLIC IDeckLinkScreenPreviewCallback : public IUnknown\n{\npublic:\n    virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkScreenPreviewCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance on platforms with native COM support or from CreateOpenGLScreenPreviewHelper/CreateOpenGL3ScreenPreviewHelper on other platforms. */\n\nclass BMD_PUBLIC IDeckLinkGLScreenPreviewHelper : public IUnknown\n{\npublic:\n\n    /* Methods must be called with OpenGL context set */\n\n    virtual HRESULT InitializeGL (void) = 0;\n    virtual HRESULT PaintGL (void) = 0;\n    virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame* theFrame) = 0;\n    virtual HRESULT Set3DPreviewFormat (/* in */ BMD3DPreviewFormat previewFormat) = 0;\n\nprotected:\n    virtual ~IDeckLinkGLScreenPreviewHelper () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkNotificationCallback - DeckLink Notification Callback Interface */\n\nclass BMD_PUBLIC IDeckLinkNotificationCallback : public IUnknown\n{\npublic:\n    virtual HRESULT Notify (/* in */ BMDNotifications topic, /* in */ uint64_t param1, /* in */ uint64_t param2) = 0;\n};\n\n/* Interface IDeckLinkNotification - DeckLink Notification interface */\n\nclass BMD_PUBLIC IDeckLinkNotification : public IUnknown\n{\npublic:\n    virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback* theCallback) = 0;\n    virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback* theCallback) = 0;\n\nprotected:\n    virtual ~IDeckLinkNotification () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkProfileAttributes - Created by QueryInterface from an IDeckLinkProfile, or from IDeckLink. When queried from IDeckLink, interrogates the active profile */\n\nclass BMD_PUBLIC IDeckLinkProfileAttributes : public IUnknown\n{\npublic:\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool* value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t* value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ const char** value) = 0;\n\nprotected:\n    virtual ~IDeckLinkProfileAttributes () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkProfileIterator - Enumerates IDeckLinkProfile interfaces */\n\nclass BMD_PUBLIC IDeckLinkProfileIterator : public IUnknown\n{\npublic:\n    virtual HRESULT Next (/* out */ IDeckLinkProfile** profile) = 0;\n\nprotected:\n    virtual ~IDeckLinkProfileIterator () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkProfile - Represents the active profile when queried from IDeckLink */\n\nclass BMD_PUBLIC IDeckLinkProfile : public IUnknown\n{\npublic:\n    virtual HRESULT GetDevice (/* out */ IDeckLink** device) = 0;\t// Device affected when this profile becomes active\n    virtual HRESULT IsActive (/* out */ bool* isActive) = 0;\n    virtual HRESULT SetActive (void) = 0;\t// Activating a profile will also change the profile on all devices enumerated by GetPeers. Activation is not complete until IDeckLinkProfileCallback::ProfileActivated is called\n    virtual HRESULT GetPeers (/* out */ IDeckLinkProfileIterator** profileIterator) = 0;\t// Profiles of other devices activated with this profile\n\nprotected:\n    virtual ~IDeckLinkProfile () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkProfileCallback - Receive notifications about profiles related to this device */\n\nclass BMD_PUBLIC IDeckLinkProfileCallback : public IUnknown\n{\npublic:\n    virtual HRESULT ProfileChanging (/* in */ IDeckLinkProfile* profileToBeActivated, /* in */ bool streamsWillBeForcedToStop) = 0;\t// Called before this device changes profile. User has an opportunity for teardown if streamsWillBeForcedToStop\n    virtual HRESULT ProfileActivated (/* in */ IDeckLinkProfile* activatedProfile) = 0;\t// Called after this device has been activated with a new profile\n\nprotected:\n    virtual ~IDeckLinkProfileCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkProfileManager - Created by QueryInterface from IDeckLink when a device has multiple optional profiles */\n\nclass BMD_PUBLIC IDeckLinkProfileManager : public IUnknown\n{\npublic:\n    virtual HRESULT GetProfiles (/* out */ IDeckLinkProfileIterator** profileIterator) = 0;\t// All available profiles for this device\n    virtual HRESULT GetProfile (/* in */ BMDProfileID profileID, /* out */ IDeckLinkProfile** profile) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkProfileCallback* callback) = 0;\n\nprotected:\n    virtual ~IDeckLinkProfileManager () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkStatus - DeckLink Status interface */\n\nclass BMD_PUBLIC IDeckLinkStatus : public IUnknown\n{\npublic:\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkStatusID statusID, /* out */ bool* value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkStatusID statusID, /* out */ int64_t* value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkStatusID statusID, /* out */ double* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkStatusID statusID, /* out */ const char** value) = 0;\n    virtual HRESULT GetBytes (/* in */ BMDDeckLinkStatusID statusID, /* out */ void* buffer, /* in, out */ uint32_t* bufferSize) = 0;\n\nprotected:\n    virtual ~IDeckLinkStatus () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkKeyer - DeckLink Keyer interface */\n\nclass BMD_PUBLIC IDeckLinkKeyer : public IUnknown\n{\npublic:\n    virtual HRESULT Enable (/* in */ bool isExternal) = 0;\n    virtual HRESULT SetLevel (/* in */ uint8_t level) = 0;\n    virtual HRESULT RampUp (/* in */ uint32_t numberOfFrames) = 0;\n    virtual HRESULT RampDown (/* in */ uint32_t numberOfFrames) = 0;\n    virtual HRESULT Disable (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkKeyer () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance. */\n\nclass BMD_PUBLIC IDeckLinkVideoConversion : public IUnknown\n{\npublic:\n    virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame* srcFrame, /* in */ IDeckLinkVideoFrame* dstFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoConversion () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkDeviceNotificationCallback - DeckLink device arrival/removal notification callbacks */\n\nclass BMD_PUBLIC IDeckLinkDeviceNotificationCallback : public IUnknown\n{\npublic:\n    virtual HRESULT DeckLinkDeviceArrived (/* in */ IDeckLink* deckLinkDevice) = 0;\n    virtual HRESULT DeckLinkDeviceRemoved (/* in */ IDeckLink* deckLinkDevice) = 0;\n\nprotected:\n    virtual ~IDeckLinkDeviceNotificationCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkDiscovery - DeckLink device discovery */\n\nclass BMD_PUBLIC IDeckLinkDiscovery : public IUnknown\n{\npublic:\n    virtual HRESULT InstallDeviceNotifications (/* in */ IDeckLinkDeviceNotificationCallback* deviceNotificationCallback) = 0;\n    virtual HRESULT UninstallDeviceNotifications (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkDiscovery () {} // call Release method to drop reference count\n};\n\n/* Functions */\n\nextern \"C\" {\n\n    IDeckLinkIterator* BMD_PUBLIC CreateDeckLinkIteratorInstance(void);\n    IDeckLinkDiscovery* BMD_PUBLIC CreateDeckLinkDiscoveryInstance(void);\n    IDeckLinkAPIInformation* BMD_PUBLIC CreateDeckLinkAPIInformationInstance(void);\n    IDeckLinkGLScreenPreviewHelper* BMD_PUBLIC CreateOpenGLScreenPreviewHelper(void);\n    IDeckLinkGLScreenPreviewHelper* BMD_PUBLIC CreateOpenGL3ScreenPreviewHelper(void);\t// Requires OpenGL 3.2 support and provides improved performance and color handling\n    IDeckLinkVideoConversion* BMD_PUBLIC CreateVideoConversionInstance(void);\n    IDeckLinkVideoFrameAncillaryPackets* BMD_PUBLIC CreateVideoFrameAncillaryPacketsInstance(void);\t// For use when creating a custom IDeckLinkVideoFrame without wrapping IDeckLinkOutput::CreateVideoFrame\n\n}\n\n\n\n#endif /* defined(__cplusplus) */\n#endif /* defined(BMD_DECKLINKAPI_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIConfiguration.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2022 Blackmagic Design\n**\n** Permission is hereby granted, free of charge, to any person or organization\n** obtaining a copy of the software and accompanying documentation covered by\n** this license (the \"Software\") to use, reproduce, display, distribute,\n** execute, and transmit the Software, and to prepare derivative works of the\n** Software, and to permit third-parties to whom the Software is furnished to\n** do so, all subject to the following:\n**\n** The copyright notices in the Software and this entire statement, including\n** the above license grant, this restriction and the following disclaimer,\n** must be included in all copies of the Software, in whole or in part, and\n** all derivative works of the Software, unless such copies or derivative\n** works are solely in the form of machine-executable object code generated by\n** a source language processor.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n** DEALINGS IN THE SOFTWARE.\n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPICONFIGURATION_H\n#define BMD_DECKLINKAPICONFIGURATION_H\n\n\n#ifndef BMD_CONST\n    #if defined(_MSC_VER)\n        #define BMD_CONST __declspec(selectany) static const\n    #else\n        #define BMD_CONST static const\n    #endif\n#endif\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n// Type Declarations\n\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkConfiguration                       = /* 912F634B-2D4E-40A4-8AAB-8D80B73F1289 */ { 0x91,0x2F,0x63,0x4B,0x2D,0x4E,0x40,0xA4,0x8A,0xAB,0x8D,0x80,0xB7,0x3F,0x12,0x89 };\nBMD_CONST REFIID IID_IDeckLinkEncoderConfiguration                = /* 138050E5-C60A-4552-BF3F-0F358049327E */ { 0x13,0x80,0x50,0xE5,0xC6,0x0A,0x45,0x52,0xBF,0x3F,0x0F,0x35,0x80,0x49,0x32,0x7E };\n\n/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */\n\ntypedef uint32_t BMDDeckLinkConfigurationID;\nenum _BMDDeckLinkConfigurationID {\n\n    /* Serial port Flags */\n\n    bmdDeckLinkConfigSwapSerialRxTx                              = /* 'ssrt' */ 0x73737274,\n\n    /* Video Input/Output Integers */\n\n    bmdDeckLinkConfigHDMI3DPackingFormat                         = /* '3dpf' */ 0x33647066,\n    bmdDeckLinkConfigBypass                                      = /* 'byps' */ 0x62797073,\n    bmdDeckLinkConfigClockTimingAdjustment                       = /* 'ctad' */ 0x63746164,\n\n    /* Audio Input/Output Flags */\n\n    bmdDeckLinkConfigAnalogAudioConsumerLevels                   = /* 'aacl' */ 0x6161636C,\n    bmdDeckLinkConfigSwapHDMICh3AndCh4OnInput                    = /* 'hi34' */ 0x68693334,\n    bmdDeckLinkConfigSwapHDMICh3AndCh4OnOutput                   = /* 'ho34' */ 0x686F3334,\n\n    /* Video Output Flags */\n\n    bmdDeckLinkConfigFieldFlickerRemoval                         = /* 'fdfr' */ 0x66646672,\n    bmdDeckLinkConfigHD1080p24ToHD1080i5994Conversion            = /* 'to59' */ 0x746F3539,\n    bmdDeckLinkConfig444SDIVideoOutput                           = /* '444o' */ 0x3434346F,\n    bmdDeckLinkConfigBlackVideoOutputDuringCapture               = /* 'bvoc' */ 0x62766F63,\n    bmdDeckLinkConfigLowLatencyVideoOutput                       = /* 'llvo' */ 0x6C6C766F,\n    bmdDeckLinkConfigDownConversionOnAllAnalogOutput             = /* 'caao' */ 0x6361616F,\n    bmdDeckLinkConfigSMPTELevelAOutput                           = /* 'smta' */ 0x736D7461,\n    bmdDeckLinkConfigRec2020Output                               = /* 'rec2' */ 0x72656332,\t// Ensure output is Rec.2020 colorspace\n    bmdDeckLinkConfigQuadLinkSDIVideoOutputSquareDivisionSplit   = /* 'SDQS' */ 0x53445153,\n    bmdDeckLinkConfigOutput1080pAsPsF                            = /* 'pfpr' */ 0x70667072,\n\n    /* Video Output Integers */\n\n    bmdDeckLinkConfigVideoOutputConnection                       = /* 'vocn' */ 0x766F636E,\n    bmdDeckLinkConfigVideoOutputConversionMode                   = /* 'vocm' */ 0x766F636D,\n    bmdDeckLinkConfigAnalogVideoOutputFlags                      = /* 'avof' */ 0x61766F66,\n    bmdDeckLinkConfigReferenceInputTimingOffset                  = /* 'glot' */ 0x676C6F74,\n    bmdDeckLinkConfigVideoOutputIdleOperation                    = /* 'voio' */ 0x766F696F,\n    bmdDeckLinkConfigDefaultVideoOutputMode                      = /* 'dvom' */ 0x64766F6D,\n    bmdDeckLinkConfigDefaultVideoOutputModeFlags                 = /* 'dvof' */ 0x64766F66,\n    bmdDeckLinkConfigSDIOutputLinkConfiguration                  = /* 'solc' */ 0x736F6C63,\n    bmdDeckLinkConfigHDMITimecodePacking                         = /* 'htpk' */ 0x6874706B,\n    bmdDeckLinkConfigPlaybackGroup                               = /* 'plgr' */ 0x706C6772,\n\n    /* Video Output Floats */\n\n    bmdDeckLinkConfigVideoOutputComponentLumaGain                = /* 'oclg' */ 0x6F636C67,\n    bmdDeckLinkConfigVideoOutputComponentChromaBlueGain          = /* 'occb' */ 0x6F636362,\n    bmdDeckLinkConfigVideoOutputComponentChromaRedGain           = /* 'occr' */ 0x6F636372,\n    bmdDeckLinkConfigVideoOutputCompositeLumaGain                = /* 'oilg' */ 0x6F696C67,\n    bmdDeckLinkConfigVideoOutputCompositeChromaGain              = /* 'oicg' */ 0x6F696367,\n    bmdDeckLinkConfigVideoOutputSVideoLumaGain                   = /* 'oslg' */ 0x6F736C67,\n    bmdDeckLinkConfigVideoOutputSVideoChromaGain                 = /* 'oscg' */ 0x6F736367,\n\n    /* Video Input Flags */\n\n    bmdDeckLinkConfigVideoInputScanning                          = /* 'visc' */ 0x76697363,\t// Applicable to H264 Pro Recorder only\n    bmdDeckLinkConfigUseDedicatedLTCInput                        = /* 'dltc' */ 0x646C7463,\t// Use timecode from LTC input instead of SDI stream\n    bmdDeckLinkConfigSDIInput3DPayloadOverride                   = /* '3dds' */ 0x33646473,\n    bmdDeckLinkConfigCapture1080pAsPsF                           = /* 'cfpr' */ 0x63667072,\n\n    /* Video Input Integers */\n\n    bmdDeckLinkConfigVideoInputConnection                        = /* 'vicn' */ 0x7669636E,\n    bmdDeckLinkConfigAnalogVideoInputFlags                       = /* 'avif' */ 0x61766966,\n    bmdDeckLinkConfigVideoInputConversionMode                    = /* 'vicm' */ 0x7669636D,\n    bmdDeckLinkConfig32PulldownSequenceInitialTimecodeFrame      = /* 'pdif' */ 0x70646966,\n    bmdDeckLinkConfigVANCSourceLine1Mapping                      = /* 'vsl1' */ 0x76736C31,\n    bmdDeckLinkConfigVANCSourceLine2Mapping                      = /* 'vsl2' */ 0x76736C32,\n    bmdDeckLinkConfigVANCSourceLine3Mapping                      = /* 'vsl3' */ 0x76736C33,\n    bmdDeckLinkConfigCapturePassThroughMode                      = /* 'cptm' */ 0x6370746D,\n    bmdDeckLinkConfigCaptureGroup                                = /* 'cpgr' */ 0x63706772,\n\n    /* Video Input Floats */\n\n    bmdDeckLinkConfigVideoInputComponentLumaGain                 = /* 'iclg' */ 0x69636C67,\n    bmdDeckLinkConfigVideoInputComponentChromaBlueGain           = /* 'iccb' */ 0x69636362,\n    bmdDeckLinkConfigVideoInputComponentChromaRedGain            = /* 'iccr' */ 0x69636372,\n    bmdDeckLinkConfigVideoInputCompositeLumaGain                 = /* 'iilg' */ 0x69696C67,\n    bmdDeckLinkConfigVideoInputCompositeChromaGain               = /* 'iicg' */ 0x69696367,\n    bmdDeckLinkConfigVideoInputSVideoLumaGain                    = /* 'islg' */ 0x69736C67,\n    bmdDeckLinkConfigVideoInputSVideoChromaGain                  = /* 'iscg' */ 0x69736367,\n\n    /* Keying Integers */\n\n    bmdDeckLinkConfigInternalKeyingAncillaryDataSource           = /* 'ikas' */ 0x696B6173,\n\n    /* Audio Input Flags */\n\n    bmdDeckLinkConfigMicrophonePhantomPower                      = /* 'mphp' */ 0x6D706870,\n\n    /* Audio Input Integers */\n\n    bmdDeckLinkConfigAudioInputConnection                        = /* 'aicn' */ 0x6169636E,\n\n    /* Audio Input Floats */\n\n    bmdDeckLinkConfigAnalogAudioInputScaleChannel1               = /* 'ais1' */ 0x61697331,\n    bmdDeckLinkConfigAnalogAudioInputScaleChannel2               = /* 'ais2' */ 0x61697332,\n    bmdDeckLinkConfigAnalogAudioInputScaleChannel3               = /* 'ais3' */ 0x61697333,\n    bmdDeckLinkConfigAnalogAudioInputScaleChannel4               = /* 'ais4' */ 0x61697334,\n    bmdDeckLinkConfigDigitalAudioInputScale                      = /* 'dais' */ 0x64616973,\n    bmdDeckLinkConfigMicrophoneInputGain                         = /* 'micg' */ 0x6D696367,\n\n    /* Audio Output Integers */\n\n    bmdDeckLinkConfigAudioOutputAESAnalogSwitch                  = /* 'aoaa' */ 0x616F6161,\n\n    /* Audio Output Floats */\n\n    bmdDeckLinkConfigAnalogAudioOutputScaleChannel1              = /* 'aos1' */ 0x616F7331,\n    bmdDeckLinkConfigAnalogAudioOutputScaleChannel2              = /* 'aos2' */ 0x616F7332,\n    bmdDeckLinkConfigAnalogAudioOutputScaleChannel3              = /* 'aos3' */ 0x616F7333,\n    bmdDeckLinkConfigAnalogAudioOutputScaleChannel4              = /* 'aos4' */ 0x616F7334,\n    bmdDeckLinkConfigDigitalAudioOutputScale                     = /* 'daos' */ 0x64616F73,\n    bmdDeckLinkConfigHeadphoneVolume                             = /* 'hvol' */ 0x68766F6C,\n\n    /* Device Information Strings */\n\n    bmdDeckLinkConfigDeviceInformationLabel                      = /* 'dila' */ 0x64696C61,\n    bmdDeckLinkConfigDeviceInformationSerialNumber               = /* 'disn' */ 0x6469736E,\n    bmdDeckLinkConfigDeviceInformationCompany                    = /* 'dico' */ 0x6469636F,\n    bmdDeckLinkConfigDeviceInformationPhone                      = /* 'diph' */ 0x64697068,\n    bmdDeckLinkConfigDeviceInformationEmail                      = /* 'diem' */ 0x6469656D,\n    bmdDeckLinkConfigDeviceInformationDate                       = /* 'dida' */ 0x64696461,\n\n    /* Deck Control Integers */\n\n    bmdDeckLinkConfigDeckControlConnection                       = /* 'dcco' */ 0x6463636F\n};\n\n/* Enum BMDDeckLinkEncoderConfigurationID - DeckLink Encoder Configuration ID */\n\ntypedef uint32_t BMDDeckLinkEncoderConfigurationID;\nenum _BMDDeckLinkEncoderConfigurationID {\n\n    /* Video Encoder Integers */\n\n    bmdDeckLinkEncoderConfigPreferredBitDepth                    = /* 'epbr' */ 0x65706272,\n    bmdDeckLinkEncoderConfigFrameCodingMode                      = /* 'efcm' */ 0x6566636D,\n\n    /* HEVC/H.265 Encoder Integers */\n\n    bmdDeckLinkEncoderConfigH265TargetBitrate                    = /* 'htbr' */ 0x68746272,\n\n    /* DNxHR/DNxHD Compression ID */\n\n    bmdDeckLinkEncoderConfigDNxHRCompressionID                   = /* 'dcid' */ 0x64636964,\n\n    /* DNxHR/DNxHD Level */\n\n    bmdDeckLinkEncoderConfigDNxHRLevel                           = /* 'dlev' */ 0x646C6576,\n\n    /* Encoded Sample Descriptions */\n\n    bmdDeckLinkEncoderConfigMPEG4SampleDescription               = /* 'stsE' */ 0x73747345,\t// Full MPEG4 sample description (aka SampleEntry of an 'stsd' atom-box). Useful for MediaFoundation, QuickTime, MKV and more\n    bmdDeckLinkEncoderConfigMPEG4CodecSpecificDesc               = /* 'esds' */ 0x65736473\t// Sample description extensions only (atom stream, each with size and fourCC header). Useful for AVFoundation, VideoToolbox, MKV and more\n};\n\n#if defined(__cplusplus)\n\n// Forward Declarations\n\nclass IDeckLinkConfiguration;\nclass IDeckLinkEncoderConfiguration;\n\n/* Interface IDeckLinkConfiguration - DeckLink Configuration interface */\n\nclass BMD_PUBLIC IDeckLinkConfiguration : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool* value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t* value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double* value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char** value) = 0;\n    virtual HRESULT WriteConfigurationToPreferences (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkConfiguration () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkEncoderConfiguration - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */\n\nclass BMD_PUBLIC IDeckLinkEncoderConfiguration : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ bool* value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ int64_t* value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ double* value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ const char* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ const char** value) = 0;\n    virtual HRESULT GetBytes (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ void* buffer /* optional */, /* in, out */ uint32_t* bufferSize) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderConfiguration () {} // call Release method to drop reference count\n};\n\n/* Functions */\n\nextern \"C\" {\n\n\n}\n\n\n\n#endif /* defined(__cplusplus) */\n#endif /* defined(BMD_DECKLINKAPICONFIGURATION_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIConfiguration_v10_11.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2017 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPICONFIGURATION_v10_11_H\n#define BMD_DECKLINKAPICONFIGURATION_v10_11_H\n\n#include \"DeckLinkAPIConfiguration.h\"\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkConfiguration_v10_11                       = /* EF90380B-4AE5-4346-9077-E288E149F129 */ {0xEF,0x90,0x38,0x0B,0x4A,0xE5,0x43,0x46,0x90,0x77,0xE2,0x88,0xE1,0x49,0xF1,0x29};\n\n/* Enum BMDDeckLinkConfigurationID_v10_11 - DeckLink Configuration ID */\n\ntypedef uint32_t BMDDeckLinkConfigurationID_v10_11;\nenum _BMDDeckLinkConfigurationID_v10_11 {\n\n    /* Video Input/Output Integers */\n\n    bmdDeckLinkConfigDuplexMode_v10_11                              = /* 'dupx' */ 0x64757078,\n};\n\n// Forward Declarations\n\nclass IDeckLinkConfiguration_v10_11;\n\n/* Interface IDeckLinkConfiguration_v10_11 - DeckLink Configuration interface */\n\nclass BMD_PUBLIC IDeckLinkConfiguration_v10_11 : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0;\n    virtual HRESULT WriteConfigurationToPreferences (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkConfiguration_v10_11 () {} // call Release method to drop reference count\n};\n\n\n#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_11_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIConfiguration_v10_2.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2014 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPICONFIGURATION_v10_2_H\n#define BMD_DECKLINKAPICONFIGURATION_v10_2_H\n\n#include \"DeckLinkAPIConfiguration.h\"\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkConfiguration_v10_2                = /* C679A35B-610C-4D09-B748-1D0478100FC0 */ {0xC6,0x79,0xA3,0x5B,0x61,0x0C,0x4D,0x09,0xB7,0x48,0x1D,0x04,0x78,0x10,0x0F,0xC0};\n\n// Forward Declarations\n\nclass IDeckLinkConfiguration_v10_2;\n\n/* Interface IDeckLinkConfiguration_v10_2 - DeckLink Configuration interface */\n\nclass BMD_PUBLIC IDeckLinkConfiguration_v10_2 : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0;\n    virtual HRESULT WriteConfigurationToPreferences (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkConfiguration_v10_2 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_2_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIConfiguration_v10_4.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2015 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPICONFIGURATION_v10_4_H\n#define BMD_DECKLINKAPICONFIGURATION_v10_4_H\n\n#include \"DeckLinkAPIConfiguration.h\"\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkConfiguration_v10_4                       = /* 1E69FCF6-4203-4936-8076-2A9F4CFD50CB */ {0x1E,0x69,0xFC,0xF6,0x42,0x03,0x49,0x36,0x80,0x76,0x2A,0x9F,0x4C,0xFD,0x50,0xCB};\n\n\n//\n// Forward Declarations\n\nclass IDeckLinkConfiguration_v10_4;\n\n/* Interface IDeckLinkConfiguration_v10_4 - DeckLink Configuration interface */\n\nclass BMD_PUBLIC IDeckLinkConfiguration_v10_4 : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0;\n    virtual HRESULT WriteConfigurationToPreferences (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkConfiguration_v10_4 () {} // call Release method to drop reference count\n};\n\n\n#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_4_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIConfiguration_v10_5.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2015 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPICONFIGURATION_v10_5_H\n#define BMD_DECKLINKAPICONFIGURATION_v10_5_H\n\n#include \"DeckLinkAPIConfiguration.h\"\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkEncoderConfiguration_v10_5          = /* 67455668-0848-45DF-8D8E-350A77C9A028 */ {0x67,0x45,0x56,0x68,0x08,0x48,0x45,0xDF,0x8D,0x8E,0x35,0x0A,0x77,0xC9,0xA0,0x28};\n\n// Forward Declarations\n\nclass IDeckLinkEncoderConfiguration_v10_5;\n\n/* Interface IDeckLinkEncoderConfiguration_v10_5 - DeckLink Encoder Configuration interface. Obtained from IDeckLinkEncoderInput */\n\nclass BMD_PUBLIC IDeckLinkEncoderConfiguration_v10_5 : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ bool *value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ int64_t *value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ double *value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* in */ const char *value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkEncoderConfigurationID cfgID, /* out */ const char **value) = 0;\n    virtual HRESULT GetDecoderConfigurationInfo (/* out */ void *buffer, /* in */ long bufferSize, /* out */ long *returnedSize) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderConfiguration_v10_5 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_5_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIConfiguration_v10_9.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2017 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPICONFIGURATION_v10_9_H\n#define BMD_DECKLINKAPICONFIGURATION_v10_9_H\n\n#include \"DeckLinkAPIConfiguration.h\"\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkConfiguration_v10_9                       = /* CB71734A-FE37-4E8D-8E13-802133A1C3F2 */ {0xCB,0x71,0x73,0x4A,0xFE,0x37,0x4E,0x8D,0x8E,0x13,0x80,0x21,0x33,0xA1,0xC3,0xF2};\n\n//\n// Forward Declarations\n\nclass IDeckLinkConfiguration_v10_9;\n\n/* Interface IDeckLinkConfiguration_v10_9 - DeckLink Configuration interface */\n\nclass BMD_PUBLIC IDeckLinkConfiguration_v10_9 : public IUnknown\n{\npublic:\n    virtual HRESULT SetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ bool value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ bool *value) = 0;\n    virtual HRESULT SetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ int64_t value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ int64_t *value) = 0;\n    virtual HRESULT SetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ double value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ double *value) = 0;\n    virtual HRESULT SetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* in */ const char *value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkConfigurationID cfgID, /* out */ const char **value) = 0;\n    virtual HRESULT WriteConfigurationToPreferences (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkConfiguration_v10_9 () {} // call Release method to drop reference count\n};\n\n\n#endif /* defined(BMD_DECKLINKAPICONFIGURATION_v10_9_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDeckControl.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2022 Blackmagic Design\n**\n** Permission is hereby granted, free of charge, to any person or organization\n** obtaining a copy of the software and accompanying documentation covered by\n** this license (the \"Software\") to use, reproduce, display, distribute,\n** execute, and transmit the Software, and to prepare derivative works of the\n** Software, and to permit third-parties to whom the Software is furnished to\n** do so, all subject to the following:\n**\n** The copyright notices in the Software and this entire statement, including\n** the above license grant, this restriction and the following disclaimer,\n** must be included in all copies of the Software, in whole or in part, and\n** all derivative works of the Software, unless such copies or derivative\n** works are solely in the form of machine-executable object code generated by\n** a source language processor.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n** DEALINGS IN THE SOFTWARE.\n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIDECKCONTROL_H\n#define BMD_DECKLINKAPIDECKCONTROL_H\n\n\n#ifndef BMD_CONST\n    #if defined(_MSC_VER)\n        #define BMD_CONST __declspec(selectany) static const\n    #else\n        #define BMD_CONST static const\n    #endif\n#endif\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n// Type Declarations\n\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkDeckControlStatusCallback           = /* 53436FFB-B434-4906-BADC-AE3060FFE8EF */ { 0x53,0x43,0x6F,0xFB,0xB4,0x34,0x49,0x06,0xBA,0xDC,0xAE,0x30,0x60,0xFF,0xE8,0xEF };\nBMD_CONST REFIID IID_IDeckLinkDeckControl                         = /* 8E1C3ACE-19C7-4E00-8B92-D80431D958BE */ { 0x8E,0x1C,0x3A,0xCE,0x19,0xC7,0x4E,0x00,0x8B,0x92,0xD8,0x04,0x31,0xD9,0x58,0xBE };\n\n/* Enum BMDDeckControlMode - DeckControl mode */\n\ntypedef uint32_t BMDDeckControlMode;\nenum _BMDDeckControlMode {\n    bmdDeckControlNotOpened                                      = /* 'ntop' */ 0x6E746F70,\n    bmdDeckControlVTRControlMode                                 = /* 'vtrc' */ 0x76747263,\n    bmdDeckControlExportMode                                     = /* 'expm' */ 0x6578706D,\n    bmdDeckControlCaptureMode                                    = /* 'capm' */ 0x6361706D\n};\n\n/* Enum BMDDeckControlEvent - DeckControl event */\n\ntypedef uint32_t BMDDeckControlEvent;\nenum _BMDDeckControlEvent {\n    bmdDeckControlAbortedEvent                                   = /* 'abte' */ 0x61627465,\t// This event is triggered when a capture or edit-to-tape operation is aborted.\n\n    /* Export-To-Tape events */\n\n    bmdDeckControlPrepareForExportEvent                          = /* 'pfee' */ 0x70666565,\t// This event is triggered a few frames before reaching the in-point. IDeckLinkInput::StartScheduledPlayback should be called at this point.\n    bmdDeckControlExportCompleteEvent                            = /* 'exce' */ 0x65786365,\t// This event is triggered a few frames after reaching the out-point. At this point, it is safe to stop playback. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode.\n\n    /* Capture events */\n\n    bmdDeckControlPrepareForCaptureEvent                         = /* 'pfce' */ 0x70666365,\t// This event is triggered a few frames before reaching the in-point. The serial timecode attached to IDeckLinkVideoInputFrames is now valid.\n    bmdDeckControlCaptureCompleteEvent                           = /* 'ccev' */ 0x63636576\t// This event is triggered a few frames after reaching the out-point. Upon reception of this event the deck's control mode is set back to bmdDeckControlVTRControlMode.\n};\n\n/* Enum BMDDeckControlVTRControlState - VTR Control state */\n\ntypedef uint32_t BMDDeckControlVTRControlState;\nenum _BMDDeckControlVTRControlState {\n    bmdDeckControlNotInVTRControlMode                            = /* 'nvcm' */ 0x6E76636D,\n    bmdDeckControlVTRControlPlaying                              = /* 'vtrp' */ 0x76747270,\n    bmdDeckControlVTRControlRecording                            = /* 'vtrr' */ 0x76747272,\n    bmdDeckControlVTRControlStill                                = /* 'vtra' */ 0x76747261,\n    bmdDeckControlVTRControlShuttleForward                       = /* 'vtsf' */ 0x76747366,\n    bmdDeckControlVTRControlShuttleReverse                       = /* 'vtsr' */ 0x76747372,\n    bmdDeckControlVTRControlJogForward                           = /* 'vtjf' */ 0x76746A66,\n    bmdDeckControlVTRControlJogReverse                           = /* 'vtjr' */ 0x76746A72,\n    bmdDeckControlVTRControlStopped                              = /* 'vtro' */ 0x7674726F\n};\n\n/* Enum BMDDeckControlStatusFlags - Deck Control status flags */\n\ntypedef uint32_t BMDDeckControlStatusFlags;\nenum _BMDDeckControlStatusFlags {\n    bmdDeckControlStatusDeckConnected                            = 1 << 0,\n    bmdDeckControlStatusRemoteMode                               = 1 << 1,\n    bmdDeckControlStatusRecordInhibited                          = 1 << 2,\n    bmdDeckControlStatusCassetteOut                              = 1 << 3\n};\n\n/* Enum BMDDeckControlExportModeOpsFlags - Export mode flags */\n\ntypedef uint32_t BMDDeckControlExportModeOpsFlags;\nenum _BMDDeckControlExportModeOpsFlags {\n    bmdDeckControlExportModeInsertVideo                          = 1 << 0,\n    bmdDeckControlExportModeInsertAudio1                         = 1 << 1,\n    bmdDeckControlExportModeInsertAudio2                         = 1 << 2,\n    bmdDeckControlExportModeInsertAudio3                         = 1 << 3,\n    bmdDeckControlExportModeInsertAudio4                         = 1 << 4,\n    bmdDeckControlExportModeInsertAudio5                         = 1 << 5,\n    bmdDeckControlExportModeInsertAudio6                         = 1 << 6,\n    bmdDeckControlExportModeInsertAudio7                         = 1 << 7,\n    bmdDeckControlExportModeInsertAudio8                         = 1 << 8,\n    bmdDeckControlExportModeInsertAudio9                         = 1 << 9,\n    bmdDeckControlExportModeInsertAudio10                        = 1 << 10,\n    bmdDeckControlExportModeInsertAudio11                        = 1 << 11,\n    bmdDeckControlExportModeInsertAudio12                        = 1 << 12,\n    bmdDeckControlExportModeInsertTimeCode                       = 1 << 13,\n    bmdDeckControlExportModeInsertAssemble                       = 1 << 14,\n    bmdDeckControlExportModeInsertPreview                        = 1 << 15,\n    bmdDeckControlUseManualExport                                = 1 << 16\n};\n\n/* Enum BMDDeckControlError - Deck Control error */\n\ntypedef uint32_t BMDDeckControlError;\nenum _BMDDeckControlError {\n    bmdDeckControlNoError                                        = /* 'noer' */ 0x6E6F6572,\n    bmdDeckControlModeError                                      = /* 'moer' */ 0x6D6F6572,\n    bmdDeckControlMissedInPointError                             = /* 'mier' */ 0x6D696572,\n    bmdDeckControlDeckTimeoutError                               = /* 'dter' */ 0x64746572,\n    bmdDeckControlCommandFailedError                             = /* 'cfer' */ 0x63666572,\n    bmdDeckControlDeviceAlreadyOpenedError                       = /* 'dalo' */ 0x64616C6F,\n    bmdDeckControlFailedToOpenDeviceError                        = /* 'fder' */ 0x66646572,\n    bmdDeckControlInLocalModeError                               = /* 'lmer' */ 0x6C6D6572,\n    bmdDeckControlEndOfTapeError                                 = /* 'eter' */ 0x65746572,\n    bmdDeckControlUserAbortError                                 = /* 'uaer' */ 0x75616572,\n    bmdDeckControlNoTapeInDeckError                              = /* 'nter' */ 0x6E746572,\n    bmdDeckControlNoVideoFromCardError                           = /* 'nvfc' */ 0x6E766663,\n    bmdDeckControlNoCommunicationError                           = /* 'ncom' */ 0x6E636F6D,\n    bmdDeckControlBufferTooSmallError                            = /* 'btsm' */ 0x6274736D,\n    bmdDeckControlBadChecksumError                               = /* 'chks' */ 0x63686B73,\n    bmdDeckControlUnknownError                                   = /* 'uner' */ 0x756E6572\n};\n\n#if defined(__cplusplus)\n\n// Forward Declarations\n\nclass IDeckLinkDeckControlStatusCallback;\nclass IDeckLinkDeckControl;\n\n/* Interface IDeckLinkDeckControlStatusCallback - Deck control state change callback. */\n\nclass BMD_PUBLIC IDeckLinkDeckControlStatusCallback : public IUnknown\n{\npublic:\n    virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0;\n    virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState newState, /* in */ BMDDeckControlError error) = 0;\n    virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0;\n    virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0;\n\nprotected:\n    virtual ~IDeckLinkDeckControlStatusCallback () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkDeckControl - Deck Control main interface */\n\nclass BMD_PUBLIC IDeckLinkDeckControl : public IUnknown\n{\npublic:\n    virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Close (/* in */ bool standbyOn) = 0;\n    virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode* mode, /* out */ BMDDeckControlVTRControlState* vtrControlState, /* out */ BMDDeckControlStatusFlags* flags) = 0;\n    virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0;\n    virtual HRESULT SendCommand (/* in */ uint8_t* inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t* outBuffer, /* out */ uint32_t* outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Play (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Stop (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Eject (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT StepForward (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT StepBack (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT GetTimecodeString (/* out */ const char** currentTimeCode, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode** currentTimecode, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD* currentTimecode, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0;\n    virtual HRESULT GetPreroll (/* out */ uint32_t* prerollSeconds) = 0;\n    virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0;\n    virtual HRESULT GetExportOffset (/* out */ int32_t* exportOffsetFields) = 0;\n    virtual HRESULT GetManualExportOffset (/* out */ int32_t* deckManualExportOffsetFields) = 0;\n    virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0;\n    virtual HRESULT GetCaptureOffset (/* out */ int32_t* captureOffsetFields) = 0;\n    virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT GetDeviceID (/* out */ uint16_t* deviceId, /* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT Abort (void) = 0;\n    virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError* error) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback* callback) = 0;\n\nprotected:\n    virtual ~IDeckLinkDeckControl () {} // call Release method to drop reference count\n};\n\n/* Functions */\n\nextern \"C\" {\n\n\n}\n\n\n\n#endif /* defined(__cplusplus) */\n#endif /* defined(BMD_DECKLINKAPIDECKCONTROL_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDiscovery.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2022 Blackmagic Design\n**\n** Permission is hereby granted, free of charge, to any person or organization\n** obtaining a copy of the software and accompanying documentation covered by\n** this license (the \"Software\") to use, reproduce, display, distribute,\n** execute, and transmit the Software, and to prepare derivative works of the\n** Software, and to permit third-parties to whom the Software is furnished to\n** do so, all subject to the following:\n**\n** The copyright notices in the Software and this entire statement, including\n** the above license grant, this restriction and the following disclaimer,\n** must be included in all copies of the Software, in whole or in part, and\n** all derivative works of the Software, unless such copies or derivative\n** works are solely in the form of machine-executable object code generated by\n** a source language processor.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n** DEALINGS IN THE SOFTWARE.\n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIDISCOVERY_H\n#define BMD_DECKLINKAPIDISCOVERY_H\n\n\n#ifndef BMD_CONST\n    #if defined(_MSC_VER)\n        #define BMD_CONST __declspec(selectany) static const\n    #else\n        #define BMD_CONST static const\n    #endif\n#endif\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n// Type Declarations\n\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLink                                    = /* C418FBDD-0587-48ED-8FE5-640F0A14AF91 */ { 0xC4,0x18,0xFB,0xDD,0x05,0x87,0x48,0xED,0x8F,0xE5,0x64,0x0F,0x0A,0x14,0xAF,0x91 };\n\n#if defined(__cplusplus)\n\n// Forward Declarations\n\nclass IDeckLink;\n\n/* Interface IDeckLink - Represents a DeckLink device */\n\nclass BMD_PUBLIC IDeckLink : public IUnknown\n{\npublic:\n    virtual HRESULT GetModelName (/* out */ const char** modelName) = 0;\n    virtual HRESULT GetDisplayName (/* out */ const char** displayName) = 0;\n\nprotected:\n    virtual ~IDeckLink () {} // call Release method to drop reference count\n};\n\n/* Functions */\n\nextern \"C\" {\n\n\n}\n\n\n\n#endif /* defined(__cplusplus) */\n#endif /* defined(BMD_DECKLINKAPIDISCOVERY_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDispatch.cpp",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n**/\n\n#include <stdio.h>\n#include <pthread.h>\n#include <dlfcn.h>\n\n#include \"DeckLinkAPI.h\"\n\n#define kDeckLinkAPI_Name \"libDeckLinkAPI.so\"\n#define KDeckLinkPreviewAPI_Name \"libDeckLinkPreviewAPI.so\"\n\ntypedef IDeckLinkIterator* (*CreateIteratorFunc)(void);\ntypedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void);\ntypedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);\ntypedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGL3ScreenPreviewHelperFunc)(void);\ntypedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);\ntypedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void);\ntypedef IDeckLinkVideoFrameAncillaryPackets* (*CreateVideoFrameAncillaryPacketsInstanceFunc)(void);\n\nstatic pthread_once_t\t\t\t\t\tgDeckLinkOnceControl = PTHREAD_ONCE_INIT;\nstatic pthread_once_t\t\t\t\t\tgPreviewOnceControl = PTHREAD_ONCE_INIT;\n\nstatic bool\t\t\t\t\t\t\t\tgLoadedDeckLinkAPI = false;\n\nstatic CreateIteratorFunc\t\t\t\t\tgCreateIteratorFunc = NULL;\nstatic CreateAPIInformationFunc\t\t\t\tgCreateAPIInformationFunc = NULL;\nstatic CreateOpenGLScreenPreviewHelperFunc\tgCreateOpenGLPreviewFunc = NULL;\nstatic CreateOpenGL3ScreenPreviewHelperFunc\tgCreateOpenGL3PreviewFunc = NULL;\nstatic CreateVideoConversionInstanceFunc\tgCreateVideoConversionFunc\t= NULL;\nstatic CreateDeckLinkDiscoveryInstanceFunc\tgCreateDeckLinkDiscoveryFunc = NULL;\nstatic CreateVideoFrameAncillaryPacketsInstanceFunc\tgCreateVideoFrameAncillaryPacketsFunc = NULL;\n\nstatic void\tInitDeckLinkAPI (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\t\n\tgLoadedDeckLinkAPI = true;\n\t\n\tgCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, \"CreateDeckLinkIteratorInstance_0004\");\n\tif (!gCreateIteratorFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, \"CreateDeckLinkAPIInformationInstance_0001\");\n\tif (!gCreateAPIInformationFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, \"CreateVideoConversionInstance_0001\");\n\tif (!gCreateVideoConversionFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, \"CreateDeckLinkDiscoveryInstance_0003\");\n\tif (!gCreateDeckLinkDiscoveryFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoFrameAncillaryPacketsFunc = (CreateVideoFrameAncillaryPacketsInstanceFunc)dlsym(libraryHandle, \"CreateVideoFrameAncillaryPacketsInstance_0001\");\n\tif (!gCreateVideoFrameAncillaryPacketsFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nstatic void\tInitDeckLinkPreviewAPI (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\tgCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, \"CreateOpenGLScreenPreviewHelper_0001\");\n\tif (!gCreateOpenGLPreviewFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateOpenGL3PreviewFunc = (CreateOpenGL3ScreenPreviewHelperFunc)dlsym(libraryHandle, \"CreateOpenGL3ScreenPreviewHelper_0001\");\n\tif (!gCreateOpenGL3PreviewFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nbool\t\tIsDeckLinkAPIPresent (void)\n{\n\t// If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller\n\treturn gLoadedDeckLinkAPI;\n}\n\nIDeckLinkIterator*\t\tCreateDeckLinkIteratorInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateIteratorFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateIteratorFunc();\n}\n\nIDeckLinkAPIInformation*\tCreateDeckLinkAPIInformationInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateAPIInformationFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateAPIInformationFunc();\n}\n\nIDeckLinkGLScreenPreviewHelper*\t\tCreateOpenGLScreenPreviewHelper (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\tpthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);\n\t\n\tif (gCreateOpenGLPreviewFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateOpenGLPreviewFunc();\n}\n\nIDeckLinkGLScreenPreviewHelper*\t\tCreateOpenGL3ScreenPreviewHelper (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\tpthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);\n\n\tif (gCreateOpenGL3PreviewFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateOpenGL3PreviewFunc();\n}\n\nIDeckLinkVideoConversion* CreateVideoConversionInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateVideoConversionFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoConversionFunc();\n}\n\nIDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateDeckLinkDiscoveryFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateDeckLinkDiscoveryFunc();\n}\n\nIDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateVideoFrameAncillaryPacketsFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoFrameAncillaryPacketsFunc();\n}\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDispatch_v10_11.cpp",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2019 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n**/\n\n#include <stdio.h>\n#include <pthread.h>\n#include <dlfcn.h>\n\n#include \"DeckLinkAPI_v10_11.h\"\n\n#define kDeckLinkAPI_Name \"libDeckLinkAPI.so\"\n#define KDeckLinkPreviewAPI_Name \"libDeckLinkPreviewAPI.so\"\n\ntypedef IDeckLinkIterator* (*CreateIteratorFunc)(void);\ntypedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void);\ntypedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);\ntypedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);\ntypedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void);\ntypedef IDeckLinkVideoFrameAncillaryPackets* (*CreateVideoFrameAncillaryPacketsInstanceFunc)(void);\n\nstatic pthread_once_t\t\t\t\t\tgDeckLinkOnceControl = PTHREAD_ONCE_INIT;\nstatic pthread_once_t\t\t\t\t\tgPreviewOnceControl = PTHREAD_ONCE_INIT;\n\nstatic bool\t\t\t\t\t\t\t\tgLoadedDeckLinkAPI = false;\n\nstatic CreateIteratorFunc\t\t\t\t\tgCreateIteratorFunc = NULL;\nstatic CreateAPIInformationFunc\t\t\t\tgCreateAPIInformationFunc = NULL;\nstatic CreateOpenGLScreenPreviewHelperFunc\tgCreateOpenGLPreviewFunc = NULL;\nstatic CreateVideoConversionInstanceFunc\tgCreateVideoConversionFunc\t= NULL;\nstatic CreateDeckLinkDiscoveryInstanceFunc\tgCreateDeckLinkDiscoveryFunc = NULL;\nstatic CreateVideoFrameAncillaryPacketsInstanceFunc\tgCreateVideoFrameAncillaryPacketsFunc = NULL;\n\nstatic void\tInitDeckLinkAPI (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\t\n\tgLoadedDeckLinkAPI = true;\n\t\n\tgCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, \"CreateDeckLinkIteratorInstance_0003\");\n\tif (!gCreateIteratorFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, \"CreateDeckLinkAPIInformationInstance_0001\");\n\tif (!gCreateAPIInformationFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, \"CreateVideoConversionInstance_0001\");\n\tif (!gCreateVideoConversionFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, \"CreateDeckLinkDiscoveryInstance_0002\");\n\tif (!gCreateDeckLinkDiscoveryFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoFrameAncillaryPacketsFunc = (CreateVideoFrameAncillaryPacketsInstanceFunc)dlsym(libraryHandle, \"CreateVideoFrameAncillaryPacketsInstance_0001\");\n\tif (!gCreateVideoFrameAncillaryPacketsFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nstatic void\tInitDeckLinkPreviewAPI (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\tgCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, \"CreateOpenGLScreenPreviewHelper_0001\");\n\tif (!gCreateOpenGLPreviewFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nbool\t\tIsDeckLinkAPIPresent_v10_11 (void)\n{\n\t// If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller\n\treturn gLoadedDeckLinkAPI;\n}\n\nIDeckLinkIterator*\t\tCreateDeckLinkIteratorInstance_v10_11 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateIteratorFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateIteratorFunc();\n}\n\nIDeckLinkAPIInformation*\tCreateDeckLinkAPIInformationInstance_v10_11 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateAPIInformationFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateAPIInformationFunc();\n}\n\nIDeckLinkGLScreenPreviewHelper*\t\tCreateOpenGLScreenPreviewHelper_v10_11 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\tpthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);\n\t\n\tif (gCreateOpenGLPreviewFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateOpenGLPreviewFunc();\n}\n\nIDeckLinkVideoConversion* CreateVideoConversionInstance_v10_11 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateVideoConversionFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoConversionFunc();\n}\n\nIDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance_v10_11 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateDeckLinkDiscoveryFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateDeckLinkDiscoveryFunc();\n}\n\nIDeckLinkVideoFrameAncillaryPackets* CreateVideoFrameAncillaryPacketsInstance_v10_11 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateVideoFrameAncillaryPacketsFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoFrameAncillaryPacketsFunc();\n}\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDispatch_v10_8.cpp",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n**/\n\n#include <stdio.h>\n#include <pthread.h>\n#include <dlfcn.h>\n\n#include \"DeckLinkAPI.h\"\n\n#define kDeckLinkAPI_Name \"libDeckLinkAPI.so\"\n#define KDeckLinkPreviewAPI_Name \"libDeckLinkPreviewAPI.so\"\n\ntypedef IDeckLinkIterator* (*CreateIteratorFunc)(void);\ntypedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void);\ntypedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);\ntypedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);\ntypedef IDeckLinkDiscovery* (*CreateDeckLinkDiscoveryInstanceFunc)(void);\n\nstatic pthread_once_t\t\t\t\t\tgDeckLinkOnceControl = PTHREAD_ONCE_INIT;\nstatic pthread_once_t\t\t\t\t\tgPreviewOnceControl = PTHREAD_ONCE_INIT;\n\nstatic bool\t\t\t\t\t\t\t\tgLoadedDeckLinkAPI = false;\n\nstatic CreateIteratorFunc\t\t\t\t\tgCreateIteratorFunc = NULL;\nstatic CreateAPIInformationFunc\t\t\t\tgCreateAPIInformationFunc = NULL;\nstatic CreateOpenGLScreenPreviewHelperFunc\tgCreateOpenGLPreviewFunc = NULL;\nstatic CreateVideoConversionInstanceFunc\tgCreateVideoConversionFunc = NULL;\nstatic CreateDeckLinkDiscoveryInstanceFunc\tgCreateDeckLinkDiscoveryFunc = NULL;\n\nstatic void\tInitDeckLinkAPI(void)\n{\n\tvoid *libraryHandle;\n\n\tlibraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW | RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\n\tgLoadedDeckLinkAPI = true;\n\n\tgCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, \"CreateDeckLinkIteratorInstance_0002\");\n\tif (!gCreateIteratorFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, \"CreateDeckLinkAPIInformationInstance_0001\");\n\tif (!gCreateAPIInformationFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, \"CreateVideoConversionInstance_0001\");\n\tif (!gCreateVideoConversionFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateDeckLinkDiscoveryFunc = (CreateDeckLinkDiscoveryInstanceFunc)dlsym(libraryHandle, \"CreateDeckLinkDiscoveryInstance_0001\");\n\tif (!gCreateDeckLinkDiscoveryFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nstatic void\tInitDeckLinkPreviewAPI(void)\n{\n\tvoid *libraryHandle;\n\n\tlibraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW | RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\tgCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, \"CreateOpenGLScreenPreviewHelper_0001\");\n\tif (!gCreateOpenGLPreviewFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nbool\t\tIsDeckLinkAPIPresent(void)\n{\n\t// If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller\n\treturn gLoadedDeckLinkAPI;\n}\n\nIDeckLinkIterator*\t\tCreateDeckLinkIteratorInstance(void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\n\tif (gCreateIteratorFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateIteratorFunc();\n}\n\nIDeckLinkAPIInformation*\tCreateDeckLinkAPIInformationInstance(void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\n\tif (gCreateAPIInformationFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateAPIInformationFunc();\n}\n\nIDeckLinkGLScreenPreviewHelper*\t\tCreateOpenGLScreenPreviewHelper(void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\tpthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);\n\n\tif (gCreateOpenGLPreviewFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateOpenGLPreviewFunc();\n}\n\nIDeckLinkVideoConversion* CreateVideoConversionInstance(void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\n\tif (gCreateVideoConversionFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoConversionFunc();\n}\n\nIDeckLinkDiscovery* CreateDeckLinkDiscoveryInstance(void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\n\tif (gCreateDeckLinkDiscoveryFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateDeckLinkDiscoveryFunc();\n}\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDispatch_v7_6.cpp",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n**/\n\n#include <stdio.h>\n#include <pthread.h>\n#include <dlfcn.h>\n\n#include \"DeckLinkAPI_v7_6.h\"\n\n#define kDeckLinkAPI_Name \"libDeckLinkAPI.so\"\n#define KDeckLinkPreviewAPI_Name \"libDeckLinkPreviewAPI.so\"\n\ntypedef IDeckLinkIterator* (*CreateIteratorFunc_v7_6)(void);\ntypedef IDeckLinkGLScreenPreviewHelper_v7_6* (*CreateOpenGLScreenPreviewHelperFunc_v7_6)(void);\ntypedef IDeckLinkVideoConversion_v7_6* (*CreateVideoConversionInstanceFunc_v7_6)(void);\n\nstatic pthread_once_t\t\t\t\t\tgDeckLinkOnceControl = PTHREAD_ONCE_INIT;\nstatic pthread_once_t\t\t\t\t\tgPreviewOnceControl = PTHREAD_ONCE_INIT;\n\nstatic CreateIteratorFunc_v7_6\t\t\t\t\t\tgCreateIteratorFunc\t\t\t= NULL;\nstatic CreateOpenGLScreenPreviewHelperFunc_v7_6\t\tgCreateOpenGLPreviewFunc\t= NULL;\nstatic CreateVideoConversionInstanceFunc_v7_6\t\tgCreateVideoConversionFunc\t= NULL;\n\nstatic void\tInitDeckLinkAPI_v7_6 (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\t\n\tgCreateIteratorFunc = (CreateIteratorFunc_v7_6)dlsym(libraryHandle, \"CreateDeckLinkIteratorInstance\");\n\tif (!gCreateIteratorFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc_v7_6)dlsym(libraryHandle, \"CreateVideoConversionInstance\");\n\tif (!gCreateVideoConversionFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nstatic void\tInitDeckLinkPreviewAPI_v7_6 (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\tgCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc_v7_6)dlsym(libraryHandle, \"CreateOpenGLScreenPreviewHelper\");\n\tif (!gCreateOpenGLPreviewFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nIDeckLinkIterator*\t\tCreateDeckLinkIteratorInstance_v7_6 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6);\n\t\n\tif (gCreateIteratorFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateIteratorFunc();\n}\n\nIDeckLinkGLScreenPreviewHelper_v7_6*\t\tCreateOpenGLScreenPreviewHelper_v7_6 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6);\n\tpthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI_v7_6);\n\t\n\tif (gCreateOpenGLPreviewFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateOpenGLPreviewFunc();\n}\n\nIDeckLinkVideoConversion_v7_6* CreateVideoConversionInstance_v7_6 (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI_v7_6);\n\t\n\tif (gCreateVideoConversionFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoConversionFunc();\n}\n\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIDispatch_v8_0.cpp",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2011 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n**/\n\n#include <stdio.h>\n#include <pthread.h>\n#include <dlfcn.h>\n\n#include \"DeckLinkAPI_v8_0.h\"\n\n#define kDeckLinkAPI_Name \"libDeckLinkAPI.so\"\n#define KDeckLinkPreviewAPI_Name \"libDeckLinkPreviewAPI.so\"\n\ntypedef IDeckLinkIterator_v8_0* (*CreateIteratorFunc)(void);\ntypedef IDeckLinkAPIInformation* (*CreateAPIInformationFunc)(void);\ntypedef IDeckLinkGLScreenPreviewHelper* (*CreateOpenGLScreenPreviewHelperFunc)(void);\ntypedef IDeckLinkVideoConversion* (*CreateVideoConversionInstanceFunc)(void);\n\nstatic pthread_once_t\t\t\t\t\tgDeckLinkOnceControl = PTHREAD_ONCE_INIT;\nstatic pthread_once_t\t\t\t\t\tgPreviewOnceControl = PTHREAD_ONCE_INIT;\n\nstatic bool\t\t\t\t\t\t\t\tgLoadedDeckLinkAPI = false;\n\nstatic CreateIteratorFunc\t\t\t\t\tgCreateIteratorFunc = NULL;\nstatic CreateAPIInformationFunc\t\t\t\tgCreateAPIInformationFunc = NULL;\nstatic CreateOpenGLScreenPreviewHelperFunc\tgCreateOpenGLPreviewFunc = NULL;\nstatic CreateVideoConversionInstanceFunc\tgCreateVideoConversionFunc\t= NULL;\n\nstatic void\tInitDeckLinkAPI (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(kDeckLinkAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\t\n\tgLoadedDeckLinkAPI = true;\n\t\n\tgCreateIteratorFunc = (CreateIteratorFunc)dlsym(libraryHandle, \"CreateDeckLinkIteratorInstance_0001\");\n\tif (!gCreateIteratorFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateAPIInformationFunc = (CreateAPIInformationFunc)dlsym(libraryHandle, \"CreateDeckLinkAPIInformationInstance_0001\");\n\tif (!gCreateAPIInformationFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\tgCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)dlsym(libraryHandle, \"CreateVideoConversionInstance_0001\");\n\tif (!gCreateVideoConversionFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nstatic void\tInitDeckLinkPreviewAPI (void)\n{\n\tvoid *libraryHandle;\n\t\n\tlibraryHandle = dlopen(KDeckLinkPreviewAPI_Name, RTLD_NOW|RTLD_GLOBAL);\n\tif (!libraryHandle)\n\t{\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n\t\treturn;\n\t}\n\tgCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)dlsym(libraryHandle, \"CreateOpenGLScreenPreviewHelper_0001\");\n\tif (!gCreateOpenGLPreviewFunc)\n\t\tfprintf(stderr, \"%s\\n\", dlerror());\n}\n\nbool\t\tIsDeckLinkAPIPresent (void)\n{\n\t// If the DeckLink API dynamic library was successfully loaded, return this knowledge to the caller\n\treturn gLoadedDeckLinkAPI;\n}\n\nIDeckLinkIterator_v8_0*\t\tCreateDeckLinkIteratorInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateIteratorFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateIteratorFunc();\n}\n\nIDeckLinkAPIInformation*\tCreateDeckLinkAPIInformationInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateAPIInformationFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateAPIInformationFunc();\n}\n\nIDeckLinkGLScreenPreviewHelper*\t\tCreateOpenGLScreenPreviewHelper (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\tpthread_once(&gPreviewOnceControl, InitDeckLinkPreviewAPI);\n\t\n\tif (gCreateOpenGLPreviewFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateOpenGLPreviewFunc();\n}\n\nIDeckLinkVideoConversion* CreateVideoConversionInstance (void)\n{\n\tpthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);\n\t\n\tif (gCreateVideoConversionFunc == NULL)\n\t\treturn NULL;\n\treturn gCreateVideoConversionFunc();\n}\n\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIModes.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2022 Blackmagic Design\n**\n** Permission is hereby granted, free of charge, to any person or organization\n** obtaining a copy of the software and accompanying documentation covered by\n** this license (the \"Software\") to use, reproduce, display, distribute,\n** execute, and transmit the Software, and to prepare derivative works of the\n** Software, and to permit third-parties to whom the Software is furnished to\n** do so, all subject to the following:\n**\n** The copyright notices in the Software and this entire statement, including\n** the above license grant, this restriction and the following disclaimer,\n** must be included in all copies of the Software, in whole or in part, and\n** all derivative works of the Software, unless such copies or derivative\n** works are solely in the form of machine-executable object code generated by\n** a source language processor.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n** DEALINGS IN THE SOFTWARE.\n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIMODES_H\n#define BMD_DECKLINKAPIMODES_H\n\n\n#ifndef BMD_CONST\n    #if defined(_MSC_VER)\n        #define BMD_CONST __declspec(selectany) static const\n    #else\n        #define BMD_CONST static const\n    #endif\n#endif\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n// Type Declarations\n\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkDisplayModeIterator                 = /* 9C88499F-F601-4021-B80B-032E4EB41C35 */ { 0x9C,0x88,0x49,0x9F,0xF6,0x01,0x40,0x21,0xB8,0x0B,0x03,0x2E,0x4E,0xB4,0x1C,0x35 };\nBMD_CONST REFIID IID_IDeckLinkDisplayMode                         = /* 3EB2C1AB-0A3D-4523-A3AD-F40D7FB14E78 */ { 0x3E,0xB2,0xC1,0xAB,0x0A,0x3D,0x45,0x23,0xA3,0xAD,0xF4,0x0D,0x7F,0xB1,0x4E,0x78 };\n\n/* Enum BMDDisplayMode - BMDDisplayMode enumerates the video modes supported. */\n\ntypedef uint32_t BMDDisplayMode;\nenum _BMDDisplayMode {\n\n    /* SD Modes */\n\n    bmdModeNTSC                                                  = /* 'ntsc' */ 0x6E747363,\n    bmdModeNTSC2398                                              = /* 'nt23' */ 0x6E743233,\t// 3:2 pulldown\n    bmdModePAL                                                   = /* 'pal ' */ 0x70616C20,\n    bmdModeNTSCp                                                 = /* 'ntsp' */ 0x6E747370,\n    bmdModePALp                                                  = /* 'palp' */ 0x70616C70,\n\n    /* HD 1080 Modes */\n\n    bmdModeHD1080p2398                                           = /* '23ps' */ 0x32337073,\n    bmdModeHD1080p24                                             = /* '24ps' */ 0x32347073,\n    bmdModeHD1080p25                                             = /* 'Hp25' */ 0x48703235,\n    bmdModeHD1080p2997                                           = /* 'Hp29' */ 0x48703239,\n    bmdModeHD1080p30                                             = /* 'Hp30' */ 0x48703330,\n    bmdModeHD1080p4795                                           = /* 'Hp47' */ 0x48703437,\n    bmdModeHD1080p48                                             = /* 'Hp48' */ 0x48703438,\n    bmdModeHD1080p50                                             = /* 'Hp50' */ 0x48703530,\n    bmdModeHD1080p5994                                           = /* 'Hp59' */ 0x48703539,\n    bmdModeHD1080p6000                                           = /* 'Hp60' */ 0x48703630,\t// N.B. This _really_ is 60.00 Hz.\n    bmdModeHD1080p9590                                           = /* 'Hp95' */ 0x48703935,\n    bmdModeHD1080p96                                             = /* 'Hp96' */ 0x48703936,\n    bmdModeHD1080p100                                            = /* 'Hp10' */ 0x48703130,\n    bmdModeHD1080p11988                                          = /* 'Hp11' */ 0x48703131,\n    bmdModeHD1080p120                                            = /* 'Hp12' */ 0x48703132,\n    bmdModeHD1080i50                                             = /* 'Hi50' */ 0x48693530,\n    bmdModeHD1080i5994                                           = /* 'Hi59' */ 0x48693539,\n    bmdModeHD1080i6000                                           = /* 'Hi60' */ 0x48693630,\t// N.B. This _really_ is 60.00 Hz.\n\n    /* HD 720 Modes */\n\n    bmdModeHD720p50                                              = /* 'hp50' */ 0x68703530,\n    bmdModeHD720p5994                                            = /* 'hp59' */ 0x68703539,\n    bmdModeHD720p60                                              = /* 'hp60' */ 0x68703630,\n\n    /* 2K Modes */\n\n    bmdMode2k2398                                                = /* '2k23' */ 0x326B3233,\n    bmdMode2k24                                                  = /* '2k24' */ 0x326B3234,\n    bmdMode2k25                                                  = /* '2k25' */ 0x326B3235,\n\n    /* 2K DCI Modes */\n\n    bmdMode2kDCI2398                                             = /* '2d23' */ 0x32643233,\n    bmdMode2kDCI24                                               = /* '2d24' */ 0x32643234,\n    bmdMode2kDCI25                                               = /* '2d25' */ 0x32643235,\n    bmdMode2kDCI2997                                             = /* '2d29' */ 0x32643239,\n    bmdMode2kDCI30                                               = /* '2d30' */ 0x32643330,\n    bmdMode2kDCI4795                                             = /* '2d47' */ 0x32643437,\n    bmdMode2kDCI48                                               = /* '2d48' */ 0x32643438,\n    bmdMode2kDCI50                                               = /* '2d50' */ 0x32643530,\n    bmdMode2kDCI5994                                             = /* '2d59' */ 0x32643539,\n    bmdMode2kDCI60                                               = /* '2d60' */ 0x32643630,\n    bmdMode2kDCI9590                                             = /* '2d95' */ 0x32643935,\n    bmdMode2kDCI96                                               = /* '2d96' */ 0x32643936,\n    bmdMode2kDCI100                                              = /* '2d10' */ 0x32643130,\n    bmdMode2kDCI11988                                            = /* '2d11' */ 0x32643131,\n    bmdMode2kDCI120                                              = /* '2d12' */ 0x32643132,\n\n    /* 4K UHD Modes */\n\n    bmdMode4K2160p2398                                           = /* '4k23' */ 0x346B3233,\n    bmdMode4K2160p24                                             = /* '4k24' */ 0x346B3234,\n    bmdMode4K2160p25                                             = /* '4k25' */ 0x346B3235,\n    bmdMode4K2160p2997                                           = /* '4k29' */ 0x346B3239,\n    bmdMode4K2160p30                                             = /* '4k30' */ 0x346B3330,\n    bmdMode4K2160p4795                                           = /* '4k47' */ 0x346B3437,\n    bmdMode4K2160p48                                             = /* '4k48' */ 0x346B3438,\n    bmdMode4K2160p50                                             = /* '4k50' */ 0x346B3530,\n    bmdMode4K2160p5994                                           = /* '4k59' */ 0x346B3539,\n    bmdMode4K2160p60                                             = /* '4k60' */ 0x346B3630,\n    bmdMode4K2160p9590                                           = /* '4k95' */ 0x346B3935,\n    bmdMode4K2160p96                                             = /* '4k96' */ 0x346B3936,\n    bmdMode4K2160p100                                            = /* '4k10' */ 0x346B3130,\n    bmdMode4K2160p11988                                          = /* '4k11' */ 0x346B3131,\n    bmdMode4K2160p120                                            = /* '4k12' */ 0x346B3132,\n\n    /* 4K DCI Modes */\n\n    bmdMode4kDCI2398                                             = /* '4d23' */ 0x34643233,\n    bmdMode4kDCI24                                               = /* '4d24' */ 0x34643234,\n    bmdMode4kDCI25                                               = /* '4d25' */ 0x34643235,\n    bmdMode4kDCI2997                                             = /* '4d29' */ 0x34643239,\n    bmdMode4kDCI30                                               = /* '4d30' */ 0x34643330,\n    bmdMode4kDCI4795                                             = /* '4d47' */ 0x34643437,\n    bmdMode4kDCI48                                               = /* '4d48' */ 0x34643438,\n    bmdMode4kDCI50                                               = /* '4d50' */ 0x34643530,\n    bmdMode4kDCI5994                                             = /* '4d59' */ 0x34643539,\n    bmdMode4kDCI60                                               = /* '4d60' */ 0x34643630,\n    bmdMode4kDCI9590                                             = /* '4d95' */ 0x34643935,\n    bmdMode4kDCI96                                               = /* '4d96' */ 0x34643936,\n    bmdMode4kDCI100                                              = /* '4d10' */ 0x34643130,\n    bmdMode4kDCI11988                                            = /* '4d11' */ 0x34643131,\n    bmdMode4kDCI120                                              = /* '4d12' */ 0x34643132,\n\n    /* 8K UHD Modes */\n\n    bmdMode8K4320p2398                                           = /* '8k23' */ 0x386B3233,\n    bmdMode8K4320p24                                             = /* '8k24' */ 0x386B3234,\n    bmdMode8K4320p25                                             = /* '8k25' */ 0x386B3235,\n    bmdMode8K4320p2997                                           = /* '8k29' */ 0x386B3239,\n    bmdMode8K4320p30                                             = /* '8k30' */ 0x386B3330,\n    bmdMode8K4320p4795                                           = /* '8k47' */ 0x386B3437,\n    bmdMode8K4320p48                                             = /* '8k48' */ 0x386B3438,\n    bmdMode8K4320p50                                             = /* '8k50' */ 0x386B3530,\n    bmdMode8K4320p5994                                           = /* '8k59' */ 0x386B3539,\n    bmdMode8K4320p60                                             = /* '8k60' */ 0x386B3630,\n\n    /* 8K DCI Modes */\n\n    bmdMode8kDCI2398                                             = /* '8d23' */ 0x38643233,\n    bmdMode8kDCI24                                               = /* '8d24' */ 0x38643234,\n    bmdMode8kDCI25                                               = /* '8d25' */ 0x38643235,\n    bmdMode8kDCI2997                                             = /* '8d29' */ 0x38643239,\n    bmdMode8kDCI30                                               = /* '8d30' */ 0x38643330,\n    bmdMode8kDCI4795                                             = /* '8d47' */ 0x38643437,\n    bmdMode8kDCI48                                               = /* '8d48' */ 0x38643438,\n    bmdMode8kDCI50                                               = /* '8d50' */ 0x38643530,\n    bmdMode8kDCI5994                                             = /* '8d59' */ 0x38643539,\n    bmdMode8kDCI60                                               = /* '8d60' */ 0x38643630,\n\n    /* PC Modes */\n\n    bmdMode640x480p60                                            = /* 'vga6' */ 0x76676136,\n    bmdMode800x600p60                                            = /* 'svg6' */ 0x73766736,\n    bmdMode1440x900p50                                           = /* 'wxg5' */ 0x77786735,\n    bmdMode1440x900p60                                           = /* 'wxg6' */ 0x77786736,\n    bmdMode1440x1080p50                                          = /* 'sxg5' */ 0x73786735,\n    bmdMode1440x1080p60                                          = /* 'sxg6' */ 0x73786736,\n    bmdMode1600x1200p50                                          = /* 'uxg5' */ 0x75786735,\n    bmdMode1600x1200p60                                          = /* 'uxg6' */ 0x75786736,\n    bmdMode1920x1200p50                                          = /* 'wux5' */ 0x77757835,\n    bmdMode1920x1200p60                                          = /* 'wux6' */ 0x77757836,\n    bmdMode1920x1440p50                                          = /* '1945' */ 0x31393435,\n    bmdMode1920x1440p60                                          = /* '1946' */ 0x31393436,\n    bmdMode2560x1440p50                                          = /* 'wqh5' */ 0x77716835,\n    bmdMode2560x1440p60                                          = /* 'wqh6' */ 0x77716836,\n    bmdMode2560x1600p50                                          = /* 'wqx5' */ 0x77717835,\n    bmdMode2560x1600p60                                          = /* 'wqx6' */ 0x77717836,\n\n    /* Special Modes */\n\n    bmdModeUnknown                                               = /* 'iunk' */ 0x69756E6B\n};\n\n/* Enum BMDFieldDominance - BMDFieldDominance enumerates settings applicable to video fields. */\n\ntypedef uint32_t BMDFieldDominance;\nenum _BMDFieldDominance {\n    bmdUnknownFieldDominance                                     = 0,\n    bmdLowerFieldFirst                                           = /* 'lowr' */ 0x6C6F7772,\n    bmdUpperFieldFirst                                           = /* 'uppr' */ 0x75707072,\n    bmdProgressiveFrame                                          = /* 'prog' */ 0x70726F67,\n    bmdProgressiveSegmentedFrame                                 = /* 'psf ' */ 0x70736620\n};\n\n/* Enum BMDPixelFormat - Video pixel formats supported for output/input */\n\ntypedef uint32_t BMDPixelFormat;\nenum _BMDPixelFormat {\n    bmdFormatUnspecified                                         = 0,\n    bmdFormat8BitYUV                                             = /* '2vuy' */ 0x32767579,\n    bmdFormat10BitYUV                                            = /* 'v210' */ 0x76323130,\n    bmdFormat8BitARGB                                            = 32,\n    bmdFormat8BitBGRA                                            = /* 'BGRA' */ 0x42475241,\n    bmdFormat10BitRGB                                            = /* 'r210' */ 0x72323130,\t// Big-endian RGB 10-bit per component with SMPTE video levels (64-960). Packed as 2:10:10:10\n    bmdFormat12BitRGB                                            = /* 'R12B' */ 0x52313242,\t// Big-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component\n    bmdFormat12BitRGBLE                                          = /* 'R12L' */ 0x5231324C,\t// Little-endian RGB 12-bit per component with full range (0-4095). Packed as 12-bit per component\n    bmdFormat10BitRGBXLE                                         = /* 'R10l' */ 0x5231306C,\t// Little-endian 10-bit RGB with SMPTE video levels (64-940)\n    bmdFormat10BitRGBX                                           = /* 'R10b' */ 0x52313062,\t// Big-endian 10-bit RGB with SMPTE video levels (64-940)\n    bmdFormatH265                                                = /* 'hev1' */ 0x68657631,\t// High Efficiency Video Coding (HEVC/h.265)\n\n    /* AVID DNxHR */\n\n    bmdFormatDNxHR                                               = /* 'AVdh' */ 0x41566468\n};\n\n/* Enum BMDDisplayModeFlags - Flags to describe the characteristics of an IDeckLinkDisplayMode. */\n\ntypedef uint32_t BMDDisplayModeFlags;\nenum _BMDDisplayModeFlags {\n    bmdDisplayModeSupports3D                                     = 1 << 0,\n    bmdDisplayModeColorspaceRec601                               = 1 << 1,\n    bmdDisplayModeColorspaceRec709                               = 1 << 2,\n    bmdDisplayModeColorspaceRec2020                              = 1 << 3\n};\n\n#if defined(__cplusplus)\n\n// Forward Declarations\n\nclass IDeckLinkDisplayModeIterator;\nclass IDeckLinkDisplayMode;\n\n/* Interface IDeckLinkDisplayModeIterator - Enumerates over supported input/output display modes. */\n\nclass BMD_PUBLIC IDeckLinkDisplayModeIterator : public IUnknown\n{\npublic:\n    virtual HRESULT Next (/* out */ IDeckLinkDisplayMode** deckLinkDisplayMode) = 0;\n\nprotected:\n    virtual ~IDeckLinkDisplayModeIterator () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkDisplayMode - Represents a display mode */\n\nclass BMD_PUBLIC IDeckLinkDisplayMode : public IUnknown\n{\npublic:\n    virtual HRESULT GetName (/* out */ const char** name) = 0;\n    virtual BMDDisplayMode GetDisplayMode (void) = 0;\n    virtual long GetWidth (void) = 0;\n    virtual long GetHeight (void) = 0;\n    virtual HRESULT GetFrameRate (/* out */ BMDTimeValue* frameDuration, /* out */ BMDTimeScale* timeScale) = 0;\n    virtual BMDFieldDominance GetFieldDominance (void) = 0;\n    virtual BMDDisplayModeFlags GetFlags (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkDisplayMode () {} // call Release method to drop reference count\n};\n\n/* Functions */\n\nextern \"C\" {\n\n\n}\n\n\n\n#endif /* defined(__cplusplus) */\n#endif /* defined(BMD_DECKLINKAPIMODES_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPITypes.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2022 Blackmagic Design\n**\n** Permission is hereby granted, free of charge, to any person or organization\n** obtaining a copy of the software and accompanying documentation covered by\n** this license (the \"Software\") to use, reproduce, display, distribute,\n** execute, and transmit the Software, and to prepare derivative works of the\n** Software, and to permit third-parties to whom the Software is furnished to\n** do so, all subject to the following:\n**\n** The copyright notices in the Software and this entire statement, including\n** the above license grant, this restriction and the following disclaimer,\n** must be included in all copies of the Software, in whole or in part, and\n** all derivative works of the Software, unless such copies or derivative\n** works are solely in the form of machine-executable object code generated by\n** a source language processor.\n**\n** THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n** DEALINGS IN THE SOFTWARE.\n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPITYPES_H\n#define BMD_DECKLINKAPITYPES_H\n\n\n#ifndef BMD_CONST\n    #if defined(_MSC_VER)\n        #define BMD_CONST __declspec(selectany) static const\n    #else\n        #define BMD_CONST static const\n    #endif\n#endif\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n// Type Declarations\n\ntypedef int64_t BMDTimeValue;\ntypedef int64_t BMDTimeScale;\ntypedef uint32_t BMDTimecodeBCD;\ntypedef uint32_t BMDTimecodeUserBits;\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkTimecode                            = /* BC6CFBD3-8317-4325-AC1C-1216391E9340 */ { 0xBC,0x6C,0xFB,0xD3,0x83,0x17,0x43,0x25,0xAC,0x1C,0x12,0x16,0x39,0x1E,0x93,0x40 };\n\n/* Enum BMDTimecodeFlags - Timecode flags */\n\ntypedef uint32_t BMDTimecodeFlags;\nenum _BMDTimecodeFlags {\n    bmdTimecodeFlagDefault                                       = 0,\n    bmdTimecodeIsDropFrame                                       = 1 << 0,\n    bmdTimecodeFieldMark                                         = 1 << 1,\n    bmdTimecodeColorFrame                                        = 1 << 2,\n    bmdTimecodeEmbedRecordingTrigger                             = 1 << 3,\t// On SDI recording trigger utilises a user-bit.\n    bmdTimecodeRecordingTriggered                                = 1 << 4\n};\n\n/* Enum BMDVideoConnection - Video connection types */\n\ntypedef uint32_t BMDVideoConnection;\nenum _BMDVideoConnection {\n    bmdVideoConnectionUnspecified                                = 0,\n    bmdVideoConnectionSDI                                        = 1 << 0,\n    bmdVideoConnectionHDMI                                       = 1 << 1,\n    bmdVideoConnectionOpticalSDI                                 = 1 << 2,\n    bmdVideoConnectionComponent                                  = 1 << 3,\n    bmdVideoConnectionComposite                                  = 1 << 4,\n    bmdVideoConnectionSVideo                                     = 1 << 5\n};\n\n/* Enum BMDAudioConnection - Audio connection types */\n\ntypedef uint32_t BMDAudioConnection;\nenum _BMDAudioConnection {\n    bmdAudioConnectionEmbedded                                   = 1 << 0,\n    bmdAudioConnectionAESEBU                                     = 1 << 1,\n    bmdAudioConnectionAnalog                                     = 1 << 2,\n    bmdAudioConnectionAnalogXLR                                  = 1 << 3,\n    bmdAudioConnectionAnalogRCA                                  = 1 << 4,\n    bmdAudioConnectionMicrophone                                 = 1 << 5,\n    bmdAudioConnectionHeadphones                                 = 1 << 6\n};\n\n/* Enum BMDDeckControlConnection - Deck control connections */\n\ntypedef uint32_t BMDDeckControlConnection;\nenum _BMDDeckControlConnection {\n    bmdDeckControlConnectionRS422Remote1                         = 1 << 0,\n    bmdDeckControlConnectionRS422Remote2                         = 1 << 1\n};\n\n#if defined(__cplusplus)\n\n// Forward Declarations\n\nclass IDeckLinkTimecode;\n\n/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */\n\nclass BMD_PUBLIC IDeckLinkTimecode : public IUnknown\n{\npublic:\n    virtual BMDTimecodeBCD GetBCD (void) = 0;\n    virtual HRESULT GetComponents (/* out */ uint8_t* hours, /* out */ uint8_t* minutes, /* out */ uint8_t* seconds, /* out */ uint8_t* frames) = 0;\n    virtual HRESULT GetString (/* out */ const char** timecode) = 0;\n    virtual BMDTimecodeFlags GetFlags (void) = 0;\n    virtual HRESULT GetTimecodeUserBits (/* out */ BMDTimecodeUserBits* userBits) = 0;\n\nprotected:\n    virtual ~IDeckLinkTimecode () {} // call Release method to drop reference count\n};\n\n/* Functions */\n\nextern \"C\" {\n\n\n}\n\n\n\n#endif /* defined(__cplusplus) */\n#endif /* defined(BMD_DECKLINKAPITYPES_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVersion.h",
    "content": "/* -LICENSE-START-\n * ** Copyright (c) 2014 Blackmagic Design\n * **  \n * ** Permission is hereby granted, free of charge, to any person or organization \n * ** obtaining a copy of the software and accompanying documentation (the \n * ** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n * ** and transmit the Software, and to prepare derivative works of the Software, \n * ** and to permit third-parties to whom the Software is furnished to do so, in \n * ** accordance with:\n * ** \n * ** (1) if the Software is obtained from Blackmagic Design, the End User License \n * ** Agreement for the Software Development Kit (“EULA”) available at \n * ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n * ** \n * ** (2) if the Software is obtained from any third party, such licensing terms \n * ** as notified by that third party,\n * ** \n * ** and all subject to the following:\n * ** \n * ** (3) the copyright notices in the Software and this entire statement, \n * ** including the above license grant, this restriction and the following \n * ** disclaimer, must be included in all copies of the Software, in whole or in \n * ** part, and all derivative works of the Software, unless such copies or \n * ** derivative works are solely in the form of machine-executable object code \n * ** generated by a source language processor.\n * ** \n * ** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n * ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n * ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n * ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n * ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n * ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n * ** DEALINGS IN THE SOFTWARE.\n * ** \n * ** A copy of the Software is available free of charge at \n * ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n * ** \n * ** -LICENSE-END-\n * */\n\n/* DeckLinkAPIVersion.h */\n\n#ifndef __DeckLink_API_Version_h__\n#define __DeckLink_API_Version_h__\n\n#define BLACKMAGIC_DECKLINK_API_VERSION\t\t\t\t\t0x0c030000\n#define BLACKMAGIC_DECKLINK_API_VERSION_STRING\t\t\t\"12.3\"\n\n#endif\t// __DeckLink_API_Version_h__\n\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVideoEncoderInput_v10_11.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2017 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H\n#define BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n\n// Type Declarations\nBMD_CONST REFIID IID_IDeckLinkEncoderInput_v10_11                        = /* 270587DA-6B7D-42E7-A1F0-6D853F581185 */ {0x27,0x05,0x87,0xDA,0x6B,0x7D,0x42,0xE7,0xA1,0xF0,0x6D,0x85,0x3F,0x58,0x11,0x85};\n\n/* Interface IDeckLinkEncoderInput_v10_11 - Created by QueryInterface from IDeckLink. */\n\nclass IDeckLinkEncoderInput_v10_11 : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailablePacketsCount (/* out */ uint32_t *availablePacketsCount) = 0;\n    virtual HRESULT SetMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioFormat audioFormat, /* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkEncoderInputCallback *theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkEncoderInput_v10_11 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPIVIDEOENCODERINPUT_v10_11_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVideoInput_v10_11.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2017 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIVIDEOINPUT_v10_11_H\n#define BMD_DECKLINKAPIVIDEOINPUT_v10_11_H\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n#include \"DeckLinkAPIVideoInput_v11_5_1.h\"\n\n// Type Declarations\nBMD_CONST REFIID IID_IDeckLinkInput_v10_11                               = /* AF22762B-DFAC-4846-AA79-FA8883560995 */ {0xAF,0x22,0x76,0x2B,0xDF,0xAC,0x48,0x46,0xAA,0x79,0xFA,0x88,0x83,0x56,0x09,0x95};\n\n/* Interface IDeckLinkInput_v10_11 - DeckLink input interface. */\n\nclass IDeckLinkInput_v10_11 : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0;\n    virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput_v10_11 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v10_11_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVideoInput_v11_4.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2019 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIVIDEOINPUT_v11_4_H\n#define BMD_DECKLINKAPIVIDEOINPUT_v11_4_H\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPIVideoInput_v11_5_1.h\"\n\n// Type Declarations\nBMD_CONST REFIID IID_IDeckLinkInput_v11_4                               = /* 2A88CF76-F494-4216-A7EF-DC74EEB83882 */ { 0x2A,0x88,0xCF,0x76,0xF4,0x94,0x42,0x16,0xA7,0xEF,0xDC,0x74,0xEE,0xB8,0x38,0x82 };\n\n/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkInput_v11_4 : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDSupportedVideoModeFlags flags, /* out */ bool* supported) = 0;\n    virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0;\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0;\n    virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1* theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput_v11_4 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v11_4_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVideoInput_v11_5_1.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2020 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H\n#define BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\n\nBMD_CONST REFIID IID_IDeckLinkInputCallback_v11_5_1                       = /* DD04E5EC-7415-42AB-AE4A-E80C4DFC044A */ { 0xDD, 0x04, 0xE5, 0xEC, 0x74, 0x15, 0x42, 0xAB, 0xAE, 0x4A, 0xE8, 0x0C, 0x4D, 0xFC, 0x04, 0x4A };\nBMD_CONST REFIID IID_IDeckLinkInput_v11_5_1                               = /* 9434C6E4-B15D-4B1C-979E-661E3DDCB4B9 */ { 0x94, 0x34, 0xC6, 0xE4, 0xB1, 0x5D, 0x4B, 0x1C, 0x97, 0x9E, 0x66, 0x1E, 0x3D, 0xDC, 0xB4, 0xB9 };\n\n/* Interface IDeckLinkInputCallback_v11_5_1 - Frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkInputCallback_v11_5_1 : public IUnknown\n{\npublic:\n    virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode* newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\n    virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0;\n\nprotected:\n    virtual ~IDeckLinkInputCallback_v11_5_1 () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkInput_v11_5_1 - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkInput_v11_5_1 : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of bmdVideoConnectionUnspecified is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDVideoInputConversionMode conversionMode, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0;\n    virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0;\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t* availableFrameCount) = 0;\n    virtual HRESULT SetVideoInputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t* availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1* theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput_v11_5_1 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPIVIDEOINPUT_v11_5_1_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVideoOutput_v10_11.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2017 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H\n#define BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n\n// Type Declarations\nBMD_CONST REFIID IID_IDeckLinkOutput_v10_11                              = /* CC5C8A6E-3F2F-4B3A-87EA-FD78AF300564 */ {0xCC,0x5C,0x8A,0x6E,0x3F,0x2F,0x4B,0x3A,0x87,0xEA,0xFD,0x78,0xAF,0x30,0x05,0x64};\n\n/* Interface IDeckLinkOutput_v10_11 - DeckLink output interface. */\n\nclass IDeckLinkOutput_v10_11 : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\n\n    /* Video Output */\n\n    virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;\n    virtual HRESULT DisableVideoOutput (void) = 0;\n\n    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;\n    virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0;\n    virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\n\n    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0;\n    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0;\n    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0;\n\n    /* Audio Output */\n\n    virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;\n    virtual HRESULT DisableAudioOutput (void) = 0;\n\n    virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT BeginAudioPreroll (void) = 0;\n    virtual HRESULT EndAudioPreroll (void) = 0;\n    virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0;\n    virtual HRESULT FlushBufferedAudioSamples (void) = 0;\n\n    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0;\n\n    /* Output Control */\n\n    virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;\n    virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0;\n    virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0;\n    virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n    virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *frameCompletionTimestamp) = 0;\n\nprotected:\n    virtual ~IDeckLinkOutput_v10_11 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPIVIDEOOUTPUT_v10_11_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPIVideoOutput_v11_4.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2019 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H\n#define BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\nBMD_CONST REFIID IID_IDeckLinkOutput_v11_4                              = /* 065A0F6C-C508-4D0D-B919-F5EB0EBFC96B */ { 0x06,0x5A,0x0F,0x6C,0xC5,0x08,0x4D,0x0D,0xB9,0x19,0xF5,0xEB,0x0E,0xBF,0xC9,0x6B };\n\n/* Interface IDeckLinkOutput_v11_4 - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkOutput_v11_4 : public IUnknown\n{\npublic:\n    virtual HRESULT DoesSupportVideoMode (/* in */ BMDVideoConnection connection /* If a value of 0 is specified, the caller does not care about the connection */, /* in */ BMDDisplayMode requestedMode, /* in */ BMDPixelFormat requestedPixelFormat, /* in */ BMDSupportedVideoModeFlags flags, /* out */ BMDDisplayMode* actualMode, /* out */ bool* supported) = 0;\n    virtual HRESULT GetDisplayMode (/* in */ BMDDisplayMode displayMode, /* out */ IDeckLinkDisplayMode** resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator** iterator) = 0;\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback* previewCallback) = 0;\n\n    /* Video Output */\n\n    virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;\n    virtual HRESULT DisableVideoOutput (void) = 0;\n    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator* theAllocator) = 0;\n    virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame** outFrame) = 0;\n    virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary** outBuffer) = 0;\t// Use of IDeckLinkVideoFrameAncillaryPackets is preferred\n    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame* theFrame) = 0;\n    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback* theCallback) = 0;\n    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t* bufferedFrameCount) = 0;\n\n    /* Audio Output */\n\n    virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;\n    virtual HRESULT DisableAudioOutput (void) = 0;\n    virtual HRESULT WriteAudioSamplesSync (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t* sampleFramesWritten) = 0;\n    virtual HRESULT BeginAudioPreroll (void) = 0;\n    virtual HRESULT EndAudioPreroll (void) = 0;\n    virtual HRESULT ScheduleAudioSamples (/* in */ void* buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t* sampleFramesWritten) = 0;\n    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t* bufferedSampleFrameCount) = 0;\n    virtual HRESULT FlushBufferedAudioSamples (void) = 0;\n    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback* theCallback) = 0;\n\n    /* Output Control */\n\n    virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;\n    virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue* actualStopTime, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool* active) = 0;\n    virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* streamTime, /* out */ double* playbackSpeed) = 0;\n    virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus* referenceStatus) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* hardwareTime, /* out */ BMDTimeValue* timeInFrame, /* out */ BMDTimeValue* ticksPerFrame) = 0;\n    virtual HRESULT GetFrameCompletionReferenceTimestamp (/* in */ IDeckLinkVideoFrame* theFrame, /* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue* frameCompletionTimestamp) = 0;\n\nprotected:\n    virtual ~IDeckLinkOutput_v11_4 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPIVIDEOOUTPUT_v11_4_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v10_11.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2018 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v10_11_H\n#define BMD_DECKLINKAPI_v10_11_H\n\n#include \"DeckLinkAPI.h\"\n\n// Interface ID Declarations\n\nBMD_CONST REFIID IID_IDeckLinkAttributes_v10_11                     = /* ABC11843-D966-44CB-96E2-A1CB5D3135C4 */ {0xAB,0xC1,0x18,0x43,0xD9,0x66,0x44,0xCB,0x96,0xE2,0xA1,0xCB,0x5D,0x31,0x35,0xC4};\nBMD_CONST REFIID IID_IDeckLinkNotification_v10_11                   = /* 0A1FB207-E215-441B-9B19-6FA1575946C5 */ {0x0A,0x1F,0xB2,0x07,0xE2,0x15,0x44,0x1B,0x9B,0x19,0x6F,0xA1,0x57,0x59,0x46,0xC5};\n\n/* Enum BMDDisplayModeSupport_v10_11 - Output mode supported flags */\n\ntypedef uint32_t BMDDisplayModeSupport_v10_11;\nenum _BMDDisplayModeSupport_v10_11 {\n\tbmdDisplayModeNotSupported_v10_11                               = 0,\n\tbmdDisplayModeSupported_v10_11,\n\tbmdDisplayModeSupportedWithConversion_v10_11\n};\n\n/* Enum BMDDuplexMode_v10_11 - Duplex for configurable ports */\n\ntypedef uint32_t BMDDuplexMode_v10_11;\nenum _BMDDuplexMode_v10_11 {\n    bmdDuplexModeFull_v10_11                                        = /* 'fdup' */ 0x66647570,\n    bmdDuplexModeHalf_v10_11                                        = /* 'hdup' */ 0x68647570\n};\n\n/* Enum BMDDeckLinkAttributeID_v10_11 - DeckLink Attribute ID */\n\nenum _BMDDeckLinkAttributeID_v10_11 {\n\n    /* Flags */\n\n    BMDDeckLinkSupportsDuplexModeConfiguration_v10_11               = 'dupx',\n    BMDDeckLinkSupportsHDKeying_v10_11                              = 'keyh',\n\n    /* Integers */\n\n    BMDDeckLinkPairedDevicePersistentID_v10_11                      = 'ppid',\n    BMDDeckLinkSupportsFullDuplex_v10_11                            = 'fdup',\n};\n\nenum  _BMDDeckLinkStatusID_v10_11 {\n    bmdDeckLinkStatusDuplexMode_v10_11                             = 'dupx',\n};\n\ntypedef uint32_t BMDDuplexStatus_v10_11;\nenum _BMDDuplexStatus_v10_11 {\n    bmdDuplexFullDuplex_v10_11                                      = 'fdup',\n    bmdDuplexHalfDuplex_v10_11                                      = 'hdup',\n    bmdDuplexSimplex_v10_11                                         = 'splx',\n    bmdDuplexInactive_v10_11                                        = 'inac',\n};\n\n#if defined(__cplusplus)\n\n/* Interface IDeckLinkAttributes_v10_11 - DeckLink Attribute interface */\n\nclass BMD_PUBLIC IDeckLinkAttributes_v10_11 : public IUnknown\n{\npublic:\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ bool *value) = 0;\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ int64_t *value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ double *value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkAttributeID cfgID, /* out */ const char **value) = 0;\n\nprotected:\n    virtual ~IDeckLinkAttributes_v10_11 () {} // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkNotification_v10_11 - DeckLink Notification interface */\n\nclass BMD_PUBLIC IDeckLinkNotification_v10_11 : public IUnknown\n{\npublic:\n    virtual HRESULT Subscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0;\n    virtual HRESULT Unsubscribe (/* in */ BMDNotifications topic, /* in */ IDeckLinkNotificationCallback *theCallback) = 0;\n};\n\n/* Functions */\n\nextern \"C\" {\n\n    IDeckLinkIterator* BMD_PUBLIC CreateDeckLinkIteratorInstance_v10_11 (void);\n    IDeckLinkDiscovery* BMD_PUBLIC CreateDeckLinkDiscoveryInstance_v10_11 (void);\n    IDeckLinkAPIInformation* BMD_PUBLIC CreateDeckLinkAPIInformationInstance_v10_11 (void);\n    IDeckLinkGLScreenPreviewHelper* BMD_PUBLIC CreateOpenGLScreenPreviewHelper_v10_11 (void);\n    IDeckLinkVideoConversion* BMD_PUBLIC CreateVideoConversionInstance_v10_11 (void);\n    IDeckLinkVideoFrameAncillaryPackets* BMD_PUBLIC CreateVideoFrameAncillaryPacketsInstance_v10_11 (void); // For use when creating a custom IDeckLinkVideoFrame without wrapping IDeckLinkOutput::CreateVideoFrame\n\n}\n\n#endif      // defined(__cplusplus)\n#endif /* defined(BMD_DECKLINKAPI_v10_11_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v10_2.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2014 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v10_2_H\n#define BMD_DECKLINKAPI_v10_2_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\n\n/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */\n\ntypedef uint32_t BMDDeckLinkConfigurationID_v10_2;\nenum  _BMDDeckLinkConfigurationID_v10_2 {\n    /* Video output flags */\n\t\n    bmdDeckLinkConfig3GBpsVideoOutput_v10_2                      = '3gbs',\n};\n\n/* Enum BMDAudioConnection_v10_2 - Audio connection types */\n\ntypedef uint32_t BMDAudioConnection_v10_2;\nenum _BMDAudioConnection_v10_2 {\n    bmdAudioConnectionEmbedded_v10_2                             = /* 'embd' */ 0x656D6264,\n    bmdAudioConnectionAESEBU_v10_2                               = /* 'aes ' */ 0x61657320,\n    bmdAudioConnectionAnalog_v10_2                               = /* 'anlg' */ 0x616E6C67,\n    bmdAudioConnectionAnalogXLR_v10_2                            = /* 'axlr' */ 0x61786C72,\n    bmdAudioConnectionAnalogRCA_v10_2                            = /* 'arca' */ 0x61726361\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v10_2_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v10_4.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2015 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v10_4_H\n#define BMD_DECKLINKAPI_v10_4_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\n\n/* Enum BMDDeckLinkConfigurationID - DeckLink Configuration ID */\n\ntypedef uint32_t BMDDeckLinkConfigurationID_v10_4;\nenum _BMDDeckLinkConfigurationID_v10_4 {\n\n    /* Video output flags */\n\n    bmdDeckLinkConfigSingleLinkVideoOutput_v10_4                       = /* 'sglo' */ 0x73676C6F,\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v10_4_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v10_5.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2015 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v10_5_H\n#define BMD_DECKLINKAPI_v10_5_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\n\n/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */\n\ntypedef uint32_t BMDDeckLinkAttributeID_v10_5;\nenum _BMDDeckLinkAttributeID_v10_5 {\n\n    /* Integers */\n\n    BMDDeckLinkDeviceBusyState_v10_5                             = /* 'dbst' */ 0x64627374,\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v10_5_H) */\n\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v10_6.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2016 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v10_6_H\n#define BMD_DECKLINKAPI_v10_6_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\n\n/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */\n\ntypedef uint32_t BMDDeckLinkAttributeID_c10_6;\nenum _BMDDeckLinkAttributeID_v10_6 {\n\n    /* Flags */\n\n    BMDDeckLinkSupportsDesktopDisplay_v10_6                      = /* 'extd' */ 0x65787464,\n};\n\ntypedef uint32_t BMDIdleVideoOutputOperation_v10_6;\nenum _BMDIdleVideoOutputOperation_v10_6 {\n    bmdIdleVideoOutputDesktop_v10_6                              = /* 'desk' */ 0x6465736B\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v10_6_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v10_9.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2017 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v10_9_H\n#define BMD_DECKLINKAPI_v10_9_H\n\n#include \"DeckLinkAPI.h\"\n\n// Type Declarations\n\n/* Enum BMDDeckLinkAttributeID - DeckLink Attribute ID */\n\ntypedef uint32_t BMDDeckLinkConfigurationID_v10_9;\nenum _BMDDeckLinkConfigurationID_v10_9 {\n\n    /* Flags */\n\n    bmdDeckLinkConfig1080pNotPsF_v10_9                      = 'fpro',\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v10_9_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v11_5.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2020 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v11_5_H\n#define BMD_DECKLINKAPI_v11_5_H\n\n#include \"DeckLinkAPI.h\"\n\nBMD_CONST REFIID IID_IDeckLinkVideoFrameMetadataExtensions_v11_5\t= /* D5973DC9-6432-46D0-8F0B-2496F8A1238F */ {0xD5,0x97,0x3D,0xC9,0x64,0x32,0x46,0xD0,0x8F,0x0B,0x24,0x96,0xF8,0xA1,0x23,0x8F};\n\n/* Enum BMDDeckLinkFrameMetadataID - DeckLink Frame Metadata ID */\n\ntypedef uint32_t BMDDeckLinkFrameMetadataID_v11_5;\nenum _BMDDeckLinkFrameMetadataID_v11_5 {\n    bmdDeckLinkFrameMetadataCintelFilmType_v11_5                       = /* 'cfty' */ 0x63667479,\t// Current film type\n    bmdDeckLinkFrameMetadataCintelFilmGauge_v11_5                      = /* 'cfga' */ 0x63666761,\t// Current film gauge\n    bmdDeckLinkFrameMetadataCintelKeykodeLow_v11_5                     = /* 'ckkl' */ 0x636B6B6C,\t// Raw keykode value - low 64 bits\n    bmdDeckLinkFrameMetadataCintelKeykodeHigh_v11_5                    = /* 'ckkh' */ 0x636B6B68,\t// Raw keykode value - high 64 bits\n    bmdDeckLinkFrameMetadataCintelTile1Size_v11_5                      = /* 'ct1s' */ 0x63743173,\t// Size in bytes of compressed raw tile 1\n    bmdDeckLinkFrameMetadataCintelTile2Size_v11_5                      = /* 'ct2s' */ 0x63743273,\t// Size in bytes of compressed raw tile 2\n    bmdDeckLinkFrameMetadataCintelTile3Size_v11_5                      = /* 'ct3s' */ 0x63743373,\t// Size in bytes of compressed raw tile 3\n    bmdDeckLinkFrameMetadataCintelTile4Size_v11_5                      = /* 'ct4s' */ 0x63743473,\t// Size in bytes of compressed raw tile 4\n    bmdDeckLinkFrameMetadataCintelImageWidth_v11_5                     = /* 'IWPx' */ 0x49575078,\t// Width in pixels of image\n    bmdDeckLinkFrameMetadataCintelImageHeight_v11_5                    = /* 'IHPx' */ 0x49485078,\t// Height in pixels of image\n    bmdDeckLinkFrameMetadataCintelLinearMaskingRedInRed_v11_5          = /* 'mrir' */ 0x6D726972,\t// Red in red linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInRed_v11_5        = /* 'mgir' */ 0x6D676972,\t// Green in red linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInRed_v11_5         = /* 'mbir' */ 0x6D626972,\t// Blue in red linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingRedInGreen_v11_5        = /* 'mrig' */ 0x6D726967,\t// Red in green linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInGreen_v11_5      = /* 'mgig' */ 0x6D676967,\t// Green in green linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInGreen_v11_5       = /* 'mbig' */ 0x6D626967,\t// Blue in green linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingRedInBlue_v11_5         = /* 'mrib' */ 0x6D726962,\t// Red in blue linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingGreenInBlue_v11_5       = /* 'mgib' */ 0x6D676962,\t// Green in blue linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLinearMaskingBlueInBlue_v11_5        = /* 'mbib' */ 0x6D626962,\t// Blue in blue linear masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingRedInRed_v11_5             = /* 'mlrr' */ 0x6D6C7272,\t// Red in red log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingGreenInRed_v11_5           = /* 'mlgr' */ 0x6D6C6772,\t// Green in red log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingBlueInRed_v11_5            = /* 'mlbr' */ 0x6D6C6272,\t// Blue in red log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingRedInGreen_v11_5           = /* 'mlrg' */ 0x6D6C7267,\t// Red in green log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingGreenInGreen_v11_5         = /* 'mlgg' */ 0x6D6C6767,\t// Green in green log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingBlueInGreen_v11_5          = /* 'mlbg' */ 0x6D6C6267,\t// Blue in green log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingRedInBlue_v11_5            = /* 'mlrb' */ 0x6D6C7262,\t// Red in blue log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingGreenInBlue_v11_5          = /* 'mlgb' */ 0x6D6C6762,\t// Green in blue log masking parameter\n    bmdDeckLinkFrameMetadataCintelLogMaskingBlueInBlue_v11_5           = /* 'mlbb' */ 0x6D6C6262,\t// Blue in blue log masking parameter\n    bmdDeckLinkFrameMetadataCintelFilmFrameRate_v11_5                  = /* 'cffr' */ 0x63666672,\t// Film frame rate\n    bmdDeckLinkFrameMetadataCintelOffsetToApplyHorizontal_v11_5        = /* 'otah' */ 0x6F746168,\t// Horizontal offset (pixels) to be applied to image\n    bmdDeckLinkFrameMetadataCintelOffsetToApplyVertical_v11_5          = /* 'otav' */ 0x6F746176,\t// Vertical offset (pixels) to be applied to image\n    bmdDeckLinkFrameMetadataCintelGainRed_v11_5                        = /* 'LfRd' */ 0x4C665264,\t// Red gain parameter to apply after log\n    bmdDeckLinkFrameMetadataCintelGainGreen_v11_5                      = /* 'LfGr' */ 0x4C664772,\t// Green gain parameter to apply after log\n    bmdDeckLinkFrameMetadataCintelGainBlue_v11_5                       = /* 'LfBl' */ 0x4C66426C,\t// Blue gain parameter to apply after log\n    bmdDeckLinkFrameMetadataCintelLiftRed_v11_5                        = /* 'GnRd' */ 0x476E5264,\t// Red lift parameter to apply after log and gain\n    bmdDeckLinkFrameMetadataCintelLiftGreen_v11_5                      = /* 'GnGr' */ 0x476E4772,\t// Green lift parameter to apply after log and gain\n    bmdDeckLinkFrameMetadataCintelLiftBlue_v11_5                       = /* 'GnBl' */ 0x476E426C,\t// Blue lift parameter to apply after log and gain\n    bmdDeckLinkFrameMetadataCintelHDRGainRed_v11_5                     = /* 'HGRd' */ 0x48475264,\t// Red gain parameter to apply to linear data for HDR Combination\n    bmdDeckLinkFrameMetadataCintelHDRGainGreen_v11_5                   = /* 'HGGr' */ 0x48474772,\t// Green gain parameter to apply to linear data for HDR Combination\n    bmdDeckLinkFrameMetadataCintelHDRGainBlue_v11_5                    = /* 'HGBl' */ 0x4847426C,\t// Blue gain parameter to apply to linear data for HDR Combination\n\tbmdDeckLinkFrameMetadataCintel16mmCropRequired_v11_5               = /* 'c16c' */ 0x63313663,\t// The image should be cropped to 16mm size\n    bmdDeckLinkFrameMetadataCintelInversionRequired_v11_5              = /* 'cinv' */ 0x63696E76,\t// The image should be colour inverted\n    bmdDeckLinkFrameMetadataCintelFlipRequired_v11_5                   = /* 'cflr' */ 0x63666C72,\t// The image should be flipped horizontally\n    bmdDeckLinkFrameMetadataCintelFocusAssistEnabled_v11_5             = /* 'cfae' */ 0x63666165,\t// Focus Assist is currently enabled\n    bmdDeckLinkFrameMetadataCintelKeykodeIsInterpolated_v11_5          = /* 'kkii' */ 0x6B6B6969\t// The keykode for this frame is interpolated from nearby keykodes\n};\n\n/* Interface IDeckLinkVideoFrameMetadataExtensions - Optional interface implemented on IDeckLinkVideoFrame to support frame metadata such as HDMI HDR information */\n\nclass BMD_PUBLIC IDeckLinkVideoFrameMetadataExtensions_v11_5 : public IUnknown\n{\npublic:\n    virtual HRESULT GetInt (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ int64_t *value) = 0;\n    virtual HRESULT GetFloat (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ double *value) = 0;\n    virtual HRESULT GetFlag (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ bool* value) = 0;\n    virtual HRESULT GetString (/* in */ BMDDeckLinkFrameMetadataID_v11_5 metadataID, /* out */ const char **value) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoFrameMetadataExtensions_v11_5 () {} // call Release method to drop reference count\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v11_5_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v11_5_1.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2020 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v11_5_1_H\n#define BMD_DECKLINKAPI_v11_5_1_H\n\n#include \"DeckLinkAPI.h\"\n\n/* Enum BMDDeckLinkStatusID - DeckLink Status ID */\n\ntypedef uint32_t BMDDeckLinkStatusID_v11_5_1;\nenum _BMDDeckLinkStatusID_v11_5_1 {\n\n    /* Video output flags */\n\n\tbmdDeckLinkStatusDetectedVideoInputFlags_v11_5_1                     = /* 'dvif' */ 0x64766966,\n\n};\n\n#endif /* defined(BMD_DECKLINKAPI_v11_5_1_H) */\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v7_1.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n/* DeckLinkAPI_v7_1.h */\n\n#ifndef __DeckLink_API_v7_1_h__\n#define __DeckLink_API_v7_1_h__\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n\n// \"B28131B6-59AC-4857-B5AC-CD75D5883E2F\"\n#define IID_IDeckLinkDisplayModeIterator_v7_1\t(REFIID){0xB2,0x81,0x31,0xB6,0x59,0xAC,0x48,0x57,0xB5,0xAC,0xCD,0x75,0xD5,0x88,0x3E,0x2F}\n\n// \"AF0CD6D5-8376-435E-8433-54F9DD530AC3\"\n#define IID_IDeckLinkDisplayMode_v7_1\t\t\t(REFIID){0xAF,0x0C,0xD6,0xD5,0x83,0x76,0x43,0x5E,0x84,0x33,0x54,0xF9,0xDD,0x53,0x0A,0xC3}\n\n// \"EBD01AFA-E4B0-49C6-A01D-EDB9D1B55FD9\"\n#define IID_IDeckLinkVideoOutputCallback_v7_1\t(REFIID){0xEB,0xD0,0x1A,0xFA,0xE4,0xB0,0x49,0xC6,0xA0,0x1D,0xED,0xB9,0xD1,0xB5,0x5F,0xD9}\n\n// \"7F94F328-5ED4-4E9F-9729-76A86BDC99CC\"\n#define IID_IDeckLinkInputCallback_v7_1\t\t\t(REFIID){0x7F,0x94,0xF3,0x28,0x5E,0xD4,0x4E,0x9F,0x97,0x29,0x76,0xA8,0x6B,0xDC,0x99,0xCC}\n\n// \"AE5B3E9B-4E1E-4535-B6E8-480FF52F6CE5\"\n#define IID_IDeckLinkOutput_v7_1\t\t\t\t(REFIID){0xAE,0x5B,0x3E,0x9B,0x4E,0x1E,0x45,0x35,0xB6,0xE8,0x48,0x0F,0xF5,0x2F,0x6C,0xE5}\n\n// \"2B54EDEF-5B32-429F-BA11-BB990596EACD\"\n#define IID_IDeckLinkInput_v7_1\t\t\t\t\t(REFIID){0x2B,0x54,0xED,0xEF,0x5B,0x32,0x42,0x9F,0xBA,0x11,0xBB,0x99,0x05,0x96,0xEA,0xCD}\n\n// \"333F3A10-8C2D-43CF-B79D-46560FEEA1CE\"\n#define IID_IDeckLinkVideoFrame_v7_1\t\t\t(REFIID){0x33,0x3F,0x3A,0x10,0x8C,0x2D,0x43,0xCF,0xB7,0x9D,0x46,0x56,0x0F,0xEE,0xA1,0xCE}\n\n// \"C8B41D95-8848-40EE-9B37-6E3417FB114B\"\n#define IID_IDeckLinkVideoInputFrame_v7_1\t\t(REFIID){0xC8,0xB4,0x1D,0x95,0x88,0x48,0x40,0xEE,0x9B,0x37,0x6E,0x34,0x17,0xFB,0x11,0x4B}\n\n// \"C86DE4F6-A29F-42E3-AB3A-1363E29F0788\"\n#define IID_IDeckLinkAudioInputPacket_v7_1\t\t(REFIID){0xC8,0x6D,0xE4,0xF6,0xA2,0x9F,0x42,0xE3,0xAB,0x3A,0x13,0x63,0xE2,0x9F,0x07,0x88}\n\n#if defined(__cplusplus)\n\nclass IDeckLinkDisplayModeIterator_v7_1;\nclass IDeckLinkDisplayMode_v7_1;\nclass IDeckLinkVideoFrame_v7_1;\nclass IDeckLinkVideoInputFrame_v7_1;\nclass IDeckLinkAudioInputPacket_v7_1;\n\nclass BMD_PUBLIC IDeckLinkDisplayModeIterator_v7_1 : public IUnknown\n{\npublic:\n\tvirtual\tHRESULT\tSTDMETHODCALLTYPE\tNext (IDeckLinkDisplayMode_v7_1* *deckLinkDisplayMode) = 0;\n};\n\n\nclass BMD_PUBLIC IDeckLinkDisplayMode_v7_1 : public IUnknown\n{\npublic:\n\tvirtual\tHRESULT\t\t\tSTDMETHODCALLTYPE\tGetName (const char **name) = 0;\n\tvirtual\tBMDDisplayMode\tSTDMETHODCALLTYPE\tGetDisplayMode () = 0;\n\tvirtual\tlong\t\t\tSTDMETHODCALLTYPE\tGetWidth () = 0;\n\tvirtual\tlong\t\t\tSTDMETHODCALLTYPE\tGetHeight () = 0;\n\tvirtual\tHRESULT\t\t\tSTDMETHODCALLTYPE\tGetFrameRate (BMDTimeValue *frameDuration, BMDTimeScale *timeScale) = 0;\n};\n\nclass BMD_PUBLIC IDeckLinkVideoOutputCallback_v7_1 : public IUnknown\n{\npublic:\n\tvirtual HRESULT STDMETHODCALLTYPE\tScheduledFrameCompleted (IDeckLinkVideoFrame_v7_1* completedFrame, BMDOutputFrameCompletionResult result) = 0;\n};\n\nclass BMD_PUBLIC IDeckLinkInputCallback_v7_1 : public IUnknown\n{\npublic:\n\tvirtual HRESULT STDMETHODCALLTYPE\tVideoInputFrameArrived (IDeckLinkVideoInputFrame_v7_1* videoFrame, IDeckLinkAudioInputPacket_v7_1* audioPacket) = 0;\n};\n\n// IDeckLinkOutput_v7_1.  Created by QueryInterface from IDeckLink.\nclass BMD_PUBLIC IDeckLinkOutput_v7_1 : public IUnknown\n{\npublic:\n\t// Display mode predicates\n\tvirtual\tHRESULT\tSTDMETHODCALLTYPE\tDoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDDisplayModeSupport_v10_11 *result) = 0;\n\tvirtual HRESULT\tSTDMETHODCALLTYPE\tGetDisplayModeIterator (IDeckLinkDisplayModeIterator_v7_1* *iterator) = 0;\n\t\n\t\n\t// Video output\n\tvirtual HRESULT STDMETHODCALLTYPE\tEnableVideoOutput (BMDDisplayMode displayMode) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tDisableVideoOutput () = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\tSetVideoOutputFrameMemoryAllocator (IDeckLinkMemoryAllocator* theAllocator) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tCreateVideoFrame (int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1* *outFrame) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tCreateVideoFrameFromBuffer (void* buffer, int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, IDeckLinkVideoFrame_v7_1* *outFrame) = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\tDisplayVideoFrameSync (IDeckLinkVideoFrame_v7_1* theFrame) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tScheduleVideoFrame (IDeckLinkVideoFrame_v7_1* theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tSetScheduledFrameCompletionCallback (IDeckLinkVideoOutputCallback_v7_1* theCallback) = 0;\n\t\n\t\n\t// Audio output\n\tvirtual HRESULT STDMETHODCALLTYPE\tEnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tDisableAudioOutput () = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\tWriteAudioSamplesSync (void* buffer, uint32_t sampleFrameCount, uint32_t *sampleFramesWritten) = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\tBeginAudioPreroll () = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tEndAudioPreroll () = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tScheduleAudioSamples (void* buffer, uint32_t sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, uint32_t *sampleFramesWritten) = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\tGetBufferedAudioSampleFrameCount (uint32_t *bufferedSampleCount) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tFlushBufferedAudioSamples () = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\tSetAudioCallback (IDeckLinkAudioOutputCallback* theCallback) = 0;\n\t\n\t\n\t// Output control\n\tvirtual HRESULT STDMETHODCALLTYPE\tStartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tStopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, BMDTimeValue *actualStopTime, BMDTimeScale timeScale) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tGetHardwareReferenceClock (BMDTimeScale desiredTimeScale, BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0;\n};\n\n// IDeckLinkInput_v7_1.  Created by QueryInterface from IDeckLink.\nclass BMD_PUBLIC IDeckLinkInput_v7_1 : public IUnknown\n{\npublic:\n\tvirtual\tHRESULT\tSTDMETHODCALLTYPE\tDoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDDisplayModeSupport_v10_11 *result) = 0;\n\tvirtual HRESULT\tSTDMETHODCALLTYPE\tGetDisplayModeIterator (IDeckLinkDisplayModeIterator_v7_1 **iterator) = 0;\n\t\n\t// Video input\n\tvirtual HRESULT STDMETHODCALLTYPE\tEnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tDisableVideoInput () = 0;\n\t\n\t// Audio input\n\tvirtual HRESULT STDMETHODCALLTYPE\tEnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tDisableAudioInput () = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tReadAudioSamples (void* buffer, uint32_t sampleFrameCount, uint32_t *sampleFramesRead, BMDTimeValue *audioPacketTime, BMDTimeScale timeScale) = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tGetBufferedAudioSampleFrameCount (uint32_t *bufferedSampleCount) = 0;\n\t\n\n\tvirtual HRESULT\tSTDMETHODCALLTYPE\tStartStreams () = 0;\n\tvirtual HRESULT\tSTDMETHODCALLTYPE\tStopStreams () = 0;\n\tvirtual HRESULT\tSTDMETHODCALLTYPE\tPauseStreams () = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\tSetCallback (IDeckLinkInputCallback_v7_1* theCallback) = 0;\n};\n\n// IDeckLinkVideoFrame_v7_1.  Created by IDeckLinkOutput::CreateVideoFrame.\nclass BMD_PUBLIC IDeckLinkVideoFrame_v7_1 : public IUnknown\n{\npublic:\n\tvirtual long STDMETHODCALLTYPE\t\t\t\t\tGetWidth () = 0;\n\tvirtual long STDMETHODCALLTYPE\t\t\t\t\tGetHeight () = 0;\n\tvirtual long STDMETHODCALLTYPE\t\t\t\t\tGetRowBytes () = 0;\n\tvirtual BMDPixelFormat STDMETHODCALLTYPE\t\tGetPixelFormat () = 0;\n\tvirtual BMDFrameFlags STDMETHODCALLTYPE\t\t\tGetFlags () = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\t\t\t\tGetBytes (void* *buffer) = 0;\n};\n\n// IDeckLinkVideoInputFrame_v7_1.  Provided by the IDeckLinkInput_v7_1 frame arrival callback.\nclass BMD_PUBLIC IDeckLinkVideoInputFrame_v7_1 : public IDeckLinkVideoFrame_v7_1\n{\npublic:\n\tvirtual HRESULT STDMETHODCALLTYPE\t\t\tGetFrameTime (BMDTimeValue *frameTime, BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0;\n};\n\n// IDeckLinkAudioInputPacket_v7_1.  Provided by the IDeckLinkInput_v7_1 callback.\nclass BMD_PUBLIC IDeckLinkAudioInputPacket_v7_1 : public IUnknown\n{\npublic:\n\tvirtual long STDMETHODCALLTYPE\t\t\t\tGetSampleCount () = 0;\n\tvirtual HRESULT STDMETHODCALLTYPE\t\t\tGetBytes (void* *buffer) = 0;\n\t\n\tvirtual HRESULT STDMETHODCALLTYPE\t\t\tGetAudioPacketTime (BMDTimeValue *packetTime, BMDTimeScale timeScale) = 0;\n};\n\n#endif\t\t// defined(__cplusplus)\n\n#endif\t\t// __DeckLink_API_v7_1_h__\n\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v7_3.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n/* DeckLinkAPI_v7_3.h */\n\n#ifndef __DeckLink_API_v7_3_h__\n#define __DeckLink_API_v7_3_h__\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v7_6.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n\n/* Interface ID Declarations */\n\n#define IID_IDeckLinkInputCallback_v7_3                  /* FD6F311D-4D00-444B-9ED4-1F25B5730AD0 */ (REFIID){0xFD,0x6F,0x31,0x1D,0x4D,0x00,0x44,0x4B,0x9E,0xD4,0x1F,0x25,0xB5,0x73,0x0A,0xD0}\n#define IID_IDeckLinkOutput_v7_3                         /* 271C65E3-C323-4344-A30F-D908BCB20AA3 */ (REFIID){0x27,0x1C,0x65,0xE3,0xC3,0x23,0x43,0x44,0xA3,0x0F,0xD9,0x08,0xBC,0xB2,0x0A,0xA3}\n#define IID_IDeckLinkInput_v7_3                          /* 4973F012-9925-458C-871C-18774CDBBECB */ (REFIID){0x49,0x73,0xF0,0x12,0x99,0x25,0x45,0x8C,0x87,0x1C,0x18,0x77,0x4C,0xDB,0xBE,0xCB}\n#define IID_IDeckLinkVideoInputFrame_v7_3                /* CF317790-2894-11DE-8C30-0800200C9A66 */ (REFIID){0xCF,0x31,0x77,0x90,0x28,0x94,0x11,0xDE,0x8C,0x30,0x08,0x00,0x20,0x0C,0x9A,0x66}\n\n/* End Interface ID Declarations */\n\n#if defined(__cplusplus)\n\n/* Forward Declarations */\n\nclass IDeckLinkVideoInputFrame_v7_3;\n\n/* End Forward Declarations */\n\n\n/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkOutput_v7_3 : public IUnknown\n{\npublic:\n\tvirtual HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\n\n    /* Video Output */\n\n    virtual HRESULT EnableVideoOutput (BMDDisplayMode displayMode, BMDVideoOutputFlags flags) = 0;\n    virtual HRESULT DisableVideoOutput (void) = 0;\n\n    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;\n    virtual HRESULT CreateVideoFrame (int32_t width, int32_t height, int32_t rowBytes, BMDPixelFormat pixelFormat, BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0;\n    virtual HRESULT CreateAncillaryData (BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\n\n    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\n    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame, BMDTimeValue displayTime, BMDTimeValue displayDuration, BMDTimeScale timeScale) = 0;\n    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0;\n    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0;\n\n    /* Audio Output */\n\n    virtual HRESULT EnableAudioOutput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount, BMDAudioOutputStreamType streamType) = 0;\n    virtual HRESULT DisableAudioOutput (void) = 0;\n\n    virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT BeginAudioPreroll (void) = 0;\n    virtual HRESULT EndAudioPreroll (void) = 0;\n    virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, uint32_t sampleFrameCount, BMDTimeValue streamTime, BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0;\n    virtual HRESULT FlushBufferedAudioSamples (void) = 0;\n\n    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0;\n\n    /* Output Control */\n\n    virtual HRESULT StartScheduledPlayback (BMDTimeValue playbackStartTime, BMDTimeScale timeScale, double playbackSpeed) = 0;\n    virtual HRESULT StopScheduledPlayback (BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, BMDTimeScale timeScale) = 0;\n    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0;\n    virtual HRESULT GetHardwareReferenceClock (BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *elapsedTimeSinceSchedulerBegan) = 0;\n\nprotected:\n    virtual ~IDeckLinkOutput_v7_3 () {}; // call Release method to drop reference count\n};\n\n/* End Interface IDeckLinkOutput */\n\n\n/* Interface IDeckLinkInputCallback - Frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkInputCallback_v7_3 : public IUnknown\n{\npublic:\n    virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode_v7_6 *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\n    virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame_v7_3 *videoFrame, /* in */ IDeckLinkAudioInputPacket *audioPacket) = 0;\n\nprotected:\n    virtual ~IDeckLinkInputCallback_v7_3 () {}; // call Release method to drop reference count\n};\n\n/* End Interface IDeckLinkInputCallback */\n\n\n/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkInput_v7_3 : public IUnknown\n{\npublic:\n\tvirtual HRESULT DoesSupportVideoMode (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (BMDDisplayMode displayMode, BMDPixelFormat pixelFormat, BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (BMDAudioSampleRate sampleRate, BMDAudioSampleType sampleType, uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v7_3 *theCallback) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput_v7_3 () {}; // call Release method to drop reference count\n};\n\n/* End Interface IDeckLinkInput */\n\n/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkVideoInputFrame_v7_3 : public IDeckLinkVideoFrame_v7_6\n{\npublic:\n    virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoInputFrame_v7_3 () {}; // call Release method to drop reference count\n};\n\n/* End Interface IDeckLinkVideoInputFrame */\n\n#endif      // defined(__cplusplus)\n#endif      // __DeckLink_API_v7_3_h__\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v7_6.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n/* DeckLinkAPI_v7_6.h */\n\n#ifndef __DeckLink_API_v7_6_h__\n#define __DeckLink_API_v7_6_h__\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n\n// Interface ID Declarations\n\n#define IID_IDeckLinkVideoOutputCallback_v7_6            /* E763A626-4A3C-49D1-BF13-E7AD3692AE52 */ (REFIID){0xE7,0x63,0xA6,0x26,0x4A,0x3C,0x49,0xD1,0xBF,0x13,0xE7,0xAD,0x36,0x92,0xAE,0x52}\n#define IID_IDeckLinkInputCallback_v7_6                  /* 31D28EE7-88B6-4CB1-897A-CDBF79A26414 */ (REFIID){0x31,0xD2,0x8E,0xE7,0x88,0xB6,0x4C,0xB1,0x89,0x7A,0xCD,0xBF,0x79,0xA2,0x64,0x14}\n#define IID_IDeckLinkDisplayModeIterator_v7_6            /* 455D741F-1779-4800-86F5-0B5D13D79751 */ (REFIID){0x45,0x5D,0x74,0x1F,0x17,0x79,0x48,0x00,0x86,0xF5,0x0B,0x5D,0x13,0xD7,0x97,0x51}\n#define IID_IDeckLinkDisplayMode_v7_6                    /* 87451E84-2B7E-439E-A629-4393EA4A8550 */ (REFIID){0x87,0x45,0x1E,0x84,0x2B,0x7E,0x43,0x9E,0xA6,0x29,0x43,0x93,0xEA,0x4A,0x85,0x50}\n#define IID_IDeckLinkOutput_v7_6                         /* 29228142-EB8C-4141-A621-F74026450955 */ (REFIID){0x29,0x22,0x81,0x42,0xEB,0x8C,0x41,0x41,0xA6,0x21,0xF7,0x40,0x26,0x45,0x09,0x55}\n#define IID_IDeckLinkInput_v7_6                          /* 300C135A-9F43-48E2-9906-6D7911D93CF1 */ (REFIID){0x30,0x0C,0x13,0x5A,0x9F,0x43,0x48,0xE2,0x99,0x06,0x6D,0x79,0x11,0xD9,0x3C,0xF1}\n#define IID_IDeckLinkTimecode_v7_6                       /* EFB9BCA6-A521-44F7-BD69-2332F24D9EE6 */ (REFIID){0xEF,0xB9,0xBC,0xA6,0xA5,0x21,0x44,0xF7,0xBD,0x69,0x23,0x32,0xF2,0x4D,0x9E,0xE6}\n#define IID_IDeckLinkVideoFrame_v7_6                     /* A8D8238E-6B18-4196-99E1-5AF717B83D32 */ (REFIID){0xA8,0xD8,0x23,0x8E,0x6B,0x18,0x41,0x96,0x99,0xE1,0x5A,0xF7,0x17,0xB8,0x3D,0x32}\n#define IID_IDeckLinkMutableVideoFrame_v7_6              /* 46FCEE00-B4E6-43D0-91C0-023A7FCEB34F */ (REFIID){0x46,0xFC,0xEE,0x00,0xB4,0xE6,0x43,0xD0,0x91,0xC0,0x02,0x3A,0x7F,0xCE,0xB3,0x4F}\n#define IID_IDeckLinkVideoInputFrame_v7_6                /* 9A74FA41-AE9F-47AC-8CF4-01F42DD59965 */ (REFIID){0x9A,0x74,0xFA,0x41,0xAE,0x9F,0x47,0xAC,0x8C,0xF4,0x01,0xF4,0x2D,0xD5,0x99,0x65}\n#define IID_IDeckLinkScreenPreviewCallback_v7_6          /* 373F499D-4B4D-4518-AD22-6354E5A5825E */ (REFIID){0x37,0x3F,0x49,0x9D,0x4B,0x4D,0x45,0x18,0xAD,0x22,0x63,0x54,0xE5,0xA5,0x82,0x5E}\n#define IID_IDeckLinkGLScreenPreviewHelper_v7_6          /* BA575CD9-A15E-497B-B2C2-F9AFE7BE4EBA */ (REFIID){0xBA,0x57,0x5C,0xD9,0xA1,0x5E,0x49,0x7B,0xB2,0xC2,0xF9,0xAF,0xE7,0xBE,0x4E,0xBA}\n#define IID_IDeckLinkVideoConversion_v7_6                /* 3EB504C9-F97D-40FE-A158-D407D48CB53B */ (REFIID){0x3E,0xB5,0x04,0xC9,0xF9,0x7D,0x40,0xFE,0xA1,0x58,0xD4,0x07,0xD4,0x8C,0xB5,0x3B}\n#define IID_IDeckLinkConfiguration_v7_6                  /* B8EAD569-B764-47F0-A73F-AE40DF6CBF10 */ (REFIID){0xB8,0xEA,0xD5,0x69,0xB7,0x64,0x47,0xF0,0xA7,0x3F,0xAE,0x40,0xDF,0x6C,0xBF,0x10}\n\n\n#if defined(__cplusplus)\n\n/* Enum BMDVideoConnection - Video connection types */\n\ntypedef uint32_t BMDVideoConnection_v7_6;\nenum _BMDVideoConnection_v7_6 {\n    bmdVideoConnectionSDI_v7_6                              = 'sdi ',\n    bmdVideoConnectionHDMI_v7_6                             = 'hdmi',\n    bmdVideoConnectionOpticalSDI_v7_6                       = 'opti',\n    bmdVideoConnectionComponent_v7_6                        = 'cpnt',\n    bmdVideoConnectionComposite_v7_6                        = 'cmst',\n    bmdVideoConnectionSVideo_v7_6                           = 'svid'\n};\n\n// Forward Declarations\n\nclass IDeckLinkVideoOutputCallback_v7_6;\nclass IDeckLinkInputCallback_v7_6;\nclass IDeckLinkDisplayModeIterator_v7_6;\nclass IDeckLinkDisplayMode_v7_6;\nclass IDeckLinkOutput_v7_6;\nclass IDeckLinkInput_v7_6;\nclass IDeckLinkTimecode_v7_6;\nclass IDeckLinkVideoFrame_v7_6;\nclass IDeckLinkMutableVideoFrame_v7_6;\nclass IDeckLinkVideoInputFrame_v7_6;\nclass IDeckLinkScreenPreviewCallback_v7_6;\nclass IDeckLinkGLScreenPreviewHelper_v7_6;\nclass IDeckLinkVideoConversion_v7_6;\n\n\n/* Interface IDeckLinkVideoOutputCallback - Frame completion callback. */\n\nclass BMD_PUBLIC IDeckLinkVideoOutputCallback_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT ScheduledFrameCompleted (/* in */ IDeckLinkVideoFrame_v7_6 *completedFrame, /* in */ BMDOutputFrameCompletionResult result) = 0;\n    virtual HRESULT ScheduledPlaybackHasStopped (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoOutputCallback_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkInputCallback - Frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkInputCallback_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT VideoInputFormatChanged (/* in */ BMDVideoInputFormatChangedEvents notificationEvents, /* in */ IDeckLinkDisplayMode_v7_6 *newDisplayMode, /* in */ BMDDetectedVideoInputFormatFlags detectedSignalFlags) = 0;\n    virtual HRESULT VideoInputFrameArrived (/* in */ IDeckLinkVideoInputFrame_v7_6* videoFrame, /* in */ IDeckLinkAudioInputPacket* audioPacket) = 0;\n\nprotected:\n    virtual ~IDeckLinkInputCallback_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkDisplayModeIterator - enumerates over supported input/output display modes. */\n\nclass BMD_PUBLIC IDeckLinkDisplayModeIterator_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT Next (/* out */ IDeckLinkDisplayMode_v7_6 **deckLinkDisplayMode) = 0;\n\nprotected:\n    virtual ~IDeckLinkDisplayModeIterator_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkDisplayMode - represents a display mode */\n\nclass BMD_PUBLIC IDeckLinkDisplayMode_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT GetName (/* out */ const char **name) = 0;\n    virtual BMDDisplayMode GetDisplayMode (void) = 0;\n    virtual long GetWidth (void) = 0;\n    virtual long GetHeight (void) = 0;\n    virtual HRESULT GetFrameRate (/* out */ BMDTimeValue *frameDuration, /* out */ BMDTimeScale *timeScale) = 0;\n    virtual BMDFieldDominance GetFieldDominance (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkDisplayMode_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkOutput_v7_6 : public IUnknown\n{\npublic:\n\tvirtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0;\n\n    /* Video Output */\n\n    virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;\n    virtual HRESULT DisableVideoOutput (void) = 0;\n\n    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;\n    virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame_v7_6 **outFrame) = 0;\n    virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\n\n    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\n    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback_v7_6 *theCallback) = 0;\n    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0;\n\n    /* Audio Output */\n\n    virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;\n    virtual HRESULT DisableAudioOutput (void) = 0;\n\n    virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT BeginAudioPreroll (void) = 0;\n    virtual HRESULT EndAudioPreroll (void) = 0;\n    virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0;\n    virtual HRESULT FlushBufferedAudioSamples (void) = 0;\n\n    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0;\n\n    /* Output Control */\n\n    virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;\n    virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0;\n    virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkOutput_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkInput_v7_6 - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkInput_v7_6 : public IUnknown\n{\npublic:\n\tvirtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* out */ BMDDisplayModeSupport_v10_11 *result) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator_v7_6 **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback_v7_6 *previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v7_6 *theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkTimecode - Used for video frame timecode representation. */\n\nclass BMD_PUBLIC IDeckLinkTimecode_v7_6 : public IUnknown\n{\npublic:\n    virtual BMDTimecodeBCD GetBCD (void) = 0;\n    virtual HRESULT GetComponents (/* out */ uint8_t *hours, /* out */ uint8_t *minutes, /* out */ uint8_t *seconds, /* out */ uint8_t *frames) = 0;\n    virtual HRESULT GetString (/* out */ const char **timecode) = 0;\n    virtual BMDTimecodeFlags GetFlags (void) = 0;\n\nprotected:\n    virtual ~IDeckLinkTimecode_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkVideoFrame - Interface to encapsulate a video frame; can be caller-implemented. */\n\nclass BMD_PUBLIC IDeckLinkVideoFrame_v7_6 : public IUnknown\n{\npublic:\n    virtual long GetWidth (void) = 0;\n    virtual long GetHeight (void) = 0;\n    virtual long GetRowBytes (void) = 0;\n    virtual BMDPixelFormat GetPixelFormat (void) = 0;\n    virtual BMDFrameFlags GetFlags (void) = 0;\n    virtual HRESULT GetBytes (/* out */ void **buffer) = 0;\n\n    virtual HRESULT GetTimecode (BMDTimecodeFormat format, /* out */ IDeckLinkTimecode_v7_6 **timecode) = 0;\n    virtual HRESULT GetAncillaryData (/* out */ IDeckLinkVideoFrameAncillary **ancillary) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoFrame_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkMutableVideoFrame - Created by IDeckLinkOutput::CreateVideoFrame. */\n\nclass BMD_PUBLIC IDeckLinkMutableVideoFrame_v7_6 : public IDeckLinkVideoFrame_v7_6\n{\npublic:\n    virtual HRESULT SetFlags (BMDFrameFlags newFlags) = 0;\n\n    virtual HRESULT SetTimecode (BMDTimecodeFormat format, /* in */ IDeckLinkTimecode_v7_6 *timecode) = 0;\n    virtual HRESULT SetTimecodeFromComponents (BMDTimecodeFormat format, uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t frames, BMDTimecodeFlags flags) = 0;\n    virtual HRESULT SetAncillaryData (/* in */ IDeckLinkVideoFrameAncillary *ancillary) = 0;\n\nprotected:\n    virtual ~IDeckLinkMutableVideoFrame_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkVideoInputFrame - Provided by the IDeckLinkVideoInput frame arrival callback. */\n\nclass BMD_PUBLIC IDeckLinkVideoInputFrame_v7_6 : public IDeckLinkVideoFrame_v7_6\n{\npublic:\n    virtual HRESULT GetStreamTime (/* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration, BMDTimeScale timeScale) = 0;\n    virtual HRESULT GetHardwareReferenceTimestamp (BMDTimeScale timeScale, /* out */ BMDTimeValue *frameTime, /* out */ BMDTimeValue *frameDuration) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoInputFrame_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkScreenPreviewCallback - Screen preview callback */\n\nclass BMD_PUBLIC IDeckLinkScreenPreviewCallback_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT DrawFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkScreenPreviewCallback_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkGLScreenPreviewHelper - Created with CoCreateInstance(). */\n\nclass BMD_PUBLIC IDeckLinkGLScreenPreviewHelper_v7_6 : public IUnknown\n{\npublic:\n\n    /* Methods must be called with OpenGL context set */\n\n    virtual HRESULT InitializeGL (void) = 0;\n    virtual HRESULT PaintGL (void) = 0;\n    virtual HRESULT SetFrame (/* in */ IDeckLinkVideoFrame_v7_6 *theFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkGLScreenPreviewHelper_v7_6 () {}; // call Release method to drop reference count\n};\n\n\n/* Interface IDeckLinkVideoConversion - Created with CoCreateInstance(). */\n\nclass BMD_PUBLIC IDeckLinkVideoConversion_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT ConvertFrame (/* in */ IDeckLinkVideoFrame_v7_6* srcFrame, /* in */ IDeckLinkVideoFrame_v7_6* dstFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkVideoConversion_v7_6 () {}; // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkConfiguration - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkConfiguration_v7_6 : public IUnknown\n{\npublic:\n    virtual HRESULT GetConfigurationValidator (/* out */ IDeckLinkConfiguration_v7_6 **configObject) = 0;\n    virtual HRESULT WriteConfigurationToPreferences (void) = 0;\n\t\n    /* Video Output Configuration */\n\t\n    virtual HRESULT SetVideoOutputFormat (/* in */ BMDVideoConnection_v7_6 videoOutputConnection) = 0;\n    virtual HRESULT IsVideoOutputActive (/* in */ BMDVideoConnection_v7_6 videoOutputConnection, /* out */ bool *active) = 0;\n\t\n    virtual HRESULT SetAnalogVideoOutputFlags (/* in */ BMDAnalogVideoFlags analogVideoFlags) = 0;\n    virtual HRESULT GetAnalogVideoOutputFlags (/* out */ BMDAnalogVideoFlags *analogVideoFlags) = 0;\n\t\n    virtual HRESULT EnableFieldFlickerRemovalWhenPaused (/* in */ bool enable) = 0;\n    virtual HRESULT IsEnabledFieldFlickerRemovalWhenPaused (/* out */ bool *enabled) = 0;\n\t\n    virtual HRESULT Set444And3GBpsVideoOutput (/* in */ bool enable444VideoOutput, /* in */ bool enable3GbsOutput) = 0;\n    virtual HRESULT Get444And3GBpsVideoOutput (/* out */ bool *is444VideoOutputEnabled, /* out */ bool *threeGbsOutputEnabled) = 0;\n\t\n    virtual HRESULT SetVideoOutputConversionMode (/* in */ BMDVideoOutputConversionMode conversionMode) = 0;\n    virtual HRESULT GetVideoOutputConversionMode (/* out */ BMDVideoOutputConversionMode *conversionMode) = 0;\n\t\n    virtual HRESULT Set_HD1080p24_to_HD1080i5994_Conversion (/* in */ bool enable) = 0;\n    virtual HRESULT Get_HD1080p24_to_HD1080i5994_Conversion (/* out */ bool *enabled) = 0;\n\t\n    /* Video Input Configuration */\n\t\n    virtual HRESULT SetVideoInputFormat (/* in */ BMDVideoConnection_v7_6 videoInputFormat) = 0;\n    virtual HRESULT GetVideoInputFormat (/* out */ BMDVideoConnection_v7_6 *videoInputFormat) = 0;\n\t\n    virtual HRESULT SetAnalogVideoInputFlags (/* in */ BMDAnalogVideoFlags analogVideoFlags) = 0;\n    virtual HRESULT GetAnalogVideoInputFlags (/* out */ BMDAnalogVideoFlags *analogVideoFlags) = 0;\n\t\n    virtual HRESULT SetVideoInputConversionMode (/* in */ BMDVideoInputConversionMode conversionMode) = 0;\n    virtual HRESULT GetVideoInputConversionMode (/* out */ BMDVideoInputConversionMode *conversionMode) = 0;\n\t\n    virtual HRESULT SetBlackVideoOutputDuringCapture (/* in */ bool blackOutInCapture) = 0;\n    virtual HRESULT GetBlackVideoOutputDuringCapture (/* out */ bool *blackOutInCapture) = 0;\n\t\n    virtual HRESULT Set32PulldownSequenceInitialTimecodeFrame (/* in */ uint32_t aFrameTimecode) = 0;\n    virtual HRESULT Get32PulldownSequenceInitialTimecodeFrame (/* out */ uint32_t *aFrameTimecode) = 0;\n\t\n    virtual HRESULT SetVancSourceLineMapping (/* in */ uint32_t activeLine1VANCsource, /* in */ uint32_t activeLine2VANCsource, /* in */ uint32_t activeLine3VANCsource) = 0;\n    virtual HRESULT GetVancSourceLineMapping (/* out */ uint32_t *activeLine1VANCsource, /* out */ uint32_t *activeLine2VANCsource, /* out */ uint32_t *activeLine3VANCsource) = 0;\n\t\n    /* Audio Input Configuration */\n\t\n    virtual HRESULT SetAudioInputFormat (/* in */ BMDAudioConnection audioInputFormat) = 0;\n    virtual HRESULT GetAudioInputFormat (/* out */ BMDAudioConnection *audioInputFormat) = 0;\n};\n\n/* Functions */\n\nextern \"C\" {\n\n\tIDeckLinkIterator*\t\t\t\t\t\t\tBMD_PUBLIC CreateDeckLinkIteratorInstance_v7_6 (void);\n\tIDeckLinkGLScreenPreviewHelper_v7_6*\t\tBMD_PUBLIC CreateOpenGLScreenPreviewHelper_v7_6 (void);\n    IDeckLinkVideoConversion_v7_6*\t\t\t\tBMD_PUBLIC CreateVideoConversionInstance_v7_6 (void);\n\n};\n\n\n#endif      // defined(__cplusplus)\n#endif      // __DeckLink_API_v7_6_h__\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v7_9.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2010 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n/* DeckLinkAPI_v7_9.h */\n\n#ifndef __DeckLink_API_v7_9_h__\n#define __DeckLink_API_v7_9_h__\n\n#include \"DeckLinkAPI.h\"\n\n// Interface ID Declarations\n#define IID_IDeckLinkDeckControl_v7_9                    /* A4D81043-0619-42B7-8ED6-602D29041DF7 */ (REFIID){0xA4,0xD8,0x10,0x43,0x06,0x19,0x42,0xB7,0x8E,0xD6,0x60,0x2D,0x29,0x04,0x1D,0xF7}\n\n#if defined(__cplusplus)\n\n\n// Forward Declarations\nclass IDeckLinkDeckControl_v7_9;\n\n/* Interface IDeckLinkDeckControl_v7_9 - Deck Control main interface */\nclass BMD_PUBLIC IDeckLinkDeckControl_v7_9 : public IUnknown\n{\npublic:\n    virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Close (/* in */ bool standbyOn) = 0;\n    virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0;\n    virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0;\n    virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetTimecodeString (/* out */ const char **currentTimeCode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0;\n    virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0;\n    virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0;\n    virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0;\n    virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0;\n    virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0;\n    virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0;\n    virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Abort (void) = 0;\n    virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback *callback) = 0;\n\t\nprotected:\n    virtual ~IDeckLinkDeckControl_v7_9 () {}; // call Release method to drop reference count\n};\n\n\n\n#endif      // defined(__cplusplus)\n#endif      // __DeckLink_API_v7_9_h__\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v8_0.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2011 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v8_0_H\n#define BMD_DECKLINKAPI_v8_0_H\n\n#include \"DeckLinkAPI.h\"\n\n// Interface ID Declarations\n\n#define IID_IDeckLink_v8_0                                    /* 62BFF75D-6569-4E55-8D4D-66AA03829ABC */ (REFIID){0x62,0xBF,0xF7,0x5D,0x65,0x69,0x4E,0x55,0x8D,0x4D,0x66,0xAA,0x03,0x82,0x9A,0xBC}\n#define IID_IDeckLinkIterator_v8_0                            /* 74E936FC-CC28-4A67-81A0-1E94E52D4E69 */ (REFIID){0x74,0xE9,0x36,0xFC,0xCC,0x28,0x4A,0x67,0x81,0xA0,0x1E,0x94,0xE5,0x2D,0x4E,0x69}\n\n#if defined (__cplusplus)\n\n/* Interface IDeckLink_v8_0 - represents a DeckLink device */\n\nclass BMD_PUBLIC IDeckLink_v8_0 : public IUnknown\n{\npublic:\n    virtual HRESULT GetModelName (/* out */ const char **modelName) = 0;\n};\n\n/* Interface IDeckLinkIterator_v8_0 - enumerates installed DeckLink hardware */\n\nclass BMD_PUBLIC IDeckLinkIterator_v8_0 : public IUnknown\n{\npublic:\n    virtual HRESULT Next (/* out */ IDeckLink_v8_0 **deckLinkInstance) = 0;\n};\n\nextern \"C\" {\n    IDeckLinkIterator_v8_0*                     BMD_PUBLIC CreateDeckLinkIteratorInstance_v8_0 (void);\n};\n\n#endif\t// defined __cplusplus\n\n#endif /* defined(BMD_DECKLINKAPI_v8_0_H) */\n\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v8_1.h",
    "content": "/* -LICENSE-START-\n ** Copyright (c) 2011 Blackmagic Design\n **  \n ** Permission is hereby granted, free of charge, to any person or organization \n ** obtaining a copy of the software and accompanying documentation (the \n ** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n ** and transmit the Software, and to prepare derivative works of the Software, \n ** and to permit third-parties to whom the Software is furnished to do so, in \n ** accordance with:\n ** \n ** (1) if the Software is obtained from Blackmagic Design, the End User License \n ** Agreement for the Software Development Kit (“EULA”) available at \n ** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n ** \n ** (2) if the Software is obtained from any third party, such licensing terms \n ** as notified by that third party,\n ** \n ** and all subject to the following:\n ** \n ** (3) the copyright notices in the Software and this entire statement, \n ** including the above license grant, this restriction and the following \n ** disclaimer, must be included in all copies of the Software, in whole or in \n ** part, and all derivative works of the Software, unless such copies or \n ** derivative works are solely in the form of machine-executable object code \n ** generated by a source language processor.\n ** \n ** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n ** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n ** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n ** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n ** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n ** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n ** DEALINGS IN THE SOFTWARE.\n ** \n ** A copy of the Software is available free of charge at \n ** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n ** \n ** -LICENSE-END-\n */\n\n#ifndef BMD_DECKLINKAPI_v8_1_H\n#define BMD_DECKLINKAPI_v8_1_H\n\n#include \"DeckLinkAPI.h\"\n\n\n// Interface ID Declarations\n\n#define IID_IDeckLinkDeckControlStatusCallback_v8_1           /* E5F693C1-4283-4716-B18F-C1431521955B */ (REFIID){0xE5,0xF6,0x93,0xC1,0x42,0x83,0x47,0x16,0xB1,0x8F,0xC1,0x43,0x15,0x21,0x95,0x5B}\n#define IID_IDeckLinkDeckControl_v8_1                         /* 522A9E39-0F3C-4742-94EE-D80DE335DA1D */ (REFIID){0x52,0x2A,0x9E,0x39,0x0F,0x3C,0x47,0x42,0x94,0xEE,0xD8,0x0D,0xE3,0x35,0xDA,0x1D}\n\n\n/* Enum BMDDeckControlVTRControlState_v8_1 - VTR Control state */\n\ntypedef uint32_t BMDDeckControlVTRControlState_v8_1;\nenum _BMDDeckControlVTRControlState_v8_1 {\n    bmdDeckControlNotInVTRControlMode_v8_1                            = 'nvcm',\n    bmdDeckControlVTRControlPlaying_v8_1                              = 'vtrp',\n    bmdDeckControlVTRControlRecording_v8_1                            = 'vtrr',\n    bmdDeckControlVTRControlStill_v8_1                                = 'vtra',\n    bmdDeckControlVTRControlSeeking_v8_1                              = 'vtrs',\n    bmdDeckControlVTRControlStopped_v8_1                              = 'vtro'\n};\n\n\n/* Interface IDeckLinkDeckControlStatusCallback_v8_1 - Deck control state change callback. */\n\nclass BMD_PUBLIC IDeckLinkDeckControlStatusCallback_v8_1 : public IUnknown\n{\npublic:\n    virtual HRESULT TimecodeUpdate (/* in */ BMDTimecodeBCD currentTimecode) = 0;\n    virtual HRESULT VTRControlStateChanged (/* in */ BMDDeckControlVTRControlState_v8_1 newState, /* in */ BMDDeckControlError error) = 0;\n    virtual HRESULT DeckControlEventReceived (/* in */ BMDDeckControlEvent event, /* in */ BMDDeckControlError error) = 0;\n    virtual HRESULT DeckControlStatusChanged (/* in */ BMDDeckControlStatusFlags flags, /* in */ uint32_t mask) = 0;\n\t\nprotected:\n    virtual ~IDeckLinkDeckControlStatusCallback_v8_1 () {}; // call Release method to drop reference count\n};\n\n/* Interface IDeckLinkDeckControl_v8_1 - Deck Control main interface */\n\nclass BMD_PUBLIC IDeckLinkDeckControl_v8_1 : public IUnknown\n{\npublic:\n    virtual HRESULT Open (/* in */ BMDTimeScale timeScale, /* in */ BMDTimeValue timeValue, /* in */ bool timecodeIsDropFrame, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Close (/* in */ bool standbyOn) = 0;\n    virtual HRESULT GetCurrentState (/* out */ BMDDeckControlMode *mode, /* out */ BMDDeckControlVTRControlState_v8_1 *vtrControlState, /* out */ BMDDeckControlStatusFlags *flags) = 0;\n    virtual HRESULT SetStandby (/* in */ bool standbyOn) = 0;\n    virtual HRESULT SendCommand (/* in */ uint8_t *inBuffer, /* in */ uint32_t inBufferSize, /* out */ uint8_t *outBuffer, /* out */ uint32_t *outDataSize, /* in */ uint32_t outBufferSize, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Play (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Stop (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT TogglePlayStop (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Eject (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GoToTimecode (/* in */ BMDTimecodeBCD timecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT FastForward (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Rewind (/* in */ bool viewTape, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT StepForward (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT StepBack (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Jog (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Shuttle (/* in */ double rate, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetTimecodeString (/* out */ const char **currentTimeCode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetTimecode (/* out */ IDeckLinkTimecode **currentTimecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetTimecodeBCD (/* out */ BMDTimecodeBCD *currentTimecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT SetPreroll (/* in */ uint32_t prerollSeconds) = 0;\n    virtual HRESULT GetPreroll (/* out */ uint32_t *prerollSeconds) = 0;\n    virtual HRESULT SetExportOffset (/* in */ int32_t exportOffsetFields) = 0;\n    virtual HRESULT GetExportOffset (/* out */ int32_t *exportOffsetFields) = 0;\n    virtual HRESULT GetManualExportOffset (/* out */ int32_t *deckManualExportOffsetFields) = 0;\n    virtual HRESULT SetCaptureOffset (/* in */ int32_t captureOffsetFields) = 0;\n    virtual HRESULT GetCaptureOffset (/* out */ int32_t *captureOffsetFields) = 0;\n    virtual HRESULT StartExport (/* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* in */ BMDDeckControlExportModeOpsFlags exportModeOps, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT StartCapture (/* in */ bool useVITC, /* in */ BMDTimecodeBCD inTimecode, /* in */ BMDTimecodeBCD outTimecode, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT GetDeviceID (/* out */ uint16_t *deviceId, /* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT Abort (void) = 0;\n    virtual HRESULT CrashRecordStart (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT CrashRecordStop (/* out */ BMDDeckControlError *error) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkDeckControlStatusCallback_v8_1 *callback) = 0;\n\t\nprotected:\n    virtual ~IDeckLinkDeckControl_v8_1 () {}; // call Release method to drop reference count\n};\n\n\n#endif\t// BMD_DECKLINKAPI_v8_1_H\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v9_2.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2012 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v9_2_H\n#define BMD_DECKLINKAPI_v9_2_H\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n#include \"DeckLinkAPIVideoInput_v11_5_1.h\"\n\n\n// Interface ID Declarations\n\n#define IID_IDeckLinkInput_v9_2                          /* 6D40EF78-28B9-4E21-990D-95BB7750A04F */ (REFIID){0x6D,0x40,0xEF,0x78,0x28,0xB9,0x4E,0x21,0x99,0x0D,0x95,0xBB,0x77,0x50,0xA0,0x4F}\n\n\n#if defined(__cplusplus)\n\n/* Interface IDeckLinkInput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkInput_v9_2 : public IUnknown\n{\npublic:\n\tvirtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\n\n    /* Video Input */\n\n    virtual HRESULT EnableVideoInput (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoInputFlags flags) = 0;\n    virtual HRESULT DisableVideoInput (void) = 0;\n    virtual HRESULT GetAvailableVideoFrameCount (/* out */ uint32_t *availableFrameCount) = 0;\n\n    /* Audio Input */\n\n    virtual HRESULT EnableAudioInput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount) = 0;\n    virtual HRESULT DisableAudioInput (void) = 0;\n    virtual HRESULT GetAvailableAudioSampleFrameCount (/* out */ uint32_t *availableSampleFrameCount) = 0;\n\n    /* Input Control */\n\n    virtual HRESULT StartStreams (void) = 0;\n    virtual HRESULT StopStreams (void) = 0;\n    virtual HRESULT PauseStreams (void) = 0;\n    virtual HRESULT FlushStreams (void) = 0;\n    virtual HRESULT SetCallback (/* in */ IDeckLinkInputCallback_v11_5_1 *theCallback) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkInput_v9_2 () {}; // call Release method to drop reference count\n};\n\n\n#endif      // defined(__cplusplus)\n#endif\t// BMD_DECKLINKAPI_v9_2_H\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/DeckLinkAPI_v9_9.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2013 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef BMD_DECKLINKAPI_v9_9_H\n#define BMD_DECKLINKAPI_v9_9_H\n\n#include \"DeckLinkAPI.h\"\n#include \"DeckLinkAPI_v10_11.h\"\n\n\n// Interface ID Declarations\n\n#define IID_IDeckLinkOutput_v9_9                         /* A3EF0963-0862-44ED-92A9-EE89ABF431C7 */ (REFIID){0xA3,0xEF,0x09,0x63,0x08,0x62,0x44,0xED,0x92,0xA9,0xEE,0x89,0xAB,0xF4,0x31,0xC7}\n\n\n#if defined(__cplusplus)\n\n/* Interface IDeckLinkOutput - Created by QueryInterface from IDeckLink. */\n\nclass BMD_PUBLIC IDeckLinkOutput_v9_9 : public IUnknown\n{\npublic:\n\tvirtual HRESULT DoesSupportVideoMode (/* in */ BMDDisplayMode displayMode, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDVideoOutputFlags flags, /* out */ BMDDisplayModeSupport_v10_11 *result, /* out */ IDeckLinkDisplayMode **resultDisplayMode) = 0;\n    virtual HRESULT GetDisplayModeIterator (/* out */ IDeckLinkDisplayModeIterator **iterator) = 0;\n\n    virtual HRESULT SetScreenPreviewCallback (/* in */ IDeckLinkScreenPreviewCallback *previewCallback) = 0;\n\n    /* Video Output */\n\n    virtual HRESULT EnableVideoOutput (/* in */ BMDDisplayMode displayMode, /* in */ BMDVideoOutputFlags flags) = 0;\n    virtual HRESULT DisableVideoOutput (void) = 0;\n\n    virtual HRESULT SetVideoOutputFrameMemoryAllocator (/* in */ IDeckLinkMemoryAllocator *theAllocator) = 0;\n    virtual HRESULT CreateVideoFrame (/* in */ int32_t width, /* in */ int32_t height, /* in */ int32_t rowBytes, /* in */ BMDPixelFormat pixelFormat, /* in */ BMDFrameFlags flags, /* out */ IDeckLinkMutableVideoFrame **outFrame) = 0;\n    virtual HRESULT CreateAncillaryData (/* in */ BMDPixelFormat pixelFormat, /* out */ IDeckLinkVideoFrameAncillary **outBuffer) = 0;\n\n    virtual HRESULT DisplayVideoFrameSync (/* in */ IDeckLinkVideoFrame *theFrame) = 0;\n    virtual HRESULT ScheduleVideoFrame (/* in */ IDeckLinkVideoFrame *theFrame, /* in */ BMDTimeValue displayTime, /* in */ BMDTimeValue displayDuration, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT SetScheduledFrameCompletionCallback (/* in */ IDeckLinkVideoOutputCallback *theCallback) = 0;\n    virtual HRESULT GetBufferedVideoFrameCount (/* out */ uint32_t *bufferedFrameCount) = 0;\n\n    /* Audio Output */\n\n    virtual HRESULT EnableAudioOutput (/* in */ BMDAudioSampleRate sampleRate, /* in */ BMDAudioSampleType sampleType, /* in */ uint32_t channelCount, /* in */ BMDAudioOutputStreamType streamType) = 0;\n    virtual HRESULT DisableAudioOutput (void) = 0;\n\n    virtual HRESULT WriteAudioSamplesSync (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT BeginAudioPreroll (void) = 0;\n    virtual HRESULT EndAudioPreroll (void) = 0;\n    virtual HRESULT ScheduleAudioSamples (/* in */ void *buffer, /* in */ uint32_t sampleFrameCount, /* in */ BMDTimeValue streamTime, /* in */ BMDTimeScale timeScale, /* out */ uint32_t *sampleFramesWritten) = 0;\n\n    virtual HRESULT GetBufferedAudioSampleFrameCount (/* out */ uint32_t *bufferedSampleFrameCount) = 0;\n    virtual HRESULT FlushBufferedAudioSamples (void) = 0;\n\n    virtual HRESULT SetAudioCallback (/* in */ IDeckLinkAudioOutputCallback *theCallback) = 0;\n\n    /* Output Control */\n\n    virtual HRESULT StartScheduledPlayback (/* in */ BMDTimeValue playbackStartTime, /* in */ BMDTimeScale timeScale, /* in */ double playbackSpeed) = 0;\n    virtual HRESULT StopScheduledPlayback (/* in */ BMDTimeValue stopPlaybackAtTime, /* out */ BMDTimeValue *actualStopTime, /* in */ BMDTimeScale timeScale) = 0;\n    virtual HRESULT IsScheduledPlaybackRunning (/* out */ bool *active) = 0;\n    virtual HRESULT GetScheduledStreamTime (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *streamTime, /* out */ double *playbackSpeed) = 0;\n    virtual HRESULT GetReferenceStatus (/* out */ BMDReferenceStatus *referenceStatus) = 0;\n\n    /* Hardware Timing */\n\n    virtual HRESULT GetHardwareReferenceClock (/* in */ BMDTimeScale desiredTimeScale, /* out */ BMDTimeValue *hardwareTime, /* out */ BMDTimeValue *timeInFrame, /* out */ BMDTimeValue *ticksPerFrame) = 0;\n\nprotected:\n    virtual ~IDeckLinkOutput_v9_9 () {}; // call Release method to drop reference count\n};\n\n#endif      // defined(__cplusplus)\n#endif\t// BMD_DECKLINKAPI_v9_9_H\n"
  },
  {
    "path": "src/modules/decklink/linux_interop/LinuxCOM.h",
    "content": "/* -LICENSE-START-\n** Copyright (c) 2009 Blackmagic Design\n**  \n** Permission is hereby granted, free of charge, to any person or organization \n** obtaining a copy of the software and accompanying documentation (the \n** \"Software\") to use, reproduce, display, distribute, sub-license, execute, \n** and transmit the Software, and to prepare derivative works of the Software, \n** and to permit third-parties to whom the Software is furnished to do so, in \n** accordance with:\n** \n** (1) if the Software is obtained from Blackmagic Design, the End User License \n** Agreement for the Software Development Kit (“EULA”) available at \n** https://www.blackmagicdesign.com/EULA/DeckLinkSDK; or\n** \n** (2) if the Software is obtained from any third party, such licensing terms \n** as notified by that third party,\n** \n** and all subject to the following:\n** \n** (3) the copyright notices in the Software and this entire statement, \n** including the above license grant, this restriction and the following \n** disclaimer, must be included in all copies of the Software, in whole or in \n** part, and all derivative works of the Software, unless such copies or \n** derivative works are solely in the form of machine-executable object code \n** generated by a source language processor.\n** \n** (4) THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS \n** OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, \n** FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT \n** SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE \n** FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, \n** ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER \n** DEALINGS IN THE SOFTWARE.\n** \n** A copy of the Software is available free of charge at \n** https://www.blackmagicdesign.com/desktopvideo_sdk under the EULA.\n** \n** -LICENSE-END-\n*/\n\n#ifndef __LINUX_COM_H_\n#define __LINUX_COM_H_\n\nstruct REFIID\n{\t\n\tunsigned char byte0;\n\tunsigned char byte1;\n\tunsigned char byte2;\n\tunsigned char byte3;\n\tunsigned char byte4;\n\tunsigned char byte5;\n\tunsigned char byte6;\n\tunsigned char byte7;\n\tunsigned char byte8;\n\tunsigned char byte9;\n\tunsigned char byte10;\n\tunsigned char byte11;\n\tunsigned char byte12;\n\tunsigned char byte13;\n\tunsigned char byte14;\n\tunsigned char byte15;\n};\n\ntypedef REFIID CFUUIDBytes;\n#define CFUUIDGetUUIDBytes(x)\tx\n\ntypedef int HRESULT;\ntypedef unsigned long ULONG;\ntypedef void *LPVOID;\n\n#define SUCCEEDED(Status) ((HRESULT)(Status) >= 0)\n#define FAILED(Status) ((HRESULT)(Status)<0)\n\n#define IS_ERROR(Status) ((unsigned long)(Status) >> 31 == SEVERITY_ERROR)\n#define HRESULT_CODE(hr) ((hr) & 0xFFFF)\n#define HRESULT_FACILITY(hr) (((hr) >> 16) & 0x1fff)\n#define HRESULT_SEVERITY(hr) (((hr) >> 31) & 0x1)\n#define SEVERITY_SUCCESS 0\n#define SEVERITY_ERROR 1\n\n#define MAKE_HRESULT(sev,fac,code) ((HRESULT) (((unsigned long)(sev)<<31) | ((unsigned long)(fac)<<16) | ((unsigned long)(code))) )\n\n#define S_OK ((HRESULT)0x00000000L)\n#define S_FALSE ((HRESULT)0x00000001L)\n#define E_UNEXPECTED ((HRESULT)0x8000FFFFL)\n#define E_NOTIMPL ((HRESULT)0x80000001L)\n#define E_OUTOFMEMORY ((HRESULT)0x80000002L)\n#define E_INVALIDARG ((HRESULT)0x80000003L)\n#define E_NOINTERFACE ((HRESULT)0x80000004L)\n#define E_POINTER ((HRESULT)0x80000005L)\n#define E_HANDLE ((HRESULT)0x80000006L)\n#define E_ABORT ((HRESULT)0x80000007L)\n#define E_FAIL ((HRESULT)0x80000008L)\n#define E_ACCESSDENIED ((HRESULT)0x80000009L)\n\n#define STDMETHODCALLTYPE\n\n#define IID_IUnknown\t\t(REFIID){0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}\n#define IUnknownUUID\t\tIID_IUnknown\n\n#ifndef BMD_PUBLIC\n\t#define BMD_PUBLIC\n#endif\n\n#ifdef __cplusplus\nclass BMD_PUBLIC IUnknown\n{\n    public:\n    \tvirtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, LPVOID *ppv) = 0;\n    \tvirtual ULONG STDMETHODCALLTYPE AddRef(void) = 0;\n    \tvirtual ULONG STDMETHODCALLTYPE Release(void) = 0;\n};\n#endif\n\n#endif \n\n"
  },
  {
    "path": "src/modules/decklink/producer/decklink_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"decklink_producer.h\"\n\n#include \"../util/util.h\"\n\n#include <common/diagnostics/graph.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/log.h>\n#include <common/param.h>\n#include <common/scope_exit.h>\n#include <common/timer.h>\n\n#include <ffmpeg/util/av_assert.h>\n#include <ffmpeg/util/av_util.h>\n\n#include <core/diagnostics/call_context.h>\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n#include <libavfilter/avfilter.h>\n#include <libavfilter/buffersink.h>\n#include <libavfilter/buffersrc.h>\n#include <libavformat/avformat.h>\n#include <libavutil/channel_layout.h>\n#include <libavutil/opt.h>\n#include <libavutil/pixfmt.h>\n#include <libavutil/samplefmt.h>\n#include <libavutil/timecode.h>\n}\n\n#include <boost/format.hpp>\n\n#include <mutex>\n\n#include \"../decklink_api.h\"\n\nusing namespace caspar::ffmpeg;\n\nnamespace caspar { namespace decklink {\n\nstruct Filter\n{\n    std::shared_ptr<AVFilterGraph> graph        = nullptr;\n    AVFilterContext*               sink         = nullptr;\n    AVFilterContext*               video_source = nullptr;\n    AVFilterContext*               audio_source = nullptr;\n\n    Filter() {}\n\n    Filter(std::string                          filter_spec,\n           AVMediaType                          type,\n           const core::video_format_desc&       format_desc,\n           const com_ptr<IDeckLinkDisplayMode>& dm,\n           bool                                 hdr)\n    {\n        BMDTimeScale timeScale;\n        BMDTimeValue frameDuration;\n        dm->GetFrameRate(&frameDuration, &timeScale);\n\n        if (type == AVMEDIA_TYPE_VIDEO) {\n            if (filter_spec.empty()) {\n                filter_spec = \"null\";\n            }\n\n            boost::rational<int> bmdFramerate(\n                timeScale / 1000 * (dm->GetFieldDominance() == bmdProgressiveFrame ? 1 : 2), frameDuration / 1000);\n            bool doFps = bmdFramerate != (format_desc.framerate * format_desc.field_count);\n            bool i2p   = (dm->GetFieldDominance() != bmdProgressiveFrame) && (1 == format_desc.field_count);\n\n            std::string deintStr = (doFps || i2p) ? \",bwdif=mode=send_field\" : \",yadif=mode=send_field_nospatial\";\n            switch (dm->GetFieldDominance()) {\n                case bmdUpperFieldFirst:\n                    filter_spec += deintStr + \":parity=tff:deint=all\";\n                    break;\n                case bmdLowerFieldFirst:\n                    filter_spec += deintStr + \":parity=bff:deint=all\";\n                    break;\n                case bmdUnknownFieldDominance:\n                    filter_spec += deintStr + \":parity=auto:deint=interlaced\";\n                    break;\n            }\n\n            if (doFps) {\n                filter_spec += (boost::format(\",fps=%d/%d\") % (format_desc.time_scale * format_desc.field_count) %\n                                format_desc.duration)\n                                   .str();\n            }\n        } else {\n            if (filter_spec.empty()) {\n                filter_spec = \"anull\";\n            }\n            filter_spec +=\n                (boost::format(\",aresample=sample_rate=%d:async=2000\") % format_desc.audio_sample_rate).str();\n        }\n\n        AVFilterInOut* outputs = nullptr;\n        AVFilterInOut* inputs  = nullptr;\n\n        CASPAR_SCOPE_EXIT\n        {\n            avfilter_inout_free(&inputs);\n            avfilter_inout_free(&outputs);\n        };\n\n        int video_input_count = 0;\n        int audio_input_count = 0;\n        {\n            auto graph2 = avfilter_graph_alloc();\n            if (!graph2) {\n                FF_RET(AVERROR(ENOMEM), \"avfilter_graph_alloc\");\n            }\n\n            CASPAR_SCOPE_EXIT\n            {\n                avfilter_graph_free(&graph2);\n                avfilter_inout_free(&inputs);\n                avfilter_inout_free(&outputs);\n            };\n\n            FF(avfilter_graph_parse2(graph2, filter_spec.c_str(), &inputs, &outputs));\n\n            for (auto cur = inputs; cur; cur = cur->next) {\n                const auto filter_type = avfilter_pad_get_type(cur->filter_ctx->input_pads, cur->pad_idx);\n                if (filter_type == AVMEDIA_TYPE_VIDEO) {\n                    video_input_count += 1;\n                } else if (filter_type == AVMEDIA_TYPE_AUDIO) {\n                    audio_input_count += 1;\n                }\n            }\n        }\n\n        graph = std::shared_ptr<AVFilterGraph>(avfilter_graph_alloc(),\n                                               [](AVFilterGraph* ptr) { avfilter_graph_free(&ptr); });\n\n        if (!graph) {\n            FF_RET(AVERROR(ENOMEM), \"avfilter_graph_alloc\");\n        }\n\n        FF(avfilter_graph_parse2(graph.get(), filter_spec.c_str(), &inputs, &outputs));\n\n        auto pix_fmt = (hdr ? AV_PIX_FMT_YUV422P10 : AV_PIX_FMT_UYVY422);\n        for (auto cur = inputs; cur; cur = cur->next) {\n            const auto filter_type = avfilter_pad_get_type(cur->filter_ctx->input_pads, cur->pad_idx);\n\n            if (filter_type == AVMEDIA_TYPE_VIDEO) {\n                if (video_source) {\n                    CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                            << msg_info_t(\"only single video input supported\"));\n                }\n                const auto sar = boost::rational<int>(format_desc.square_width, format_desc.square_height) /\n                                 boost::rational<int>(format_desc.width, format_desc.height);\n\n                auto args =\n                    (boost::format(\"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:sar=%d/%d:frame_rate=%d/%d\") %\n                     dm->GetWidth() % dm->GetHeight() % pix_fmt % 1 % AV_TIME_BASE % sar.numerator() %\n                     sar.denominator() % (timeScale / 1000 * (dm->GetFieldDominance() == bmdProgressiveFrame ? 1 : 2)) %\n                     (frameDuration / 1000))\n                        .str();\n                auto name = (boost::format(\"in_%d\") % 0).str();\n\n                FF(avfilter_graph_create_filter(\n                    &video_source, avfilter_get_by_name(\"buffer\"), name.c_str(), args.c_str(), nullptr, graph.get()));\n                FF(avfilter_link(video_source, 0, cur->filter_ctx, cur->pad_idx));\n            } else if (filter_type == AVMEDIA_TYPE_AUDIO) {\n                if (audio_source) {\n                    CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                            << msg_info_t(\"only single audio input supported\"));\n                }\n\n                auto args = (boost::format(\"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%#x\") % 1 %\n                             format_desc.audio_sample_rate % format_desc.audio_sample_rate % AV_SAMPLE_FMT_S32 %\n                             ffmpeg::get_channel_layout_mask_for_channels(format_desc.audio_channels))\n                                .str();\n                auto name = (boost::format(\"in_%d\") % 0).str();\n\n                FF(avfilter_graph_create_filter(\n                    &audio_source, avfilter_get_by_name(\"abuffer\"), name.c_str(), args.c_str(), nullptr, graph.get()));\n                FF(avfilter_link(audio_source, 0, cur->filter_ctx, cur->pad_idx));\n            } else {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"only video and audio filters supported\"));\n            }\n        }\n\n        if (type == AVMEDIA_TYPE_VIDEO) {\n            FF(avfilter_graph_create_filter(\n                &sink, avfilter_get_by_name(\"buffersink\"), \"out\", nullptr, nullptr, graph.get()));\n\n            AVPixelFormat pix_fmts[] = {pix_fmt, AV_PIX_FMT_NONE};\n            FF(av_opt_set_int_list(sink, \"pix_fmts\", pix_fmts, -1, AV_OPT_SEARCH_CHILDREN));\n        } else if (type == AVMEDIA_TYPE_AUDIO) {\n            FF(avfilter_graph_create_filter(\n                &sink, avfilter_get_by_name(\"abuffersink\"), \"out\", nullptr, nullptr, graph.get()));\n\n            AVSampleFormat sample_fmts[]  = {AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE};\n            int            sample_rates[] = {format_desc.audio_sample_rate, 0};\n            FF(av_opt_set_int_list(sink, \"sample_fmts\", sample_fmts, -1, AV_OPT_SEARCH_CHILDREN));\n            FF(av_opt_set_int_list(sink, \"sample_rates\", sample_rates, 0, AV_OPT_SEARCH_CHILDREN));\n\n            // TODO - we might want to force the filter to produce 16 channels\n            // But this segfaults (changing the property name causes it to fail with an error)\n            // As 16 channel packets are fed into the filter, with the filter set to the same, that is what we get out\n            /*\n            AVChannelLayout channel_layout = AV_CHANNEL_LAYOUT_STEREO;\n            av_channel_layout_default(&channel_layout, format_desc.audio_channels);\n\n            FF(av_opt_set_chlayout(sink, \"ch_layouts\", &channel_layout, AV_OPT_SEARCH_CHILDREN));\n            av_channel_layout_uninit(&channel_layout);\n             */\n\n        } else {\n            CASPAR_THROW_EXCEPTION(ffmpeg_error_t()\n                                   << boost::errinfo_errno(EINVAL) << msg_info_t(\"invalid output media type\"));\n        }\n\n        {\n            const auto cur = outputs;\n\n            if (!cur || cur->next) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter graph output count\"));\n            }\n\n            if (avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx) != type) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter output media type\"));\n            }\n\n            FF(avfilter_link(cur->filter_ctx, cur->pad_idx, sink, 0));\n        }\n\n        FF(avfilter_graph_config(graph.get(), nullptr));\n\n        CASPAR_LOG(debug) << avfilter_graph_dump(graph.get(), nullptr);\n    }\n};\n\nstruct Decoder\n{\n    Decoder(const Decoder&) = delete;\n\n    bool hdr_ = false;\n\n  public:\n    std::shared_ptr<AVCodecContext> ctx;\n\n    Decoder() = default;\n\n    explicit Decoder(bool hdr, const com_ptr<IDeckLinkDisplayMode>& mode)\n        : hdr_(hdr)\n    {\n        const auto codec = avcodec_find_decoder(AV_CODEC_ID_V210);\n        if (!codec) {\n            FF_RET(AVERROR_DECODER_NOT_FOUND, \"avcodec_find_decoder\");\n        }\n\n        ctx = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(codec),\n                                              [](AVCodecContext* ptr) { avcodec_free_context(&ptr); });\n        if (!ctx) {\n            FF_RET(AVERROR(ENOMEM), \"avcodec_alloc_context3\");\n        }\n\n        auto params = std::shared_ptr<AVCodecParameters>(avcodec_parameters_alloc(),\n                                                         [](AVCodecParameters* ptr) { avcodec_parameters_free(&ptr); });\n        if (!params) {\n            FF_RET(AVERROR(ENOMEM), \"avcodec_parameters_alloc\");\n        }\n        params->width      = mode->GetWidth();\n        params->height     = mode->GetHeight();\n        params->codec_type = AVMEDIA_TYPE_VIDEO;\n        params->codec_id   = AV_CODEC_ID_V210;\n        params->format     = AV_PIX_FMT_YUV422P10;\n\n        FF(avcodec_parameters_to_context(ctx.get(), params.get()));\n\n        // int thread_count = env::properties().get(L\"configuration.ffmpeg.producer.threads\", 0);\n        FF(av_opt_set_image_size(ctx.get(), \"video_size\", mode->GetWidth(), mode->GetHeight(), 0));\n        FF(avcodec_open2(ctx.get(), codec, nullptr));\n    }\n\n    std::shared_ptr<AVFrame> decode(IDeckLinkVideoInputFrame* video, const com_ptr<IDeckLinkDisplayMode>& mode)\n    {\n        void* video_bytes = nullptr;\n        if (SUCCEEDED(video->GetBytes(&video_bytes)) && video_bytes) {\n            video->AddRef();\n\n            auto frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [video](AVFrame* ptr) {\n                video->Release();\n                av_frame_free(&ptr);\n            });\n            if (!frame)\n                FF_RET(AVERROR(ENOMEM), \"av_frame_alloc\");\n\n            if (hdr_) {\n                const auto size = video->GetRowBytes() * video->GetHeight();\n                AVPacket   packet;\n                av_init_packet(&packet);\n                packet.data = reinterpret_cast<uint8_t*>(video_bytes);\n                packet.size = size;\n                FF(avcodec_send_packet(ctx.get(), &packet));\n                FF(avcodec_receive_frame(ctx.get(), frame.get()));\n            } else {\n                frame->format      = AV_PIX_FMT_UYVY422;\n                frame->width       = video->GetWidth();\n                frame->height      = video->GetHeight();\n                frame->data[0]     = reinterpret_cast<uint8_t*>(video_bytes);\n                frame->linesize[0] = video->GetRowBytes();\n#if LIBAVCODEC_VERSION_MAJOR < 61\n                frame->key_frame = 1;\n#else\n                frame->flags |= AV_FRAME_FLAG_KEY;\n#endif\n            }\n\n#if LIBAVCODEC_VERSION_MAJOR < 61\n            frame->interlaced_frame = mode->GetFieldDominance() != bmdProgressiveFrame;\n            frame->top_field_first  = mode->GetFieldDominance() == bmdUpperFieldFirst ? 1 : 0;\n#else\n            frame->flags |= mode->GetFieldDominance() != bmdProgressiveFrame ? AV_FRAME_FLAG_INTERLACED : 0;\n            frame->flags |= mode->GetFieldDominance() == bmdUpperFieldFirst ? AV_FRAME_FLAG_TOP_FIELD_FIRST : 0;\n#endif\n\n            return frame;\n        }\n        return nullptr;\n    }\n};\n\ncore::color_space get_color_space(IDeckLinkVideoInputFrame* video)\n{\n    IDeckLinkVideoFrameMetadataExtensions* md = nullptr;\n\n    if (SUCCEEDED(video->QueryInterface(IID_IDeckLinkVideoFrameMetadataExtensions, (void**)&md))) {\n        auto     metadata = wrap_raw<com_ptr>(md, true);\n        LONGLONG color_space;\n        if (SUCCEEDED(md->GetInt(bmdDeckLinkFrameMetadataColorspace, &color_space))) {\n            if (color_space == bmdColorspaceRec2020) {\n                return core::color_space::bt2020;\n            } else if (color_space == bmdColorspaceRec601) {\n                return core::color_space::bt601;\n            }\n        }\n    }\n\n    return core::color_space::bt709;\n}\n\ncom_ptr<IDeckLinkDisplayMode> get_display_mode(const com_iface_ptr<IDeckLinkInput>& device,\n                                               BMDDisplayMode                       format,\n                                               BMDPixelFormat                       pix_fmt,\n                                               BMDSupportedVideoModeFlags           flag)\n{\n    IDeckLinkDisplayMode*         m = nullptr;\n    IDeckLinkDisplayModeIterator* iter;\n    if (SUCCEEDED(device->GetDisplayModeIterator(&iter))) {\n        auto iterator = wrap_raw<com_ptr>(iter, true);\n        while (SUCCEEDED(iterator->Next(&m)) && m != nullptr && m->GetDisplayMode() != format) {\n            m->Release();\n        }\n    }\n\n    if (!m)\n        CASPAR_THROW_EXCEPTION(user_error()\n                               << msg_info(\"Device could not find requested video-format: \" + std::to_string(format)));\n\n    com_ptr<IDeckLinkDisplayMode> mode = wrap_raw<com_ptr>(m, true);\n\n    BMDDisplayMode actualMode = bmdModeUnknown;\n    BOOL           supported  = false;\n\n    if (FAILED(device->DoesSupportVideoMode(bmdVideoConnectionUnspecified,\n                                            mode->GetDisplayMode(),\n                                            pix_fmt,\n                                            bmdNoVideoInputConversion,\n                                            flag,\n                                            &actualMode,\n                                            &supported)))\n        CASPAR_THROW_EXCEPTION(caspar_exception()\n                               << msg_info(L\"Could not determine whether device supports requested video format: \" +\n                                           get_mode_name(mode)));\n    else if (!supported)\n        CASPAR_LOG(info) << L\"Device may not support video-format: \" << get_mode_name(mode);\n    else if (actualMode != bmdModeUnknown)\n        CASPAR_LOG(warning) << L\"Device supports video-format with conversion: \" << get_mode_name(mode);\n\n    return mode;\n}\nstatic com_ptr<IDeckLinkDisplayMode> get_display_mode(const com_iface_ptr<IDeckLinkInput>& device,\n                                                      core::video_format                   fmt,\n                                                      BMDPixelFormat                       pix_fmt,\n                                                      BMDSupportedVideoModeFlags           flag)\n{\n    return get_display_mode(device, get_decklink_video_format(fmt), pix_fmt, flag);\n}\n\nBMDPixelFormat get_pixel_format2(bool hdr) { return hdr ? bmdFormat10BitYUV : bmdFormat8BitYUV; }\n\nclass decklink_producer : public IDeckLinkInputCallback\n{\n    const int                           device_index_;\n    core::monitor::state                state_;\n    mutable std::mutex                  state_mutex_;\n    spl::shared_ptr<diagnostics::graph> graph_;\n    caspar::timer                       tick_timer_;\n\n    com_ptr<IDeckLink>                        decklink_   = get_device(device_index_);\n    com_iface_ptr<IDeckLinkInput>             input_      = iface_cast<IDeckLinkInput>(decklink_);\n    com_iface_ptr<IDeckLinkProfileAttributes> attributes_ = iface_cast<IDeckLinkProfileAttributes>(decklink_);\n\n    const std::wstring model_name_ = get_model_name(decklink_);\n\n    core::video_format_desc              format_desc_;\n    std::vector<int>                     audio_cadence_ = format_desc_.audio_cadence;\n    spl::shared_ptr<core::frame_factory> frame_factory_;\n    const core::video_format_repository  format_repository_;\n\n    int64_t frame_count_ = 0;\n\n    double in_sync_  = 0.0;\n    double out_sync_ = 0.0;\n\n    bool freeze_on_lost_;\n    bool has_signal_;\n    bool hdr_;\n\n    core::draw_frame last_frame_;\n\n    int                                                        buffer_capacity_ = 4;\n    std::deque<std::pair<core::draw_frame, core::video_field>> buffer_;\n    mutable std::mutex                                         buffer_mutex_;\n\n    std::exception_ptr exception_;\n\n    com_ptr<IDeckLinkDisplayMode> mode_;\n\n    core::video_format_desc input_format;\n\n    std::string vfilter_;\n    std::string afilter_;\n\n    Filter video_filter_;\n    Filter audio_filter_;\n\n    Decoder video_decoder_;\n\n  public:\n    decklink_producer(core::video_format_desc                     format_desc,\n                      int                                         device_index,\n                      const spl::shared_ptr<core::frame_factory>& frame_factory,\n                      const core::video_format_repository&        format_repository,\n                      std::string                                 vfilter,\n                      std::string                                 afilter,\n                      const std::wstring&                         format,\n                      bool                                        freeze_on_lost,\n                      bool                                        hdr)\n        : device_index_(device_index)\n        , format_desc_(std::move(format_desc))\n        , frame_factory_(frame_factory)\n        , format_repository_(format_repository)\n        , freeze_on_lost_(freeze_on_lost)\n        , hdr_(hdr)\n        , input_format(format_desc_)\n        , vfilter_(std::move(vfilter))\n        , afilter_(std::move(afilter))\n    {\n        // use user-provided format if available, or choose the channel's output format\n        if (!format.empty()) {\n            input_format = format_repository.find(format);\n        }\n\n        mode_ = get_display_mode(input_, input_format.format, get_pixel_format2(hdr_), bmdSupportedVideoModeDefault);\n        video_filter_  = Filter(vfilter_, AVMEDIA_TYPE_VIDEO, format_desc_, mode_, hdr_);\n        audio_filter_  = Filter(afilter_, AVMEDIA_TYPE_AUDIO, format_desc_, mode_, hdr_);\n        video_decoder_ = Decoder(hdr_, mode_);\n\n        boost::range::rotate(audio_cadence_, std::end(audio_cadence_) - 1);\n\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        graph_->set_color(\"frame-time\", diagnostics::color(1.0f, 0.0f, 0.0f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"output-buffer\", diagnostics::color(0.0f, 1.0f, 0.0f));\n        graph_->set_color(\"in-sync\", diagnostics::color(1.0f, 0.2f, 0.0f));\n        graph_->set_color(\"out-sync\", diagnostics::color(0.0f, 0.2f, 1.0f));\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        BOOL status = FALSE;\n        int  flags  = bmdVideoInputEnableFormatDetection;\n\n        if (!format.empty()) {\n            flags = 0;\n        } else if (FAILED(attributes_->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &status)) || !status) {\n            CASPAR_LOG(warning) << L\"Decklink producer does not support auto detect input, you can explicitly choose a \"\n                                   L\"format by appending FORMAT\";\n            flags = 0;\n        }\n\n        if (FAILED(input_->EnableVideoInput(mode_->GetDisplayMode(), get_pixel_format2(hdr_), flags))) {\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Could not enable video input.\")\n                                                      << boost::errinfo_api_function(\"EnableVideoInput\"));\n        }\n\n        if (FAILED(input_->EnableAudioInput(bmdAudioSampleRate48kHz,\n                                            bmdAudioSampleType32bitInteger,\n                                            static_cast<int>(format_desc_.audio_channels)))) {\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Could not enable audio input.\")\n                                                      << boost::errinfo_api_function(\"EnableAudioInput\"));\n        }\n\n        if (FAILED(input_->SetCallback(this)) != S_OK) {\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Unable to set input callback.\")\n                                                      << boost::errinfo_api_function(\"SetCallback\"));\n        }\n\n        if (FAILED(input_->StartStreams())) {\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Unable to start input stream.\")\n                                                      << boost::errinfo_api_function(\"StartStreams\"));\n        }\n\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    ~decklink_producer()\n    {\n        if (input_ != nullptr) {\n            input_->StopStreams();\n            input_->DisableVideoInput();\n        }\n    }\n\n    HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID*) override { return E_NOINTERFACE; }\n    ULONG STDMETHODCALLTYPE   AddRef() override { return 1; }\n    ULONG STDMETHODCALLTYPE   Release() override { return 1; }\n\n    HRESULT STDMETHODCALLTYPE VideoInputFormatChanged(BMDVideoInputFormatChangedEvents notificationEvents,\n                                                      IDeckLinkDisplayMode*            newDisplayMode,\n                                                      BMDDetectedVideoInputFormatFlags /*detectedSignalFlags*/) override\n    {\n        try {\n            auto newMode = newDisplayMode->GetDisplayMode();\n            auto fmt     = get_caspar_video_format(newMode);\n\n            if (fmt == input_format.format) {\n                // This gets called often if the enabled pixel format doesn't match the signal\n                // https://forum.blackmagicdesign.com/viewtopic.php?f=12&t=144234 So if the video format hasn't actually\n                // changed, then we can ignore this event. In the future we may wish to respect this in order to unpack\n                // the pixels ourselves\n                return S_OK;\n            }\n\n            auto new_fmt = format_repository_.find_format(fmt);\n\n            CASPAR_LOG(info) << print() << L\" Input format changed from \" << input_format.name << L\" to \"\n                             << new_fmt.name;\n\n            input_->PauseStreams();\n\n            // reinitializing filters because not all filters can handle on-the-fly format changes\n            input_format = new_fmt;\n            mode_        = get_display_mode(input_, newMode, get_pixel_format2(hdr_), bmdSupportedVideoModeDefault);\n\n            graph_->set_text(print());\n\n            video_filter_ = Filter(vfilter_, AVMEDIA_TYPE_VIDEO, format_desc_, mode_, hdr_);\n            audio_filter_ = Filter(afilter_, AVMEDIA_TYPE_AUDIO, format_desc_, mode_, hdr_);\n\n            // reinitializing video input with the new display mode\n            if (FAILED(\n                    input_->EnableVideoInput(newMode, get_pixel_format2(hdr_), bmdVideoInputEnableFormatDetection))) {\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Unable to enable video input.\")\n                                                          << boost::errinfo_api_function(\"EnableVideoInput\"));\n            }\n\n            if (FAILED(input_->FlushStreams())) {\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Unable to flush input stream.\")\n                                                          << boost::errinfo_api_function(\"FlushStreams\"));\n            }\n\n            if (FAILED(input_->StartStreams())) {\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Unable to start input stream.\")\n                                                          << boost::errinfo_api_function(\"StartStreams\"));\n            }\n            return S_OK;\n        } catch (...) {\n            exception_ = std::current_exception();\n            return E_FAIL;\n        }\n    }\n\n    HRESULT STDMETHODCALLTYPE VideoInputFrameArrived(IDeckLinkVideoInputFrame*  video,\n                                                     IDeckLinkAudioInputPacket* audio) override\n    {\n        caspar::timer frame_timer;\n\n        CASPAR_SCOPE_EXIT\n        {\n            size_t buffer_size = 0;\n            {\n                std::lock_guard<std::mutex> lock(buffer_mutex_);\n                buffer_size = buffer_.size();\n            }\n\n            {\n                std::lock_guard<std::mutex> lock(state_mutex_);\n                state_[\"file/name\"]              = model_name_;\n                state_[\"file/path\"]              = device_index_;\n                state_[\"file/format\"]            = format_desc_.name;\n                state_[\"file/audio/sample-rate\"] = format_desc_.audio_sample_rate;\n                state_[\"file/audio/channels\"]    = format_desc_.audio_channels;\n                state_[\"file/fps\"]               = format_desc_.fps;\n                state_[\"profiler/time\"]          = {frame_timer.elapsed(), format_desc_.fps};\n                state_[\"buffer\"]                 = {static_cast<int>(buffer_size), buffer_capacity_};\n                state_[\"has_signal\"]             = has_signal_;\n\n                if (video) {\n                    state_[\"file/video/width\"]  = static_cast<int>(video->GetWidth());\n                    state_[\"file/video/height\"] = static_cast<int>(video->GetHeight());\n                }\n            }\n\n            graph_->set_value(\"frame-time\", frame_timer.elapsed() * format_desc_.fps * 0.5);\n            graph_->set_value(\"output-buffer\", static_cast<float>(buffer_size) / static_cast<float>(buffer_capacity_));\n        };\n\n        try {\n            graph_->set_value(\"tick-time\", tick_timer_.elapsed() * format_desc_.hz * 0.5);\n            tick_timer_.restart();\n\n            BMDTimeValue      in_video_pts = 0LL;\n            BMDTimeValue      in_audio_pts = 0LL;\n            core::color_space color_space  = core::color_space::bt709;\n\n            if (video) {\n                const auto flags = video->GetFlags();\n                has_signal_      = !(flags & bmdFrameHasNoInputSource);\n                if (freeze_on_lost_ && !has_signal_) {\n                    frame_count_ = 0;\n                    return S_OK;\n                }\n\n                color_space = get_color_space(video);\n                auto src    = video_decoder_.decode(video, mode_);\n\n                BMDTimeValue duration;\n                if (SUCCEEDED(video->GetStreamTime(&in_video_pts, &duration, AV_TIME_BASE))) {\n                    src->pts = in_video_pts;\n                }\n\n                if (src) {\n                    if (video_filter_.video_source) {\n                        FF(av_buffersrc_write_frame(video_filter_.video_source, src.get()));\n                    }\n                    if (audio_filter_.video_source) {\n                        FF(av_buffersrc_write_frame(audio_filter_.video_source, src.get()));\n                    }\n                }\n            }\n\n            if (audio) {\n                auto src    = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });\n                src->format = AV_SAMPLE_FMT_S32;\n                av_channel_layout_default(&src->ch_layout, format_desc_.audio_channels);\n                src->sample_rate = format_desc_.audio_sample_rate;\n\n                void* audio_bytes = nullptr;\n                if (SUCCEEDED(audio->GetBytes(&audio_bytes)) && audio_bytes) {\n                    audio->AddRef();\n                    src = std::shared_ptr<AVFrame>(src.get(), [src, audio](AVFrame* ptr) { audio->Release(); });\n                    src->nb_samples  = audio->GetSampleFrameCount();\n                    src->data[0]     = reinterpret_cast<uint8_t*>(audio_bytes);\n                    src->linesize[0] = src->nb_samples * format_desc_.audio_channels *\n                                       av_get_bytes_per_sample(static_cast<AVSampleFormat>(src->format));\n\n                    if (SUCCEEDED(audio->GetPacketTime(&in_audio_pts, format_desc_.audio_sample_rate))) {\n                        src->pts = in_audio_pts;\n                    }\n\n                    if (video_filter_.audio_source) {\n                        FF(av_buffersrc_write_frame(video_filter_.audio_source, src.get()));\n                    }\n                    if (audio_filter_.audio_source) {\n                        FF(av_buffersrc_write_frame(audio_filter_.audio_source, src.get()));\n                    }\n                }\n            }\n\n            av_buffersink_set_frame_size(audio_filter_.sink, audio_cadence_[0]);\n            while (true) {\n                {\n                    auto av_video = alloc_frame();\n                    auto av_audio = alloc_frame();\n\n                    // TODO (fix) this may get stuck if the decklink sends a frame of video or audio\n\n                    if (av_buffersink_get_frame_flags(video_filter_.sink, av_video.get(), AV_BUFFERSINK_FLAG_PEEK) <\n                        0) {\n                        return S_OK;\n                    }\n\n                    if (av_buffersink_get_frame_flags(audio_filter_.sink, av_audio.get(), AV_BUFFERSINK_FLAG_PEEK) <\n                        0) {\n                        return S_OK;\n                    }\n                }\n                auto av_video = alloc_frame();\n                auto av_audio = alloc_frame();\n\n                // TODO (fix) auto V/A sync even if decklink is wrong.\n\n                av_buffersink_get_frame(video_filter_.sink, av_video.get());\n                av_buffersink_get_samples(audio_filter_.sink, av_audio.get(), audio_cadence_[0]);\n\n                auto video_tb = av_buffersink_get_time_base(video_filter_.sink);\n                auto audio_tb = av_buffersink_get_time_base(audio_filter_.sink);\n\n                // CASPAR_LOG(trace) << \"decklink a/v pts:\" << av_video->pts << \" \" << av_audio->pts;\n\n                auto in_sync = static_cast<double>(in_video_pts) / AV_TIME_BASE -\n                               static_cast<double>(in_audio_pts) / format_desc_.audio_sample_rate;\n                auto out_sync = static_cast<double>(av_video->pts * video_tb.num) / video_tb.den -\n                                static_cast<double>(av_audio->pts * audio_tb.num) / audio_tb.den;\n\n                if (std::abs(in_sync - in_sync_) > 0.01) {\n                    CASPAR_LOG(warning) << print() << \" in-sync changed: \" << in_sync;\n                }\n                in_sync_ = in_sync;\n\n                if (std::abs(out_sync - out_sync_) > 0.01) {\n                    CASPAR_LOG(warning) << print() << \" out-sync changed: \" << out_sync;\n                }\n                out_sync_ = out_sync;\n\n                // If filter output sync has drifted too far from input sync, recreate the filters to resync.\n                // This usually happens after signal loss/regain from receiving incomplete frames.\n                const double frame_duration_threshold = 1.5 / input_format.hz;\n                const double sync_drift               = std::abs(out_sync - in_sync);\n                if (sync_drift > frame_duration_threshold) {\n                    CASPAR_LOG(warning) << print() << \" Excessive A/V sync drift detected (\"\n                                        << static_cast<int>(sync_drift * 1000) << \"ms), recreating filters to resync\";\n\n                    // Recreate filters to clear all buffered data\n                    video_filter_ = Filter(vfilter_, AVMEDIA_TYPE_VIDEO, format_desc_, mode_, hdr_);\n                    audio_filter_ = Filter(afilter_, AVMEDIA_TYPE_AUDIO, format_desc_, mode_, hdr_);\n\n                    in_sync_  = 0.0;\n                    out_sync_ = 0.0;\n\n                    // Skip this iteration and start fresh\n                    return S_OK;\n                }\n\n                graph_->set_value(\"in-sync\", in_sync * 2.0 + 0.5);\n                graph_->set_value(\"out-sync\", out_sync * 2.0 + 0.5);\n\n                auto frame = core::draw_frame(make_frame(this, *frame_factory_, av_video, av_audio, color_space));\n                auto field = core::video_field::progressive;\n                if (format_desc_.field_count == 2) {\n                    field = frame_count_ % 2 == 0 ? core::video_field::a : core::video_field::b;\n                }\n\n                {\n                    std::lock_guard<std::mutex> lock(buffer_mutex_);\n\n                    buffer_.emplace_back(std::make_pair(frame, field));\n                    frame_count_++;\n\n                    if (buffer_.size() > buffer_capacity_) {\n                        buffer_.pop_front();\n                        // If interlaced, pop a second frame, to drop a whole source frame.\n                        if (format_desc_.field_count == 2)\n                            buffer_.pop_front();\n                        graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n                    }\n                }\n\n                boost::range::rotate(audio_cadence_, std::end(audio_cadence_) - 1);\n            }\n        } catch (...) {\n            exception_ = std::current_exception();\n            return E_FAIL;\n        }\n\n        return S_OK;\n    }\n\n    core::draw_frame get_frame(const core::video_field field, bool use_last_frame)\n    {\n        if (exception_ != nullptr) {\n            std::rethrow_exception(exception_);\n        }\n\n        core::draw_frame frame;\n        bool             wrong_field = false;\n        {\n            std::lock_guard<std::mutex> lock(buffer_mutex_);\n            if (!buffer_.empty()) {\n                auto& candidate = buffer_.front();\n                if (candidate.second == field || candidate.second == core::video_field::progressive) {\n                    frame = std::move(candidate.first);\n                    buffer_.pop_front();\n                } else {\n                    wrong_field = true;\n                }\n            } else {\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"late-frame\");\n            }\n\n            graph_->set_value(\"output-buffer\",\n                              static_cast<float>(buffer_.size()) / static_cast<float>(buffer_capacity_));\n        }\n\n        if (wrong_field) {\n            return last_frame_;\n        } else if (!frame && (freeze_on_lost_ || use_last_frame)) {\n            return last_frame_;\n        } else {\n            if (frame) {\n                last_frame_ = frame;\n            }\n            return frame;\n        }\n    }\n\n    bool is_ready()\n    {\n        std::lock_guard<std::mutex> lock(buffer_mutex_);\n        return !buffer_.empty() || last_frame_;\n    }\n\n    std::wstring print() const\n    {\n        return model_name_ + L\" [\" + std::to_wstring(device_index_) + L\"|\" + input_format.name + L\"]\";\n    }\n\n    core::monitor::state state() const\n    {\n        std::lock_guard<std::mutex> lock(state_mutex_);\n        return state_;\n    }\n};\n\nclass decklink_producer_proxy : public core::frame_producer\n{\n    std::unique_ptr<decklink_producer> producer_;\n    const uint32_t                     length_;\n    executor                           executor_;\n\n  public:\n    explicit decklink_producer_proxy(const core::video_format_desc&              format_desc,\n                                     const spl::shared_ptr<core::frame_factory>& frame_factory,\n                                     const core::video_format_repository&        format_repository,\n                                     int                                         device_index,\n                                     const std::string&                          vfilter,\n                                     const std::string&                          afilter,\n                                     uint32_t                                    length,\n                                     const std::wstring&                         format,\n                                     bool                                        freeze_on_lost,\n                                     bool                                        hdr)\n        : length_(length)\n        , executor_(L\"decklink_producer[\" + std::to_wstring(device_index) + L\"]\")\n    {\n        auto ctx = core::diagnostics::call_context::for_thread();\n        executor_.invoke([=, this] {\n            core::diagnostics::call_context::for_thread() = ctx;\n            com_initialize();\n            producer_.reset(new decklink_producer(format_desc,\n                                                  device_index,\n                                                  frame_factory,\n                                                  format_repository,\n                                                  vfilter,\n                                                  afilter,\n                                                  format,\n                                                  freeze_on_lost,\n                                                  hdr));\n        });\n    }\n\n    ~decklink_producer_proxy() override\n    {\n        executor_.invoke([this] {\n            producer_.reset();\n            com_uninitialize();\n        });\n    }\n\n    core::monitor::state state() const override { return producer_->state(); }\n\n    // frame_producer\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        return producer_->get_frame(field, false);\n    }\n\n    core::draw_frame first_frame(const core::video_field field) override { return receive_impl(field, 0); }\n\n    core::draw_frame last_frame(const core::video_field field) override\n    {\n        return core::draw_frame::still(producer_->get_frame(field, true));\n    }\n\n    bool is_ready() override { return producer_->is_ready(); }\n\n    uint32_t nb_frames() const override { return length_; }\n\n    std::wstring print() const override { return producer_->print(); }\n\n    std::wstring name() const override { return L\"decklink\"; }\n};\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params)\n{\n    if (params.empty() || !boost::iequals(params.at(0), \"decklink\"))\n        return core::frame_producer::empty();\n\n    auto device_index = get_param(L\"DEVICE\", params, -1);\n    if (device_index == -1)\n        device_index = std::stoi(params.at(1));\n\n    auto freeze_on_lost = contains_param(L\"FREEZE_ON_LOST\", params);\n\n    auto hdr = contains_param(L\"10BIT\", params);\n\n    auto format_str = get_param(L\"FORMAT\", params);\n\n    auto filter_str = get_param(L\"FILTER\", params);\n    auto length     = get_param(L\"LENGTH\", params, std::numeric_limits<uint32_t>::max());\n\n    boost::ireplace_all(filter_str, L\"DEINTERLACE_BOB\", L\"YADIF=1:-1\");\n    boost::ireplace_all(filter_str, L\"DEINTERLACE_LQ\", L\"SEPARATEFIELDS\");\n    boost::ireplace_all(filter_str, L\"DEINTERLACE\", L\"YADIF=0:-1\");\n\n    auto vfilter = boost::to_lower_copy(get_param(L\"VF\", params, filter_str));\n    auto afilter = boost::to_lower_copy(get_param(L\"AF\", params, get_param(L\"FILTER\", params, L\"\")));\n\n    return spl::make_shared<decklink_producer_proxy>(dependencies.format_desc,\n                                                     dependencies.frame_factory,\n                                                     dependencies.format_repository,\n                                                     device_index,\n                                                     u8(vfilter),\n                                                     u8(afilter),\n                                                     length,\n                                                     format_str,\n                                                     freeze_on_lost,\n                                                     hdr);\n}\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/producer/decklink_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/fwd.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace decklink {\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/decklink/util/util.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/except.h>\n#include <common/log.h>\n#include <core/video_format.h>\n\n#include \"../decklink_api.h\"\n\n#include <string>\n\nnamespace caspar { namespace decklink {\n\nstatic BMDDisplayMode get_decklink_video_format(core::video_format fmt)\n{\n    switch (fmt) {\n        case core::video_format::pal:\n            return bmdModePAL;\n        case core::video_format::ntsc:\n            return bmdModeNTSC;\n        case core::video_format::x576p2500:\n            return (BMDDisplayMode)ULONG_MAX;\n        case core::video_format::x720p2398:\n            return (BMDDisplayMode)ULONG_MAX;\n        case core::video_format::x720p2400:\n            return (BMDDisplayMode)ULONG_MAX;\n        case core::video_format::x720p2500:\n            return (BMDDisplayMode)ULONG_MAX;\n        case core::video_format::x720p5000:\n            return bmdModeHD720p50;\n        case core::video_format::x720p2997:\n            return (BMDDisplayMode)ULONG_MAX;\n        case core::video_format::x720p5994:\n            return bmdModeHD720p5994;\n        case core::video_format::x720p3000:\n            return (BMDDisplayMode)ULONG_MAX;\n        case core::video_format::x720p6000:\n            return bmdModeHD720p60;\n        case core::video_format::x1080p2398:\n            return bmdModeHD1080p2398;\n        case core::video_format::x1080p2400:\n            return bmdModeHD1080p24;\n        case core::video_format::x1080i5000:\n            return bmdModeHD1080i50;\n        case core::video_format::x1080i5994:\n            return bmdModeHD1080i5994;\n        case core::video_format::x1080i6000:\n            return bmdModeHD1080i6000;\n        case core::video_format::x1080p2500:\n            return bmdModeHD1080p25;\n        case core::video_format::x1080p2997:\n            return bmdModeHD1080p2997;\n        case core::video_format::x1080p3000:\n            return bmdModeHD1080p30;\n        case core::video_format::x1080p5000:\n            return bmdModeHD1080p50;\n        case core::video_format::x1080p5994:\n            return bmdModeHD1080p5994;\n        case core::video_format::x1080p6000:\n            return bmdModeHD1080p6000;\n        case core::video_format::x1556p2398:\n            return bmdMode2k2398;\n        case core::video_format::x1556p2400:\n            return bmdMode2k24;\n        case core::video_format::x1556p2500:\n            return bmdMode2k25;\n        case core::video_format::x2160p2398:\n            return bmdMode4K2160p2398;\n        case core::video_format::x2160p2400:\n            return bmdMode4K2160p24;\n        case core::video_format::x2160p2500:\n            return bmdMode4K2160p25;\n        case core::video_format::x2160p2997:\n            return bmdMode4K2160p2997;\n        case core::video_format::x2160p3000:\n            return bmdMode4K2160p30;\n        case core::video_format::x2160p5000:\n            return bmdMode4K2160p50;\n        case core::video_format::x2160p5994:\n            return bmdMode4K2160p5994;\n        case core::video_format::x2160p6000:\n            return bmdMode4K2160p60;\n        case core::video_format::x4kDCIp2398:\n            return bmdMode4kDCI2398;\n        case core::video_format::x4kDCIp2400:\n            return bmdMode4kDCI24;\n        case core::video_format::x4kDCIp2500:\n            return bmdMode4kDCI25;\n        case core::video_format::x4kDCIp2997:\n            return bmdMode4kDCI2997;\n        case core::video_format::x4kDCIp3000:\n            return bmdMode4kDCI30;\n        case core::video_format::x4kDCIp5000:\n            return bmdMode4kDCI50;\n        case core::video_format::x4kDCIp5994:\n            return bmdMode4kDCI5994;\n        case core::video_format::x4kDCIp6000:\n            return bmdMode4kDCI60;\n        default:\n            return (BMDDisplayMode)ULONG_MAX;\n    }\n}\n\nstatic core::video_format get_caspar_video_format(BMDDisplayMode fmt)\n{\n    switch (fmt) {\n        case bmdModePAL:\n            return core::video_format::pal;\n        case bmdModeNTSC:\n            return core::video_format::ntsc;\n        case bmdModeHD720p50:\n            return core::video_format::x720p5000;\n        case bmdModeHD720p5994:\n            return core::video_format::x720p5994;\n        case bmdModeHD720p60:\n            return core::video_format::x720p6000;\n        case bmdModeHD1080p2398:\n            return core::video_format::x1080p2398;\n        case bmdModeHD1080p24:\n            return core::video_format::x1080p2400;\n        case bmdModeHD1080i50:\n            return core::video_format::x1080i5000;\n        case bmdModeHD1080i5994:\n            return core::video_format::x1080i5994;\n        case bmdModeHD1080i6000:\n            return core::video_format::x1080i6000;\n        case bmdModeHD1080p25:\n            return core::video_format::x1080p2500;\n        case bmdModeHD1080p2997:\n            return core::video_format::x1080p2997;\n        case bmdModeHD1080p30:\n            return core::video_format::x1080p3000;\n        case bmdModeHD1080p50:\n            return core::video_format::x1080p5000;\n        case bmdModeHD1080p5994:\n            return core::video_format::x1080p5994;\n        case bmdModeHD1080p6000:\n            return core::video_format::x1080p6000;\n        case bmdMode2k2398:\n            return core::video_format::x1556p2398;\n        case bmdMode2k24:\n            return core::video_format::x1556p2400;\n        case bmdMode2k25:\n            return core::video_format::x1556p2500;\n        case bmdMode4K2160p2398:\n            return core::video_format::x2160p2398;\n        case bmdMode4K2160p24:\n            return core::video_format::x2160p2400;\n        case bmdMode4K2160p25:\n            return core::video_format::x2160p2500;\n        case bmdMode4K2160p2997:\n            return core::video_format::x2160p2997;\n        case bmdMode4K2160p30:\n            return core::video_format::x2160p3000;\n        case bmdMode4K2160p50:\n            return core::video_format::x2160p5000;\n        case bmdMode4K2160p5994:\n            return core::video_format::x2160p5994;\n        case bmdMode4K2160p60:\n            return core::video_format::x2160p6000;\n        case bmdMode4kDCI2398:\n            return core::video_format::x4kDCIp2398;\n        case bmdMode4kDCI24:\n            return core::video_format::x4kDCIp2400;\n        case bmdMode4kDCI25:\n            return core::video_format::x4kDCIp2500;\n        case bmdMode4kDCI2997:\n            return core::video_format::x4kDCIp2997;\n        case bmdMode4kDCI30:\n            return core::video_format::x4kDCIp3000;\n        case bmdMode4kDCI50:\n            return core::video_format::x4kDCIp5000;\n        case bmdMode4kDCI5994:\n            return core::video_format::x4kDCIp5994;\n        case bmdMode4kDCI60:\n            return core::video_format::x4kDCIp6000;\n        default:\n            return core::video_format::invalid;\n    }\n}\n\nstatic std::wstring get_mode_name(const com_ptr<IDeckLinkDisplayMode>& mode)\n{\n    String mode_name;\n    if (SUCCEEDED(mode->GetName(&mode_name)))\n        return to_string(mode_name);\n    return L\"Unknown\";\n}\n\ntemplate <typename T>\nstatic std::wstring version(T iterator)\n{\n    auto info = iface_cast<IDeckLinkAPIInformation>(iterator);\n    if (info) {\n        String ver;\n        if (SUCCEEDED(info->GetString(BMDDeckLinkAPIVersion, &ver)))\n            return to_string(ver);\n    }\n    return L\"Not found\";\n}\n\nstatic com_ptr<IDeckLink> get_device(size_t device_index)\n{\n    auto pDecklinkIterator = create_iterator();\n\n    IDeckLink* current = nullptr;\n    for (int n = 1; pDecklinkIterator->Next(&current) == S_OK; ++n) {\n        auto decklink = wrap_raw<com_ptr>(current, true);\n\n        // Match index\n        if (n == device_index) {\n            return decklink;\n        }\n\n        // Match persistent id\n        int64_t id         = 0;\n        auto    attributes = iface_cast<IDeckLinkProfileAttributes>(decklink);\n        attributes->GetInt(BMDDeckLinkPersistentID, &id);\n        if (id != 0 && id == static_cast<int64_t>(device_index)) {\n            return decklink;\n        }\n    }\n\n    CASPAR_THROW_EXCEPTION(user_error() << msg_info(\"Decklink device \" + std::to_string(device_index) + \" not found.\"));\n}\n\ntemplate <typename T>\nstatic std::wstring get_model_name(const T& device)\n{\n    String pModelName;\n    if (SUCCEEDED(device->GetModelName(&pModelName)))\n        return to_string(pModelName);\n    return L\"Unknown\";\n}\n\nclass reference_signal_detector\n{\n    com_iface_ptr<IDeckLinkOutput> output_;\n    BMDReferenceStatus             last_reference_status_ = static_cast<BMDReferenceStatus>(-1);\n\n  public:\n    reference_signal_detector(const com_iface_ptr<IDeckLinkOutput>& output)\n        : output_(output)\n    {\n    }\n\n    template <typename Print>\n    void detect_change(const Print& print)\n    {\n        BMDReferenceStatus reference_status;\n\n        if (output_->GetReferenceStatus(&reference_status) != S_OK) {\n            CASPAR_LOG(error) << print() << L\" Reference signal: failed while querying status\";\n        } else if (reference_status != last_reference_status_) {\n            last_reference_status_ = reference_status;\n\n            if (reference_status == 0)\n                CASPAR_LOG(info) << print() << L\" Reference signal: not detected.\";\n            else if (reference_status & bmdReferenceNotSupportedByHardware)\n                CASPAR_LOG(info) << print() << L\" Reference signal: not supported by hardware.\";\n            else if (reference_status & bmdReferenceLocked)\n                CASPAR_LOG(info) << print() << L\" Reference signal: locked.\";\n            else\n                CASPAR_LOG(info) << print() << L\" Reference signal: Unhandled enum bitfield: \" << reference_status;\n        }\n    }\n};\n\n}} // namespace caspar::decklink\n"
  },
  {
    "path": "src/modules/ffmpeg/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (ffmpeg)\n\nset(SOURCES\n\tproducer/av_producer.cpp\n\tproducer/av_producer.h\n\tproducer/av_input.cpp\n\tproducer/av_input.h\n\tproducer/ffmpeg_producer.cpp\n\tproducer/ffmpeg_producer.h\n\tconsumer/ffmpeg_consumer.cpp\n\tconsumer/ffmpeg_consumer.h\n\n\tutil/av_util.cpp\n\tutil/av_util.h\n\tutil/audio_resampler.cpp\n\tutil/audio_resampler.h\n\tutil/av_assert.h\n\n\tffmpeg.cpp\n\tffmpeg.h\n\tStdAfx.h\n)\n\ncasparcg_add_module_project(ffmpeg\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"ffmpeg::init\"\n\tUNINIT_FUNCTION \"ffmpeg::uninit\"\n)\n\ntarget_include_directories(ffmpeg PRIVATE\n    ${FFMPEG_INCLUDE_PATH}\n    )\ntarget_precompile_headers(ffmpeg PRIVATE \"StdAfx.h\")\n\nset_target_properties(ffmpeg PROPERTIES FOLDER modules)\nsource_group(sources ./*)\nsource_group(sources\\\\consumer ./consumer/.*)\nsource_group(sources\\\\producer ./producer/.*)\nsource_group(sources\\\\util ./util/.*)\n\nif (MSVC)\n\t# target_link_libraries(ffmpeg\n\t# )\nelse()\n\ttarget_link_libraries(ffmpeg PRIVATE\n\t\t\t${FFMPEG_LIBRARIES}\n\t)\nendif()\n"
  },
  {
    "path": "src/modules/ffmpeg/StdAfx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include <algorithm>\n#include <atomic>\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/exception/all.hpp>\n#include <boost/exception/exception.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/format.hpp>\n#include <boost/lexical_cast.hpp>\n#include <boost/range/algorithm/rotate.hpp>\n#include <boost/rational.hpp>\n#include <cinttypes>\n#include <common/compiler/vs/disable_silly_warnings.h>\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/log.h>\n#include <common/memory.h>\n#include <common/os/filesystem.h>\n#include <common/param.h>\n#include <common/scope_exit.h>\n#include <condition_variable>\n#include <core/consumer/frame_consumer.h>\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/pixel_format.h>\n#include <core/fwd.h>\n#include <core/producer/frame_producer.h>\n#include <core/video_format.h>\n#include <deque>\n#include <exception>\n#include <functional>\n#include <memory>\n#include <mutex>\n#include <optional>\n#include <queue>\n#include <set>\n#include <string>\n#include <tbb/concurrent_queue.h>\n#include <thread>\n#include <vector>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavcodec/avcodec.h>\n#include <libavdevice/avdevice.h>\n#include <libavfilter/avfilter.h>\n#include <libavfilter/buffersink.h>\n#include <libavfilter/buffersrc.h>\n#include <libavformat/avformat.h>\n#include <libavutil/avutil.h>\n#include <libavutil/frame.h>\n#include <libavutil/opt.h>\n#include <libavutil/pixfmt.h>\n#include <libavutil/samplefmt.h>\n#include <libavutil/timecode.h>\n#include <libswscale/swscale.h>\n}\n"
  },
  {
    "path": "src/modules/ffmpeg/consumer/ffmpeg_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"ffmpeg_consumer.h\"\n\n#include \"../util/av_assert.h\"\n#include \"../util/av_util.h\"\n\n#include <common/bit_depth.h>\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/executor.h>\n#include <common/future.h>\n#include <common/memory.h>\n#include <common/scope_exit.h>\n#include <common/timer.h>\n\n#include <core/consumer/channel_info.h>\n#include <core/frame/frame.h>\n#include <core/video_format.h>\n\n#if defined(__GNUC__) && __GNUC__ == 14\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n#endif\n#include <boost/algorithm/string.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/format.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/regex.hpp>\n#if defined(__GNUC__) && __GNUC__ == 14\n#pragma GCC diagnostic pop\n#endif\n\n#include <boost/crc.hpp>\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n#include <libavfilter/avfilter.h>\n#include <libavfilter/buffersink.h>\n#include <libavfilter/buffersrc.h>\n#include <libavformat/avformat.h>\n#include <libavutil/channel_layout.h>\n#include <libavutil/opt.h>\n#include <libavutil/pixfmt.h>\n#include <libavutil/samplefmt.h>\n}\n\n#include <tbb/concurrent_queue.h>\n#include <tbb/parallel_for.h>\n#include <tbb/parallel_invoke.h>\n\n#include <memory>\n#include <optional>\n#include <thread>\n\nnamespace caspar { namespace ffmpeg {\n\n// TODO multiple output streams\n// TODO multiple output files\n// TODO run video filter, video encoder, audio filter, audio encoder in separate threads.\n// TODO realtime with smaller buffer?\n\nstruct Stream\n{\n    std::shared_ptr<AVFilterGraph> graph  = nullptr;\n    AVFilterContext*               sink   = nullptr;\n    AVFilterContext*               source = nullptr;\n\n    std::shared_ptr<AVCodecContext> enc = nullptr;\n    AVStream*                       st  = nullptr;\n\n    Stream(AVFormatContext*                    oc,\n           std::string                         suffix,\n           AVCodecID                           codec_id,\n           const core::video_format_desc&      format_desc,\n           bool                                realtime,\n           common::bit_depth                   depth,\n           std::map<std::string, std::string>& options)\n    {\n        std::map<std::string, std::string> stream_options;\n\n        {\n            auto tmp = std::move(options);\n            for (auto& p : tmp) {\n                if (boost::algorithm::ends_with(p.first, suffix)) {\n                    const auto key = p.first.substr(0, p.first.size() - suffix.size());\n                    stream_options.emplace(key, std::move(p.second));\n                } else {\n                    options.insert(std::move(p));\n                }\n            }\n        }\n\n        std::string filter_spec = \"\";\n        {\n            const auto it = stream_options.find(\"filter\");\n            if (it != stream_options.end()) {\n                filter_spec = std::move(it->second);\n                stream_options.erase(it);\n            }\n        }\n\n        auto codec = avcodec_find_encoder(codec_id);\n        {\n            const auto it = stream_options.find(\"codec\");\n            if (it != stream_options.end()) {\n                codec = avcodec_find_encoder_by_name(it->second.c_str());\n                stream_options.erase(it);\n            }\n        }\n\n        if (!codec) {\n            FF_RET(AVERROR(EINVAL), \"avcodec_find_encoder\");\n        }\n\n        AVFilterInOut* outputs = nullptr;\n        AVFilterInOut* inputs  = nullptr;\n\n        CASPAR_SCOPE_EXIT\n        {\n            avfilter_inout_free(&inputs);\n            avfilter_inout_free(&outputs);\n        };\n\n        graph = std::shared_ptr<AVFilterGraph>(avfilter_graph_alloc(),\n                                               [](AVFilterGraph* ptr) { avfilter_graph_free(&ptr); });\n\n        if (!graph) {\n            FF_RET(AVERROR(ENOMEM), \"avfilter_graph_alloc\");\n        }\n\n        if (codec->type == AVMEDIA_TYPE_VIDEO) {\n            if (filter_spec.empty()) {\n                filter_spec = \"null\";\n            }\n        } else {\n            if (filter_spec.empty()) {\n                filter_spec = \"anull\";\n            }\n        }\n\n        FF(avfilter_graph_parse2(graph.get(), filter_spec.c_str(), &inputs, &outputs));\n\n        {\n            auto cur = inputs;\n\n            if (!cur || cur->next) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter graph input count\"));\n            }\n\n            if (codec->type == AVMEDIA_TYPE_VIDEO) {\n                const auto sar = boost::rational<int>(format_desc.square_width, format_desc.square_height) /\n                                 boost::rational<int>(format_desc.width, format_desc.height);\n\n                const auto pix_fmt = (depth == common::bit_depth::bit8) ? AV_PIX_FMT_BGRA : AV_PIX_FMT_BGRA64LE;\n\n                auto args = (boost::format(\"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:sar=%d/%d:frame_rate=%d/%d\") %\n                             format_desc.width % format_desc.height % pix_fmt % format_desc.duration %\n                             (format_desc.time_scale * format_desc.field_count) % sar.numerator() % sar.denominator() %\n                             (format_desc.framerate.numerator() * format_desc.field_count) %\n                             format_desc.framerate.denominator())\n                                .str();\n                auto name = (boost::format(\"in_%d\") % 0).str();\n\n                FF(avfilter_graph_create_filter(\n                    &source, avfilter_get_by_name(\"buffer\"), name.c_str(), args.c_str(), nullptr, graph.get()));\n                FF(avfilter_link(source, 0, cur->filter_ctx, cur->pad_idx));\n            } else if (codec->type == AVMEDIA_TYPE_AUDIO) {\n                auto args = (boost::format(\"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%#x\") % 1 %\n                             format_desc.audio_sample_rate % format_desc.audio_sample_rate % AV_SAMPLE_FMT_S32 %\n                             get_channel_layout_mask_for_channels(format_desc.audio_channels))\n                                .str();\n                auto name = (boost::format(\"in_%d\") % 0).str();\n\n                FF(avfilter_graph_create_filter(\n                    &source, avfilter_get_by_name(\"abuffer\"), name.c_str(), args.c_str(), nullptr, graph.get()));\n                FF(avfilter_link(source, 0, cur->filter_ctx, cur->pad_idx));\n            } else {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter input media type\"));\n            }\n        }\n\n        if (codec->type == AVMEDIA_TYPE_VIDEO) {\n            sink = FFMEM(avfilter_graph_alloc_filter(graph.get(), avfilter_get_by_name(\"buffersink\"), \"out\"));\n\n            // TODO codec->profiles\n            // TODO FF(av_opt_set_int_list(sink, \"framerates\", codec->supported_framerates, { 0, 0 },\n            // AV_OPT_SEARCH_CHILDREN));\n#if LIBAVUTIL_VERSION_MAJOR >= 60 // FFmpeg 8\n            const void* pix_fmts;\n            int         nb_pix_fmts = 0;\n            FF(avcodec_get_supported_config(nullptr, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, &pix_fmts, &nb_pix_fmts));\n\n            FF(av_opt_set_array(sink,\n                                \"pixel_formats\",\n                                AV_OPT_SEARCH_CHILDREN | AV_OPT_ARRAY_REPLACE,\n                                0,\n                                nb_pix_fmts,\n                                AV_OPT_TYPE_PIXEL_FMT,\n                                pix_fmts));\n#else\n            FF(av_opt_set_int_list(sink, \"pix_fmts\", codec->pix_fmts, -1, AV_OPT_SEARCH_CHILDREN));\n#endif\n\n        } else if (codec->type == AVMEDIA_TYPE_AUDIO) {\n            sink = FFMEM(avfilter_graph_alloc_filter(graph.get(), avfilter_get_by_name(\"abuffersink\"), \"out\"));\n            // TODO codec->profiles\n\n#if LIBAVUTIL_VERSION_MAJOR >= 60 // FFmpeg 8\n            const void* sample_fmts;\n            int         nb_sample_fmts = 0;\n            FF(avcodec_get_supported_config(\n                nullptr, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, &sample_fmts, &nb_sample_fmts));\n\n            FF(av_opt_set_array(sink,\n                                \"sample_formats\",\n                                AV_OPT_SEARCH_CHILDREN | AV_OPT_ARRAY_REPLACE,\n                                0,\n                                nb_sample_fmts,\n                                AV_OPT_TYPE_SAMPLE_FMT,\n                                sample_fmts));\n\n            const void* sample_rates;\n            int         nb_sample_rates = 0;\n            FF(avcodec_get_supported_config(\n                nullptr, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0, &sample_rates, &nb_sample_rates));\n\n            FF(av_opt_set_array(sink,\n                                \"samplerates\",\n                                AV_OPT_SEARCH_CHILDREN | AV_OPT_ARRAY_REPLACE,\n                                0,\n                                nb_sample_rates,\n                                AV_OPT_TYPE_INT,\n                                sample_rates));\n#else\n            FF(av_opt_set_int_list(sink, \"sample_fmts\", codec->sample_fmts, -1, AV_OPT_SEARCH_CHILDREN));\n            FF(av_opt_set_int_list(sink, \"sample_rates\", codec->supported_samplerates, 0, AV_OPT_SEARCH_CHILDREN));\n#endif\n\n            // TODO: need to translate codec->ch_layouts into something that can be passed via av_opt_set_*\n            // FF(av_opt_set_chlayout(sink, \"ch_layouts\", codec->ch_layouts, AV_OPT_SEARCH_CHILDREN));\n\n        } else {\n            CASPAR_THROW_EXCEPTION(ffmpeg_error_t()\n                                   << boost::errinfo_errno(EINVAL) << msg_info_t(\"invalid output media type\"));\n        }\n\n        FF(avfilter_init_str(sink, nullptr));\n\n        {\n            const auto cur = outputs;\n\n            if (!cur || cur->next) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter graph output count\"));\n            }\n\n            if (avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx) != codec->type) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter output media type\"));\n            }\n\n            FF(avfilter_link(cur->filter_ctx, cur->pad_idx, sink, 0));\n        }\n\n        FF(avfilter_graph_config(graph.get(), nullptr));\n\n        st = avformat_new_stream(oc, nullptr);\n        if (!st) {\n            FF_RET(AVERROR(ENOMEM), \"avformat_new_stream\");\n        }\n\n        enc = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(codec),\n                                              [](AVCodecContext* ptr) { avcodec_free_context(&ptr); });\n\n        if (!enc) {\n            FF_RET(AVERROR(ENOMEM), \"avcodec_alloc_context3\")\n        }\n\n        if (codec->type == AVMEDIA_TYPE_VIDEO) {\n            st->time_base = av_inv_q(av_buffersink_get_frame_rate(sink));\n\n            // Ensure the frame_rate is set in a way that rtmp will find it\n            st->avg_frame_rate = av_buffersink_get_frame_rate(sink);\n\n            enc->width               = av_buffersink_get_w(sink);\n            enc->height              = av_buffersink_get_h(sink);\n            enc->framerate           = av_buffersink_get_frame_rate(sink);\n            enc->sample_aspect_ratio = av_buffersink_get_sample_aspect_ratio(sink);\n            enc->time_base           = st->time_base;\n            enc->pix_fmt             = static_cast<AVPixelFormat>(av_buffersink_get_format(sink));\n        } else if (codec->type == AVMEDIA_TYPE_AUDIO) {\n            st->time_base = {1, av_buffersink_get_sample_rate(sink)};\n\n            enc->sample_fmt  = static_cast<AVSampleFormat>(av_buffersink_get_format(sink));\n            enc->sample_rate = av_buffersink_get_sample_rate(sink);\n            enc->time_base   = st->time_base;\n\n            FF(av_buffersink_get_ch_layout(sink, &enc->ch_layout));\n\n        } else {\n            // TODO\n        }\n\n        if (realtime && codec->capabilities & AV_CODEC_CAP_SLICE_THREADS) {\n            enc->thread_type = FF_THREAD_SLICE;\n        }\n\n        if (oc->oformat->flags & AVFMT_GLOBALHEADER) {\n            enc->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;\n        }\n\n        auto dict = to_dict(std::move(stream_options));\n        CASPAR_SCOPE_EXIT { av_dict_free(&dict); };\n        FF(avcodec_open2(enc.get(), codec, &dict));\n        for (auto& p : to_map(&dict)) {\n            options[p.first] = p.second + suffix;\n        }\n\n        FF(avcodec_parameters_from_context(st->codecpar, enc.get()));\n\n        if (codec->type == AVMEDIA_TYPE_AUDIO && !(codec->capabilities & AV_CODEC_CAP_VARIABLE_FRAME_SIZE)) {\n            av_buffersink_set_frame_size(sink, enc->frame_size);\n        }\n    }\n\n    void send(std::tuple<core::const_frame, std::int64_t, std::int64_t>& data,\n              const core::video_format_desc&                             format_desc,\n              std::function<void(std::shared_ptr<AVPacket>)>             cb)\n    {\n        std::shared_ptr<AVFrame>  frame;\n        std::shared_ptr<AVPacket> pkt;\n\n        const auto [in_frame, video_pts, audio_pts] = data;\n\n        if (in_frame) {\n            if (enc->codec_type == AVMEDIA_TYPE_VIDEO) {\n                frame      = make_av_video_frame(in_frame, format_desc);\n                frame->pts = video_pts;\n            } else if (enc->codec_type == AVMEDIA_TYPE_AUDIO) {\n                frame      = make_av_audio_frame(in_frame, format_desc);\n                frame->pts = audio_pts;\n            } else {\n                // TODO\n            }\n            FF(av_buffersrc_write_frame(source, frame.get()));\n        } else {\n            FF(av_buffersrc_close(source, AV_NOPTS_VALUE, 0));\n        }\n\n        while (true) {\n            pkt     = alloc_packet();\n            int ret = avcodec_receive_packet(enc.get(), pkt.get());\n\n            if (ret == AVERROR(EAGAIN)) {\n                frame = alloc_frame();\n                ret   = av_buffersink_get_frame(sink, frame.get());\n                if (ret == AVERROR(EAGAIN)) {\n                    return;\n                }\n                if (ret == AVERROR_EOF) {\n                    FF(avcodec_send_frame(enc.get(), nullptr));\n                } else {\n                    FF_RET(ret, \"av_buffersink_get_frame\");\n                    FF(avcodec_send_frame(enc.get(), frame.get()));\n                }\n            } else if (ret == AVERROR_EOF) {\n                return;\n            } else {\n                FF_RET(ret, \"avcodec_receive_packet\");\n                pkt->stream_index = st->index;\n                av_packet_rescale_ts(pkt.get(), enc->time_base, st->time_base);\n                cb(std::move(pkt));\n            }\n        }\n    }\n};\n\nstruct ffmpeg_consumer : public core::frame_consumer\n{\n    core::monitor::state    state_;\n    mutable std::mutex      state_mutex_;\n    int                     channel_index_ = -1;\n    core::video_format_desc format_desc_;\n    bool                    realtime_ = false;\n    std::int64_t            video_pts = 0;\n    std::int64_t            audio_pts = 0;\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n\n    std::string path_;\n    std::string args_;\n\n    std::exception_ptr exception_;\n    std::mutex         exception_mutex_;\n\n    tbb::concurrent_bounded_queue<std::tuple<core::const_frame, std::int64_t, std::int64_t>> frame_buffer_;\n    std::thread                                                                              frame_thread_;\n\n    common::bit_depth depth_;\n\n  public:\n    ffmpeg_consumer(std::string path, std::string args, bool realtime, common::bit_depth depth)\n        : channel_index_([&] {\n            boost::crc_16_type result;\n            result.process_bytes(path.data(), path.length());\n            return result.checksum();\n        }())\n        , realtime_(realtime)\n        , path_(std::move(path))\n        , args_(std::move(args))\n        , depth_(depth)\n    {\n        state_[\"file/path\"] = u8(path_);\n\n        frame_buffer_.set_capacity(realtime_ ? 1 : 64);\n\n        diagnostics::register_graph(graph_);\n        graph_->set_color(\"frame-time\", diagnostics::color(0.1f, 1.0f, 0.1f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"input\", diagnostics::color(0.7f, 0.4f, 0.4f));\n    }\n\n    ~ffmpeg_consumer()\n    {\n        if (frame_thread_.joinable()) {\n            frame_buffer_.push({core::const_frame{}, -1, -1});\n            frame_thread_.join();\n        }\n    }\n\n    // frame consumer\n\n    void initialize(const core::video_format_desc& format_desc,\n                    const core::channel_info&      channel_info,\n                    int                            port_index) override\n    {\n        if (frame_thread_.joinable()) {\n            CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(\"Cannot reinitialize ffmpeg-consumer.\"));\n        }\n\n        format_desc_   = format_desc;\n        channel_index_ = channel_info.index;\n\n        graph_->set_text(print());\n\n        frame_thread_ = std::thread([=, this] {\n            try {\n                std::map<std::string, std::string> options;\n                {\n                    static boost::regex opt_exp(\"-(?<NAME>[^\\\\s]+)(\\\\s+(?<VALUE>[^\\\\s]+))?\");\n                    for (auto it = boost::sregex_iterator(args_.begin(), args_.end(), opt_exp);\n                         it != boost::sregex_iterator();\n                         ++it) {\n                        options[(*it)[\"NAME\"].str().c_str()] =\n                            (*it)[\"VALUE\"].matched ? (*it)[\"VALUE\"].str().c_str() : \"\";\n                    }\n                }\n\n                boost::filesystem::path full_path = path_;\n\n                static boost::regex prot_exp(\"^.+:.*\");\n                if (!boost::regex_match(path_, prot_exp)) {\n                    if (!full_path.is_absolute()) {\n                        full_path = u8(env::media_folder()) + path_;\n                    }\n\n                    // TODO -y?\n                    if (boost::filesystem::exists(full_path)) {\n                        boost::filesystem::remove(full_path);\n                    }\n\n                    boost::filesystem::create_directories(full_path.parent_path());\n                }\n\n                AVFormatContext* oc = nullptr;\n\n                {\n                    std::string format;\n                    {\n                        const auto format_it = options.find(\"format\");\n                        if (format_it != options.end()) {\n                            format = std::move(format_it->second);\n                            options.erase(format_it);\n                        }\n                    }\n\n                    FF(avformat_alloc_output_context2(\n                        &oc, nullptr, !format.empty() ? format.c_str() : nullptr, path_.c_str()));\n                }\n\n                CASPAR_SCOPE_EXIT { avformat_free_context(oc); };\n\n                std::optional<Stream> video_stream;\n                if (oc->oformat->video_codec != AV_CODEC_ID_NONE) {\n                    if (oc->oformat->video_codec == AV_CODEC_ID_H264 && options.find(\"preset:v\") == options.end()) {\n                        options[\"preset:v\"] = \"veryfast\";\n                    }\n                    video_stream.emplace(oc, \":v\", oc->oformat->video_codec, format_desc, realtime_, depth_, options);\n\n                    {\n                        std::lock_guard<std::mutex> lock(state_mutex_);\n                        state_[\"file/fps\"] = av_q2d(av_buffersink_get_frame_rate(video_stream->sink));\n                    }\n                }\n\n                std::optional<Stream> audio_stream;\n                if (oc->oformat->audio_codec != AV_CODEC_ID_NONE) {\n                    audio_stream.emplace(oc, \":a\", oc->oformat->audio_codec, format_desc, realtime_, depth_, options);\n                }\n\n                if (!(oc->oformat->flags & AVFMT_NOFILE)) {\n                    // TODO (fix) interrupt_cb\n                    auto dict = to_dict(std::move(options));\n                    CASPAR_SCOPE_EXIT { av_dict_free(&dict); };\n                    FF(avio_open2(&oc->pb, full_path.string().c_str(), AVIO_FLAG_WRITE, nullptr, &dict));\n                    options = to_map(&dict);\n                }\n\n                {\n                    auto dict = to_dict(std::move(options));\n                    CASPAR_SCOPE_EXIT { av_dict_free(&dict); };\n                    FF(avformat_write_header(oc, &dict));\n                    options = to_map(&dict);\n                }\n\n                {\n                    for (auto& p : options) {\n                        CASPAR_LOG(warning) << print() << \" Unused option \" << p.first << \"=\" << p.second;\n                    }\n                }\n\n                tbb::concurrent_bounded_queue<std::shared_ptr<AVPacket>> packet_buffer;\n                packet_buffer.set_capacity(realtime_ ? 1 : 128);\n                auto packet_thread = std::thread([&] {\n                    try {\n                        CASPAR_SCOPE_EXIT\n                        {\n                            if (!(oc->oformat->flags & AVFMT_NOFILE)) {\n                                FF(avio_closep(&oc->pb));\n                            }\n                        };\n\n                        std::map<int, int64_t> count;\n\n                        std::shared_ptr<AVPacket> pkt;\n                        while (true) {\n                            packet_buffer.pop(pkt);\n                            if (!pkt) {\n                                break;\n                            }\n                            count[pkt->stream_index] += 1;\n                            FF(av_interleaved_write_frame(oc, pkt.get()));\n                        }\n\n                        auto video_st = video_stream ? video_stream->st : nullptr;\n                        auto audio_st = audio_stream ? audio_stream->st : nullptr;\n\n                        if ((!video_st || count[video_st->index]) && (!audio_st || count[audio_st->index])) {\n                            FF(av_write_trailer(oc));\n                        }\n\n                    } catch (...) {\n                        CASPAR_LOG_CURRENT_EXCEPTION();\n                        // TODO\n                        packet_buffer.abort();\n                    }\n                });\n                CASPAR_SCOPE_EXIT\n                {\n                    if (packet_thread.joinable()) {\n                        // TODO Is nullptr needed?\n                        packet_buffer.push(nullptr);\n                        packet_buffer.abort();\n                        packet_thread.join();\n                    }\n                };\n\n                auto packet_cb = [&](std::shared_ptr<AVPacket>&& pkt) { packet_buffer.push(std::move(pkt)); };\n\n                std::int64_t frame_number = 0;\n                while (true) {\n                    {\n                        std::lock_guard<std::mutex> lock(state_mutex_);\n                        state_[\"file/frame\"] = frame_number++;\n                    }\n\n                    std::tuple<core::const_frame, std::int64_t, std::int64_t> data;\n                    frame_buffer_.pop(data);\n                    graph_->set_value(\"input\",\n                                      static_cast<double>(frame_buffer_.size() + 0.001) / frame_buffer_.capacity());\n\n                    caspar::timer frame_timer;\n                    tbb::parallel_invoke(\n                        [&] {\n                            if (video_stream) {\n                                video_stream->send(data, format_desc, packet_cb);\n                            }\n                        },\n                        [&] {\n                            if (audio_stream) {\n                                audio_stream->send(data, format_desc, packet_cb);\n                            }\n                        });\n                    graph_->set_value(\"frame-time\", frame_timer.elapsed() * format_desc.fps * 0.5);\n\n                    if (!std::get<0>(data)) {\n                        packet_buffer.push(nullptr);\n                        break;\n                    }\n                }\n\n                packet_thread.join();\n            } catch (...) {\n                std::lock_guard<std::mutex> lock(exception_mutex_);\n                exception_ = std::current_exception();\n            }\n        });\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        // TODO - field alignment\n\n        {\n            std::lock_guard<std::mutex> lock(exception_mutex_);\n            if (exception_ != nullptr) {\n                std::rethrow_exception(exception_);\n            }\n        }\n\n        if (!frame_buffer_.try_push({frame, video_pts, audio_pts})) {\n            graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n        }\n\n        video_pts += 1;\n        audio_pts += frame.audio_data().size() / format_desc_.audio_channels;\n\n        graph_->set_value(\"input\", static_cast<double>(frame_buffer_.size() + 0.001) / frame_buffer_.capacity());\n\n        return make_ready_future(true);\n    }\n\n    std::wstring print() const override { return L\"ffmpeg[\" + u16(path_) + L\"]\"; }\n\n    std::wstring name() const override { return L\"ffmpeg\"; }\n\n    bool has_synchronization_clock() const override { return false; }\n\n    int index() const override { return 100000 + channel_index_; }\n\n    core::monitor::state state() const override\n    {\n        std::lock_guard<std::mutex> lock(state_mutex_);\n        return state_;\n    }\n};\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info)\n{\n    if (params.size() < 2 || (!boost::iequals(params.at(0), L\"STREAM\") && !boost::iequals(params.at(0), L\"FILE\")))\n        return core::frame_consumer::empty();\n\n    auto                     path = u8(params.at(1));\n    std::vector<std::string> args;\n    for (auto n = 2; n < params.size(); ++n) {\n        args.emplace_back(u8(params[n]));\n    }\n    return spl::make_shared<ffmpeg_consumer>(\n        path, boost::join(args, \" \"), boost::iequals(params.at(0), L\"STREAM\"), channel_info.depth);\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info)\n{\n    return spl::make_shared<ffmpeg_consumer>(u8(ptree.get<std::wstring>(L\"path\", L\"\")),\n                                             u8(ptree.get<std::wstring>(L\"args\", L\"\")),\n                                             ptree.get(L\"realtime\", false),\n                                             channel_info.depth);\n}\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/consumer/ffmpeg_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/consumer/frame_consumer.h>\n#include <core/video_channel.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <vector>\n\nnamespace caspar { namespace ffmpeg {\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info);\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info);\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/ffmpeg.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"StdAfx.h\"\n\n#include \"ffmpeg.h\"\n\n#include \"consumer/ffmpeg_consumer.h\"\n#include \"producer/ffmpeg_producer.h\"\n\n#include <common/log.h>\n\n#include <core/module_dependencies.h>\n\n#include <mutex>\n\nextern \"C\" {\n#include <libavdevice/avdevice.h>\n#include <libavfilter/avfilter.h>\n#include <libavformat/avformat.h>\n#include <libavutil/avutil.h>\n}\n\nnamespace caspar { namespace ffmpeg {\nstatic void sanitize(uint8_t* line)\n{\n    while (*line != 0u) {\n        if (*line < 0x08 || (*line > 0x0D && *line < 0x20))\n            *line = '?';\n        line++;\n    }\n}\n\nvoid log_callback(void* ptr, int level, const char* fmt, va_list vl)\n{\n    static thread_local bool print_prefix_tss = true;\n\n    char     line[1024];\n    AVClass* avc = ptr != nullptr ? *static_cast<AVClass**>(ptr) : nullptr;\n    if (level > AV_LOG_DEBUG)\n        return;\n    line[0] = 0;\n\n#undef fprintf\n    if (print_prefix_tss && (avc != nullptr)) {\n        if (avc->parent_log_context_offset != 0) {\n            AVClass** parent =\n                *reinterpret_cast<AVClass***>(static_cast<uint8_t*>(ptr) + avc->parent_log_context_offset);\n            if ((parent != nullptr) && (*parent != nullptr))\n                std::snprintf(line, sizeof(line), \"[%s @ %p] \", (*parent)->item_name(parent), parent);\n        }\n        std::snprintf(line + strlen(line), sizeof(line) - strlen(line), \"[%s @ %p] \", avc->item_name(ptr), ptr);\n    }\n\n    std::vsnprintf(line + strlen(line), sizeof(line) - strlen(line), fmt, vl);\n\n    print_prefix_tss = (strlen(line) != 0u) && line[strlen(line) - 1] == '\\n';\n\n    sanitize(reinterpret_cast<uint8_t*>(line));\n\n    if (strstr(line, \"Assuming an incorrectly\") != nullptr) {\n        return;\n    }\n\n    try {\n        if (level == AV_LOG_VERBOSE)\n            CASPAR_LOG(trace) << L\"[ffmpeg] \" << line;\n        else if (level == AV_LOG_DEBUG)\n            CASPAR_LOG(trace) << L\"[ffmpeg] \" << line;\n        else if (level == AV_LOG_INFO)\n            CASPAR_LOG(info) << L\"[ffmpeg] \" << line;\n        else if (level == AV_LOG_WARNING)\n            CASPAR_LOG(warning) << L\"[ffmpeg] \" << line;\n        else if (level == AV_LOG_ERROR)\n            CASPAR_LOG(error) << L\"[ffmpeg] \" << line;\n        else if (level == AV_LOG_FATAL)\n            CASPAR_LOG(fatal) << L\"[ffmpeg] \" << line;\n        else\n            CASPAR_LOG(trace) << L\"[ffmpeg] \" << line;\n    } catch (...) {\n    }\n}\n\nvoid log_for_thread(void* ptr, int level, const char* fmt, va_list vl) { log_callback(ptr, level, fmt, vl); }\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    av_log_set_callback(log_for_thread);\n\n    avformat_network_init();\n    avdevice_register_all();\n\n    dependencies.consumer_registry->register_consumer_factory(L\"FFmpeg Consumer\", create_consumer);\n    dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"ffmpeg\", create_preconfigured_consumer);\n\n    dependencies.producer_registry->register_producer_factory(L\"FFmpeg Producer\", create_producer);\n}\n\nvoid uninit()\n{\n    // avfilter_uninit();\n    avformat_network_deinit();\n}\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/ffmpeg.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\nnamespace caspar { namespace ffmpeg {\n\nvoid                  init(const core::module_dependencies& dependencies);\nvoid                  uninit();\nstd::shared_ptr<void> temporary_enable_quiet_logging_for_thread(bool enable);\nvoid                  enable_quiet_logging_for_thread();\nbool                  is_logging_quiet_for_thread();\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/producer/av_input.cpp",
    "content": "#include \"av_input.h\"\n\n#include \"../util/av_assert.h\"\n#include \"../util/av_util.h\"\n\n#include <common/except.h>\n#include <common/os/thread.h>\n#include <common/param.h>\n#include <common/scope_exit.h>\n\n#include <boost/algorithm/string/case_conv.hpp>\n#include <boost/filesystem.hpp>\n\n#include <set>\n\nextern \"C\" {\n#include <libavformat/avformat.h>\n}\n\nnamespace caspar { namespace ffmpeg {\n\nInput::Input(const std::string& filename, std::shared_ptr<diagnostics::graph> graph, std::optional<bool> seekable)\n    : filename_(filename)\n    , graph_(graph)\n    , seekable_(seekable)\n{\n    graph_->set_color(\"seek\", diagnostics::color(1.0f, 0.5f, 0.0f));\n    graph_->set_color(\"input\", diagnostics::color(0.7f, 0.4f, 0.4f));\n\n    buffer_.set_capacity(256);\n    thread_ = boost::thread([this] {\n        try {\n            set_thread_name(L\"[ffmpeg::av_producer::Input]\");\n\n            int consecutive_enomem = 0;\n\n            while (true) {\n                auto packet = alloc_packet();\n                int  ret    = 0;\n\n                {\n                    std::unique_lock<std::mutex> lock(ic_mutex_);\n                    ic_cond_.wait(lock, [&] { return ic_ || abort_request_; });\n\n                    if (abort_request_) {\n                        break;\n                    }\n\n                    // TODO (perf) Non blocking av_read_frame when possible.\n                    ret = av_read_frame(ic_.get(), packet.get());\n                }\n\n                if (abort_request_) {\n                    break;\n                }\n\n                if (ret == AVERROR_EXIT) {\n                    break;\n                } else if (ret == AVERROR(EAGAIN)) {\n                    boost::this_thread::yield();\n                    continue;\n                } else if (ret == AVERROR_EOF) {\n                    eof_   = true;\n                    packet = nullptr;\n                } else if (ret == AVERROR(ENOMEM)) {\n                    // Transient memory allocation failure inside the demuxer; log and retry rather\n                    // than letting the exception escape and kill the read thread permanently.\n                    // Sleep briefly to give the system a chance to free memory before retrying.\n                    ++consecutive_enomem;\n                    if (consecutive_enomem == 1) {\n                        CASPAR_LOG(warning) << \"av_input[\" << filename_ << \"] av_read_frame: out of memory, retrying\";\n                    } else if (consecutive_enomem >= 20) {\n                        CASPAR_LOG(error) << \"av_input[\" << filename_\n                                          << \"] av_read_frame: too many consecutive out-of-memory errors, aborting\";\n\n                        // Pretend we reached EOF, to avoid the producer stalling expecting more packets\n                        eof_   = true;\n                        packet = nullptr;\n                        buffer_.push(std::move(packet));\n                        break;\n                    }\n                    boost::this_thread::sleep_for(boost::chrono::milliseconds(5));\n                    continue;\n                } else {\n                    consecutive_enomem = 0;\n                    FF_RET(ret, \"av_read_frame\");\n                }\n\n                consecutive_enomem = 0;\n                buffer_.push(std::move(packet));\n                graph_->set_value(\"input\", (static_cast<double>(buffer_.size()) / buffer_.capacity()));\n            }\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n            boost::this_thread::sleep_for(boost::chrono::milliseconds(5));\n        }\n    });\n}\n\nInput::~Input()\n{\n    graph_         = spl::shared_ptr<diagnostics::graph>();\n    abort_request_ = true;\n    ic_cond_.notify_all();\n\n    std::shared_ptr<AVPacket> packet;\n    while (buffer_.try_pop(packet))\n        ;\n\n    thread_.join();\n}\n\nint Input::interrupt_cb(void* ctx)\n{\n    auto input = reinterpret_cast<Input*>(ctx);\n    return input->abort_request_ ? 1 : 0;\n}\n\nbool Input::try_pop(std::shared_ptr<AVPacket>& packet)\n{\n    auto result = buffer_.try_pop(packet);\n    graph_->set_value(\"input\", (static_cast<double>(buffer_.size()) / buffer_.capacity()));\n    return result;\n}\n\nAVFormatContext*       Input::operator->() { return ic_.get(); }\nAVFormatContext* const Input::operator->() const { return ic_.get(); }\n\nvoid Input::abort()\n{\n    abort_request_ = true;\n    ic_cond_.notify_all();\n\n    std::shared_ptr<AVPacket> packet;\n    while (buffer_.try_pop(packet))\n        ;\n}\n\nvoid Input::reset()\n{\n    std::unique_lock<std::mutex> lock(ic_mutex_);\n    internal_reset();\n}\n\nvoid Input::internal_reset()\n{\n    AVDictionary* options = nullptr;\n    CASPAR_SCOPE_EXIT { av_dict_free(&options); };\n\n    static const std::set<std::wstring> PROTOCOLS_TREATED_AS_FORMATS = {L\"dshow\", L\"v4l2\", L\"iec61883\"};\n\n    const AVInputFormat* input_format = nullptr;\n    auto                 url_parts    = caspar::protocol_split(u16(filename_));\n    if (url_parts.first == L\"http\" || url_parts.first == L\"https\") {\n        FF(av_dict_set(&options, \"multiple_requests\", \"1\", 0)); // NOTE https://trac.ffmpeg.org/ticket/7034#comment:3\n        FF(av_dict_set(&options, \"reconnect\", \"1\", 0));\n        FF(av_dict_set(&options, \"reconnect_streamed\", \"1\", 0));\n        FF(av_dict_set(&options, \"reconnect_delay_max\", \"120\", 0));\n        FF(av_dict_set(&options, \"referer\", filename_.c_str(), 0)); // HTTP referer header\n    } else if (url_parts.first == L\"rtmp\" || url_parts.first == L\"rtmps\") {\n        FF(av_dict_set(&options, \"rtmp_live\", \"live\", 0));\n    } else if (PROTOCOLS_TREATED_AS_FORMATS.find(url_parts.first) != PROTOCOLS_TREATED_AS_FORMATS.end()) {\n        input_format = av_find_input_format(u8(url_parts.first).c_str());\n        filename_    = u8(url_parts.second);\n    }\n\n    if (seekable_) {\n        CASPAR_LOG(debug) << \"av_input[\" + filename_ + \"] Disabled seeking\";\n        FF(av_dict_set(&options, \"seekable\", *seekable_ ? \"1\" : \"0\", 0));\n    }\n\n    if (input_format == nullptr) {\n        // TODO (fix) timeout?\n        FF(av_dict_set(&options, \"rw_timeout\", \"60000000\", 0)); // 60 second IO timeout\n    }\n\n    AVFormatContext* ic             = avformat_alloc_context();\n    ic->interrupt_callback.callback = Input::interrupt_cb;\n    ic->interrupt_callback.opaque   = this;\n\n    FF(avformat_open_input(&ic, filename_.c_str(), input_format, &options));\n    auto ic2 = std::shared_ptr<AVFormatContext>(ic, [](AVFormatContext* ctx) { avformat_close_input(&ctx); });\n\n    for (auto& p : to_map(&options)) {\n        CASPAR_LOG(warning) << \"av_input[\" + filename_ + \"]\" << \" Unused option \" << p.first << \"=\" << p.second;\n    }\n\n    FF(avformat_find_stream_info(ic2.get(), nullptr));\n    ic_ = std::move(ic2);\n    ic_cond_.notify_all();\n}\n\nbool Input::eof() const { return eof_; }\n\nvoid Input::seek(int64_t ts, bool flush)\n{\n    std::unique_lock<std::mutex> lock(ic_mutex_);\n\n    if (ic_ && ts != ic_->start_time && ts != AV_NOPTS_VALUE) {\n        FF(avformat_seek_file(ic_.get(), -1, INT64_MIN, ts, ts, 0));\n    } else {\n        internal_reset();\n    }\n\n    if (flush) {\n        std::shared_ptr<AVPacket> packet;\n        while (buffer_.try_pop(packet))\n            ;\n    }\n    eof_ = false;\n\n    graph_->set_tag(diagnostics::tag_severity::INFO, \"seek\");\n}\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/producer/av_input.h",
    "content": "#pragma once\n\n#include <common/diagnostics/graph.h>\n\n#include <atomic>\n#include <condition_variable>\n#include <cstdint>\n#include <functional>\n#include <memory>\n#include <mutex>\n#include <optional>\n#include <queue>\n#include <string>\n\n#include <tbb/concurrent_queue.h>\n\n#include <boost/thread.hpp>\n\nstruct AVPacket;\nstruct AVFormatContext;\n\nnamespace caspar { namespace ffmpeg {\n\nclass Input\n{\n  public:\n    Input(const std::string& filename, std::shared_ptr<diagnostics::graph> graph, std::optional<bool> seekable);\n    ~Input();\n\n    static int interrupt_cb(void* ctx);\n\n    bool try_pop(std::shared_ptr<AVPacket>& packet);\n\n    AVFormatContext* operator->();\n\n    AVFormatContext* const operator->() const;\n\n    void reset();\n    void abort();\n    bool eof() const;\n    void seek(int64_t ts, bool flush = true);\n\n  private:\n    void internal_reset();\n\n    std::optional<bool> seekable_;\n\n    std::string                         filename_;\n    std::shared_ptr<diagnostics::graph> graph_;\n\n    mutable std::mutex               ic_mutex_;\n    std::shared_ptr<AVFormatContext> ic_;\n    std::condition_variable          ic_cond_;\n\n    tbb::concurrent_bounded_queue<std::shared_ptr<AVPacket>> buffer_;\n\n    std::atomic<bool> eof_{false};\n\n    std::atomic<bool> abort_request_{false};\n    boost::thread     thread_;\n};\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/producer/av_producer.cpp",
    "content": "#include \"av_producer.h\"\n\n#include \"av_input.h\"\n\n#include \"../util/av_assert.h\"\n#include \"../util/av_util.h\"\n\n#include <boost/exception/exception.hpp>\n#include <boost/format.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/range/algorithm/rotate.hpp>\n#include <boost/rational.hpp>\n#include <boost/thread.hpp>\n#include <boost/thread/condition_variable.hpp>\n#include <boost/thread/mutex.hpp>\n\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/os/thread.h>\n#include <common/scope_exit.h>\n#include <common/timer.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/monitor/monitor.h>\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n#include <libavfilter/avfilter.h>\n#include <libavfilter/buffersink.h>\n#include <libavfilter/buffersrc.h>\n#include <libavformat/avformat.h>\n#include <libavutil/avutil.h>\n#include <libavutil/channel_layout.h>\n#include <libavutil/error.h>\n#include <libavutil/opt.h>\n#include <libavutil/pixfmt.h>\n#include <libavutil/samplefmt.h>\n}\n\n#include <algorithm>\n#include <atomic>\n#include <deque>\n#include <iomanip>\n#include <memory>\n#include <queue>\n#include <sstream>\n#include <string>\n#include <thread>\n\nnamespace caspar { namespace ffmpeg {\n\nconst AVRational TIME_BASE_Q = {1, AV_TIME_BASE};\n\nstruct Frame\n{\n    std::shared_ptr<AVFrame> video;\n    std::shared_ptr<AVFrame> audio;\n    core::draw_frame         frame;\n    int64_t                  start_time  = AV_NOPTS_VALUE;\n    int64_t                  pts         = AV_NOPTS_VALUE;\n    int64_t                  duration    = 0;\n    int64_t                  frame_count = 0;\n};\n\nAVPixelFormat get_pix_fmt_with_alpha(AVPixelFormat fmt)\n{\n    switch (fmt) {\n        case AV_PIX_FMT_YUV420P:\n            return AV_PIX_FMT_YUVA420P;\n        case AV_PIX_FMT_YUV422P:\n            return AV_PIX_FMT_YUVA422P;\n        case AV_PIX_FMT_YUV444P:\n            return AV_PIX_FMT_YUVA444P;\n        default:\n            break;\n    }\n    return fmt;\n}\n\nconst AVCodec* get_decoder(AVCodecID codec_id)\n{\n    // enforce use of libvpx for vp8 and vp9 codecs to be able\n    // to decode webm files with alpha channel\n    const AVCodec* result = nullptr;\n    if (codec_id == AV_CODEC_ID_VP9)\n        result = avcodec_find_decoder_by_name(\"libvpx-vp9\");\n    else if (codec_id == AV_CODEC_ID_VP8)\n        result = avcodec_find_decoder_by_name(\"libvpx\");\n    return result != nullptr ? result : avcodec_find_decoder(codec_id);\n}\n\n// TODO (fix) Handle ts discontinuities.\n// TODO (feat) Forward options.\n\ncore::color_space get_color_space(const std::shared_ptr<AVFrame>& video)\n{\n    auto result = core::color_space::bt709;\n    if (video) {\n        switch (video->colorspace) {\n            case AVColorSpace::AVCOL_SPC_BT2020_NCL:\n                result = core::color_space::bt2020;\n                break;\n            case AVColorSpace::AVCOL_SPC_BT470BG:\n            case AVColorSpace::AVCOL_SPC_SMPTE170M:\n            case AVColorSpace::AVCOL_SPC_SMPTE240M:\n                result = core::color_space::bt601;\n                break;\n            default:\n                break;\n        }\n    }\n\n    return result;\n}\n\nclass Decoder\n{\n    Decoder(const Decoder&)            = delete;\n    Decoder& operator=(const Decoder&) = delete;\n\n    AVStream*         st       = nullptr;\n    int64_t           next_pts = AV_NOPTS_VALUE;\n    std::atomic<bool> eof      = {false};\n\n    std::queue<std::shared_ptr<AVPacket>> input;\n    mutable boost::mutex                  input_mutex;\n    boost::condition_variable             input_cond;\n    int                                   input_capacity = 2;\n\n    std::queue<std::shared_ptr<AVFrame>> output;\n    mutable boost::mutex                 output_mutex;\n    boost::condition_variable            output_cond;\n    int                                  output_capacity = 8;\n\n    boost::thread thread;\n\n  public:\n    std::shared_ptr<AVCodecContext> ctx;\n\n    Decoder() = default;\n\n    explicit Decoder(AVStream* stream)\n        : st(stream)\n    {\n        const auto codec = get_decoder(stream->codecpar->codec_id);\n\n        if (!codec) {\n            FF_RET(AVERROR_DECODER_NOT_FOUND, \"avcodec_find_decoder\");\n        }\n\n        ctx = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(codec),\n                                              [](AVCodecContext* ptr) { avcodec_free_context(&ptr); });\n\n        if (!ctx) {\n            FF_RET(AVERROR(ENOMEM), \"avcodec_alloc_context3\");\n        }\n\n        FF(avcodec_parameters_to_context(ctx.get(), stream->codecpar));\n\n        if (stream->metadata != NULL) {\n            auto entry = av_dict_get(stream->metadata, \"alpha_mode\", NULL, AV_DICT_MATCH_CASE);\n            if (entry != NULL && entry->value != NULL && *entry->value == '1')\n                ctx->pix_fmt = get_pix_fmt_with_alpha(ctx->pix_fmt);\n        }\n\n        int thread_count = env::properties().get(L\"configuration.ffmpeg.producer.threads\", 0);\n        FF(av_opt_set_int(ctx.get(), \"threads\", thread_count, 0));\n\n        ctx->pkt_timebase = stream->time_base;\n\n        if (ctx->codec_type == AVMEDIA_TYPE_VIDEO) {\n            ctx->framerate           = av_guess_frame_rate(nullptr, stream, nullptr);\n            ctx->sample_aspect_ratio = av_guess_sample_aspect_ratio(nullptr, stream, nullptr);\n        } else if (ctx->codec_type == AVMEDIA_TYPE_AUDIO) {\n        }\n\n        FF(avcodec_open2(ctx.get(), codec, nullptr));\n\n        thread = boost::thread([this]() {\n            try {\n                while (!thread.interruption_requested()) {\n                    auto av_frame = alloc_frame();\n                    auto ret      = avcodec_receive_frame(ctx.get(), av_frame.get());\n\n                    if (ret == AVERROR(EAGAIN)) {\n                        std::shared_ptr<AVPacket> packet;\n                        {\n                            boost::unique_lock<boost::mutex> lock(input_mutex);\n                            input_cond.wait(lock, [&]() { return !input.empty(); });\n                            packet = std::move(input.front());\n                            input.pop();\n                        }\n                        FF(avcodec_send_packet(ctx.get(), packet.get()));\n                    } else if (ret == AVERROR_EOF) {\n                        avcodec_flush_buffers(ctx.get());\n                        av_frame->pts = next_pts;\n                        next_pts      = AV_NOPTS_VALUE;\n                        eof           = true;\n\n                        {\n                            boost::unique_lock<boost::mutex> lock(output_mutex);\n                            output_cond.wait(lock, [&]() { return output.size() < output_capacity; });\n                            output.push(std::move(av_frame));\n                        }\n                    } else {\n                        FF_RET(ret, \"avcodec_receive_frame\");\n\n                        // TODO: Maybe Fixed in:\n                        // https://github.com/FFmpeg/FFmpeg/commit/33203a08e0a26598cb103508327a1dc184b27bc6\n                        // NOTE This is a workaround for DVCPRO HD.\n#if LIBAVCODEC_VERSION_MAJOR < 61\n                        if (av_frame->width > 1024 && av_frame->interlaced_frame) {\n                            av_frame->top_field_first = 1;\n                        }\n#else\n                        if (av_frame->width > 1024 && (av_frame->flags & AV_FRAME_FLAG_INTERLACED)) {\n                            av_frame->flags |= AV_FRAME_FLAG_TOP_FIELD_FIRST;\n                        }\n#endif\n\n                        // TODO (fix) is this always best?\n                        av_frame->pts = av_frame->best_effort_timestamp;\n\n                        auto duration_pts = av_frame->duration;\n                        if (duration_pts <= 0) {\n                            if (ctx->codec_type == AVMEDIA_TYPE_VIDEO) {\n#if LIBAVCODEC_VERSION_MAJOR < 62\n                                const int ticks_per_frame = ctx->ticks_per_frame;\n#else\n                                // https://github.com/FFmpeg/FFmpeg/commit/e930b834a928546f9cbc937f6633709053448232#diff-115616f8a2b59cab3aac4e7f4c8c31e69e94e7fcfa339b9f65b0bf34308aa80fR682\n                                const int ticks_per_frame =\n                                    (ctx->codec_descriptor && (ctx->codec_descriptor->props & AV_CODEC_PROP_FIELDS))\n                                        ? 2\n                                        : 1;\n#endif\n                                const auto ticks = av_stream_get_parser(st) ? av_stream_get_parser(st)->repeat_pict + 1\n                                                                            : ticks_per_frame;\n                                duration_pts     = static_cast<int64_t>(AV_TIME_BASE) * ctx->framerate.den * ticks /\n                                               ctx->framerate.num / ticks_per_frame;\n                                duration_pts = av_rescale_q(duration_pts, {1, AV_TIME_BASE}, st->time_base);\n                            } else if (ctx->codec_type == AVMEDIA_TYPE_AUDIO) {\n                                duration_pts = av_rescale_q(av_frame->nb_samples, {1, ctx->sample_rate}, st->time_base);\n                            }\n                        }\n\n                        if (duration_pts > 0) {\n                            next_pts = av_frame->pts + duration_pts;\n                        } else {\n                            next_pts = AV_NOPTS_VALUE;\n                        }\n\n                        {\n                            boost::unique_lock<boost::mutex> lock(output_mutex);\n                            output_cond.wait(lock, [&]() { return output.size() < output_capacity; });\n                            output.push(std::move(av_frame));\n                        }\n                    }\n                }\n            } catch (boost::thread_interrupted&) {\n                // Do nothing...\n            } catch (...) {\n                eof = true;\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        });\n    }\n\n    ~Decoder()\n    {\n        try {\n            if (thread.joinable()) {\n                thread.interrupt();\n                thread.join();\n            }\n        } catch (boost::thread_interrupted&) {\n            // Do nothing...\n        }\n    }\n\n    bool want_packet() const\n    {\n        if (eof) {\n            return false;\n        }\n\n        {\n            boost::lock_guard<boost::mutex> lock(input_mutex);\n            return input.size() < input_capacity;\n        }\n    }\n\n    void push(std::shared_ptr<AVPacket> packet)\n    {\n        if (eof) {\n            return;\n        }\n\n        {\n            boost::lock_guard<boost::mutex> lock(input_mutex);\n            input.push(std::move(packet));\n        }\n\n        input_cond.notify_all();\n    }\n\n    std::shared_ptr<AVFrame> pop()\n    {\n        std::shared_ptr<AVFrame> frame;\n\n        {\n            boost::lock_guard<boost::mutex> lock(output_mutex);\n\n            if (!output.empty()) {\n                frame = std::move(output.front());\n                output.pop();\n            }\n        }\n\n        if (frame) {\n            output_cond.notify_all();\n        } else if (eof) {\n            frame = alloc_frame();\n        }\n\n        return frame;\n    }\n};\n\nstruct Filter\n{\n    std::shared_ptr<AVFilterGraph>  graph;\n    AVFilterContext*                sink = nullptr;\n    std::map<int, AVFilterContext*> sources;\n    std::shared_ptr<AVFrame>        frame;\n    bool                            eof = false;\n\n    Filter() = default;\n\n    Filter(std::string                    filter_spec,\n           const Input&                   input,\n           std::map<int, Decoder>&        streams,\n           int64_t                        start_time,\n           AVMediaType                    media_type,\n           const core::video_format_desc& format_desc)\n    {\n        if (media_type == AVMEDIA_TYPE_VIDEO) {\n            if (filter_spec.empty()) {\n                filter_spec = \"null\";\n            }\n\n            auto deint = u8(\n                env::properties().get<std::wstring>(L\"configuration.ffmpeg.producer.auto-deinterlace\", L\"interlaced\"));\n\n            if (deint != \"none\") {\n                filter_spec += (boost::format(\",bwdif=mode=send_field:parity=auto:deint=%s\") % deint).str();\n            }\n\n            filter_spec += (boost::format(\",fps=fps=%d/%d:start_time=%f\") %\n                            (format_desc.framerate.numerator() * format_desc.field_count) %\n                            format_desc.framerate.denominator() % (static_cast<double>(start_time) / AV_TIME_BASE))\n                               .str();\n        } else if (media_type == AVMEDIA_TYPE_AUDIO) {\n            if (filter_spec.empty()) {\n                filter_spec = \"anull\";\n            }\n\n            // Find first audio stream to get a time_base for the first_pts calculation\n            AVRational tb = {1, format_desc.audio_sample_rate};\n            for (auto n = 0U; n < input->nb_streams; ++n) {\n                const auto st             = input->streams[n];\n                const auto codec_channels = st->codecpar->ch_layout.nb_channels;\n                if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_channels > 0) {\n                    tb = {1, st->codecpar->sample_rate};\n                    break;\n                }\n            }\n            filter_spec += (boost::format(\",aresample=async=1000:first_pts=%d:min_comp=0.01:osr=%d,\"\n                                          \"asetnsamples=n=1024:p=0\") %\n                            av_rescale_q(start_time, TIME_BASE_Q, tb) % format_desc.audio_sample_rate)\n                               .str();\n        }\n\n        AVFilterInOut* outputs = nullptr;\n        AVFilterInOut* inputs  = nullptr;\n\n        CASPAR_SCOPE_EXIT\n        {\n            avfilter_inout_free(&inputs);\n            avfilter_inout_free(&outputs);\n        };\n\n        int video_input_count = 0;\n        int audio_input_count = 0;\n        {\n            auto graph2 = avfilter_graph_alloc();\n            if (!graph2) {\n                FF_RET(AVERROR(ENOMEM), \"avfilter_graph_alloc\");\n            }\n\n            CASPAR_SCOPE_EXIT\n            {\n                avfilter_graph_free(&graph2);\n                avfilter_inout_free(&inputs);\n                avfilter_inout_free(&outputs);\n            };\n\n            FF(avfilter_graph_parse2(graph2, filter_spec.c_str(), &inputs, &outputs));\n\n            for (auto cur = inputs; cur; cur = cur->next) {\n                const auto type = avfilter_pad_get_type(cur->filter_ctx->input_pads, cur->pad_idx);\n                if (type == AVMEDIA_TYPE_VIDEO) {\n                    video_input_count += 1;\n                } else if (type == AVMEDIA_TYPE_AUDIO) {\n                    audio_input_count += 1;\n                }\n            }\n        }\n\n        std::vector<AVStream*> av_streams;\n        for (auto n = 0U; n < input->nb_streams; ++n) {\n            const auto st = input->streams[n];\n\n            const auto codec_channels = st->codecpar->ch_layout.nb_channels;\n            if (st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && codec_channels == 0) {\n                continue;\n            }\n\n            auto disposition = st->disposition;\n            if (!disposition || disposition == AV_DISPOSITION_DEFAULT) {\n                av_streams.push_back(st);\n            }\n        }\n\n        if (audio_input_count == 1) {\n            auto count = std::count_if(av_streams.begin(), av_streams.end(), [](auto s) {\n                return s->codecpar->codec_type == AVMEDIA_TYPE_AUDIO;\n            });\n\n            // TODO (fix) Use some form of stream meta data to do this.\n            // https://github.com/CasparCG/server/issues/833\n            if (count > 1) {\n                filter_spec = (boost::format(\"amerge=inputs=%d,\") % count).str() + filter_spec;\n            }\n        }\n\n        if (video_input_count == 1) {\n            std::stable_sort(av_streams.begin(), av_streams.end(), [](auto lhs, auto rhs) {\n                return lhs->codecpar->codec_type == AVMEDIA_TYPE_VIDEO && lhs->codecpar->height > rhs->codecpar->height;\n            });\n\n            std::vector<AVStream*> video_av_streams;\n            std::copy_if(av_streams.begin(), av_streams.end(), std::back_inserter(video_av_streams), [](auto s) {\n                return s->codecpar->codec_type == AVMEDIA_TYPE_VIDEO;\n            });\n\n            // TODO (fix) Use some form of stream meta data to do this.\n            // https://github.com/CasparCG/server/issues/832\n            if (video_av_streams.size() >= 2 &&\n                video_av_streams[0]->codecpar->height == video_av_streams[1]->codecpar->height) {\n                filter_spec = \"alphamerge,\" + filter_spec;\n            }\n        }\n\n        graph = std::shared_ptr<AVFilterGraph>(avfilter_graph_alloc(),\n                                               [](AVFilterGraph* ptr) { avfilter_graph_free(&ptr); });\n\n        if (!graph) {\n            FF_RET(AVERROR(ENOMEM), \"avfilter_graph_alloc\");\n        }\n\n        FF(avfilter_graph_parse2(graph.get(), filter_spec.c_str(), &inputs, &outputs));\n\n        // inputs\n        {\n            for (auto cur = inputs; cur; cur = cur->next) {\n                const auto type = avfilter_pad_get_type(cur->filter_ctx->input_pads, cur->pad_idx);\n                if (type != AVMEDIA_TYPE_VIDEO && type != AVMEDIA_TYPE_AUDIO) {\n                    CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                            << msg_info_t(\"only video and audio filters supported\"));\n                }\n\n                unsigned index = 0;\n\n                // TODO find stream based on link name\n                while (true) {\n                    if (index == av_streams.size()) {\n                        graph = nullptr;\n                        return;\n                    }\n                    if (av_streams.at(index)->codecpar->codec_type == type &&\n                        sources.find(static_cast<int>(index)) == sources.end()) {\n                        break;\n                    }\n                    index++;\n                }\n\n                index = av_streams.at(index)->index;\n\n                auto it = streams.find(index);\n                if (it == streams.end()) {\n                    it = streams.emplace(index, input->streams[index]).first;\n                }\n\n                auto st = it->second.ctx;\n\n                if (st->codec_type == AVMEDIA_TYPE_VIDEO) {\n                    auto args = (boost::format(\"video_size=%dx%d:pix_fmt=%d:time_base=%d/%d\") % st->width % st->height %\n                                 st->pix_fmt % st->pkt_timebase.num % st->pkt_timebase.den)\n                                    .str();\n                    auto name = (boost::format(\"in_%d\") % index).str();\n\n                    if (st->sample_aspect_ratio.num > 0 && st->sample_aspect_ratio.den > 0) {\n                        args +=\n                            (boost::format(\":sar=%d/%d\") % st->sample_aspect_ratio.num % st->sample_aspect_ratio.den)\n                                .str();\n                    }\n\n                    if (st->framerate.num > 0 && st->framerate.den > 0) {\n                        args += (boost::format(\":frame_rate=%d/%d\") % st->framerate.num % st->framerate.den).str();\n                    }\n\n                    AVFilterContext* source = nullptr;\n                    FF(avfilter_graph_create_filter(\n                        &source, avfilter_get_by_name(\"buffer\"), name.c_str(), args.c_str(), nullptr, graph.get()));\n                    FF(avfilter_link(source, 0, cur->filter_ctx, cur->pad_idx));\n                    sources.emplace(index, source);\n                } else if (st->codec_type == AVMEDIA_TYPE_AUDIO) {\n                    char channel_layout[128];\n                    FF(av_channel_layout_describe(&st->ch_layout, channel_layout, sizeof(channel_layout)));\n\n                    auto args = (boost::format(\"time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%#x\") %\n                                 st->pkt_timebase.num % st->pkt_timebase.den % st->sample_rate %\n                                 av_get_sample_fmt_name(st->sample_fmt) % channel_layout)\n                                    .str();\n                    auto name = (boost::format(\"in_%d\") % index).str();\n\n                    AVFilterContext* source = nullptr;\n                    FF(avfilter_graph_create_filter(\n                        &source, avfilter_get_by_name(\"abuffer\"), name.c_str(), args.c_str(), nullptr, graph.get()));\n                    FF(avfilter_link(source, 0, cur->filter_ctx, cur->pad_idx));\n                    sources.emplace(index, source);\n                } else {\n                    CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                            << msg_info_t(\"invalid filter input media type\"));\n                }\n            }\n        }\n\n        if (media_type == AVMEDIA_TYPE_VIDEO) {\n            sink = FFMEM(avfilter_graph_alloc_filter(graph.get(), avfilter_get_by_name(\"buffersink\"), \"out\"));\n\n            const AVPixelFormat pix_fmts[] = {AV_PIX_FMT_RGB24,\n                                              AV_PIX_FMT_BGR24,\n                                              AV_PIX_FMT_BGRA,\n                                              AV_PIX_FMT_ARGB,\n                                              AV_PIX_FMT_RGBA,\n                                              AV_PIX_FMT_ABGR,\n                                              AV_PIX_FMT_YUV444P,\n                                              AV_PIX_FMT_YUV444P10,\n                                              AV_PIX_FMT_YUV444P12,\n                                              AV_PIX_FMT_YUV422P,\n                                              AV_PIX_FMT_YUV422P10,\n                                              AV_PIX_FMT_YUV422P12,\n                                              AV_PIX_FMT_YUV420P,\n                                              AV_PIX_FMT_YUV420P10,\n                                              AV_PIX_FMT_YUV420P12,\n                                              AV_PIX_FMT_YUV410P,\n                                              AV_PIX_FMT_YUVA444P,\n                                              AV_PIX_FMT_YUVA422P,\n                                              AV_PIX_FMT_YUVA420P,\n                                              AV_PIX_FMT_UYVY422,\n                                              // bwdif needs planar rgb\n                                              AV_PIX_FMT_GBRP,\n                                              AV_PIX_FMT_GBRP10,\n                                              AV_PIX_FMT_GBRP12,\n                                              AV_PIX_FMT_GBRP16,\n                                              AV_PIX_FMT_GBRAP,\n                                              AV_PIX_FMT_GBRAP16,\n                                              AV_PIX_FMT_NONE};\n#if LIBAVUTIL_VERSION_MAJOR >= 60 // FFmpeg 8\n            FF(av_opt_set_array(sink,\n                                \"pixel_formats\",\n                                AV_OPT_SEARCH_CHILDREN | AV_OPT_ARRAY_REPLACE,\n                                0,\n                                FF_ARRAY_ELEMS(pix_fmts) - 1,\n                                AV_OPT_TYPE_PIXEL_FMT,\n                                pix_fmts));\n#else\n            FF(av_opt_set_int_list(sink, \"pix_fmts\", pix_fmts, -1, AV_OPT_SEARCH_CHILDREN));\n#endif\n        } else if (media_type == AVMEDIA_TYPE_AUDIO) {\n            sink = FFMEM(avfilter_graph_alloc_filter(graph.get(), avfilter_get_by_name(\"abuffersink\"), \"out\"));\n\n            const AVSampleFormat sample_fmts[]  = {AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE};\n            const int            sample_rates[] = {format_desc.audio_sample_rate, -1};\n\n            FF(av_opt_set_int(sink, \"all_channel_counts\", 1, AV_OPT_SEARCH_CHILDREN));\n\n#if LIBAVUTIL_VERSION_MAJOR >= 60 // FFmpeg 8\n            FF(av_opt_set_array(sink,\n                                \"sample_formats\",\n                                AV_OPT_SEARCH_CHILDREN | AV_OPT_ARRAY_REPLACE,\n                                0,\n                                FF_ARRAY_ELEMS(sample_fmts) - 1,\n                                AV_OPT_TYPE_SAMPLE_FMT,\n                                sample_fmts));\n            FF(av_opt_set_array(sink,\n                                \"samplerates\",\n                                AV_OPT_SEARCH_CHILDREN | AV_OPT_ARRAY_REPLACE,\n                                0,\n                                FF_ARRAY_ELEMS(sample_rates) - 1,\n                                AV_OPT_TYPE_INT,\n                                sample_rates));\n#else\n            FF(av_opt_set_int_list(sink, \"sample_fmts\", sample_fmts, -1, AV_OPT_SEARCH_CHILDREN));\n            FF(av_opt_set_int_list(sink, \"sample_rates\", sample_rates, -1, AV_OPT_SEARCH_CHILDREN));\n#endif\n        } else {\n            CASPAR_THROW_EXCEPTION(ffmpeg_error_t()\n                                   << boost::errinfo_errno(EINVAL) << msg_info_t(\"invalid output media type\"));\n        }\n\n        FF(avfilter_init_str(sink, nullptr));\n\n        // output\n        {\n            const auto cur = outputs;\n\n            if (!cur || cur->next) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter graph output count\"));\n            }\n\n            if (avfilter_pad_get_type(cur->filter_ctx->output_pads, cur->pad_idx) != media_type) {\n                CASPAR_THROW_EXCEPTION(ffmpeg_error_t() << boost::errinfo_errno(EINVAL)\n                                                        << msg_info_t(\"invalid filter output media type\"));\n            }\n\n            FF(avfilter_link(cur->filter_ctx, cur->pad_idx, sink, 0));\n        }\n\n        FF(avfilter_graph_config(graph.get(), nullptr));\n\n        CASPAR_LOG(debug) << avfilter_graph_dump(graph.get(), nullptr);\n    }\n\n    bool operator()(int nb_samples = -1)\n    {\n        if (frame || eof) {\n            return false;\n        }\n\n        if (!sink || sources.empty()) {\n            eof   = true;\n            frame = nullptr;\n            return true;\n        }\n\n        auto av_frame = alloc_frame();\n        auto ret      = nb_samples >= 0 ? av_buffersink_get_samples(sink, av_frame.get(), nb_samples)\n                                        : av_buffersink_get_frame(sink, av_frame.get());\n\n        if (ret == AVERROR(EAGAIN)) {\n            return false;\n        }\n        if (ret == AVERROR_EOF) {\n            eof   = true;\n            frame = nullptr;\n            return true;\n        }\n        FF_RET(ret, \"av_buffersink_get_frame\");\n        frame = std::move(av_frame);\n        return true;\n    }\n};\n\nstruct AVProducer::Impl\n{\n    caspar::core::monitor::state state_;\n    mutable boost::mutex         state_mutex_;\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n\n    const std::shared_ptr<core::frame_factory> frame_factory_;\n    const core::video_format_desc              format_desc_;\n    const AVRational                           format_tb_;\n    const std::string                          name_;\n    const std::string                          path_;\n\n    Input                  input_;\n    std::map<int, Decoder> decoders_;\n    Filter                 video_filter_;\n    Filter                 audio_filter_;\n\n    std::map<int, std::vector<AVFilterContext*>> sources_;\n\n    std::atomic<int64_t> start_{AV_NOPTS_VALUE};\n    std::atomic<int64_t> duration_{AV_NOPTS_VALUE};\n    std::atomic<int64_t> input_duration_{AV_NOPTS_VALUE};\n    std::atomic<int64_t> seek_{AV_NOPTS_VALUE};\n    std::atomic<bool>    loop_{false};\n\n    std::string afilter_;\n    std::string vfilter_;\n\n    int                              seekable_ = 2;\n    core::frame_geometry::scale_mode scale_mode_;\n    int64_t                          frame_count_    = 0;\n    bool                             frame_flush_    = true;\n    int64_t                          frame_time_     = AV_NOPTS_VALUE;\n    int64_t                          frame_duration_ = AV_NOPTS_VALUE;\n    core::draw_frame                 frame_;\n\n    std::deque<Frame>         buffer_;\n    mutable boost::mutex      buffer_mutex_;\n    boost::condition_variable buffer_cond_;\n    std::atomic<bool>         buffer_eof_{false};\n    int                       buffer_capacity_ = static_cast<int>(format_desc_.fps) / 4;\n\n    std::optional<caspar::executor> video_executor_;\n    std::optional<caspar::executor> audio_executor_;\n\n    int latency_ = 0;\n\n    boost::thread thread_;\n\n    Impl(std::shared_ptr<core::frame_factory> frame_factory,\n         core::video_format_desc              format_desc,\n         std::string                          name,\n         std::string                          path,\n         std::string                          vfilter,\n         std::string                          afilter,\n         std::optional<int64_t>               start,\n         std::optional<int64_t>               seek,\n         std::optional<int64_t>               duration,\n         bool                                 loop,\n         int                                  seekable,\n         core::frame_geometry::scale_mode     scale_mode)\n        : frame_factory_(frame_factory)\n        , format_desc_(format_desc)\n        , format_tb_({format_desc.duration, format_desc.time_scale * format_desc.field_count})\n        , name_(name)\n        , path_(path)\n        , input_(path, graph_, seekable >= 0 && seekable < 2 ? std::optional<bool>(false) : std::optional<bool>())\n        , start_(start ? av_rescale_q(*start, format_tb_, TIME_BASE_Q) : AV_NOPTS_VALUE)\n        , duration_(duration ? av_rescale_q(*duration, format_tb_, TIME_BASE_Q) : AV_NOPTS_VALUE)\n        , loop_(loop)\n        , afilter_(afilter)\n        , vfilter_(vfilter)\n        , seekable_(seekable)\n        , scale_mode_(scale_mode)\n        , video_executor_(L\"video-executor\")\n        , audio_executor_(L\"audio-executor\")\n    {\n        diagnostics::register_graph(graph_);\n        graph_->set_color(\"underflow\", diagnostics::color(0.6f, 0.3f, 0.9f));\n        graph_->set_color(\"frame-time\", diagnostics::color(0.0f, 1.0f, 0.0f));\n        graph_->set_color(\"decode-time\", diagnostics::color(0.0f, 1.0f, 1.0f));\n        graph_->set_color(\"buffer\", diagnostics::color(1.0f, 1.0f, 0.0f));\n\n        state_[\"file/name\"] = u8(name_);\n        state_[\"file/path\"] = u8(path_);\n        state_[\"loop\"]      = loop;\n        update_state();\n\n        CASPAR_LOG(debug) << print() << \" seekable: \" << seekable_;\n\n        thread_ = boost::thread([=, this] {\n            try {\n                run(seek);\n            } catch (boost::thread_interrupted&) {\n                // Do nothing...\n            } catch (ffmpeg::ffmpeg_error_t& ex) {\n                if (auto errn = boost::get_error_info<ffmpeg_errn_info>(ex)) {\n                    if (*errn == AVERROR_EXIT) {\n                        return;\n                    }\n                }\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        });\n    }\n\n    ~Impl()\n    {\n        input_.abort();\n\n        try {\n            if (thread_.joinable()) {\n                thread_.interrupt();\n                thread_.join();\n            }\n        } catch (boost::thread_interrupted&) {\n            // Do nothing...\n        }\n\n        video_executor_.reset();\n        audio_executor_.reset();\n\n        CASPAR_LOG(debug) << print() << \" Joined\";\n    }\n\n    void run(std::optional<int64_t> firstSeek)\n    {\n        std::vector<int> audio_cadence = format_desc_.audio_cadence;\n\n        input_.reset();\n        {\n            core::monitor::state streams;\n            for (auto n = 0UL; n < input_->nb_streams; ++n) {\n                auto st                             = input_->streams[n];\n                auto framerate                      = av_guess_frame_rate(nullptr, st, nullptr);\n                streams[std::to_string(n) + \"/fps\"] = {framerate.num, framerate.den};\n            }\n\n            boost::lock_guard<boost::mutex> lock(state_mutex_);\n            state_[\"file/streams\"] = streams;\n        }\n\n        if (input_duration_ == AV_NOPTS_VALUE) {\n            input_duration_ = input_->duration;\n        }\n\n        {\n            const auto start = start_.load();\n            if (duration_ == AV_NOPTS_VALUE && input_->duration > 0) {\n                if (start != AV_NOPTS_VALUE) {\n                    duration_ = input_->duration - start;\n                } else {\n                    duration_ = input_->duration;\n                }\n            }\n\n            const auto firstStart = firstSeek ? av_rescale_q(*firstSeek, format_tb_, TIME_BASE_Q) : start;\n            if (firstStart != AV_NOPTS_VALUE) {\n                seek_internal(firstStart);\n            } else {\n                reset(input_->start_time != AV_NOPTS_VALUE ? input_->start_time : 0);\n            }\n        }\n\n        set_thread_name(L\"[ffmpeg::av_producer]\");\n\n        boost::range::rotate(audio_cadence, std::end(audio_cadence) - 1);\n\n        Frame frame;\n        timer frame_timer;\n        timer decode_timer;\n\n        int warning_debounce = 0;\n\n        while (!thread_.interruption_requested()) {\n            {\n                const auto seek = seek_.exchange(AV_NOPTS_VALUE);\n\n                if (seek != AV_NOPTS_VALUE) {\n                    seek_internal(seek);\n                    frame = Frame{};\n                    continue;\n                }\n            }\n\n            {\n                // TODO (perf) seek as soon as input is past duration or eof.\n\n                auto start    = start_.load();\n                auto duration = duration_.load();\n\n                start       = start != AV_NOPTS_VALUE ? start : 0;\n                auto end    = duration != AV_NOPTS_VALUE ? start + duration : INT64_MAX;\n                auto time   = frame.pts != AV_NOPTS_VALUE ? frame.pts + frame.duration : 0;\n                buffer_eof_ = (video_filter_.eof && audio_filter_.eof) ||\n                              av_rescale_q(time, TIME_BASE_Q, format_tb_) >= av_rescale_q(end, TIME_BASE_Q, format_tb_);\n\n                if (buffer_eof_) {\n                    if (loop_ && frame_count_ > 2) {\n                        frame = Frame{};\n                        seek_internal(start);\n                    } else {\n                        std::this_thread::sleep_for(std::chrono::milliseconds(10));\n                    }\n                    // TODO (fix) Limit live polling due to bugs.\n                    continue;\n                }\n            }\n\n            bool progress = false;\n            {\n                progress |= schedule();\n\n                std::vector<std::future<bool>> futures;\n\n                if (!video_filter_.frame) {\n                    futures.push_back(video_executor_->begin_invoke([&]() { return video_filter_(); }));\n                }\n\n                if (!audio_filter_.frame) {\n                    futures.push_back(audio_executor_->begin_invoke([&]() { return audio_filter_(audio_cadence[0]); }));\n                }\n\n                for (auto& future : futures) {\n                    progress |= future.get();\n                }\n            }\n\n            if ((!video_filter_.frame && !video_filter_.eof) || (!audio_filter_.frame && !audio_filter_.eof)) {\n                if (!progress) {\n                    if (warning_debounce++ % 500 == 100) {\n                        if (!video_filter_.frame && !video_filter_.eof) {\n                            CASPAR_LOG(warning) << print() << \" Waiting for video frame...\";\n                        } else if (!audio_filter_.frame && !audio_filter_.eof) {\n                            CASPAR_LOG(warning) << print() << \" Waiting for audio frame...\";\n                        } else {\n                            CASPAR_LOG(warning) << print() << \" Waiting for frame...\";\n                        }\n                    }\n\n                    // TODO (perf): Avoid live loop.\n                    std::this_thread::sleep_for(std::chrono::milliseconds(warning_debounce > 25 ? 20 : 5));\n                }\n                continue;\n            }\n\n            warning_debounce = 0;\n\n            // TODO (fix)\n            // if (start_ != AV_NOPTS_VALUE && frame.pts < start_) {\n            //    seek_internal(start_);\n            //    continue;\n            //}\n\n            const auto start_time = input_->start_time != AV_NOPTS_VALUE ? input_->start_time : 0;\n\n            if (video_filter_.frame) {\n                frame.video      = std::move(video_filter_.frame);\n                const auto tb    = av_buffersink_get_time_base(video_filter_.sink);\n                const auto fr    = av_buffersink_get_frame_rate(video_filter_.sink);\n                frame.start_time = start_time;\n                frame.pts        = av_rescale_q(frame.video->pts, tb, TIME_BASE_Q) - start_time;\n                frame.duration   = av_rescale_q(1, av_inv_q(fr), TIME_BASE_Q);\n            }\n\n            if (audio_filter_.frame) {\n                frame.audio      = std::move(audio_filter_.frame);\n                const auto tb    = av_buffersink_get_time_base(audio_filter_.sink);\n                const auto sr    = av_buffersink_get_sample_rate(audio_filter_.sink);\n                frame.start_time = start_time;\n                frame.pts        = av_rescale_q(frame.audio->pts, tb, TIME_BASE_Q) - start_time;\n                frame.duration   = av_rescale_q(frame.audio->nb_samples, {1, sr}, TIME_BASE_Q);\n            }\n\n            frame.frame = core::draw_frame(\n                make_frame(this, *frame_factory_, frame.video, frame.audio, get_color_space(frame.video), scale_mode_));\n            frame.frame_count = frame_count_++;\n\n            graph_->set_value(\"decode-time\", decode_timer.elapsed() * format_desc_.fps * 0.5);\n\n            {\n                boost::unique_lock<boost::mutex> buffer_lock(buffer_mutex_);\n                buffer_cond_.wait(buffer_lock, [&] { return buffer_.size() < buffer_capacity_; });\n                if (seek_ == AV_NOPTS_VALUE) {\n                    buffer_.push_back(frame);\n                }\n            }\n\n            if (format_desc_.field_count != 2 || frame_count_ % 2 == 1) {\n                // Update the frame-time every other frame when interlaced\n                graph_->set_value(\"frame-time\", frame_timer.elapsed() * format_desc_.hz * 0.5);\n                frame_timer.restart();\n            }\n\n            decode_timer.restart();\n\n            graph_->set_value(\"buffer\", static_cast<double>(buffer_.size()) / static_cast<double>(buffer_capacity_));\n\n            boost::range::rotate(audio_cadence, std::end(audio_cadence) - 1);\n        }\n    }\n\n    void update_state()\n    {\n        graph_->set_text(u16(print()));\n        boost::lock_guard<boost::mutex> lock(state_mutex_);\n        state_[\"file/clip\"] = {start().value_or(0) / format_desc_.fps, duration().value_or(0) / format_desc_.fps};\n        state_[\"file/time\"] = {time() / format_desc_.fps, file_duration().value_or(0) / format_desc_.fps};\n        state_[\"loop\"]      = loop_;\n    }\n\n    core::draw_frame prev_frame(const core::video_field field)\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        // Don't start a new frame on the 2nd field\n        if (field != core::video_field::b) {\n            if (frame_flush_ || !frame_) {\n                boost::lock_guard<boost::mutex> lock(buffer_mutex_);\n\n                if (!buffer_.empty()) {\n                    frame_          = buffer_[0].frame;\n                    frame_time_     = buffer_[0].pts;\n                    frame_duration_ = buffer_[0].duration;\n                    frame_flush_    = false;\n                }\n            }\n        }\n\n        return core::draw_frame::still(frame_);\n    }\n\n    bool is_ready()\n    {\n        boost::lock_guard<boost::mutex> lock(buffer_mutex_);\n        return !buffer_.empty() || frame_;\n    }\n\n    core::draw_frame next_frame(const core::video_field field)\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        boost::lock_guard<boost::mutex> lock(buffer_mutex_);\n\n        if (buffer_.empty() || (frame_flush_ && buffer_.size() < 4)) {\n            auto start    = start_.load();\n            auto duration = duration_.load();\n\n            start    = start != AV_NOPTS_VALUE ? start : 0;\n            auto end = duration != AV_NOPTS_VALUE ? start + duration : INT64_MAX;\n\n            if (buffer_eof_ && !frame_flush_) {\n                if (frame_time_ < end && frame_duration_ != AV_NOPTS_VALUE) {\n                    frame_time_ += frame_duration_;\n                } else if (frame_time_ < end) {\n                    frame_time_ = input_duration_;\n                }\n                return core::draw_frame::still(frame_);\n            }\n            graph_->set_tag(diagnostics::tag_severity::WARNING, \"underflow\");\n            latency_ += 1;\n            return core::draw_frame{};\n        }\n\n        if (format_desc_.field_count == 2) {\n            // Check if the next frame is the correct 'field'\n            auto is_field_1 = (buffer_[0].frame_count % 2) == 0;\n            if ((field == core::video_field::a && !is_field_1) || (field == core::video_field::b && is_field_1)) {\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"underflow\");\n                latency_ += 1;\n                return core::draw_frame{};\n            }\n        }\n\n        if (latency_ != -1) {\n            CASPAR_LOG(warning) << print() << \" Latency: \" << latency_;\n            latency_ = -1;\n        }\n\n        frame_          = buffer_[0].frame;\n        frame_time_     = buffer_[0].pts;\n        frame_duration_ = buffer_[0].duration;\n        frame_flush_    = false;\n\n        buffer_.pop_front();\n        buffer_cond_.notify_all();\n\n        graph_->set_value(\"buffer\", static_cast<double>(buffer_.size()) / static_cast<double>(buffer_capacity_));\n\n        return frame_;\n    }\n\n    void seek(int64_t time)\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        seek_ = av_rescale_q(time, format_tb_, TIME_BASE_Q);\n\n        {\n            boost::lock_guard<boost::mutex> lock(buffer_mutex_);\n            buffer_.clear();\n            buffer_cond_.notify_all();\n            graph_->set_value(\"buffer\", static_cast<double>(buffer_.size()) / static_cast<double>(buffer_capacity_));\n        }\n    }\n\n    int64_t time() const\n    {\n        if (frame_time_ == AV_NOPTS_VALUE) {\n            // TODO (fix) How to handle NOPTS case?\n            return 0;\n        }\n\n        return av_rescale_q(frame_time_, TIME_BASE_Q, format_tb_);\n    }\n\n    void loop(bool loop)\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        loop_ = loop;\n    }\n\n    bool loop() const { return loop_; }\n\n    void start(int64_t start)\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n        start_ = av_rescale_q(start, format_tb_, TIME_BASE_Q);\n    }\n\n    std::optional<int64_t> start() const\n    {\n        auto start = start_.load();\n        return start != AV_NOPTS_VALUE ? av_rescale_q(start, TIME_BASE_Q, format_tb_) : std::optional<int64_t>();\n    }\n\n    void duration(int64_t duration)\n    {\n        CASPAR_SCOPE_EXIT { update_state(); };\n\n        duration_ = av_rescale_q(duration, format_tb_, TIME_BASE_Q);\n    }\n\n    std::optional<int64_t> duration() const\n    {\n        const auto duration = duration_.load();\n        if (duration == AV_NOPTS_VALUE) {\n            return {};\n        }\n        return av_rescale_q(duration, TIME_BASE_Q, format_tb_);\n    }\n\n    std::optional<int64_t> file_duration() const\n    {\n        const auto input_duration = input_duration_.load();\n        if (input_duration == AV_NOPTS_VALUE) {\n            return {};\n        }\n        return av_rescale_q(input_duration, TIME_BASE_Q, format_tb_);\n    }\n\n  private:\n    bool want_packet()\n    {\n        return std::any_of(decoders_.begin(), decoders_.end(), [](auto& p) { return p.second.want_packet(); });\n    }\n\n    bool schedule()\n    {\n        auto result = false;\n\n        std::shared_ptr<AVPacket> packet;\n        while (want_packet() && input_.try_pop(packet)) {\n            result = true;\n\n            if (!packet) {\n                for (auto& p : decoders_) {\n                    p.second.push(nullptr);\n                }\n            } else if (sources_.find(packet->stream_index) != sources_.end()) {\n                auto it = decoders_.find(packet->stream_index);\n                if (it != decoders_.end()) {\n                    // TODO (fix): limit it->second.input.size()?\n                    it->second.push(std::move(packet));\n                }\n            }\n        }\n\n        std::vector<int> eof;\n\n        for (auto& p : sources_) {\n            auto it = decoders_.find(p.first);\n            if (it == decoders_.end()) {\n                continue;\n            }\n\n            auto nb_requests = 0U;\n            for (auto source : p.second) {\n                nb_requests = std::max(nb_requests, av_buffersrc_get_nb_failed_requests(source));\n            }\n\n            if (nb_requests == 0) {\n                continue;\n            }\n\n            auto frame = it->second.pop();\n            if (!frame) {\n                continue;\n            }\n\n            for (auto& source : p.second) {\n                if (!frame->data[0]) {\n                    FF(av_buffersrc_close(source, frame->pts, 0));\n                } else {\n                    // TODO (fix) Guard against overflow?\n                    FF(av_buffersrc_write_frame(source, frame.get()));\n                }\n                result = true;\n            }\n\n            // End Of File\n            if (!frame->data[0]) {\n                eof.push_back(p.first);\n            }\n        }\n\n        for (auto index : eof) {\n            sources_.erase(index);\n        }\n\n        return result;\n    }\n\n    void seek_internal(int64_t time)\n    {\n        time = time != AV_NOPTS_VALUE ? time : 0;\n        time = time + (input_->start_time != AV_NOPTS_VALUE ? input_->start_time : 0);\n\n        // TODO (fix) Dont seek if time is close future.\n        if (seekable_) {\n            input_.seek(time);\n        }\n        frame_flush_ = true;\n        frame_count_ = 0;\n        buffer_eof_  = false;\n\n        decoders_.clear();\n\n        reset(time);\n    }\n\n    void reset(int64_t start_time)\n    {\n        video_filter_ = Filter(vfilter_, input_, decoders_, start_time, AVMEDIA_TYPE_VIDEO, format_desc_);\n        audio_filter_ = Filter(afilter_, input_, decoders_, start_time, AVMEDIA_TYPE_AUDIO, format_desc_);\n\n        sources_.clear();\n        for (auto& p : video_filter_.sources) {\n            sources_[p.first].push_back(p.second);\n        }\n        for (auto& p : audio_filter_.sources) {\n            sources_[p.first].push_back(p.second);\n        }\n\n        std::vector<int> keys;\n        // Flush unused inputs.\n        for (auto& p : decoders_) {\n            if (sources_.find(p.first) == sources_.end()) {\n                keys.push_back(p.first);\n            }\n        }\n\n        for (auto& key : keys) {\n            decoders_.erase(key);\n        }\n    }\n\n    std::string print() const\n    {\n        const int          position = std::max(static_cast<int>(time() - start().value_or(0)), 0);\n        std::ostringstream str;\n        str << std::fixed << std::setprecision(4) << \"ffmpeg[\" << name_ << \"|\"\n            << av_q2d({position * format_tb_.num, format_tb_.den}) << \"/\"\n            << av_q2d({static_cast<int>(duration().value_or(0LL)) * format_tb_.num, format_tb_.den}) << \"]\";\n        return str.str();\n    }\n};\n\nAVProducer::AVProducer(std::shared_ptr<core::frame_factory> frame_factory,\n                       core::video_format_desc              format_desc,\n                       std::string                          name,\n                       std::string                          path,\n                       std::optional<std::string>           vfilter,\n                       std::optional<std::string>           afilter,\n                       std::optional<int64_t>               start,\n                       std::optional<int64_t>               seek,\n                       std::optional<int64_t>               duration,\n                       std::optional<bool>                  loop,\n                       int                                  seekable,\n                       core::frame_geometry::scale_mode     scale_mode)\n    : impl_(new Impl(std::move(frame_factory),\n                     std::move(format_desc),\n                     std::move(name),\n                     std::move(path),\n                     std::move(vfilter.value_or(\"\")),\n                     std::move(afilter.value_or(\"\")),\n                     std::move(start),\n                     std::move(seek),\n                     std::move(duration),\n                     std::move(loop.value_or(false)),\n                     seekable,\n                     scale_mode))\n{\n}\n\ncore::draw_frame AVProducer::next_frame(const core::video_field field) { return impl_->next_frame(field); }\n\ncore::draw_frame AVProducer::prev_frame(const core::video_field field) { return impl_->prev_frame(field); }\n\nbool AVProducer::is_ready() { return impl_->is_ready(); }\n\nAVProducer& AVProducer::seek(int64_t time)\n{\n    impl_->seek(time);\n    return *this;\n}\n\nAVProducer& AVProducer::loop(bool loop)\n{\n    impl_->loop(loop);\n    return *this;\n}\n\nbool AVProducer::loop() const { return impl_->loop(); }\n\nAVProducer& AVProducer::start(int64_t start)\n{\n    impl_->start(start);\n    return *this;\n}\n\nint64_t AVProducer::time() const { return impl_->time(); }\n\nint64_t AVProducer::start() const { return impl_->start().value_or(0); }\n\nAVProducer& AVProducer::duration(int64_t duration)\n{\n    impl_->duration(duration);\n    return *this;\n}\n\nint64_t AVProducer::duration() const { return impl_->duration().value_or(std::numeric_limits<int64_t>::max()); }\n\ncore::monitor::state AVProducer::state() const\n{\n    boost::lock_guard<boost::mutex> lock(impl_->state_mutex_);\n    return impl_->state_;\n}\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/producer/av_producer.h",
    "content": "#include <memory>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/geometry.h>\n#include <core/monitor/monitor.h>\n#include <core/video_format.h>\n\n#include <memory>\n#include <optional>\n#include <string>\n\nnamespace caspar { namespace ffmpeg {\n\nclass AVProducer\n{\n  public:\n    AVProducer(std::shared_ptr<core::frame_factory> frame_factory,\n               core::video_format_desc              format_desc,\n               std::string                          name,\n               std::string                          path,\n               std::optional<std::string>           vfilter,\n               std::optional<std::string>           afilter,\n               std::optional<int64_t>               start,\n               std::optional<int64_t>               seek,\n               std::optional<int64_t>               duration,\n               std::optional<bool>                  loop,\n               int                                  seekable,\n               core::frame_geometry::scale_mode     scale_mode);\n\n    core::draw_frame prev_frame(const core::video_field field);\n    core::draw_frame next_frame(const core::video_field field);\n    bool             is_ready();\n\n    AVProducer& seek(int64_t time);\n    int64_t     time() const;\n\n    AVProducer& loop(bool loop);\n    bool        loop() const;\n\n    AVProducer& start(int64_t start);\n    int64_t     start() const;\n\n    AVProducer& duration(int64_t duration);\n    int64_t     duration() const;\n\n    caspar::core::monitor::state state() const;\n\n  private:\n    struct Impl;\n    std::shared_ptr<Impl> impl_;\n};\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/producer/ffmpeg_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"ffmpeg_producer.h\"\n\n#include \"av_producer.h\"\n\n#include <common/env.h>\n#include <common/os/filesystem.h>\n#include <common/param.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/geometry.h>\n#include <core/producer/frame_producer.h>\n#include <core/video_format.h>\n\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/filesystem/fstream.hpp>\n#include <boost/logic/tribool.hpp>\n#include <common/filesystem.h>\n\n#include <chrono>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavformat/avformat.h>\n}\n\nnamespace caspar { namespace ffmpeg {\n\nusing namespace std::chrono_literals;\n\nstruct ffmpeg_producer : public core::frame_producer\n{\n    const std::wstring                   filename_;\n    spl::shared_ptr<core::frame_factory> frame_factory_;\n    core::video_format_desc              format_desc_;\n\n    std::shared_ptr<AVProducer> producer_;\n\n  public:\n    explicit ffmpeg_producer(spl::shared_ptr<core::frame_factory> frame_factory,\n                             core::video_format_desc              format_desc,\n                             std::wstring                         path,\n                             std::wstring                         filename,\n                             std::wstring                         vfilter,\n                             std::wstring                         afilter,\n                             std::optional<int64_t>               start,\n                             std::optional<int64_t>               seek,\n                             std::optional<int64_t>               duration,\n                             std::optional<bool>                  loop,\n                             int                                  seekable,\n                             core::frame_geometry::scale_mode     scale_mode)\n        : filename_(filename)\n        , frame_factory_(frame_factory)\n        , format_desc_(format_desc)\n        , producer_(new AVProducer(frame_factory_,\n                                   format_desc_,\n                                   u8(path),\n                                   u8(filename),\n                                   u8(vfilter),\n                                   u8(afilter),\n                                   start,\n                                   seek,\n                                   duration,\n                                   loop,\n                                   seekable,\n                                   scale_mode))\n    {\n    }\n\n    ~ffmpeg_producer()\n    {\n        std::thread([producer = std::move(producer_)]() mutable {\n            try {\n                producer.reset();\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        }).detach();\n    }\n\n    // frame_producer\n\n    core::draw_frame last_frame(const core::video_field field) override { return producer_->prev_frame(field); }\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        return producer_->next_frame(field);\n    }\n\n    std::uint32_t frame_number() const override\n    {\n        return static_cast<std::uint32_t>(producer_->time() - producer_->start());\n    }\n\n    std::uint32_t nb_frames() const override\n    {\n        return producer_->loop() ? std::numeric_limits<std::uint32_t>::max()\n                                 : static_cast<std::uint32_t>(producer_->duration());\n    }\n\n    bool is_ready() override { return producer_->is_ready(); }\n\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        std::wstring result;\n\n        std::wstring cmd = params.at(0);\n        std::wstring value;\n        if (params.size() > 1) {\n            value = params.at(1);\n        }\n\n        if (boost::iequals(cmd, L\"loop\")) {\n            if (!value.empty()) {\n                producer_->loop(boost::lexical_cast<bool>(value));\n            }\n\n            result = std::to_wstring(producer_->loop());\n        } else if (boost::iequals(cmd, L\"in\") || boost::iequals(cmd, L\"start\")) {\n            if (!value.empty()) {\n                producer_->start(boost::lexical_cast<int64_t>(value));\n            }\n\n            result = std::to_wstring(producer_->start());\n        } else if (boost::iequals(cmd, L\"out\")) {\n            if (!value.empty()) {\n                producer_->duration(boost::lexical_cast<int64_t>(value) - producer_->start());\n            }\n\n            result = std::to_wstring(producer_->start() + producer_->duration());\n        } else if (boost::iequals(cmd, L\"length\")) {\n            if (!value.empty()) {\n                producer_->duration(boost::lexical_cast<std::int64_t>(value));\n            }\n\n            result = std::to_wstring(producer_->duration());\n        } else if (boost::iequals(cmd, L\"seek\") && !value.empty()) {\n            int64_t seek;\n            if (boost::iequals(value, L\"rel\")) {\n                seek = producer_->time();\n            } else if (boost::iequals(value, L\"in\")) {\n                seek = producer_->start();\n            } else if (boost::iequals(value, L\"out\")) {\n                seek = producer_->start() + producer_->duration();\n            } else if (boost::iequals(value, L\"end\")) {\n                seek = producer_->duration();\n            } else {\n                seek = boost::lexical_cast<int64_t>(value);\n            }\n\n            if (params.size() > 2) {\n                seek += boost::lexical_cast<int64_t>(params.at(2));\n            }\n\n            producer_->seek(seek);\n\n            result = std::to_wstring(seek);\n        } else {\n            CASPAR_THROW_EXCEPTION(invalid_argument());\n        }\n\n        std::promise<std::wstring> promise;\n        promise.set_value(result);\n        return promise.get_future();\n    }\n\n    std::wstring print() const override\n    {\n        const int64_t position = std::max(producer_->time() - producer_->start(), INT64_C(0));\n        return L\"ffmpeg[\" + filename_ + L\"|\" + std::to_wstring(position) + L\"/\" +\n               std::to_wstring(producer_->duration()) + L\"]\";\n    }\n\n    std::wstring name() const override { return L\"ffmpeg\"; }\n\n    core::monitor::state state() const override { return producer_->state(); }\n};\n\nboost::tribool has_valid_extension(const boost::filesystem::path& filename)\n{\n    static const auto invalid_exts = {\n        L\".tga\", L\".tiff\", L\".tif\", L\".jp2\", L\".jpx\", L\".j2k\", L\".j2c\", L\".swf\", L\".ct\", L\".html\", L\".htm\"};\n    static const auto valid_exts = {L\".m2t\",  L\".m2ts\",   L\".mov\",  L\".mp4\", L\".dv\",  L\".flv\", L\".mpg\",  L\".dnxhd\",\n                                    L\".h264\", L\".prores\", L\".mkv\",  L\".mxf\", L\".ts\",  L\".mp3\", L\".wav\",  L\".wma\",\n                                    L\".nut\",  L\".flac\",   L\".opus\", L\".ogg\", L\".ogv\", L\".oga\", L\".webm\", L\".webp\"};\n\n    auto ext = boost::to_lower_copy(filename.extension().wstring());\n\n    if (std::find(valid_exts.begin(), valid_exts.end(), ext) != valid_exts.end()) {\n        return boost::tribool(true);\n    }\n\n    if (std::find(invalid_exts.begin(), invalid_exts.end(), ext) != invalid_exts.end()) {\n        return boost::tribool(false);\n    }\n    return boost::tribool(boost::indeterminate);\n}\n\nbool has_invalid_protocol(const std::wstring& filename) { return boost::algorithm::istarts_with(filename, L\"ndi://\"); }\n\nbool is_readable(const boost::filesystem::path& filename)\n{\n    boost::filesystem::ifstream file(filename);\n    if (file) {\n        return true;\n    }\n    return false;\n}\n\nbool is_valid_file(const boost::filesystem::path& filename)\n{\n    if (!is_readable(filename)) {\n        return false;\n    }\n\n    const auto valid_ext = has_valid_extension(filename);\n    if (valid_ext) {\n        return true;\n    }\n    if (!valid_ext) {\n        return false;\n    }\n\n    int         score = 0;\n    AVProbeData pb    = {};\n    pb.filename       = filename.generic_string().c_str();\n\n    if (av_probe_input_format2(&pb, false, &score) != nullptr) {\n        return true;\n    }\n\n    boost::filesystem::ifstream file(filename);\n\n    std::vector<unsigned char> buf;\n    for (auto file_it = std::istreambuf_iterator<char>(file);\n         file_it != std::istreambuf_iterator<char>() && buf.size() < 1024;\n         ++file_it) {\n        buf.push_back(*file_it);\n    }\n\n    if (buf.empty()) {\n        return false;\n    }\n\n    pb.buf      = buf.data();\n    pb.buf_size = static_cast<int>(buf.size());\n\n    return av_probe_input_format2(&pb, true, &score) != nullptr;\n}\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params)\n{\n    auto name = params.at(0);\n    auto path = name;\n\n    if (!boost::contains(path, L\"://\")) {\n        auto fullMediaPath = find_file_within_dir_or_absolute(env::media_folder(), path, is_valid_file);\n        if (fullMediaPath) {\n            path = fullMediaPath->wstring();\n        } else {\n            return core::frame_producer::empty();\n        }\n    } else if (!has_valid_extension(path) || has_invalid_protocol(path)) {\n        return core::frame_producer::empty();\n    }\n\n    if (path.empty()) {\n        return core::frame_producer::empty();\n    }\n\n    auto seekable = get_param(L\"SEEKABLE\", params, static_cast<int>(2));\n\n    auto loop = contains_param(L\"LOOP\", params);\n\n    auto seek = get_param(L\"SEEK\", params, static_cast<uint32_t>(0));\n    auto in   = get_param(L\"IN\", params, seek);\n\n    if (!contains_param(L\"SEEK\", params)) {\n        // Default to the same when only one is defined\n        seek = in;\n    }\n\n    auto out = get_param(L\"LENGTH\", params, std::numeric_limits<uint32_t>::max());\n    if (out < std::numeric_limits<uint32_t>::max() - in)\n        out += in;\n    else\n        out = std::numeric_limits<uint32_t>::max();\n    out = get_param(L\"OUT\", params, out);\n\n    auto filter_str = get_param(L\"FILTER\", params, L\"\");\n\n    auto scale_mode = core::scale_mode_from_string(get_param(L\"SCALE_MODE\", params, L\"STRETCH\"));\n\n    boost::ireplace_all(filter_str, L\"DEINTERLACE_BOB\", L\"YADIF=1:-1\");\n    boost::ireplace_all(filter_str, L\"DEINTERLACE_LQ\", L\"SEPARATEFIELDS\");\n    boost::ireplace_all(filter_str, L\"DEINTERLACE\", L\"YADIF=0:-1\");\n\n    std::optional<std::int64_t> start;\n    std::optional<std::int64_t> seek2;\n    std::optional<std::int64_t> duration;\n\n    if (in != 0) {\n        start = in;\n    }\n    if (seek != 0) {\n        seek2 = seek;\n    }\n\n    if (out != std::numeric_limits<uint32_t>::max()) {\n        duration = out - in;\n    }\n\n    auto vfilter = get_param(L\"VF\", params, filter_str);\n    auto afilter = get_param(L\"AF\", params, get_param(L\"FILTER\", params, L\"\"));\n\n    try {\n        return spl::make_shared<ffmpeg_producer>(dependencies.frame_factory,\n                                                 dependencies.format_desc,\n                                                 name,\n                                                 path,\n                                                 vfilter,\n                                                 afilter,\n                                                 start,\n                                                 seek2,\n                                                 duration,\n                                                 loop,\n                                                 seekable,\n                                                 scale_mode);\n    } catch (...) {\n        CASPAR_LOG_CURRENT_EXCEPTION();\n    }\n    return core::frame_producer::empty();\n}\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/producer/ffmpeg_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace ffmpeg {\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/util/audio_resampler.cpp",
    "content": "#include \"audio_resampler.h\"\n#include \"av_assert.h\"\n\nextern \"C\" {\n#include <libavutil/samplefmt.h>\n#include <libswresample/swresample.h>\n}\n\nnamespace caspar::ffmpeg {\n\nAudioResampler::AudioResampler(int sample_rate, AVSampleFormat in_sample_fmt)\n{\n    AVChannelLayout channel_layout     = AV_CHANNEL_LAYOUT_7POINT1;\n    AVChannelLayout channel_layout_out = AV_CHANNEL_LAYOUT_HEXADECAGONAL;\n\n    SwrContext* raw_ctx = nullptr;\n    FF(swr_alloc_set_opts2(&raw_ctx,\n                           &channel_layout_out,\n                           AV_SAMPLE_FMT_S32,\n                           sample_rate,\n                           &channel_layout,\n                           in_sample_fmt,\n                           sample_rate,\n                           0,\n                           nullptr));\n\n    ctx = std::shared_ptr<SwrContext>(raw_ctx, [](SwrContext* ptr) { swr_free(&ptr); });\n\n    FF_RET(swr_init(ctx.get()), \"swr_init\");\n}\n\ncaspar::array<int32_t> AudioResampler::convert(int frames, const void** src)\n{\n    auto result = caspar::array<int32_t>(frames * 16 * sizeof(int32_t));\n    auto ptr    = result.data();\n    swr_convert(ctx.get(), (uint8_t**)&ptr, frames, reinterpret_cast<const uint8_t**>(src), frames);\n\n    return result;\n}\n\n}; // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/util/audio_resampler.h",
    "content": "#include <common/array.h>\n#include <memory>\n\n#pragma once\n\nextern \"C\" {\n#include <libavutil/samplefmt.h>\n}\n\nstruct SwrContext;\n\nnamespace caspar::ffmpeg {\n\nclass AudioResampler\n{\n    std::shared_ptr<SwrContext> ctx;\n\n  public:\n    AudioResampler(int sample_rate, AVSampleFormat in_sample_fmt);\n\n    AudioResampler(const AudioResampler&)            = delete;\n    AudioResampler& operator=(const AudioResampler&) = delete;\n\n    caspar::array<int32_t> convert(int frames, const void** src);\n};\n\n}; // namespace caspar::ffmpeg"
  },
  {
    "path": "src/modules/ffmpeg/util/av_assert.h",
    "content": "#pragma once\n\n#include <common/except.h>\n\nnamespace caspar { namespace ffmpeg {\n\nstruct ffmpeg_error_t : virtual caspar_exception\n{\n};\n\nusing ffmpeg_errn_info = boost::error_info<struct tag_ffmpeg_errn_info, int>;\n\n}} // namespace caspar::ffmpeg\n\n#define THROW_ON_ERROR_STR_(call) #call\n#define THROW_ON_ERROR_STR(call) THROW_ON_ERROR_STR_(call)\n\n#define FF_RET(ret, func)                                                                                              \\\n    if (ret < 0) {                                                                                                     \\\n        CASPAR_THROW_EXCEPTION(caspar::ffmpeg::ffmpeg_error_t()                                                        \\\n                               << boost::errinfo_api_function(func) << caspar::ffmpeg::ffmpeg_errn_info(ret)           \\\n                               << boost::errinfo_errno(AVUNERROR(ret)));                                               \\\n    }\n\n#define FF(call)                                                                                                       \\\n    [&] {                                                                                                              \\\n        auto ret = call;                                                                                               \\\n        FF_RET(ret, THROW_ON_ERROR_STR(call));                                                                         \\\n    }()\n\n#define FFMEM(call)                                                                                                    \\\n    [&] {                                                                                                              \\\n        auto val = call;                                                                                               \\\n        if (!val)                                                                                                      \\\n            FF_RET(AVERROR(ENOMEM), THROW_ON_ERROR_STR(call))                                                          \\\n        return std::move(val);                                                                                         \\\n    }()\n"
  },
  {
    "path": "src/modules/ffmpeg/util/av_util.cpp",
    "content": "#include \"av_util.h\"\n#include \"av_assert.h\"\n\n#include <common/bit_depth.h>\n\nextern \"C\" {\n#include <libavcodec/avcodec.h>\n#include <libavfilter/avfilter.h>\n#include <libavutil/channel_layout.h>\n#include <libavutil/frame.h>\n#include <libavutil/imgutils.h>\n#include <libavutil/pixfmt.h>\n}\n\n#include <array>\n#include <tbb/parallel_for.h>\n#include <tbb/parallel_invoke.h>\n\n#include <tuple>\n\nnamespace caspar { namespace ffmpeg {\n\nstd::shared_ptr<AVFrame> alloc_frame()\n{\n    const auto frame = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });\n    if (!frame)\n        FF_RET(AVERROR(ENOMEM), \"av_frame_alloc\");\n    return frame;\n}\n\nstd::shared_ptr<AVPacket> alloc_packet()\n{\n    const auto packet = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket* ptr) { av_packet_free(&ptr); });\n    if (!packet)\n        FF_RET(AVERROR(ENOMEM), \"av_packet_alloc\");\n    return packet;\n}\n\ncore::mutable_frame make_frame(void*                            tag,\n                               core::frame_factory&             frame_factory,\n                               std::shared_ptr<AVFrame>         video,\n                               std::shared_ptr<AVFrame>         audio,\n                               core::color_space                color_space,\n                               core::frame_geometry::scale_mode scale_mode,\n                               bool                             is_straight_alpha)\n{\n    std::vector<int> data_map; // TODO(perf) when using data_map, avoid uploading duplicate planes\n\n    auto pix_desc =\n        video ? pixel_format_desc(\n                    static_cast<AVPixelFormat>(video->format), video->width, video->height, data_map, color_space)\n              : core::pixel_format_desc(core::pixel_format::invalid);\n    pix_desc.is_straight_alpha = is_straight_alpha;\n\n    auto frame = frame_factory.create_frame(tag, pix_desc);\n    if (scale_mode != core::frame_geometry::scale_mode::stretch) {\n        frame.geometry() = core::frame_geometry::get_default(scale_mode);\n    }\n\n    tbb::parallel_invoke(\n        [&]() {\n            if (video) {\n                for (int n = 0; n < static_cast<int>(pix_desc.planes.size()); ++n) {\n                    auto frame_plan_index = data_map.empty() ? n : data_map.at(n);\n\n                    tbb::parallel_for(0, pix_desc.planes[n].height, [&](int y) {\n                        std::memcpy(frame.image_data(n).begin() + y * pix_desc.planes[n].linesize,\n                                    video->data[frame_plan_index] + y * video->linesize[frame_plan_index],\n                                    pix_desc.planes[n].linesize);\n                    });\n                }\n            }\n        },\n        [&]() {\n            if (audio) {\n                const int channel_count = 16;\n                frame.audio_data()      = std::vector<int32_t>(audio->nb_samples * channel_count, 0);\n\n                auto source_channel_count = audio->ch_layout.nb_channels;\n                if (source_channel_count == channel_count) {\n                    std::memcpy(frame.audio_data().data(),\n                                reinterpret_cast<int32_t*>(audio->data[0]),\n                                sizeof(int32_t) * channel_count * audio->nb_samples);\n                } else {\n                    // This isn't pretty, but some callers may not provide 16 channels\n\n                    auto dst = frame.audio_data().data();\n                    auto src = reinterpret_cast<int32_t*>(audio->data[0]);\n                    for (auto i = 0; i < audio->nb_samples; i++) {\n                        for (auto j = 0; j < std::min(channel_count, source_channel_count); ++j) {\n                            dst[i * channel_count + j] = src[i * source_channel_count + j];\n                        }\n                    }\n                }\n            }\n        });\n\n    return frame;\n}\n\nstd::tuple<core::pixel_format, common::bit_depth> get_pixel_format(AVPixelFormat pix_fmt)\n{\n    switch (pix_fmt) {\n        case AV_PIX_FMT_GRAY8:\n            return {core::pixel_format::gray, common::bit_depth::bit8};\n        case AV_PIX_FMT_RGB24:\n            return {core::pixel_format::rgb, common::bit_depth::bit8};\n        case AV_PIX_FMT_BGR24:\n            return {core::pixel_format::bgr, common::bit_depth::bit8};\n        case AV_PIX_FMT_BGRA:\n            return {core::pixel_format::bgra, common::bit_depth::bit8};\n        case AV_PIX_FMT_ARGB:\n            return {core::pixel_format::argb, common::bit_depth::bit8};\n        case AV_PIX_FMT_RGBA:\n            return {core::pixel_format::rgba, common::bit_depth::bit8};\n        case AV_PIX_FMT_ABGR:\n            return {core::pixel_format::abgr, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUV444P:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUV444P10:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit10};\n        case AV_PIX_FMT_YUV444P12:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit12};\n        case AV_PIX_FMT_YUV422P:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUV422P10:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit10};\n        case AV_PIX_FMT_YUV422P12:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit12};\n        case AV_PIX_FMT_YUV420P:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUV420P10:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit10};\n        case AV_PIX_FMT_YUV420P12:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit12};\n        case AV_PIX_FMT_YUV411P:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUV410P:\n            return {core::pixel_format::ycbcr, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUVA420P:\n            return {core::pixel_format::ycbcra, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUVA422P:\n            return {core::pixel_format::ycbcra, common::bit_depth::bit8};\n        case AV_PIX_FMT_YUVA444P:\n            return {core::pixel_format::ycbcra, common::bit_depth::bit8};\n        case AV_PIX_FMT_UYVY422:\n            return {core::pixel_format::uyvy, common::bit_depth::bit8};\n        case AV_PIX_FMT_GBRP:\n            return {core::pixel_format::gbrp, common::bit_depth::bit8};\n        case AV_PIX_FMT_GBRP10:\n            return {core::pixel_format::gbrp, common::bit_depth::bit10};\n        case AV_PIX_FMT_GBRP12:\n            return {core::pixel_format::gbrp, common::bit_depth::bit12};\n        case AV_PIX_FMT_GBRP16:\n            return {core::pixel_format::gbrp, common::bit_depth::bit16};\n        case AV_PIX_FMT_GBRAP:\n            return {core::pixel_format::gbrap, common::bit_depth::bit8};\n        case AV_PIX_FMT_GBRAP16:\n            return {core::pixel_format::gbrap, common::bit_depth::bit16};\n        default:\n            return {core::pixel_format::invalid, common::bit_depth::bit8};\n    }\n}\n\ncore::pixel_format_desc pixel_format_desc(AVPixelFormat     pix_fmt,\n                                          int               width,\n                                          int               height,\n                                          std::vector<int>& data_map,\n                                          core::color_space color_space)\n{\n    // Get linesizes\n    int linesizes[4];\n    av_image_fill_linesizes(linesizes, pix_fmt, width);\n\n    const auto fmt   = get_pixel_format(pix_fmt);\n    auto       desc  = core::pixel_format_desc(std::get<0>(fmt), color_space);\n    auto       depth = std::get<1>(fmt);\n    auto       bpc   = depth == common::bit_depth::bit8 ? 1 : 2;\n\n    for (int i = 0; i < 4; i++)\n        linesizes[i] /= bpc;\n\n    switch (desc.format) {\n        case core::pixel_format::gray:\n        case core::pixel_format::luma: {\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0], height, 1, depth));\n            return desc;\n        }\n        case core::pixel_format::bgr:\n        case core::pixel_format::rgb: {\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0] / 3, height, 3, depth));\n            return desc;\n        }\n        case core::pixel_format::gbrp: {\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0], height, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[1], height, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[2], height, 1, depth));\n            return desc;\n        }\n        case core::pixel_format::gbrap: {\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0], height, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[1], height, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[2], height, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[3], height, 1, depth));\n            return desc;\n        }\n        case core::pixel_format::bgra:\n        case core::pixel_format::argb:\n        case core::pixel_format::rgba:\n        case core::pixel_format::abgr: {\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0] / 4, height, 4, depth));\n            return desc;\n        }\n        case core::pixel_format::ycbcr:\n        case core::pixel_format::ycbcra: {\n            // Find chroma height\n            size_t    sizes[4];\n            ptrdiff_t linesizes1[4];\n            for (int i = 0; i < 4; i++)\n                linesizes1[i] = linesizes[i];\n            av_image_fill_plane_sizes(sizes, pix_fmt, height, linesizes1);\n            auto size2 = static_cast<int>(sizes[1]);\n            auto h2    = size2 / linesizes[1];\n\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0], height, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[1], h2, 1, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[2], h2, 1, depth));\n\n            if (desc.format == core::pixel_format::ycbcra)\n                desc.planes.push_back(core::pixel_format_desc::plane(linesizes[3], height, 1, depth));\n\n            return desc;\n        }\n        case core::pixel_format::uyvy: {\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0] / 2, height, 2, depth));\n            desc.planes.push_back(core::pixel_format_desc::plane(linesizes[0] / 4, height, 4, depth));\n\n            data_map.clear();\n            data_map.push_back(0);\n            data_map.push_back(0);\n\n            return desc;\n        }\n        default:\n            desc.format = core::pixel_format::invalid;\n            return desc;\n    }\n}\n\nstd::shared_ptr<AVFrame> make_av_video_frame(const core::const_frame& frame, const core::video_format_desc& format_desc)\n{\n    auto av_frame = alloc_frame();\n\n    auto pix_desc = frame.pixel_format_desc();\n\n    auto planes = pix_desc.planes;\n    auto format = pix_desc.format;\n\n    const auto sar = boost::rational<int>(format_desc.square_width, format_desc.square_height) /\n                     boost::rational<int>(format_desc.width, format_desc.height);\n\n    av_frame->sample_aspect_ratio = {sar.numerator(), sar.denominator()};\n    av_frame->width               = format_desc.width;\n    av_frame->height              = format_desc.height;\n\n    const auto is_16bit = planes[0].depth != common::bit_depth::bit8;\n    switch (format) {\n        case core::pixel_format::rgb:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_RGB48 : AVPixelFormat::AV_PIX_FMT_RGB24;\n            break;\n        case core::pixel_format::bgr:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_BGR48 : AVPixelFormat::AV_PIX_FMT_BGR24;\n            break;\n        case core::pixel_format::rgba:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_RGBA64 : AVPixelFormat::AV_PIX_FMT_RGBA;\n            break;\n        case core::pixel_format::argb:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_BGRA64 : AVPixelFormat::AV_PIX_FMT_ARGB;\n            break;\n        case core::pixel_format::bgra:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_BGRA64 : AVPixelFormat::AV_PIX_FMT_BGRA;\n            break;\n        case core::pixel_format::abgr:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_BGRA64 : AVPixelFormat::AV_PIX_FMT_ABGR;\n            break;\n        case core::pixel_format::gray:\n        case core::pixel_format::luma:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_GRAY16 : AVPixelFormat::AV_PIX_FMT_GRAY8;\n            break;\n        case core::pixel_format::ycbcr: {\n            int y_w = planes[0].width;\n            int y_h = planes[0].height;\n            int c_w = planes[1].width;\n            int c_h = planes[1].height;\n\n            if (c_h == y_h && c_w == y_w)\n                av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_YUV444P10 : AVPixelFormat::AV_PIX_FMT_YUV444P;\n            else if (c_h == y_h && c_w * 2 == y_w)\n                av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_YUV422P10 : AVPixelFormat::AV_PIX_FMT_YUV422P;\n            else if (c_h == y_h && c_w * 4 == y_w)\n                av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_YUV422P10 : AVPixelFormat::AV_PIX_FMT_YUV411P;\n            else if (c_h * 2 == y_h && c_w * 2 == y_w)\n                av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_YUV420P10 : AVPixelFormat::AV_PIX_FMT_YUV420P;\n            else if (c_h * 2 == y_h && c_w * 4 == y_w)\n                av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_YUV420P10 : AVPixelFormat::AV_PIX_FMT_YUV410P;\n\n            break;\n        }\n        case core::pixel_format::ycbcra:\n            av_frame->format = is_16bit ? AVPixelFormat::AV_PIX_FMT_YUVA420P10 : AVPixelFormat::AV_PIX_FMT_YUVA420P;\n            break;\n        case core::pixel_format::uyvy:\n            // TODO\n            break;\n        case core::pixel_format::gbrp:\n        case core::pixel_format::gbrap:\n            // TODO\n            break;\n        case core::pixel_format::count:\n        case core::pixel_format::invalid:\n            break;\n    }\n\n    FF(av_frame_get_buffer(av_frame.get(), is_16bit ? 64 : 32));\n\n    // TODO (perf) Avoid extra memcpy.\n    for (int n = 0; n < planes.size(); ++n) {\n        for (int y = 0; y < av_frame->height; ++y) {\n            std::memcpy(av_frame->data[n] + y * av_frame->linesize[n],\n                        frame.image_data(n).data() + y * planes[n].linesize,\n                        planes[n].linesize);\n        }\n    }\n\n    return av_frame;\n}\n\nstd::shared_ptr<AVFrame> make_av_audio_frame(const core::const_frame& frame, const core::video_format_desc& format_desc)\n{\n    auto av_frame = alloc_frame();\n\n    const auto& buffer = frame.audio_data();\n\n    // TODO (fix) Use sample_format_desc.\n    av_channel_layout_default(&av_frame->ch_layout, format_desc.audio_channels);\n    av_frame->sample_rate = format_desc.audio_sample_rate;\n    av_frame->format      = AV_SAMPLE_FMT_S32;\n    av_frame->nb_samples  = static_cast<int>(buffer.size() / format_desc.audio_channels);\n    FF(av_frame_get_buffer(av_frame.get(), 32));\n    std::memcpy(av_frame->data[0], buffer.data(), buffer.size() * sizeof(buffer.data()[0]));\n\n    return av_frame;\n}\n\nAVDictionary* to_dict(std::map<std::string, std::string>&& map)\n{\n    AVDictionary* dict = nullptr;\n    for (auto& p : map) {\n        if (!p.second.empty()) {\n            av_dict_set(&dict, p.first.c_str(), p.second.c_str(), 0);\n        }\n    }\n    return dict;\n}\n\nstd::map<std::string, std::string> to_map(AVDictionary** dict)\n{\n    std::map<std::string, std::string> map;\n    AVDictionaryEntry*                 t = nullptr;\n    while (*dict) {\n        t = av_dict_get(*dict, \"\", t, AV_DICT_IGNORE_SUFFIX);\n        if (!t) {\n            break;\n        }\n        if (t->value) {\n            map[t->key] = t->value;\n        }\n    }\n    av_dict_free(dict);\n    return map;\n}\n\nuint64_t get_channel_layout_mask_for_channels(int channel_count)\n{\n    AVChannelLayout layout = AV_CHANNEL_LAYOUT_STEREO;\n    av_channel_layout_default(&layout, channel_count);\n    uint64_t channel_layout = layout.u.mask;\n    av_channel_layout_uninit(&layout);\n\n    return channel_layout;\n}\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/ffmpeg/util/av_util.h",
    "content": "#pragma once\n\nextern \"C\" {\n#include <libavutil/pixfmt.h>\n}\n\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <core/video_format.h>\n\n#include <map>\n#include <memory>\n#include <vector>\n\nstruct AVFrame;\nstruct AVPacket;\nstruct AVFilterContext;\nstruct AVCodecContext;\nstruct AVDictionary;\n\nnamespace caspar { namespace ffmpeg {\n\nstd::shared_ptr<AVFrame>  alloc_frame();\nstd::shared_ptr<AVPacket> alloc_packet();\n\ncore::pixel_format_desc pixel_format_desc(AVPixelFormat     pix_fmt,\n                                          int               width,\n                                          int               height,\n                                          std::vector<int>& data_map,\n                                          core::color_space color_space = core::color_space::bt709);\ncore::mutable_frame     make_frame(void*                    tag,\n                                   core::frame_factory&     frame_factory,\n                                   std::shared_ptr<AVFrame> video,\n                                   std::shared_ptr<AVFrame> audio,\n                                   core::color_space        color_space = core::color_space::bt709,\n                                   core::frame_geometry::scale_mode     = core::frame_geometry::scale_mode::stretch,\n                                   bool is_straight_alpha               = false);\n\nstd::shared_ptr<AVFrame> make_av_video_frame(const core::const_frame& frame, const core::video_format_desc& format_des);\nstd::shared_ptr<AVFrame> make_av_audio_frame(const core::const_frame& frame, const core::video_format_desc& format_des);\n\nAVDictionary*                      to_dict(std::map<std::string, std::string>&& map);\nstd::map<std::string, std::string> to_map(AVDictionary** dict);\n\nuint64_t get_channel_layout_mask_for_channels(int channel_count);\n\n}} // namespace caspar::ffmpeg\n"
  },
  {
    "path": "src/modules/flash/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (flash)\n\nset(SOURCES\n\t\tinterop/Flash9e_i.c\n\t\tinterop/axflash.h\n\t\tinterop/TimerHelper.h\n\n\t\tproducer/FlashAxContainer.cpp\n\t\tproducer/FlashAxContainer.h\n\t\tproducer/flash_producer.cpp\n\t\tproducer/flash_producer.h\n\n\t\tutil/swf.cpp\n\t\tutil/swf.h\n\n\t\tflash.cpp\n\t\tflash.h\n\t\tStdAfx.h\n)\n\ncasparcg_add_module_project(flash\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"flash::init\"\n)\ntarget_include_directories(flash PRIVATE\n    ${ZLIB_INCLUDE_PATH}\n    )\ntarget_precompile_headers(flash PRIVATE \"StdAfx.h\")\n\nset_target_properties(flash PROPERTIES FOLDER modules)\nsource_group(sources\\\\interop interop/*)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources\\\\util util/*)\nsource_group(sources ./*)\n\n\n"
  },
  {
    "path": "src/modules/flash/StdAfx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#ifdef __cplusplus\n#define NOMINMAX\n#define WIN32_LEAN_AND_MEAN\n\n#include <common/compiler/vs/disable_silly_warnings.h>\n\n#if defined _DEBUG && defined _MSC_VER\n#include <crtdbg.h>\n#endif\n\n#include <algorithm>\n#include <array>\n#include <assert.h>\n#include <deque>\n#include <functional>\n#include <math.h>\n#include <memory>\n#include <queue>\n#include <string>\n#include <vector>\n\n#include <tbb/concurrent_queue.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/format.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/range/algorithm.hpp>\n#include <boost/regex.hpp>\n\n#include <common/memory.h>\n#include <common/utf.h>\n\n#include <common/except.h>\n#include <common/log.h>\n#endif\n#include <rpc.h>\n#include <rpcndr.h>\n"
  },
  {
    "path": "src/modules/flash/flash.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"StdAfx.h\"\n\n#include \"flash.h\"\n#include \"util/swf.h\"\n\n#include \"producer/flash_producer.h\"\n\n#include <common/env.h>\n#include <common/os/windows/windows.h>\n\n#include <core/producer/cg_proxy.h>\n#include <core/video_format.h>\n\n#include <boost/filesystem.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <future>\n#include <string>\n#include <utility>\n\nnamespace caspar { namespace flash {\n\nstd::wstring version();\nstd::wstring cg_version();\n\nstd::wstring get_absolute(const std::wstring& base_folder, const std::wstring& filename)\n{\n    return (boost::filesystem::path(base_folder) / filename).wstring();\n}\n\nclass flash_cg_proxy : public core::cg_proxy\n{\n    spl::shared_ptr<core::frame_producer> flash_producer_;\n    std::wstring                          base_folder_;\n\n    flash_cg_proxy(const flash_cg_proxy&)            = delete;\n    flash_cg_proxy& operator=(const flash_cg_proxy&) = delete;\n\n  public:\n    explicit flash_cg_proxy(const spl::shared_ptr<core::frame_producer>& producer,\n                            std::wstring                                 base_folder = env::template_folder())\n        : flash_producer_(producer)\n        , base_folder_(std::move(base_folder))\n    {\n    }\n\n    // cg_proxy\n\n    void add(int                 layer,\n             const std::wstring& template_name,\n             bool                play_on_load,\n             const std::wstring& label,\n             const std::wstring& data) override\n    {\n        auto filename = template_name;\n\n        if (!filename.empty() && filename[0] == L'/')\n            filename = filename.substr(1, filename.size() - 1);\n\n        filename = (boost::filesystem::path(base_folder_) / filename).wstring();\n        filename = find_template(filename);\n\n        auto str = (boost::wformat(L\"<invoke name=\\\"Add\\\" \"\n                                   L\"returntype=\\\"xml\\\"><arguments><number>%1%</number><string>%2%</\"\n                                   L\"string>%3%<string>%4%</string><string><![CDATA[%5%]]></\"\n                                   L\"string></arguments></invoke>\") %\n                    layer % filename % (play_on_load ? L\"<true/>\" : L\"<false/>\") % label % data)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking add-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        flash_producer_->call(std::move(params)).get();\n    }\n\n    void verify_flash_player()\n    {\n        if (flash_producer_->call({L\"?\"}).get() == L\"0\")\n            CASPAR_THROW_EXCEPTION(expected_user_error() << msg_info(\"No flash player running on video layer.\"));\n    }\n\n    void remove(int layer) override\n    {\n        verify_flash_player();\n\n        auto str = (boost::wformat(L\"<invoke name=\\\"Delete\\\" returntype=\\\"xml\\\"><arguments><array><property \"\n                                   L\"id=\\\"0\\\"><number>%1%</number></property></array></arguments></invoke>\") %\n                    layer)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking remove-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        flash_producer_->call(std::move(params));\n    }\n\n    void play(int layer) override\n    {\n        verify_flash_player();\n\n        auto str = (boost::wformat(L\"<invoke name=\\\"Play\\\" returntype=\\\"xml\\\"><arguments><array><property \"\n                                   L\"id=\\\"0\\\"><number>%1%</number></property></array></arguments></invoke>\") %\n                    layer)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking play-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        flash_producer_->call(std::move(params));\n    }\n\n    void stop(int layer) override\n    {\n        verify_flash_player();\n\n        auto str = (boost::wformat(\n                        L\"<invoke name=\\\"Stop\\\" returntype=\\\"xml\\\"><arguments><array><property \"\n                        L\"id=\\\"0\\\"><number>%1%</number></property></array><number>0</number></arguments></invoke>\") %\n                    layer)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking stop-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        flash_producer_->call(std::move(params));\n    }\n\n    void next(int layer) override\n    {\n        verify_flash_player();\n\n        auto str = (boost::wformat(L\"<invoke name=\\\"Next\\\" returntype=\\\"xml\\\"><arguments><array><property \"\n                                   L\"id=\\\"0\\\"><number>%1%</number></property></array></arguments></invoke>\") %\n                    layer)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking next-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        flash_producer_->call(std::move(params));\n    }\n\n    void update(int layer, const std::wstring& data) override\n    {\n        verify_flash_player();\n\n        auto str = (boost::wformat(L\"<invoke name=\\\"SetData\\\" returntype=\\\"xml\\\"><arguments><array><property \"\n                                   L\"id=\\\"0\\\"><number>%1%</number></property></array><string><![CDATA[%2%]]></string></\"\n                                   L\"arguments></invoke>\") %\n                    layer % data)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking update-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        flash_producer_->call(std::move(params));\n    }\n\n    std::wstring invoke(int layer, const std::wstring& label) override\n    {\n        verify_flash_player();\n\n        auto str = (boost::wformat(\n                        L\"<invoke name=\\\"Invoke\\\" returntype=\\\"xml\\\"><arguments><array><property \"\n                        L\"id=\\\"0\\\"><number>%1%</number></property></array><string>%2%</string></arguments></invoke>\") %\n                    layer % label)\n                       .str();\n        CASPAR_LOG(debug) << flash_producer_->print() << \" Invoking invoke-command: \" << str;\n        std::vector<std::wstring> params;\n        params.push_back(std::move(str));\n        // TODO: because of std::async deferred timed waiting does not work so for now we have to block\n        return flash_producer_->call(std::move(params)).get();\n    }\n};\n\nspl::shared_ptr<core::frame_producer> create_ct_producer(const core::frame_producer_dependencies& dependencies,\n                                                         const std::vector<std::wstring>&         params)\n{\n    if (params.empty() || !boost::filesystem::exists(get_absolute(env::media_folder(), params.at(0)) + L\".ct\"))\n        return core::frame_producer::empty();\n\n    auto flash_producer = flash::create_producer(dependencies, {});\n    auto producer       = flash_producer;\n    flash_cg_proxy(producer, env::media_folder()).add(0, params.at(0), true, L\"\", L\"\");\n\n    return producer;\n}\n\nvoid copy_template_hosts()\n{\n    try {\n        for (auto it = boost::filesystem::directory_iterator(env::initial_folder());\n             it != boost::filesystem::directory_iterator();\n             ++it) {\n            if (it->path().wstring().find(L\".fth\") != std::wstring::npos) {\n                auto from_path = *it;\n                auto to_path = boost::filesystem::path(env::template_folder() + L\"/\" + it->path().filename().wstring());\n\n                if (boost::filesystem::exists(to_path))\n                    boost::filesystem::remove(to_path);\n\n                boost::filesystem::copy_file(from_path, to_path);\n            }\n        }\n    } catch (...) {\n        CASPAR_LOG_CURRENT_EXCEPTION();\n        CASPAR_LOG(error) << L\"Failed to copy template-hosts from initial-path to template-path.\";\n    }\n}\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    if (env::properties().get(L\"configuration.flash.enabled\", false)) {\n        CASPAR_LOG(warning) << \"Flash is no longer a recommended way of creating dynamic templates. Adobe have \"\n                               \"declared flash end-of-life at the end of 2020, and we cannot guarantee it will \"\n                               \"continue to work in any version after that time.\\n\"\n                               \"All support for flash templates will be removed in a future release of CasparCG\";\n\n        copy_template_hosts();\n\n        dependencies.producer_registry->register_producer_factory(L\"Flash Producer (.ct)\", create_ct_producer);\n        dependencies.producer_registry->register_producer_factory(L\"Flash Producer (.swf)\", create_swf_producer);\n        dependencies.cg_registry->register_cg_producer(\n            L\"flash\",\n            {L\".ft\", L\".ct\"},\n            [](const spl::shared_ptr<core::frame_producer>& producer) {\n                return spl::make_shared<flash_cg_proxy>(producer);\n            },\n            [](const core::frame_producer_dependencies& dependencies, const std::wstring&) {\n                return flash::create_producer(dependencies, {});\n            },\n            true);\n    } else {\n        CASPAR_LOG(info) << \"Flash support is disabled\";\n    }\n}\n\nstd::wstring cg_version() { return L\"Unknown\"; }\n\nstd::wstring version()\n{\n    std::wstring version = L\"Not found\";\n#ifdef WIN32\n    HKEY hkey;\n\n    DWORD dwType, dwSize;\n    if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT(\"SOFTWARE\\\\Macromedia\\\\FlashPlayerActiveX\"), 0, KEY_QUERY_VALUE, &hkey) ==\n        ERROR_SUCCESS) {\n        wchar_t ver_str[1024];\n\n        dwType = REG_SZ;\n        dwSize = sizeof(ver_str);\n        RegQueryValueEx(hkey, TEXT(\"Version\"), nullptr, &dwType, reinterpret_cast<PBYTE>(&ver_str), &dwSize);\n\n        version = ver_str;\n\n        RegCloseKey(hkey);\n    }\n#endif\n    return version;\n}\n\n}} // namespace caspar::flash\n"
  },
  {
    "path": "src/modules/flash/flash.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace flash {\n\nvoid init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::flash\n"
  },
  {
    "path": "src/modules/flash/interop/Flash9e.IDL",
    "content": "// Generated .IDL file (by the OLE/COM Object Viewer)\n// \n// typelib filename: Flash9e.ocx\n\n[\n  uuid(D27CDB6B-AE6D-11CF-96B8-444553540000),\n  version(1.0),\n  helpstring(\"Shockwave Flash\"),\n  custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 100663662),\n  custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1180654890)\n\n]\nlibrary ShockwaveFlashObjects\n{\n    // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}\n    importlib(\"stdole2.tlb\");\n\n    // Forward declare all types defined in this typelib\n    interface IShockwaveFlash;\n    dispinterface _IShockwaveFlashEvents;\n    interface IFlashFactory;\n    interface IFlashObjectInterface;\n    interface IDispatchEx;\n    interface IServiceProvider;\n\n    [\n      odl,\n      uuid(D27CDB6C-AE6D-11CF-96B8-444553540000),\n      helpstring(\"Shockwave Flash\"),\n      dual,\n      oleautomation\n    ]\n    interface IShockwaveFlash : IDispatch {\n        [id(0xfffffdf3), propget, helpstring(\"property ReadyState\")]\n        HRESULT ReadyState([out, retval] long* pVal);\n        [id(0x0000007c), propget, helpstring(\"property TotalFrames\")]\n        HRESULT TotalFrames([out, retval] long* pVal);\n        [id(0x0000007d), propget, helpstring(\"property Playing\")]\n        HRESULT Playing([out, retval] VARIANT_BOOL* pVal);\n        [id(0x0000007d), propput, helpstring(\"property Playing\")]\n        HRESULT Playing([in] VARIANT_BOOL pVal);\n        [id(0x00000069), propget, helpstring(\"property Quality\")]\n        HRESULT Quality([out, retval] int* pVal);\n        [id(0x00000069), propput, helpstring(\"property Quality\")]\n        HRESULT Quality([in] int pVal);\n        [id(0x00000078), propget, helpstring(\"property ScaleMode\")]\n        HRESULT ScaleMode([out, retval] int* pVal);\n        [id(0x00000078), propput, helpstring(\"property ScaleMode\")]\n        HRESULT ScaleMode([in] int pVal);\n        [id(0x00000079), propget, helpstring(\"property AlignMode\")]\n        HRESULT AlignMode([out, retval] int* pVal);\n        [id(0x00000079), propput, helpstring(\"property AlignMode\")]\n        HRESULT AlignMode([in] int pVal);\n        [id(0x0000007b), propget, helpstring(\"property BackgroundColor\")]\n        HRESULT BackgroundColor([out, retval] long* pVal);\n        [id(0x0000007b), propput, helpstring(\"property BackgroundColor\")]\n        HRESULT BackgroundColor([in] long pVal);\n        [id(0x0000006a), propget, helpstring(\"property Loop\")]\n        HRESULT Loop([out, retval] VARIANT_BOOL* pVal);\n        [id(0x0000006a), propput, helpstring(\"property Loop\")]\n        HRESULT Loop([in] VARIANT_BOOL pVal);\n        [id(0x00000066), propget, helpstring(\"property Movie\")]\n        HRESULT Movie([out, retval] BSTR* pVal);\n        [id(0x00000066), propput, helpstring(\"property Movie\")]\n        HRESULT Movie([in] BSTR pVal);\n        [id(0x0000006b), propget, helpstring(\"property FrameNum\")]\n        HRESULT FrameNum([out, retval] long* pVal);\n        [id(0x0000006b), propput, helpstring(\"property FrameNum\")]\n        HRESULT FrameNum([in] long pVal);\n        [id(0x0000006d), helpstring(\"method SetZoomRect\")]\n        HRESULT SetZoomRect(\n                        [in] long left, \n                        [in] long top, \n                        [in] long right, \n                        [in] long bottom);\n        [id(0x00000076), helpstring(\"method Zoom\")]\n        HRESULT Zoom([in] int factor);\n        [id(0x00000077), helpstring(\"method Pan\")]\n        HRESULT Pan(\n                        [in] long x, \n                        [in] long y, \n                        [in] int mode);\n        [id(0x00000070), helpstring(\"method Play\")]\n        HRESULT Play();\n        [id(0x00000071), helpstring(\"method Stop\")]\n        HRESULT Stop();\n        [id(0x00000072), helpstring(\"method Back\")]\n        HRESULT Back();\n        [id(0x00000073), helpstring(\"method Forward\")]\n        HRESULT Forward();\n        [id(0x00000074), helpstring(\"method Rewind\")]\n        HRESULT Rewind();\n        [id(0x0000007e), helpstring(\"method StopPlay\")]\n        HRESULT StopPlay();\n        [id(0x0000007f), helpstring(\"method GotoFrame\")]\n        HRESULT GotoFrame([in] long FrameNum);\n        [id(0x00000080), helpstring(\"method CurrentFrame\")]\n        HRESULT CurrentFrame([out, retval] long* FrameNum);\n        [id(0x00000081), helpstring(\"method IsPlaying\")]\n        HRESULT IsPlaying([out, retval] VARIANT_BOOL* Playing);\n        [id(0x00000082), helpstring(\"method PercentLoaded\")]\n        HRESULT PercentLoaded([out, retval] long* percent);\n        [id(0x00000083), helpstring(\"method FrameLoaded\")]\n        HRESULT FrameLoaded(\n                        [in] long FrameNum, \n                        [out, retval] VARIANT_BOOL* loaded);\n        [id(0x00000084), helpstring(\"method FlashVersion\")]\n        HRESULT FlashVersion([out, retval] long* version);\n        [id(0x00000085), propget, helpstring(\"property WMode\")]\n        HRESULT WMode([out, retval] BSTR* pVal);\n        [id(0x00000085), propput, helpstring(\"property WMode\")]\n        HRESULT WMode([in] BSTR pVal);\n        [id(0x00000086), propget, helpstring(\"property SAlign\")]\n        HRESULT SAlign([out, retval] BSTR* pVal);\n        [id(0x00000086), propput, helpstring(\"property SAlign\")]\n        HRESULT SAlign([in] BSTR pVal);\n        [id(0x00000087), propget, helpstring(\"property Menu\")]\n        HRESULT Menu([out, retval] VARIANT_BOOL* pVal);\n        [id(0x00000087), propput, helpstring(\"property Menu\")]\n        HRESULT Menu([in] VARIANT_BOOL pVal);\n        [id(0x00000088), propget, helpstring(\"property Base\")]\n        HRESULT Base([out, retval] BSTR* pVal);\n        [id(0x00000088), propput, helpstring(\"property Base\")]\n        HRESULT Base([in] BSTR pVal);\n        [id(0x00000089), propget, helpstring(\"property Scale\")]\n        HRESULT Scale([out, retval] BSTR* pVal);\n        [id(0x00000089), propput, helpstring(\"property Scale\")]\n        HRESULT Scale([in] BSTR pVal);\n        [id(0x0000008a), propget, helpstring(\"property DeviceFont\")]\n        HRESULT DeviceFont([out, retval] VARIANT_BOOL* pVal);\n        [id(0x0000008a), propput, helpstring(\"property DeviceFont\")]\n        HRESULT DeviceFont([in] VARIANT_BOOL pVal);\n        [id(0x0000008b), propget, helpstring(\"property EmbedMovie\")]\n        HRESULT EmbedMovie([out, retval] VARIANT_BOOL* pVal);\n        [id(0x0000008b), propput, helpstring(\"property EmbedMovie\")]\n        HRESULT EmbedMovie([in] VARIANT_BOOL pVal);\n        [id(0x0000008c), propget, helpstring(\"property BGColor\")]\n        HRESULT BGColor([out, retval] BSTR* pVal);\n        [id(0x0000008c), propput, helpstring(\"property BGColor\")]\n        HRESULT BGColor([in] BSTR pVal);\n        [id(0x0000008d), propget, helpstring(\"property Quality2\")]\n        HRESULT Quality2([out, retval] BSTR* pVal);\n        [id(0x0000008d), propput, helpstring(\"property Quality2\")]\n        HRESULT Quality2([in] BSTR pVal);\n        [id(0x0000008e), helpstring(\"method LoadMovie\")]\n        HRESULT LoadMovie(\n                        [in] int layer, \n                        [in] BSTR url);\n        [id(0x0000008f), helpstring(\"method TGotoFrame\")]\n        HRESULT TGotoFrame(\n                        [in] BSTR target, \n                        [in] long FrameNum);\n        [id(0x00000090), helpstring(\"method TGotoLabel\")]\n        HRESULT TGotoLabel(\n                        [in] BSTR target, \n                        [in] BSTR label);\n        [id(0x00000091), helpstring(\"method TCurrentFrame\")]\n        HRESULT TCurrentFrame(\n                        [in] BSTR target, \n                        [out, retval] long* FrameNum);\n        [id(0x00000092), helpstring(\"method TCurrentLabel\")]\n        HRESULT TCurrentLabel(\n                        [in] BSTR target, \n                        [out, retval] BSTR* pVal);\n        [id(0x00000093), helpstring(\"method TPlay\")]\n        HRESULT TPlay([in] BSTR target);\n        [id(0x00000094), helpstring(\"method TStopPlay\")]\n        HRESULT TStopPlay([in] BSTR target);\n        [id(0x00000097), helpstring(\"method SetVariable\")]\n        HRESULT SetVariable(\n                        [in] BSTR name, \n                        [in] BSTR value);\n        [id(0x00000098), helpstring(\"method GetVariable\")]\n        HRESULT GetVariable(\n                        [in] BSTR name, \n                        [out, retval] BSTR* pVal);\n        [id(0x00000099), helpstring(\"method TSetProperty\")]\n        HRESULT TSetProperty(\n                        [in] BSTR target, \n                        [in] int property, \n                        [in] BSTR value);\n        [id(0x0000009a), helpstring(\"method TGetProperty\")]\n        HRESULT TGetProperty(\n                        [in] BSTR target, \n                        [in] int property, \n                        [out, retval] BSTR* pVal);\n        [id(0x0000009b), helpstring(\"method TCallFrame\")]\n        HRESULT TCallFrame(\n                        [in] BSTR target, \n                        [in] int FrameNum);\n        [id(0x0000009c), helpstring(\"method TCallLabel\")]\n        HRESULT TCallLabel(\n                        [in] BSTR target, \n                        [in] BSTR label);\n        [id(0x0000009d), helpstring(\"method TSetPropertyNum\")]\n        HRESULT TSetPropertyNum(\n                        [in] BSTR target, \n                        [in] int property, \n                        [in] double value);\n        [id(0x0000009e), helpstring(\"method TGetPropertyNum\")]\n        HRESULT TGetPropertyNum(\n                        [in] BSTR target, \n                        [in] int property, \n                        [out, retval] double* pVal);\n        [id(0x000000ac), helpstring(\"method TGetPropertyAsNumber\")]\n        HRESULT TGetPropertyAsNumber(\n                        [in] BSTR target, \n                        [in] int property, \n                        [out, retval] double* pVal);\n        [id(0x0000009f), propget, helpstring(\"property SWRemote\")]\n        HRESULT SWRemote([out, retval] BSTR* pVal);\n        [id(0x0000009f), propput, helpstring(\"property SWRemote\")]\n        HRESULT SWRemote([in] BSTR pVal);\n        [id(0x000000aa), propget, helpstring(\"property FlashVars\")]\n        HRESULT FlashVars([out, retval] BSTR* pVal);\n        [id(0x000000aa), propput, helpstring(\"property FlashVars\")]\n        HRESULT FlashVars([in] BSTR pVal);\n        [id(0x000000ab), propget, helpstring(\"property AllowScriptAccess\")]\n        HRESULT AllowScriptAccess([out, retval] BSTR* pVal);\n        [id(0x000000ab), propput, helpstring(\"property AllowScriptAccess\")]\n        HRESULT AllowScriptAccess([in] BSTR pVal);\n        [id(0x000000be), propget, helpstring(\"property MovieData\")]\n        HRESULT MovieData([out, retval] BSTR* pVal);\n        [id(0x000000be), propput, helpstring(\"property MovieData\")]\n        HRESULT MovieData([in] BSTR pVal);\n        [id(0x000000bf), propget, helpstring(\"property inline-data\")]\n        HRESULT InlineData([out, retval] IUnknown** ppIUnknown);\n        [id(0x000000bf), propput, helpstring(\"property inline-data\")]\n        HRESULT InlineData([in] IUnknown* ppIUnknown);\n        [id(0x000000c0), propget, helpstring(\"property SeamlessTabbing\")]\n        HRESULT SeamlessTabbing([out, retval] VARIANT_BOOL* pVal);\n        [id(0x000000c0), propput, helpstring(\"property SeamlessTabbing\")]\n        HRESULT SeamlessTabbing([in] VARIANT_BOOL pVal);\n        [id(0x000000c1), helpstring(\"method EnforceLocalSecurity\")]\n        HRESULT EnforceLocalSecurity();\n        [id(0x000000c2), propget, helpstring(\"property Profile\")]\n        HRESULT Profile([out, retval] VARIANT_BOOL* pVal);\n        [id(0x000000c2), propput, helpstring(\"property Profile\")]\n        HRESULT Profile([in] VARIANT_BOOL pVal);\n        [id(0x000000c3), propget, helpstring(\"property ProfileAddress\")]\n        HRESULT ProfileAddress([out, retval] BSTR* pVal);\n        [id(0x000000c3), propput, helpstring(\"property ProfileAddress\")]\n        HRESULT ProfileAddress([in] BSTR pVal);\n        [id(0x000000c4), propget, helpstring(\"property ProfilePort\")]\n        HRESULT ProfilePort([out, retval] long* pVal);\n        [id(0x000000c4), propput, helpstring(\"property ProfilePort\")]\n        HRESULT ProfilePort([in] long pVal);\n        [id(0x000000c6), helpstring(\"method Call\")]\n        HRESULT CallFunction(\n                        [in] BSTR request, \n                        [out, retval] BSTR* response);\n        [id(0x000000c7), helpstring(\"method SetReturnValue\")]\n        HRESULT SetReturnValue([in] BSTR returnValue);\n        [id(0x000000c8), helpstring(\"method DisableLocalSecurity\")]\n        HRESULT DisableLocalSecurity();\n        [id(0x000000c9), propget, helpstring(\"property AllowNetworking\")]\n        HRESULT AllowNetworking([out, retval] BSTR* pVal);\n        [id(0x000000c9), propput, helpstring(\"property AllowNetworking\")]\n        HRESULT AllowNetworking([in] BSTR pVal);\n        [id(0x000000ca), propget, helpstring(\"property AllowFullScreen\")]\n        HRESULT AllowFullScreen([out, retval] BSTR* pVal);\n        [id(0x000000ca), propput, helpstring(\"property AllowFullScreen\")]\n        HRESULT AllowFullScreen([in] BSTR pVal);\n    };\n\n    [\n      uuid(D27CDB6D-AE6D-11CF-96B8-444553540000),\n      helpstring(\"Event interface for Shockwave Flash\"),\n\t  hidden\n    ]\n    dispinterface _IShockwaveFlashEvents {\n        properties:\n        methods:\n            [id(0xfffffd9f)]\n            void OnReadyStateChange(long newState);\n            [id(0x000007a6)]\n            void OnProgress(long percentDone);\n            [id(0x00000096)]\n            void FSCommand(\n                            [in] BSTR command, \n                            [in] BSTR args);\n            [id(0x000000c5)]\n            void FlashCall([in] BSTR request);\n    };\n\n    [\n      uuid(D27CDB6E-AE6D-11CF-96B8-444553540000),\n      helpstring(\"Shockwave Flash\")\n    ]\n    coclass ShockwaveFlash {\n        [default] interface IShockwaveFlash;\n        [default, source] dispinterface _IShockwaveFlashEvents;\n    };\n\n    [\n      odl,\n      uuid(D27CDB70-AE6D-11CF-96B8-444553540000),\n      helpstring(\"IFlashFactory Interface\")\n    ]\n    interface IFlashFactory : IUnknown {\n    };\n\n    [\n      odl,\n      uuid(D27CDB72-AE6D-11CF-96B8-444553540000),\n      helpstring(\"IFlashObjectInterface Interface\")\n    ]\n    interface IFlashObjectInterface : IDispatchEx {\n    };\n\n    [\n      odl,\n      uuid(A6EF9860-C720-11D0-9337-00A0C90DCAA9)\n    ]\n    interface IDispatchEx : IDispatch {\n        HRESULT _stdcall GetDispID(\n                        [in] BSTR bstrName, \n                        [in] unsigned long grfdex, \n                        [out] long* pid);\n        HRESULT _stdcall RemoteInvokeEx(\n                        [in] long id, \n                        [in] unsigned long lcid, \n                        [in] unsigned long dwFlags, \n                        [in] DISPPARAMS* pdp, \n                        [out] VARIANT* pvarRes, \n                        [out] EXCEPINFO* pei, \n                        [in] IServiceProvider* pspCaller, \n                        [in] unsigned int cvarRefArg, \n                        [in] unsigned int* rgiRefArg, \n                        [in, out] VARIANT* rgvarRefArg);\n        HRESULT _stdcall DeleteMemberByName(\n                        [in] BSTR bstrName, \n                        [in] unsigned long grfdex);\n        HRESULT _stdcall DeleteMemberByDispID([in] long id);\n        HRESULT _stdcall GetMemberProperties(\n                        [in] long id, \n                        [in] unsigned long grfdexFetch, \n                        [out] unsigned long* pgrfdex);\n        HRESULT _stdcall GetMemberName(\n                        [in] long id, \n                        [out] BSTR* pbstrName);\n        HRESULT _stdcall GetNextDispID(\n                        [in] unsigned long grfdex, \n                        [in] long id, \n                        [out] long* pid);\n        HRESULT _stdcall GetNameSpaceParent([out] IUnknown** ppunk);\n    };\n\n    [\n      odl,\n      uuid(6D5140C1-7436-11CE-8034-00AA006009FA)\n    ]\n    interface IServiceProvider : IUnknown {\n        HRESULT _stdcall RemoteQueryService(\n                        [in] GUID* guidService, \n                        [in] GUID* riid, \n                        [out] IUnknown** ppvObject);\n    };\n\n    [\n      uuid(D27CDB71-AE6D-11CF-96B8-444553540000),\n      helpstring(\"IFlashObjectInterface Interface\")\n    ]\n    coclass FlashObjectInterface {\n        [default] interface IFlashObjectInterface;\n    };\n};\n"
  },
  {
    "path": "src/modules/flash/interop/Flash9e_i.c",
    "content": "\n\n/* this ALWAYS GENERATED file contains the IIDs and CLSIDs */\n\n/* link this file in with the server and any clients */\n\n\n /* File created by MIDL compiler version 6.00.0366 */\n/* at Tue Mar 18 13:05:00 2008\n */\n/* Compiler settings for .\\flash\\Flash9e.IDL:\n    Oicf, W4, Zp8, env=Win32 (32b run)\n    protocol : dce , ms_ext, c_ext, robust\n    error checks: allocation ref bounds_check enum stub_data \n    VC __declspec() decoration level: \n         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\n         DECLSPEC_UUID(), MIDL_INTERFACE()\n*/\n//@@MIDL_FILE_HEADING(  )\n\n#pragma warning( disable: 4049 )  /* more than 64k source lines */\n\n\n#ifdef __cplusplus\nextern \"C\"{\n#endif \n\n\n#include <rpc.h>\n\n#ifdef _MIDL_USE_GUIDDEF_\n\n#ifndef INITGUID\n#define INITGUID\n#include <guiddef.h>\n#undef INITGUID\n#else\n#include <guiddef.h>\n#endif\n\n#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n        DEFINE_GUID(name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8)\n\n#else // !_MIDL_USE_GUIDDEF_\n\n#ifndef __IID_DEFINED__\n#define __IID_DEFINED__\n\ntypedef struct _IID\n{\n    unsigned long x;\n    unsigned short s1;\n    unsigned short s2;\n    unsigned char  c[8];\n} IID;\n\n#endif // __IID_DEFINED__\n\n#ifndef CLSID_DEFINED\n#define CLSID_DEFINED\ntypedef IID CLSID;\n#endif // CLSID_DEFINED\n\n#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \\\n        const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}\n\n#endif !_MIDL_USE_GUIDDEF_\n\nMIDL_DEFINE_GUID(IID, LIBID_ShockwaveFlashObjects,0xD27CDB6B,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n\nMIDL_DEFINE_GUID(IID, IID_IShockwaveFlash,0xD27CDB6C,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n\nMIDL_DEFINE_GUID(IID, DIID__IShockwaveFlashEvents,0xD27CDB6D,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n\nMIDL_DEFINE_GUID(IID, IID_IFlashFactory,0xD27CDB70,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n\nMIDL_DEFINE_GUID(IID, IID_IDispatchEx,0xA6EF9860,0xC720,0x11D0,0x93,0x37,0x00,0xA0,0xC9,0x0D,0xCA,0xA9);\n\n\nMIDL_DEFINE_GUID(IID, IID_IFlashObjectInterface,0xD27CDB72,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n\nMIDL_DEFINE_GUID(IID, IID_IServiceProvider,0x6D5140C1,0x7436,0x11CE,0x80,0x34,0x00,0xAA,0x00,0x60,0x09,0xFA);\n\n\nMIDL_DEFINE_GUID(CLSID, CLSID_ShockwaveFlash,0xD27CDB6E,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n\nMIDL_DEFINE_GUID(CLSID, CLSID_FlashObjectInterface,0xD27CDB71,0xAE6D,0x11CF,0x96,0xB8,0x44,0x45,0x53,0x54,0x00,0x00);\n\n#undef MIDL_DEFINE_GUID\n\n#ifdef __cplusplus\n}\n#endif\n\n\n\n"
  },
  {
    "path": "src/modules/flash/interop/TimerHelper.h",
    "content": "/*\n* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\n*\n*  This file is part of CasparCG.\n*\n*    CasparCG 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*    CasparCG 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 CasparCG.  If not, see <http://www.gnu.org/licenses/>.\n*\n*/\n\n#ifndef _TIMER_HELPER_H__\n#define _TIMER_HELPER_H__\n\n#include \"FlashAxContainer.h\"\n\nnamespace caspar { namespace flash {\n\nclass TimerHelper\n{\n    TimerHelper(const TimerHelper&);\n    const TimerHelper& operator=(const TimerHelper&);\n\n  public:\n    TimerHelper() {}\n    TimerHelper(DWORD id, DWORD first, DWORD interv, ITimerSink* pTS)\n        : ID(id)\n        , firstTime(first)\n        , interval(interv)\n        , currentTime(first)\n        , pTimerSink(pTS)\n    {\n    }\n\n    ~TimerHelper() {}\n    void Setup(DWORD id, DWORD first, DWORD interv, ITimerSink* pTS)\n    {\n        ID          = id;\n        firstTime   = first;\n        interval    = interv;\n        currentTime = first;\n        pTimerSink  = pTS;\n    }\n\n    DWORD\n    Invoke()\n    {\n        if (pTimerSink != nullptr) {\n            VARIANT value;\n            value.vt    = VT_UI4;\n            value.ulVal = currentTime;\n\n            pTimerSink->OnTimer(value);\n            currentTime += interval;\n        }\n        return currentTime;\n    }\n\n    DWORD                    ID;\n    DWORD                    firstTime;\n    DWORD                    interval;\n    DWORD                    currentTime;\n    ATL::CComPtr<ITimerSink> pTimerSink;\n};\n\n}} // namespace caspar::flash\n\n#endif //_TIMER_HELPER_H__"
  },
  {
    "path": "src/modules/flash/interop/axflash.h",
    "content": "\n\n/* this ALWAYS GENERATED file contains the definitions for the interfaces */\n\n/* File created by MIDL compiler version 6.00.0366 */\n/* at Tue Mar 18 13:05:00 2008\n */\n/* Compiler settings for .\\flash\\Flash9e.IDL:\n    Oicf, W4, Zp8, env=Win32 (32b run)\n    protocol : dce , ms_ext, c_ext, robust\n    error checks: allocation ref bounds_check enum stub_data\n    VC __declspec() decoration level:\n         __declspec(uuid()), __declspec(selectany), __declspec(novtable)\n         DECLSPEC_UUID(), MIDL_INTERFACE()\n*/\n//@@MIDL_FILE_HEADING(  )\n\n#pragma warning(disable : 4049) /* more than 64k source lines */\n\n/* verify that the <rpcndr.h> version is high enough to compile this file*/\n#ifndef __REQUIRED_RPCNDR_H_VERSION__\n#define __REQUIRED_RPCNDR_H_VERSION__ 475\n#endif\n\n#include \"rpc.h\"\n#include \"rpcndr.h\"\n#include <dispex.h>\n\n#ifndef __RPCNDR_H_VERSION__\n#error this stub requires an updated version of <rpcndr.h>\n#endif // __RPCNDR_H_VERSION__\n\n#ifndef __axflash_h__\n#define __axflash_h__\n\n#if defined(_MSC_VER) && (_MSC_VER >= 1020)\n#pragma once\n#endif\n\n/* Forward Declarations */\n\n#ifndef __IShockwaveFlash_FWD_DEFINED__\n#define __IShockwaveFlash_FWD_DEFINED__\ntypedef interface IShockwaveFlash IShockwaveFlash;\n#endif /* __IShockwaveFlash_FWD_DEFINED__ */\n\n#ifndef ___IShockwaveFlashEvents_FWD_DEFINED__\n#define ___IShockwaveFlashEvents_FWD_DEFINED__\ntypedef interface _IShockwaveFlashEvents _IShockwaveFlashEvents;\n#endif /* ___IShockwaveFlashEvents_FWD_DEFINED__ */\n\n#ifndef __IFlashFactory_FWD_DEFINED__\n#define __IFlashFactory_FWD_DEFINED__\ntypedef interface IFlashFactory IFlashFactory;\n#endif /* __IFlashFactory_FWD_DEFINED__ */\n\n#ifndef __IDispatchEx_FWD_DEFINED__\n#define __IDispatchEx_FWD_DEFINED__\ntypedef interface IDispatchEx IDispatchEx;\n#endif /* __IDispatchEx_FWD_DEFINED__ */\n\n#ifndef __IFlashObjectInterface_FWD_DEFINED__\n#define __IFlashObjectInterface_FWD_DEFINED__\ntypedef interface IFlashObjectInterface IFlashObjectInterface;\n#endif /* __IFlashObjectInterface_FWD_DEFINED__ */\n\n#ifndef __IServiceProvider_FWD_DEFINED__\n#define __IServiceProvider_FWD_DEFINED__\ntypedef interface IServiceProvider IServiceProvider;\n#endif /* __IServiceProvider_FWD_DEFINED__ */\n\n#ifndef __ShockwaveFlash_FWD_DEFINED__\n#define __ShockwaveFlash_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class ShockwaveFlash ShockwaveFlash;\n#else\ntypedef struct ShockwaveFlash       ShockwaveFlash;\n#endif /* __cplusplus */\n\n#endif /* __ShockwaveFlash_FWD_DEFINED__ */\n\n#ifndef __FlashObjectInterface_FWD_DEFINED__\n#define __FlashObjectInterface_FWD_DEFINED__\n\n#ifdef __cplusplus\ntypedef class FlashObjectInterface FlashObjectInterface;\n#else\ntypedef struct FlashObjectInterface FlashObjectInterface;\n#endif /* __cplusplus */\n\n#endif /* __FlashObjectInterface_FWD_DEFINED__ */\n\n#ifdef __cplusplus\nextern \"C\"\n{\n#endif\n\n    void* __RPC_USER MIDL_user_allocate(size_t);\n    void __RPC_USER MIDL_user_free(void*);\n\n#ifndef __ShockwaveFlashObjects_LIBRARY_DEFINED__\n#define __ShockwaveFlashObjects_LIBRARY_DEFINED__\n\n    /* library ShockwaveFlashObjects */\n    /* [custom][custom][helpstring][version][uuid] */\n\n    EXTERN_C const IID LIBID_ShockwaveFlashObjects;\n\n#ifndef __IShockwaveFlash_INTERFACE_DEFINED__\n#define __IShockwaveFlash_INTERFACE_DEFINED__\n\n    /* interface IShockwaveFlash */\n    /* [object][oleautomation][dual][helpstring][uuid] */\n\n    EXTERN_C const IID IID_IShockwaveFlash;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n\n    MIDL_INTERFACE(\"D27CDB6C-AE6D-11CF-96B8-444553540000\")\n    IShockwaveFlash : public IDispatch\n    {\n      public:\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ReadyState(\n            /* [retval][out] */ long* pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_TotalFrames(\n            /* [retval][out] */ long* pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Playing(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Playing(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Quality(\n            /* [retval][out] */ int* pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Quality(\n            /* [in] */ int pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ScaleMode(\n            /* [retval][out] */ int* pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_ScaleMode(\n            /* [in] */ int pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AlignMode(\n            /* [retval][out] */ int* pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AlignMode(\n            /* [in] */ int pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_BackgroundColor(\n            /* [retval][out] */ long* pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_BackgroundColor(\n            /* [in] */ long pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Loop(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Loop(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Movie(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Movie(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE receiveNum(\n            /* [retval][out] */ long* pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_FrameNum(\n            /* [in] */ long pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetZoomRect(\n            /* [in] */ long left,\n            /* [in] */ long top,\n            /* [in] */ long right,\n            /* [in] */ long bottom) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Zoom(\n            /* [in] */ int factor) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Pan(\n            /* [in] */ long x,\n            /* [in] */ long y,\n            /* [in] */ int  mode) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Play(void) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Stop(void) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Back(void) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Forward(void) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE Rewind(void) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE StopPlay(void) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GotoFrame(\n            /* [in] */ long FrameNum) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CurrentFrame(\n            /* [retval][out] */ long* FrameNum) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IsPlaying(\n            /* [retval][out] */ VARIANT_BOOL * Playing) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE PercentLoaded(\n            /* [retval][out] */ long* percent) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FrameLoaded(\n            /* [in] */ long                   FrameNum,\n            /* [retval][out] */ VARIANT_BOOL* loaded) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE FlashVersion(\n            /* [retval][out] */ long* version) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_WMode(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_WMode(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_SAlign(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_SAlign(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Menu(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Menu(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Base(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Base(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Scale(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Scale(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_DeviceFont(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_DeviceFont(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_EmbedMovie(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_EmbedMovie(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_BGColor(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_BGColor(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Quality2(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Quality2(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE LoadMovie(\n            /* [in] */ int  layer,\n            /* [in] */ BSTR url) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGotoFrame(\n            /* [in] */ BSTR target,\n            /* [in] */ long FrameNum) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGotoLabel(\n            /* [in] */ BSTR target,\n            /* [in] */ BSTR label) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCurrentFrame(\n            /* [in] */ BSTR           target,\n            /* [retval][out] */ long* FrameNum) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCurrentLabel(\n            /* [in] */ BSTR target,\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TPlay(\n            /* [in] */ BSTR target) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TStopPlay(\n            /* [in] */ BSTR target) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetVariable(\n            /* [in] */ BSTR name,\n            /* [in] */ BSTR value) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetVariable(\n            /* [in] */ BSTR name,\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TSetProperty(\n            /* [in] */ BSTR target,\n            /* [in] */ int  property,\n            /* [in] */ BSTR value) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGetProperty(\n            /* [in] */ BSTR           target,\n            /* [in] */ int            property,\n            /* [retval][out] */ BSTR* pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCallFrame(\n            /* [in] */ BSTR target,\n            /* [in] */ int  FrameNum) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TCallLabel(\n            /* [in] */ BSTR target,\n            /* [in] */ BSTR label) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TSetPropertyNum(\n            /* [in] */ BSTR   target,\n            /* [in] */ int    property,\n            /* [in] */ double value) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGetPropertyNum(\n            /* [in] */ BSTR             target,\n            /* [in] */ int              property,\n            /* [retval][out] */ double* pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE TGetPropertyAsNumber(\n            /* [in] */ BSTR             target,\n            /* [in] */ int              property,\n            /* [retval][out] */ double* pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_SWRemote(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_SWRemote(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_FlashVars(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_FlashVars(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AllowScriptAccess(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AllowScriptAccess(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_MovieData(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_MovieData(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_InlineData(\n            /* [retval][out] */ IUnknown * *ppIUnknown) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_InlineData(\n            /* [in] */ IUnknown * ppIUnknown) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_SeamlessTabbing(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_SeamlessTabbing(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE EnforceLocalSecurity(void) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_Profile(\n            /* [retval][out] */ VARIANT_BOOL * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_Profile(\n            /* [in] */ VARIANT_BOOL pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ProfileAddress(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_ProfileAddress(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_ProfilePort(\n            /* [retval][out] */ long* pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_ProfilePort(\n            /* [in] */ long pVal) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE CallFunction(\n            /* [in] */ BSTR request,\n            /* [retval][out] */ BSTR * response) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE SetReturnValue(\n            /* [in] */ BSTR returnValue) = 0;\n\n        virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE DisableLocalSecurity(void) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AllowNetworking(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AllowNetworking(\n            /* [in] */ BSTR pVal) = 0;\n\n        virtual /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE get_AllowFullScreen(\n            /* [retval][out] */ BSTR * pVal) = 0;\n\n        virtual /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE put_AllowFullScreen(\n            /* [in] */ BSTR pVal) = 0;\n    };\n\n#else /* C style interface */\n\n    typedef struct IShockwaveFlashVtbl\n    {\n        BEGIN_INTERFACE\n\n        HRESULT(STDMETHODCALLTYPE* QueryInterface)\n        (IShockwaveFlash*           This,\n         /* [in] */ REFIID          riid,\n         /* [iid_is][out] */ void** ppvObject);\n\n        ULONG(STDMETHODCALLTYPE* AddRef)(IShockwaveFlash* This);\n\n        ULONG(STDMETHODCALLTYPE* Release)(IShockwaveFlash* This);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount)\n        (IShockwaveFlash*  This,\n         /* [out] */ UINT* pctinfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfo)\n        (IShockwaveFlash*        This,\n         /* [in] */ UINT         iTInfo,\n         /* [in] */ LCID         lcid,\n         /* [out] */ ITypeInfo** ppTInfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetIDsOfNames)\n        (IShockwaveFlash*              This,\n         /* [in] */ REFIID             riid,\n         /* [size_is][in] */ LPOLESTR* rgszNames,\n         /* [in] */ UINT               cNames,\n         /* [in] */ LCID               lcid,\n         /* [size_is][out] */ DISPID*  rgDispId);\n\n        /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke)(IShockwaveFlash*            This,\n                                                         /* [in] */ DISPID           dispIdMember,\n                                                         /* [in] */ REFIID           riid,\n                                                         /* [in] */ LCID             lcid,\n                                                         /* [in] */ WORD             wFlags,\n                                                         /* [out][in] */ DISPPARAMS* pDispParams,\n                                                         /* [out] */ VARIANT*        pVarResult,\n                                                         /* [out] */ EXCEPINFO*      pExcepInfo,\n                                                         /* [out] */ UINT*           puArgErr);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_ReadyState)(IShockwaveFlash*          This,\n                                                                                   /* [retval][out] */ long* pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_TotalFrames)(IShockwaveFlash*          This,\n                                                                                    /* [retval][out] */ long* pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Playing)(IShockwaveFlash*                  This,\n                                                                                /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Playing)(IShockwaveFlash*        This,\n                                                                                /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Quality)(IShockwaveFlash*         This,\n                                                                                /* [retval][out] */ int* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Quality)(IShockwaveFlash* This,\n                                                                                /* [in] */ int   pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_ScaleMode)(IShockwaveFlash*         This,\n                                                                                  /* [retval][out] */ int* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_ScaleMode)(IShockwaveFlash* This,\n                                                                                  /* [in] */ int   pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_AlignMode)(IShockwaveFlash*         This,\n                                                                                  /* [retval][out] */ int* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_AlignMode)(IShockwaveFlash* This,\n                                                                                  /* [in] */ int   pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_BackgroundColor)(IShockwaveFlash*          This,\n                                                                                        /* [retval][out] */ long* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_BackgroundColor)(IShockwaveFlash* This,\n                                                                                        /* [in] */ long  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Loop)(IShockwaveFlash*                  This,\n                                                                             /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Loop)(IShockwaveFlash*        This,\n                                                                             /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Movie)(IShockwaveFlash*          This,\n                                                                              /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Movie)(IShockwaveFlash* This,\n                                                                              /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* receiveNum)(IShockwaveFlash*          This,\n                                                                               /* [retval][out] */ long* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_FrameNum)(IShockwaveFlash* This,\n                                                                                 /* [in] */ long  pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* SetZoomRect)(IShockwaveFlash* This,\n                                                                       /* [in] */ long  left,\n                                                                       /* [in] */ long  top,\n                                                                       /* [in] */ long  right,\n                                                                       /* [in] */ long  bottom);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Zoom)(IShockwaveFlash* This,\n                                                                /* [in] */ int   factor);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Pan)(IShockwaveFlash* This,\n                                                               /* [in] */ long  x,\n                                                               /* [in] */ long  y,\n                                                               /* [in] */ int   mode);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Play)(IShockwaveFlash* This);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Stop)(IShockwaveFlash* This);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Back)(IShockwaveFlash* This);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Forward)(IShockwaveFlash* This);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* Rewind)(IShockwaveFlash* This);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* StopPlay)(IShockwaveFlash* This);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* GotoFrame)(IShockwaveFlash* This,\n                                                                     /* [in] */ long  FrameNum);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* CurrentFrame)(IShockwaveFlash*          This,\n                                                                        /* [retval][out] */ long* FrameNum);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* IsPlaying)(IShockwaveFlash*                  This,\n                                                                     /* [retval][out] */ VARIANT_BOOL* Playing);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* PercentLoaded)(IShockwaveFlash*          This,\n                                                                         /* [retval][out] */ long* percent);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* FrameLoaded)(IShockwaveFlash*                  This,\n                                                                       /* [in] */ long                   FrameNum,\n                                                                       /* [retval][out] */ VARIANT_BOOL* loaded);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* FlashVersion)(IShockwaveFlash*          This,\n                                                                        /* [retval][out] */ long* version);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_WMode)(IShockwaveFlash*          This,\n                                                                              /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_WMode)(IShockwaveFlash* This,\n                                                                              /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_SAlign)(IShockwaveFlash*          This,\n                                                                               /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_SAlign)(IShockwaveFlash* This,\n                                                                               /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Menu)(IShockwaveFlash*                  This,\n                                                                             /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Menu)(IShockwaveFlash*        This,\n                                                                             /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Base)(IShockwaveFlash*          This,\n                                                                             /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Base)(IShockwaveFlash* This,\n                                                                             /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Scale)(IShockwaveFlash*          This,\n                                                                              /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Scale)(IShockwaveFlash* This,\n                                                                              /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_DeviceFont)(\n            IShockwaveFlash*                  This,\n            /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_DeviceFont)(IShockwaveFlash*        This,\n                                                                                   /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_EmbedMovie)(\n            IShockwaveFlash*                  This,\n            /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_EmbedMovie)(IShockwaveFlash*        This,\n                                                                                   /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_BGColor)(IShockwaveFlash*          This,\n                                                                                /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_BGColor)(IShockwaveFlash* This,\n                                                                                /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Quality2)(IShockwaveFlash*          This,\n                                                                                 /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Quality2)(IShockwaveFlash* This,\n                                                                                 /* [in] */ BSTR  pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* LoadMovie)(IShockwaveFlash* This,\n                                                                     /* [in] */ int   layer,\n                                                                     /* [in] */ BSTR  url);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TGotoFrame)(IShockwaveFlash* This,\n                                                                      /* [in] */ BSTR  target,\n                                                                      /* [in] */ long  FrameNum);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TGotoLabel)(IShockwaveFlash* This,\n                                                                      /* [in] */ BSTR  target,\n                                                                      /* [in] */ BSTR  label);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TCurrentFrame)(IShockwaveFlash*          This,\n                                                                         /* [in] */ BSTR           target,\n                                                                         /* [retval][out] */ long* FrameNum);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TCurrentLabel)(IShockwaveFlash*          This,\n                                                                         /* [in] */ BSTR           target,\n                                                                         /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TPlay)(IShockwaveFlash* This,\n                                                                 /* [in] */ BSTR  target);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TStopPlay)(IShockwaveFlash* This,\n                                                                     /* [in] */ BSTR  target);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* SetVariable)(IShockwaveFlash* This,\n                                                                       /* [in] */ BSTR  name,\n                                                                       /* [in] */ BSTR  value);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* GetVariable)(IShockwaveFlash*          This,\n                                                                       /* [in] */ BSTR           name,\n                                                                       /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TSetProperty)(IShockwaveFlash* This,\n                                                                        /* [in] */ BSTR  target,\n                                                                        /* [in] */ int   property,\n                                                                        /* [in] */ BSTR  value);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TGetProperty)(IShockwaveFlash*          This,\n                                                                        /* [in] */ BSTR           target,\n                                                                        /* [in] */ int            property,\n                                                                        /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TCallFrame)(IShockwaveFlash* This,\n                                                                      /* [in] */ BSTR  target,\n                                                                      /* [in] */ int   FrameNum);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TCallLabel)(IShockwaveFlash* This,\n                                                                      /* [in] */ BSTR  target,\n                                                                      /* [in] */ BSTR  label);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TSetPropertyNum)(IShockwaveFlash*  This,\n                                                                           /* [in] */ BSTR   target,\n                                                                           /* [in] */ int    property,\n                                                                           /* [in] */ double value);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TGetPropertyNum)(IShockwaveFlash*            This,\n                                                                           /* [in] */ BSTR             target,\n                                                                           /* [in] */ int              property,\n                                                                           /* [retval][out] */ double* pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* TGetPropertyAsNumber)(IShockwaveFlash*            This,\n                                                                                /* [in] */ BSTR             target,\n                                                                                /* [in] */ int              property,\n                                                                                /* [retval][out] */ double* pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_SWRemote)(IShockwaveFlash*          This,\n                                                                                 /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_SWRemote)(IShockwaveFlash* This,\n                                                                                 /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_FlashVars)(IShockwaveFlash*          This,\n                                                                                  /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_FlashVars)(IShockwaveFlash* This,\n                                                                                  /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_AllowScriptAccess)(\n            IShockwaveFlash*          This,\n            /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_AllowScriptAccess)(IShockwaveFlash* This,\n                                                                                          /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_MovieData)(IShockwaveFlash*          This,\n                                                                                  /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_MovieData)(IShockwaveFlash* This,\n                                                                                  /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_InlineData)(\n            IShockwaveFlash*               This,\n            /* [retval][out] */ IUnknown** ppIUnknown);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_InlineData)(IShockwaveFlash*     This,\n                                                                                   /* [in] */ IUnknown* ppIUnknown);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_SeamlessTabbing)(\n            IShockwaveFlash*                  This,\n            /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_SeamlessTabbing)(IShockwaveFlash*        This,\n                                                                                        /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* EnforceLocalSecurity)(IShockwaveFlash* This);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_Profile)(IShockwaveFlash*                  This,\n                                                                                /* [retval][out] */ VARIANT_BOOL* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_Profile)(IShockwaveFlash*        This,\n                                                                                /* [in] */ VARIANT_BOOL pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_ProfileAddress)(IShockwaveFlash*          This,\n                                                                                       /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_ProfileAddress)(IShockwaveFlash* This,\n                                                                                       /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_ProfilePort)(IShockwaveFlash*          This,\n                                                                                    /* [retval][out] */ long* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_ProfilePort)(IShockwaveFlash* This,\n                                                                                    /* [in] */ long  pVal);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* CallFunction)(IShockwaveFlash*          This,\n                                                                        /* [in] */ BSTR           request,\n                                                                        /* [retval][out] */ BSTR* response);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* SetReturnValue)(IShockwaveFlash* This,\n                                                                          /* [in] */ BSTR  returnValue);\n\n        /* [helpstring][id] */ HRESULT(STDMETHODCALLTYPE* DisableLocalSecurity)(IShockwaveFlash* This);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_AllowNetworking)(IShockwaveFlash*          This,\n                                                                                        /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_AllowNetworking)(IShockwaveFlash* This,\n                                                                                        /* [in] */ BSTR  pVal);\n\n        /* [helpstring][propget][id] */ HRESULT(STDMETHODCALLTYPE* get_AllowFullScreen)(IShockwaveFlash*          This,\n                                                                                        /* [retval][out] */ BSTR* pVal);\n\n        /* [helpstring][propput][id] */ HRESULT(STDMETHODCALLTYPE* put_AllowFullScreen)(IShockwaveFlash* This,\n                                                                                        /* [in] */ BSTR  pVal);\n\n        END_INTERFACE\n    } IShockwaveFlashVtbl;\n\n    interface IShockwaveFlash { CONST_VTBL struct IShockwaveFlashVtbl* lpVtbl; };\n\n#ifdef COBJMACROS\n\n#define IShockwaveFlash_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\n\n#define IShockwaveFlash_AddRef(This) (This)->lpVtbl->AddRef(This)\n\n#define IShockwaveFlash_Release(This) (This)->lpVtbl->Release(This)\n\n#define IShockwaveFlash_GetTypeInfoCount(This, pctinfo) (This)->lpVtbl->GetTypeInfoCount(This, pctinfo)\n\n#define IShockwaveFlash_GetTypeInfo(This, iTInfo, lcid, ppTInfo)                                                       \\\n    (This)->lpVtbl->GetTypeInfo(This, iTInfo, lcid, ppTInfo)\n\n#define IShockwaveFlash_GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)                                   \\\n    (This)->lpVtbl->GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)\n\n#define IShockwaveFlash_Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)  \\\n    (This)->lpVtbl->Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)\n\n#define IShockwaveFlash_get_ReadyState(This, pVal) (This)->lpVtbl->get_ReadyState(This, pVal)\n\n#define IShockwaveFlash_get_TotalFrames(This, pVal) (This)->lpVtbl->get_TotalFrames(This, pVal)\n\n#define IShockwaveFlash_get_Playing(This, pVal) (This)->lpVtbl->get_Playing(This, pVal)\n\n#define IShockwaveFlash_put_Playing(This, pVal) (This)->lpVtbl->put_Playing(This, pVal)\n\n#define IShockwaveFlash_get_Quality(This, pVal) (This)->lpVtbl->get_Quality(This, pVal)\n\n#define IShockwaveFlash_put_Quality(This, pVal) (This)->lpVtbl->put_Quality(This, pVal)\n\n#define IShockwaveFlash_get_ScaleMode(This, pVal) (This)->lpVtbl->get_ScaleMode(This, pVal)\n\n#define IShockwaveFlash_put_ScaleMode(This, pVal) (This)->lpVtbl->put_ScaleMode(This, pVal)\n\n#define IShockwaveFlash_get_AlignMode(This, pVal) (This)->lpVtbl->get_AlignMode(This, pVal)\n\n#define IShockwaveFlash_put_AlignMode(This, pVal) (This)->lpVtbl->put_AlignMode(This, pVal)\n\n#define IShockwaveFlash_get_BackgroundColor(This, pVal) (This)->lpVtbl->get_BackgroundColor(This, pVal)\n\n#define IShockwaveFlash_put_BackgroundColor(This, pVal) (This)->lpVtbl->put_BackgroundColor(This, pVal)\n\n#define IShockwaveFlash_get_Loop(This, pVal) (This)->lpVtbl->get_Loop(This, pVal)\n\n#define IShockwaveFlash_put_Loop(This, pVal) (This)->lpVtbl->put_Loop(This, pVal)\n\n#define IShockwaveFlash_get_Movie(This, pVal) (This)->lpVtbl->get_Movie(This, pVal)\n\n#define IShockwaveFlash_put_Movie(This, pVal) (This)->lpVtbl->put_Movie(This, pVal)\n\n#define IShockwaveFlash_receiveNum(This, pVal) (This)->lpVtbl->receiveNum(This, pVal)\n\n#define IShockwaveFlash_put_FrameNum(This, pVal) (This)->lpVtbl->put_FrameNum(This, pVal)\n\n#define IShockwaveFlash_SetZoomRect(This, left, top, right, bottom)                                                    \\\n    (This)->lpVtbl->SetZoomRect(This, left, top, right, bottom)\n\n#define IShockwaveFlash_Zoom(This, factor) (This)->lpVtbl->Zoom(This, factor)\n\n#define IShockwaveFlash_Pan(This, x, y, mode) (This)->lpVtbl->Pan(This, x, y, mode)\n\n#define IShockwaveFlash_Play(This) (This)->lpVtbl->Play(This)\n\n#define IShockwaveFlash_Stop(This) (This)->lpVtbl->Stop(This)\n\n#define IShockwaveFlash_Back(This) (This)->lpVtbl->Back(This)\n\n#define IShockwaveFlash_Forward(This) (This)->lpVtbl->Forward(This)\n\n#define IShockwaveFlash_Rewind(This) (This)->lpVtbl->Rewind(This)\n\n#define IShockwaveFlash_StopPlay(This) (This)->lpVtbl->StopPlay(This)\n\n#define IShockwaveFlash_GotoFrame(This, FrameNum) (This)->lpVtbl->GotoFrame(This, FrameNum)\n\n#define IShockwaveFlash_CurrentFrame(This, FrameNum) (This)->lpVtbl->CurrentFrame(This, FrameNum)\n\n#define IShockwaveFlash_IsPlaying(This, Playing) (This)->lpVtbl->IsPlaying(This, Playing)\n\n#define IShockwaveFlash_PercentLoaded(This, percent) (This)->lpVtbl->PercentLoaded(This, percent)\n\n#define IShockwaveFlash_FrameLoaded(This, FrameNum, loaded) (This)->lpVtbl->FrameLoaded(This, FrameNum, loaded)\n\n#define IShockwaveFlash_FlashVersion(This, version) (This)->lpVtbl->FlashVersion(This, version)\n\n#define IShockwaveFlash_get_WMode(This, pVal) (This)->lpVtbl->get_WMode(This, pVal)\n\n#define IShockwaveFlash_put_WMode(This, pVal) (This)->lpVtbl->put_WMode(This, pVal)\n\n#define IShockwaveFlash_get_SAlign(This, pVal) (This)->lpVtbl->get_SAlign(This, pVal)\n\n#define IShockwaveFlash_put_SAlign(This, pVal) (This)->lpVtbl->put_SAlign(This, pVal)\n\n#define IShockwaveFlash_get_Menu(This, pVal) (This)->lpVtbl->get_Menu(This, pVal)\n\n#define IShockwaveFlash_put_Menu(This, pVal) (This)->lpVtbl->put_Menu(This, pVal)\n\n#define IShockwaveFlash_get_Base(This, pVal) (This)->lpVtbl->get_Base(This, pVal)\n\n#define IShockwaveFlash_put_Base(This, pVal) (This)->lpVtbl->put_Base(This, pVal)\n\n#define IShockwaveFlash_get_Scale(This, pVal) (This)->lpVtbl->get_Scale(This, pVal)\n\n#define IShockwaveFlash_put_Scale(This, pVal) (This)->lpVtbl->put_Scale(This, pVal)\n\n#define IShockwaveFlash_get_DeviceFont(This, pVal) (This)->lpVtbl->get_DeviceFont(This, pVal)\n\n#define IShockwaveFlash_put_DeviceFont(This, pVal) (This)->lpVtbl->put_DeviceFont(This, pVal)\n\n#define IShockwaveFlash_get_EmbedMovie(This, pVal) (This)->lpVtbl->get_EmbedMovie(This, pVal)\n\n#define IShockwaveFlash_put_EmbedMovie(This, pVal) (This)->lpVtbl->put_EmbedMovie(This, pVal)\n\n#define IShockwaveFlash_get_BGColor(This, pVal) (This)->lpVtbl->get_BGColor(This, pVal)\n\n#define IShockwaveFlash_put_BGColor(This, pVal) (This)->lpVtbl->put_BGColor(This, pVal)\n\n#define IShockwaveFlash_get_Quality2(This, pVal) (This)->lpVtbl->get_Quality2(This, pVal)\n\n#define IShockwaveFlash_put_Quality2(This, pVal) (This)->lpVtbl->put_Quality2(This, pVal)\n\n#define IShockwaveFlash_LoadMovie(This, layer, url) (This)->lpVtbl->LoadMovie(This, layer, url)\n\n#define IShockwaveFlash_TGotoFrame(This, target, FrameNum) (This)->lpVtbl->TGotoFrame(This, target, FrameNum)\n\n#define IShockwaveFlash_TGotoLabel(This, target, label) (This)->lpVtbl->TGotoLabel(This, target, label)\n\n#define IShockwaveFlash_TCurrentFrame(This, target, FrameNum) (This)->lpVtbl->TCurrentFrame(This, target, FrameNum)\n\n#define IShockwaveFlash_TCurrentLabel(This, target, pVal) (This)->lpVtbl->TCurrentLabel(This, target, pVal)\n\n#define IShockwaveFlash_TPlay(This, target) (This)->lpVtbl->TPlay(This, target)\n\n#define IShockwaveFlash_TStopPlay(This, target) (This)->lpVtbl->TStopPlay(This, target)\n\n#define IShockwaveFlash_SetVariable(This, name, value) (This)->lpVtbl->SetVariable(This, name, value)\n\n#define IShockwaveFlash_GetVariable(This, name, pVal) (This)->lpVtbl->GetVariable(This, name, pVal)\n\n#define IShockwaveFlash_TSetProperty(This, target, property, value)                                                    \\\n    (This)->lpVtbl->TSetProperty(This, target, property, value)\n\n#define IShockwaveFlash_TGetProperty(This, target, property, pVal)                                                     \\\n    (This)->lpVtbl->TGetProperty(This, target, property, pVal)\n\n#define IShockwaveFlash_TCallFrame(This, target, FrameNum) (This)->lpVtbl->TCallFrame(This, target, FrameNum)\n\n#define IShockwaveFlash_TCallLabel(This, target, label) (This)->lpVtbl->TCallLabel(This, target, label)\n\n#define IShockwaveFlash_TSetPropertyNum(This, target, property, value)                                                 \\\n    (This)->lpVtbl->TSetPropertyNum(This, target, property, value)\n\n#define IShockwaveFlash_TGetPropertyNum(This, target, property, pVal)                                                  \\\n    (This)->lpVtbl->TGetPropertyNum(This, target, property, pVal)\n\n#define IShockwaveFlash_TGetPropertyAsNumber(This, target, property, pVal)                                             \\\n    (This)->lpVtbl->TGetPropertyAsNumber(This, target, property, pVal)\n\n#define IShockwaveFlash_get_SWRemote(This, pVal) (This)->lpVtbl->get_SWRemote(This, pVal)\n\n#define IShockwaveFlash_put_SWRemote(This, pVal) (This)->lpVtbl->put_SWRemote(This, pVal)\n\n#define IShockwaveFlash_get_FlashVars(This, pVal) (This)->lpVtbl->get_FlashVars(This, pVal)\n\n#define IShockwaveFlash_put_FlashVars(This, pVal) (This)->lpVtbl->put_FlashVars(This, pVal)\n\n#define IShockwaveFlash_get_AllowScriptAccess(This, pVal) (This)->lpVtbl->get_AllowScriptAccess(This, pVal)\n\n#define IShockwaveFlash_put_AllowScriptAccess(This, pVal) (This)->lpVtbl->put_AllowScriptAccess(This, pVal)\n\n#define IShockwaveFlash_get_MovieData(This, pVal) (This)->lpVtbl->get_MovieData(This, pVal)\n\n#define IShockwaveFlash_put_MovieData(This, pVal) (This)->lpVtbl->put_MovieData(This, pVal)\n\n#define IShockwaveFlash_get_InlineData(This, ppIUnknown) (This)->lpVtbl->get_InlineData(This, ppIUnknown)\n\n#define IShockwaveFlash_put_InlineData(This, ppIUnknown) (This)->lpVtbl->put_InlineData(This, ppIUnknown)\n\n#define IShockwaveFlash_get_SeamlessTabbing(This, pVal) (This)->lpVtbl->get_SeamlessTabbing(This, pVal)\n\n#define IShockwaveFlash_put_SeamlessTabbing(This, pVal) (This)->lpVtbl->put_SeamlessTabbing(This, pVal)\n\n#define IShockwaveFlash_EnforceLocalSecurity(This) (This)->lpVtbl->EnforceLocalSecurity(This)\n\n#define IShockwaveFlash_get_Profile(This, pVal) (This)->lpVtbl->get_Profile(This, pVal)\n\n#define IShockwaveFlash_put_Profile(This, pVal) (This)->lpVtbl->put_Profile(This, pVal)\n\n#define IShockwaveFlash_get_ProfileAddress(This, pVal) (This)->lpVtbl->get_ProfileAddress(This, pVal)\n\n#define IShockwaveFlash_put_ProfileAddress(This, pVal) (This)->lpVtbl->put_ProfileAddress(This, pVal)\n\n#define IShockwaveFlash_get_ProfilePort(This, pVal) (This)->lpVtbl->get_ProfilePort(This, pVal)\n\n#define IShockwaveFlash_put_ProfilePort(This, pVal) (This)->lpVtbl->put_ProfilePort(This, pVal)\n\n#define IShockwaveFlash_CallFunction(This, request, response) (This)->lpVtbl->CallFunction(This, request, response)\n\n#define IShockwaveFlash_SetReturnValue(This, returnValue) (This)->lpVtbl->SetReturnValue(This, returnValue)\n\n#define IShockwaveFlash_DisableLocalSecurity(This) (This)->lpVtbl->DisableLocalSecurity(This)\n\n#define IShockwaveFlash_get_AllowNetworking(This, pVal) (This)->lpVtbl->get_AllowNetworking(This, pVal)\n\n#define IShockwaveFlash_put_AllowNetworking(This, pVal) (This)->lpVtbl->put_AllowNetworking(This, pVal)\n\n#define IShockwaveFlash_get_AllowFullScreen(This, pVal) (This)->lpVtbl->get_AllowFullScreen(This, pVal)\n\n#define IShockwaveFlash_put_AllowFullScreen(This, pVal) (This)->lpVtbl->put_AllowFullScreen(This, pVal)\n\n#endif /* COBJMACROS */\n\n#endif /* C style interface */\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_ReadyState_Proxy(IShockwaveFlash*          This,\n                                                                                 /* [retval][out] */ long* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_ReadyState_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_TotalFrames_Proxy(IShockwaveFlash*          This,\n                                                                                  /* [retval][out] */ long* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_TotalFrames_Stub(IRpcStubBuffer*    This,\n                                                         IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                         PRPC_MESSAGE       _pRpcMessage,\n                                                         DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Playing_Proxy(IShockwaveFlash*                  This,\n                                                                              /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Playing_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_Playing_Proxy(IShockwaveFlash*        This,\n                                                                              /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Playing_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Quality_Proxy(IShockwaveFlash*         This,\n                                                                              /* [retval][out] */ int* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Quality_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Quality_Proxy(IShockwaveFlash* This,\n                                                                                                /* [in] */ int   pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Quality_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_ScaleMode_Proxy(IShockwaveFlash*         This,\n                                                                                /* [retval][out] */ int* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_ScaleMode_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_ScaleMode_Proxy(IShockwaveFlash* This,\n                                                                                                  /* [in] */ int pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_ScaleMode_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_AlignMode_Proxy(IShockwaveFlash*         This,\n                                                                                /* [retval][out] */ int* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_AlignMode_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_AlignMode_Proxy(IShockwaveFlash* This,\n                                                                                                  /* [in] */ int pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_AlignMode_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_BackgroundColor_Proxy(IShockwaveFlash*          This,\n                                                                                      /* [retval][out] */ long* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_BackgroundColor_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_BackgroundColor_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ long  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_BackgroundColor_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Loop_Proxy(IShockwaveFlash*                  This,\n                                                                           /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Loop_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_Loop_Proxy(IShockwaveFlash*        This,\n                                                                           /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Loop_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Movie_Proxy(IShockwaveFlash*          This,\n                                                                            /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Movie_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Movie_Proxy(IShockwaveFlash* This,\n                                                                                              /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Movie_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_receiveNum_Proxy(IShockwaveFlash*          This,\n                                                                             /* [retval][out] */ long* pVal);\n\n    void __RPC_STUB IShockwaveFlash_receiveNum_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_FrameNum_Proxy(IShockwaveFlash* This,\n                                                                                                 /* [in] */ long  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_FrameNum_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_SetZoomRect_Proxy(IShockwaveFlash* This,\n                                                                                       /* [in] */ long  left,\n                                                                                       /* [in] */ long  top,\n                                                                                       /* [in] */ long  right,\n                                                                                       /* [in] */ long  bottom);\n\n    void __RPC_STUB IShockwaveFlash_SetZoomRect_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Zoom_Proxy(IShockwaveFlash* This,\n                                                                                /* [in] */ int   factor);\n\n    void __RPC_STUB IShockwaveFlash_Zoom_Stub(IRpcStubBuffer*    This,\n                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                              PRPC_MESSAGE       _pRpcMessage,\n                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Pan_Proxy(IShockwaveFlash* This,\n                                                                               /* [in] */ long  x,\n                                                                               /* [in] */ long  y,\n                                                                               /* [in] */ int   mode);\n\n    void __RPC_STUB IShockwaveFlash_Pan_Stub(IRpcStubBuffer*    This,\n                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                             PRPC_MESSAGE       _pRpcMessage,\n                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Play_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_Play_Stub(IRpcStubBuffer*    This,\n                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                              PRPC_MESSAGE       _pRpcMessage,\n                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Stop_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_Stop_Stub(IRpcStubBuffer*    This,\n                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                              PRPC_MESSAGE       _pRpcMessage,\n                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Back_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_Back_Stub(IRpcStubBuffer*    This,\n                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                              PRPC_MESSAGE       _pRpcMessage,\n                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Forward_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_Forward_Stub(IRpcStubBuffer*    This,\n                                                 IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                 PRPC_MESSAGE       _pRpcMessage,\n                                                 DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_Rewind_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_Rewind_Stub(IRpcStubBuffer*    This,\n                                                IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                PRPC_MESSAGE       _pRpcMessage,\n                                                DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_StopPlay_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_StopPlay_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_GotoFrame_Proxy(IShockwaveFlash* This,\n                                                                                     /* [in] */ long  FrameNum);\n\n    void __RPC_STUB IShockwaveFlash_GotoFrame_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_CurrentFrame_Proxy(IShockwaveFlash*          This,\n                                                                      /* [retval][out] */ long* FrameNum);\n\n    void __RPC_STUB IShockwaveFlash_CurrentFrame_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_IsPlaying_Proxy(IShockwaveFlash*                  This,\n                                                                   /* [retval][out] */ VARIANT_BOOL* Playing);\n\n    void __RPC_STUB IShockwaveFlash_IsPlaying_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_PercentLoaded_Proxy(IShockwaveFlash*          This,\n                                                                       /* [retval][out] */ long* percent);\n\n    void __RPC_STUB IShockwaveFlash_PercentLoaded_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_FrameLoaded_Proxy(IShockwaveFlash*                  This,\n                                                                     /* [in] */ long                   FrameNum,\n                                                                     /* [retval][out] */ VARIANT_BOOL* loaded);\n\n    void __RPC_STUB IShockwaveFlash_FrameLoaded_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_FlashVersion_Proxy(IShockwaveFlash*          This,\n                                                                      /* [retval][out] */ long* version);\n\n    void __RPC_STUB IShockwaveFlash_FlashVersion_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_WMode_Proxy(IShockwaveFlash*          This,\n                                                                            /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_WMode_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_WMode_Proxy(IShockwaveFlash* This,\n                                                                                              /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_WMode_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_SAlign_Proxy(IShockwaveFlash*          This,\n                                                                             /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_SAlign_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_SAlign_Proxy(IShockwaveFlash* This,\n                                                                                               /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_SAlign_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Menu_Proxy(IShockwaveFlash*                  This,\n                                                                           /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Menu_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_Menu_Proxy(IShockwaveFlash*        This,\n                                                                           /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Menu_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Base_Proxy(IShockwaveFlash*          This,\n                                                                           /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Base_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Base_Proxy(IShockwaveFlash* This,\n                                                                                             /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Base_Stub(IRpcStubBuffer*    This,\n                                                  IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                  PRPC_MESSAGE       _pRpcMessage,\n                                                  DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Scale_Proxy(IShockwaveFlash*          This,\n                                                                            /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Scale_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Scale_Proxy(IShockwaveFlash* This,\n                                                                                              /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Scale_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_DeviceFont_Proxy(IShockwaveFlash*                  This,\n                                                                                 /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_DeviceFont_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_DeviceFont_Proxy(IShockwaveFlash*        This,\n                                                                                 /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_DeviceFont_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_EmbedMovie_Proxy(IShockwaveFlash*                  This,\n                                                                                 /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_EmbedMovie_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_EmbedMovie_Proxy(IShockwaveFlash*        This,\n                                                                                 /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_EmbedMovie_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_BGColor_Proxy(IShockwaveFlash*          This,\n                                                                              /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_BGColor_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_BGColor_Proxy(IShockwaveFlash* This,\n                                                                                                /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_BGColor_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Quality2_Proxy(IShockwaveFlash*          This,\n                                                                               /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Quality2_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_Quality2_Proxy(IShockwaveFlash* This,\n                                                                                                 /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Quality2_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_LoadMovie_Proxy(IShockwaveFlash* This,\n                                                                                     /* [in] */ int   layer,\n                                                                                     /* [in] */ BSTR  url);\n\n    void __RPC_STUB IShockwaveFlash_LoadMovie_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGotoFrame_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ BSTR  target,\n                                                                                      /* [in] */ long  FrameNum);\n\n    void __RPC_STUB IShockwaveFlash_TGotoFrame_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGotoLabel_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ BSTR  target,\n                                                                                      /* [in] */ BSTR  label);\n\n    void __RPC_STUB IShockwaveFlash_TGotoLabel_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_TCurrentFrame_Proxy(IShockwaveFlash*          This,\n                                                                       /* [in] */ BSTR           target,\n                                                                       /* [retval][out] */ long* FrameNum);\n\n    void __RPC_STUB IShockwaveFlash_TCurrentFrame_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_TCurrentLabel_Proxy(IShockwaveFlash*          This,\n                                                                       /* [in] */ BSTR           target,\n                                                                       /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_TCurrentLabel_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TPlay_Proxy(IShockwaveFlash* This,\n                                                                                 /* [in] */ BSTR  target);\n\n    void __RPC_STUB IShockwaveFlash_TPlay_Stub(IRpcStubBuffer*    This,\n                                               IRpcChannelBuffer* _pRpcChannelBuffer,\n                                               PRPC_MESSAGE       _pRpcMessage,\n                                               DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TStopPlay_Proxy(IShockwaveFlash* This,\n                                                                                     /* [in] */ BSTR  target);\n\n    void __RPC_STUB IShockwaveFlash_TStopPlay_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_SetVariable_Proxy(IShockwaveFlash* This,\n                                                                                       /* [in] */ BSTR  name,\n                                                                                       /* [in] */ BSTR  value);\n\n    void __RPC_STUB IShockwaveFlash_SetVariable_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_GetVariable_Proxy(IShockwaveFlash*          This,\n                                                                                       /* [in] */ BSTR           name,\n                                                                                       /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_GetVariable_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TSetProperty_Proxy(IShockwaveFlash* This,\n                                                                                        /* [in] */ BSTR  target,\n                                                                                        /* [in] */ int   property,\n                                                                                        /* [in] */ BSTR  value);\n\n    void __RPC_STUB IShockwaveFlash_TSetProperty_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TGetProperty_Proxy(IShockwaveFlash* This,\n                                                                                        /* [in] */ BSTR  target,\n                                                                                        /* [in] */ int   property,\n                                                                                        /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_TGetProperty_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TCallFrame_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ BSTR  target,\n                                                                                      /* [in] */ int   FrameNum);\n\n    void __RPC_STUB IShockwaveFlash_TCallFrame_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TCallLabel_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ BSTR  target,\n                                                                                      /* [in] */ BSTR  label);\n\n    void __RPC_STUB IShockwaveFlash_TCallLabel_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_TSetPropertyNum_Proxy(IShockwaveFlash*  This,\n                                                                                           /* [in] */ BSTR   target,\n                                                                                           /* [in] */ int    property,\n                                                                                           /* [in] */ double value);\n\n    void __RPC_STUB IShockwaveFlash_TSetPropertyNum_Stub(IRpcStubBuffer*    This,\n                                                         IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                         PRPC_MESSAGE       _pRpcMessage,\n                                                         DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_TGetPropertyNum_Proxy(IShockwaveFlash*            This,\n                                                                         /* [in] */ BSTR             target,\n                                                                         /* [in] */ int              property,\n                                                                         /* [retval][out] */ double* pVal);\n\n    void __RPC_STUB IShockwaveFlash_TGetPropertyNum_Stub(IRpcStubBuffer*    This,\n                                                         IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                         PRPC_MESSAGE       _pRpcMessage,\n                                                         DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_TGetPropertyAsNumber_Proxy(IShockwaveFlash*            This,\n                                                                              /* [in] */ BSTR             target,\n                                                                              /* [in] */ int              property,\n                                                                              /* [retval][out] */ double* pVal);\n\n    void __RPC_STUB IShockwaveFlash_TGetPropertyAsNumber_Stub(IRpcStubBuffer*    This,\n                                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                              PRPC_MESSAGE       _pRpcMessage,\n                                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_SWRemote_Proxy(IShockwaveFlash*          This,\n                                                                               /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_SWRemote_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_SWRemote_Proxy(IShockwaveFlash* This,\n                                                                                                 /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_SWRemote_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_FlashVars_Proxy(IShockwaveFlash*          This,\n                                                                                /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_FlashVars_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_FlashVars_Proxy(IShockwaveFlash* This,\n                                                                                                  /* [in] */ BSTR pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_FlashVars_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_AllowScriptAccess_Proxy(IShockwaveFlash*          This,\n                                                                                        /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_AllowScriptAccess_Stub(IRpcStubBuffer*    This,\n                                                               IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                               PRPC_MESSAGE       _pRpcMessage,\n                                                               DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_AllowScriptAccess_Proxy(IShockwaveFlash* This,\n                                                                                        /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_AllowScriptAccess_Stub(IRpcStubBuffer*    This,\n                                                               IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                               PRPC_MESSAGE       _pRpcMessage,\n                                                               DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_MovieData_Proxy(IShockwaveFlash*          This,\n                                                                                /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_MovieData_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_put_MovieData_Proxy(IShockwaveFlash* This,\n                                                                                                  /* [in] */ BSTR pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_MovieData_Stub(IRpcStubBuffer*    This,\n                                                       IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                       PRPC_MESSAGE       _pRpcMessage,\n                                                       DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_InlineData_Proxy(IShockwaveFlash*               This,\n                                                                                 /* [retval][out] */ IUnknown** ppIUnknown);\n\n    void __RPC_STUB IShockwaveFlash_get_InlineData_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_InlineData_Proxy(IShockwaveFlash*     This,\n                                                                                 /* [in] */ IUnknown* ppIUnknown);\n\n    void __RPC_STUB IShockwaveFlash_put_InlineData_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_SeamlessTabbing_Proxy(IShockwaveFlash*                  This,\n                                                                                      /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_SeamlessTabbing_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_SeamlessTabbing_Proxy(IShockwaveFlash*        This,\n                                                                                      /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_SeamlessTabbing_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_EnforceLocalSecurity_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_EnforceLocalSecurity_Stub(IRpcStubBuffer*    This,\n                                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                              PRPC_MESSAGE       _pRpcMessage,\n                                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_Profile_Proxy(IShockwaveFlash*                  This,\n                                                                              /* [retval][out] */ VARIANT_BOOL* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_Profile_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_Profile_Proxy(IShockwaveFlash*        This,\n                                                                              /* [in] */ VARIANT_BOOL pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_Profile_Stub(IRpcStubBuffer*    This,\n                                                     IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                     PRPC_MESSAGE       _pRpcMessage,\n                                                     DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_ProfileAddress_Proxy(IShockwaveFlash*          This,\n                                                                                     /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_ProfileAddress_Stub(IRpcStubBuffer*    This,\n                                                            IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                            PRPC_MESSAGE       _pRpcMessage,\n                                                            DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_ProfileAddress_Proxy(IShockwaveFlash* This,\n                                                                                     /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_ProfileAddress_Stub(IRpcStubBuffer*    This,\n                                                            IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                            PRPC_MESSAGE       _pRpcMessage,\n                                                            DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_ProfilePort_Proxy(IShockwaveFlash*          This,\n                                                                                  /* [retval][out] */ long* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_ProfilePort_Stub(IRpcStubBuffer*    This,\n                                                         IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                         PRPC_MESSAGE       _pRpcMessage,\n                                                         DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_ProfilePort_Proxy(IShockwaveFlash* This,\n                                                                                  /* [in] */ long  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_ProfilePort_Stub(IRpcStubBuffer*    This,\n                                                         IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                         PRPC_MESSAGE       _pRpcMessage,\n                                                         DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE\n                                   IShockwaveFlash_CallFunction_Proxy(IShockwaveFlash*          This,\n                                                                      /* [in] */ BSTR           request,\n                                                                      /* [retval][out] */ BSTR* response);\n\n    void __RPC_STUB IShockwaveFlash_CallFunction_Stub(IRpcStubBuffer*    This,\n                                                      IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                      PRPC_MESSAGE       _pRpcMessage,\n                                                      DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_SetReturnValue_Proxy(IShockwaveFlash* This,\n                                                                                          /* [in] */ BSTR  returnValue);\n\n    void __RPC_STUB IShockwaveFlash_SetReturnValue_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE IShockwaveFlash_DisableLocalSecurity_Proxy(IShockwaveFlash* This);\n\n    void __RPC_STUB IShockwaveFlash_DisableLocalSecurity_Stub(IRpcStubBuffer*    This,\n                                                              IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                              PRPC_MESSAGE       _pRpcMessage,\n                                                              DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_AllowNetworking_Proxy(IShockwaveFlash*          This,\n                                                                                      /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_AllowNetworking_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_AllowNetworking_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_AllowNetworking_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propget][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_get_AllowFullScreen_Proxy(IShockwaveFlash*          This,\n                                                                                      /* [retval][out] */ BSTR* pVal);\n\n    void __RPC_STUB IShockwaveFlash_get_AllowFullScreen_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n    /* [helpstring][propput][id] */ HRESULT STDMETHODCALLTYPE\n                                            IShockwaveFlash_put_AllowFullScreen_Proxy(IShockwaveFlash* This,\n                                                                                      /* [in] */ BSTR  pVal);\n\n    void __RPC_STUB IShockwaveFlash_put_AllowFullScreen_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n#endif /* __IShockwaveFlash_INTERFACE_DEFINED__ */\n\n#ifndef ___IShockwaveFlashEvents_DISPINTERFACE_DEFINED__\n#define ___IShockwaveFlashEvents_DISPINTERFACE_DEFINED__\n\n    /* dispinterface _IShockwaveFlashEvents */\n    /* [hidden][helpstring][uuid] */\n\n    EXTERN_C const IID DIID__IShockwaveFlashEvents;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n\n    MIDL_INTERFACE(\"D27CDB6D-AE6D-11CF-96B8-444553540000\")\n    _IShockwaveFlashEvents : public IDispatch{};\n\n#else /* C style interface */\n\n    typedef struct _IShockwaveFlashEventsVtbl\n    {\n        BEGIN_INTERFACE\n\n        HRESULT(STDMETHODCALLTYPE* QueryInterface)\n        (_IShockwaveFlashEvents*    This,\n         /* [in] */ REFIID          riid,\n         /* [iid_is][out] */ void** ppvObject);\n\n        ULONG(STDMETHODCALLTYPE* AddRef)(_IShockwaveFlashEvents* This);\n\n        ULONG(STDMETHODCALLTYPE* Release)(_IShockwaveFlashEvents* This);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount)\n        (_IShockwaveFlashEvents* This,\n         /* [out] */ UINT*       pctinfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfo)\n        (_IShockwaveFlashEvents* This,\n         /* [in] */ UINT         iTInfo,\n         /* [in] */ LCID         lcid,\n         /* [out] */ ITypeInfo** ppTInfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetIDsOfNames)\n        (_IShockwaveFlashEvents*       This,\n         /* [in] */ REFIID             riid,\n         /* [size_is][in] */ LPOLESTR* rgszNames,\n         /* [in] */ UINT               cNames,\n         /* [in] */ LCID               lcid,\n         /* [size_is][out] */ DISPID*  rgDispId);\n\n        /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke)(_IShockwaveFlashEvents*     This,\n                                                         /* [in] */ DISPID           dispIdMember,\n                                                         /* [in] */ REFIID           riid,\n                                                         /* [in] */ LCID             lcid,\n                                                         /* [in] */ WORD             wFlags,\n                                                         /* [out][in] */ DISPPARAMS* pDispParams,\n                                                         /* [out] */ VARIANT*        pVarResult,\n                                                         /* [out] */ EXCEPINFO*      pExcepInfo,\n                                                         /* [out] */ UINT*           puArgErr);\n\n        END_INTERFACE\n    } _IShockwaveFlashEventsVtbl;\n\n    interface _IShockwaveFlashEvents { CONST_VTBL struct _IShockwaveFlashEventsVtbl* lpVtbl; };\n\n#ifdef COBJMACROS\n\n#define _IShockwaveFlashEvents_QueryInterface(This, riid, ppvObject)                                                   \\\n    (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\n\n#define _IShockwaveFlashEvents_AddRef(This) (This)->lpVtbl->AddRef(This)\n\n#define _IShockwaveFlashEvents_Release(This) (This)->lpVtbl->Release(This)\n\n#define _IShockwaveFlashEvents_GetTypeInfoCount(This, pctinfo) (This)->lpVtbl->GetTypeInfoCount(This, pctinfo)\n\n#define _IShockwaveFlashEvents_GetTypeInfo(This, iTInfo, lcid, ppTInfo)                                                \\\n    (This)->lpVtbl->GetTypeInfo(This, iTInfo, lcid, ppTInfo)\n\n#define _IShockwaveFlashEvents_GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)                            \\\n    (This)->lpVtbl->GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)\n\n#define _IShockwaveFlashEvents_Invoke(                                                                                 \\\n    This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)                             \\\n    (This)->lpVtbl->Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)\n\n#endif /* COBJMACROS */\n\n#endif /* C style interface */\n\n#endif /* ___IShockwaveFlashEvents_DISPINTERFACE_DEFINED__ */\n\n#ifndef __IFlashFactory_INTERFACE_DEFINED__\n#define __IFlashFactory_INTERFACE_DEFINED__\n\n    /* interface IFlashFactory */\n    /* [object][helpstring][uuid] */\n\n    EXTERN_C const IID IID_IFlashFactory;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n\n    MIDL_INTERFACE(\"D27CDB70-AE6D-11CF-96B8-444553540000\")\n    IFlashFactory : public IUnknown{public : };\n\n#else /* C style interface */\n\n    typedef struct IFlashFactoryVtbl\n    {\n        BEGIN_INTERFACE\n\n        HRESULT(STDMETHODCALLTYPE* QueryInterface)\n        (IFlashFactory*             This,\n         /* [in] */ REFIID          riid,\n         /* [iid_is][out] */ void** ppvObject);\n\n        ULONG(STDMETHODCALLTYPE* AddRef)(IFlashFactory* This);\n\n        ULONG(STDMETHODCALLTYPE* Release)(IFlashFactory* This);\n\n        END_INTERFACE\n    } IFlashFactoryVtbl;\n\n    interface IFlashFactory { CONST_VTBL struct IFlashFactoryVtbl* lpVtbl; };\n\n#ifdef COBJMACROS\n\n#define IFlashFactory_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\n\n#define IFlashFactory_AddRef(This) (This)->lpVtbl->AddRef(This)\n\n#define IFlashFactory_Release(This) (This)->lpVtbl->Release(This)\n\n#endif /* COBJMACROS */\n\n#endif /* C style interface */\n\n#endif /* __IFlashFactory_INTERFACE_DEFINED__ */\n\n#ifndef __IFlashObjectInterface_INTERFACE_DEFINED__\n#define __IFlashObjectInterface_INTERFACE_DEFINED__\n\n    /* interface IFlashObjectInterface */\n    /* [object][helpstring][uuid] */\n\n    EXTERN_C const IID IID_IFlashObjectInterface;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n\n    MIDL_INTERFACE(\"D27CDB72-AE6D-11CF-96B8-444553540000\")\n    IFlashObjectInterface : public IDispatchEx{public : };\n\n#else /* C style interface */\n\n    typedef struct IFlashObjectInterfaceVtbl\n    {\n        BEGIN_INTERFACE\n\n        HRESULT(STDMETHODCALLTYPE* QueryInterface)\n        (IFlashObjectInterface*     This,\n         /* [in] */ REFIID          riid,\n         /* [iid_is][out] */ void** ppvObject);\n\n        ULONG(STDMETHODCALLTYPE* AddRef)(IFlashObjectInterface* This);\n\n        ULONG(STDMETHODCALLTYPE* Release)(IFlashObjectInterface* This);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount)\n        (IFlashObjectInterface* This,\n         /* [out] */ UINT*      pctinfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfo)\n        (IFlashObjectInterface*  This,\n         /* [in] */ UINT         iTInfo,\n         /* [in] */ LCID         lcid,\n         /* [out] */ ITypeInfo** ppTInfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetIDsOfNames)\n        (IFlashObjectInterface*        This,\n         /* [in] */ REFIID             riid,\n         /* [size_is][in] */ LPOLESTR* rgszNames,\n         /* [in] */ UINT               cNames,\n         /* [in] */ LCID               lcid,\n         /* [size_is][out] */ DISPID*  rgDispId);\n\n        /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke)(IFlashObjectInterface*      This,\n                                                         /* [in] */ DISPID           dispIdMember,\n                                                         /* [in] */ REFIID           riid,\n                                                         /* [in] */ LCID             lcid,\n                                                         /* [in] */ WORD             wFlags,\n                                                         /* [out][in] */ DISPPARAMS* pDispParams,\n                                                         /* [out] */ VARIANT*        pVarResult,\n                                                         /* [out] */ EXCEPINFO*      pExcepInfo,\n                                                         /* [out] */ UINT*           puArgErr);\n\n        HRESULT(__stdcall* GetDispID)\n        (IFlashObjectInterface*   This,\n         /* [in] */ BSTR          bstrName,\n         /* [in] */ unsigned long grfdex,\n         /* [out] */ long*        pid);\n\n        HRESULT(__stdcall* RemoteInvokeEx)\n        (IFlashObjectInterface*       This,\n         /* [in] */ long              id,\n         /* [in] */ unsigned long     lcid,\n         /* [in] */ unsigned long     dwFlags,\n         /* [in] */ DISPPARAMS*       pdp,\n         /* [out] */ VARIANT*         pvarRes,\n         /* [out] */ EXCEPINFO*       pei,\n         /* [in] */ IServiceProvider* pspCaller,\n         /* [in] */ unsigned int      cvarRefArg,\n         /* [in] */ unsigned int*     rgiRefArg,\n         /* [out][in] */ VARIANT*     rgvarRefArg);\n\n        HRESULT(__stdcall* DeleteMemberByName)\n        (IFlashObjectInterface*   This,\n         /* [in] */ BSTR          bstrName,\n         /* [in] */ unsigned long grfdex);\n\n        HRESULT(__stdcall* DeleteMemberByDispID)\n        (IFlashObjectInterface* This,\n         /* [in] */ long        id);\n\n        HRESULT(__stdcall* GetMemberProperties)\n        (IFlashObjectInterface*     This,\n         /* [in] */ long            id,\n         /* [in] */ unsigned long   grfdexFetch,\n         /* [out] */ unsigned long* pgrfdex);\n\n        HRESULT(__stdcall* GetMemberName)\n        (IFlashObjectInterface* This,\n         /* [in] */ long        id,\n         /* [out] */ BSTR*      pbstrName);\n\n        HRESULT(__stdcall* GetNextDispID)\n        (IFlashObjectInterface*   This,\n         /* [in] */ unsigned long grfdex,\n         /* [in] */ long          id,\n         /* [out] */ long*        pid);\n\n        HRESULT(__stdcall* GetNameSpaceParent)\n        (IFlashObjectInterface* This,\n         /* [out] */ IUnknown** ppunk);\n\n        END_INTERFACE\n    } IFlashObjectInterfaceVtbl;\n\n    interface IFlashObjectInterface { CONST_VTBL struct IFlashObjectInterfaceVtbl* lpVtbl; };\n\n#ifdef COBJMACROS\n\n#define IFlashObjectInterface_QueryInterface(This, riid, ppvObject)                                                    \\\n    (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\n\n#define IFlashObjectInterface_AddRef(This) (This)->lpVtbl->AddRef(This)\n\n#define IFlashObjectInterface_Release(This) (This)->lpVtbl->Release(This)\n\n#define IFlashObjectInterface_GetTypeInfoCount(This, pctinfo) (This)->lpVtbl->GetTypeInfoCount(This, pctinfo)\n\n#define IFlashObjectInterface_GetTypeInfo(This, iTInfo, lcid, ppTInfo)                                                 \\\n    (This)->lpVtbl->GetTypeInfo(This, iTInfo, lcid, ppTInfo)\n\n#define IFlashObjectInterface_GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)                             \\\n    (This)->lpVtbl->GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)\n\n#define IFlashObjectInterface_Invoke(                                                                                  \\\n    This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)                             \\\n    (This)->lpVtbl->Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)\n\n#define IFlashObjectInterface_GetDispID(This, bstrName, grfdex, pid)                                                   \\\n    (This)->lpVtbl->GetDispID(This, bstrName, grfdex, pid)\n\n#define IFlashObjectInterface_RemoteInvokeEx(                                                                          \\\n    This, id, lcid, dwFlags, pdp, pvarRes, pei, pspCaller, cvarRefArg, rgiRefArg, rgvarRefArg)                         \\\n    (This)->lpVtbl->RemoteInvokeEx(                                                                                    \\\n        This, id, lcid, dwFlags, pdp, pvarRes, pei, pspCaller, cvarRefArg, rgiRefArg, rgvarRefArg)\n\n#define IFlashObjectInterface_DeleteMemberByName(This, bstrName, grfdex)                                               \\\n    (This)->lpVtbl->DeleteMemberByName(This, bstrName, grfdex)\n\n#define IFlashObjectInterface_DeleteMemberByDispID(This, id) (This)->lpVtbl->DeleteMemberByDispID(This, id)\n\n#define IFlashObjectInterface_GetMemberProperties(This, id, grfdexFetch, pgrfdex)                                      \\\n    (This)->lpVtbl->GetMemberProperties(This, id, grfdexFetch, pgrfdex)\n\n#define IFlashObjectInterface_GetMemberName(This, id, pbstrName) (This)->lpVtbl->GetMemberName(This, id, pbstrName)\n\n#define IFlashObjectInterface_GetNextDispID(This, grfdex, id, pid) (This)->lpVtbl->GetNextDispID(This, grfdex, id, pid)\n\n#define IFlashObjectInterface_GetNameSpaceParent(This, ppunk) (This)->lpVtbl->GetNameSpaceParent(This, ppunk)\n\n#endif /* COBJMACROS */\n\n#endif /* C style interface */\n\n#endif /* __IFlashObjectInterface_INTERFACE_DEFINED__ */\n\n#ifndef __IDispatchEx_INTERFACE_DEFINED__\n#define __IDispatchEx_INTERFACE_DEFINED__\n\n    /* interface IDispatchEx */\n    /* [object][uuid] */\n\n    EXTERN_C const IID IID_IDispatchEx;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n\n    MIDL_INTERFACE(\"A6EF9860-C720-11D0-9337-00A0C90DCAA9\")\n    IDispatchEx : public IDispatch\n    {\n      public:\n        virtual HRESULT __stdcall GetDispID(\n            /* [in] */ BSTR          bstrName,\n            /* [in] */ unsigned long grfdex,\n            /* [out] */ long*        pid) = 0;\n\n        virtual HRESULT __stdcall RemoteInvokeEx(\n            /* [in] */ long              id,\n            /* [in] */ unsigned long     lcid,\n            /* [in] */ unsigned long     dwFlags,\n            /* [in] */ DISPPARAMS*       pdp,\n            /* [out] */ VARIANT*         pvarRes,\n            /* [out] */ EXCEPINFO*       pei,\n            /* [in] */ IServiceProvider* pspCaller,\n            /* [in] */ unsigned int      cvarRefArg,\n            /* [in] */ unsigned int*     rgiRefArg,\n            /* [out][in] */ VARIANT*     rgvarRefArg) = 0;\n\n        virtual HRESULT __stdcall DeleteMemberByName(\n            /* [in] */ BSTR          bstrName,\n            /* [in] */ unsigned long grfdex) = 0;\n\n        virtual HRESULT __stdcall DeleteMemberByDispID(\n            /* [in] */ long id) = 0;\n\n        virtual HRESULT __stdcall GetMemberProperties(\n            /* [in] */ long            id,\n            /* [in] */ unsigned long   grfdexFetch,\n            /* [out] */ unsigned long* pgrfdex) = 0;\n\n        virtual HRESULT __stdcall GetMemberName(\n            /* [in] */ long   id,\n            /* [out] */ BSTR* pbstrName) = 0;\n\n        virtual HRESULT __stdcall GetNextDispID(\n            /* [in] */ unsigned long grfdex,\n            /* [in] */ long          id,\n            /* [out] */ long*        pid) = 0;\n\n        virtual HRESULT __stdcall GetNameSpaceParent(\n            /* [out] */ IUnknown * *ppunk) = 0;\n    };\n\n#else /* C style interface */\n\n    typedef struct IDispatchExVtbl\n    {\n        BEGIN_INTERFACE\n\n        HRESULT(STDMETHODCALLTYPE* QueryInterface)\n        (IDispatchEx*               This,\n         /* [in] */ REFIID          riid,\n         /* [iid_is][out] */ void** ppvObject);\n\n        ULONG(STDMETHODCALLTYPE* AddRef)(IDispatchEx* This);\n\n        ULONG(STDMETHODCALLTYPE* Release)(IDispatchEx* This);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfoCount)\n        (IDispatchEx*      This,\n         /* [out] */ UINT* pctinfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetTypeInfo)\n        (IDispatchEx*            This,\n         /* [in] */ UINT         iTInfo,\n         /* [in] */ LCID         lcid,\n         /* [out] */ ITypeInfo** ppTInfo);\n\n        HRESULT(STDMETHODCALLTYPE* GetIDsOfNames)\n        (IDispatchEx*                  This,\n         /* [in] */ REFIID             riid,\n         /* [size_is][in] */ LPOLESTR* rgszNames,\n         /* [in] */ UINT               cNames,\n         /* [in] */ LCID               lcid,\n         /* [size_is][out] */ DISPID*  rgDispId);\n\n        /* [local] */ HRESULT(STDMETHODCALLTYPE* Invoke)(IDispatchEx*                This,\n                                                         /* [in] */ DISPID           dispIdMember,\n                                                         /* [in] */ REFIID           riid,\n                                                         /* [in] */ LCID             lcid,\n                                                         /* [in] */ WORD             wFlags,\n                                                         /* [out][in] */ DISPPARAMS* pDispParams,\n                                                         /* [out] */ VARIANT*        pVarResult,\n                                                         /* [out] */ EXCEPINFO*      pExcepInfo,\n                                                         /* [out] */ UINT*           puArgErr);\n\n        HRESULT(__stdcall* GetDispID)\n        (IDispatchEx*             This,\n         /* [in] */ BSTR          bstrName,\n         /* [in] */ unsigned long grfdex,\n         /* [out] */ long*        pid);\n\n        HRESULT(__stdcall* RemoteInvokeEx)\n        (IDispatchEx*                 This,\n         /* [in] */ long              id,\n         /* [in] */ unsigned long     lcid,\n         /* [in] */ unsigned long     dwFlags,\n         /* [in] */ DISPPARAMS*       pdp,\n         /* [out] */ VARIANT*         pvarRes,\n         /* [out] */ EXCEPINFO*       pei,\n         /* [in] */ IServiceProvider* pspCaller,\n         /* [in] */ unsigned int      cvarRefArg,\n         /* [in] */ unsigned int*     rgiRefArg,\n         /* [out][in] */ VARIANT*     rgvarRefArg);\n\n        HRESULT(__stdcall* DeleteMemberByName)\n        (IDispatchEx*             This,\n         /* [in] */ BSTR          bstrName,\n         /* [in] */ unsigned long grfdex);\n\n        HRESULT(__stdcall* DeleteMemberByDispID)\n        (IDispatchEx*    This,\n         /* [in] */ long id);\n\n        HRESULT(__stdcall* GetMemberProperties)\n        (IDispatchEx*               This,\n         /* [in] */ long            id,\n         /* [in] */ unsigned long   grfdexFetch,\n         /* [out] */ unsigned long* pgrfdex);\n\n        HRESULT(__stdcall* GetMemberName)\n        (IDispatchEx*      This,\n         /* [in] */ long   id,\n         /* [out] */ BSTR* pbstrName);\n\n        HRESULT(__stdcall* GetNextDispID)\n        (IDispatchEx*             This,\n         /* [in] */ unsigned long grfdex,\n         /* [in] */ long          id,\n         /* [out] */ long*        pid);\n\n        HRESULT(__stdcall* GetNameSpaceParent)\n        (IDispatchEx*           This,\n         /* [out] */ IUnknown** ppunk);\n\n        END_INTERFACE\n    } IDispatchExVtbl;\n\n    interface IDispatchEx { CONST_VTBL struct IDispatchExVtbl* lpVtbl; };\n\n#ifdef COBJMACROS\n\n#define IDispatchEx_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\n\n#define IDispatchEx_AddRef(This) (This)->lpVtbl->AddRef(This)\n\n#define IDispatchEx_Release(This) (This)->lpVtbl->Release(This)\n\n#define IDispatchEx_GetTypeInfoCount(This, pctinfo) (This)->lpVtbl->GetTypeInfoCount(This, pctinfo)\n\n#define IDispatchEx_GetTypeInfo(This, iTInfo, lcid, ppTInfo) (This)->lpVtbl->GetTypeInfo(This, iTInfo, lcid, ppTInfo)\n\n#define IDispatchEx_GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)                                       \\\n    (This)->lpVtbl->GetIDsOfNames(This, riid, rgszNames, cNames, lcid, rgDispId)\n\n#define IDispatchEx_Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)      \\\n    (This)->lpVtbl->Invoke(This, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr)\n\n#define IDispatchEx_GetDispID(This, bstrName, grfdex, pid) (This)->lpVtbl->GetDispID(This, bstrName, grfdex, pid)\n\n#define IDispatchEx_RemoteInvokeEx(                                                                                    \\\n    This, id, lcid, dwFlags, pdp, pvarRes, pei, pspCaller, cvarRefArg, rgiRefArg, rgvarRefArg)                         \\\n    (This)->lpVtbl->RemoteInvokeEx(                                                                                    \\\n        This, id, lcid, dwFlags, pdp, pvarRes, pei, pspCaller, cvarRefArg, rgiRefArg, rgvarRefArg)\n\n#define IDispatchEx_DeleteMemberByName(This, bstrName, grfdex)                                                         \\\n    (This)->lpVtbl->DeleteMemberByName(This, bstrName, grfdex)\n\n#define IDispatchEx_DeleteMemberByDispID(This, id) (This)->lpVtbl->DeleteMemberByDispID(This, id)\n\n#define IDispatchEx_GetMemberProperties(This, id, grfdexFetch, pgrfdex)                                                \\\n    (This)->lpVtbl->GetMemberProperties(This, id, grfdexFetch, pgrfdex)\n\n#define IDispatchEx_GetMemberName(This, id, pbstrName) (This)->lpVtbl->GetMemberName(This, id, pbstrName)\n\n#define IDispatchEx_GetNextDispID(This, grfdex, id, pid) (This)->lpVtbl->GetNextDispID(This, grfdex, id, pid)\n\n#define IDispatchEx_GetNameSpaceParent(This, ppunk) (This)->lpVtbl->GetNameSpaceParent(This, ppunk)\n\n#endif /* COBJMACROS */\n\n#endif /* C style interface */\n\n    HRESULT __stdcall IDispatchEx_GetDispID_Proxy(IDispatchEx*             This,\n                                                  /* [in] */ BSTR          bstrName,\n                                                  /* [in] */ unsigned long grfdex,\n                                                  /* [out] */ long*        pid);\n\n    void __RPC_STUB IDispatchEx_GetDispID_Stub(IRpcStubBuffer*    This,\n                                               IRpcChannelBuffer* _pRpcChannelBuffer,\n                                               PRPC_MESSAGE       _pRpcMessage,\n                                               DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_RemoteInvokeEx_Proxy(IDispatchEx*                 This,\n                                                       /* [in] */ long              id,\n                                                       /* [in] */ unsigned long     lcid,\n                                                       /* [in] */ unsigned long     dwFlags,\n                                                       /* [in] */ DISPPARAMS*       pdp,\n                                                       /* [out] */ VARIANT*         pvarRes,\n                                                       /* [out] */ EXCEPINFO*       pei,\n                                                       /* [in] */ IServiceProvider* pspCaller,\n                                                       /* [in] */ unsigned int      cvarRefArg,\n                                                       /* [in] */ unsigned int*     rgiRefArg,\n                                                       /* [out][in] */ VARIANT*     rgvarRefArg);\n\n    void __RPC_STUB IDispatchEx_RemoteInvokeEx_Stub(IRpcStubBuffer*    This,\n                                                    IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                    PRPC_MESSAGE       _pRpcMessage,\n                                                    DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_DeleteMemberByName_Proxy(IDispatchEx*             This,\n                                                           /* [in] */ BSTR          bstrName,\n                                                           /* [in] */ unsigned long grfdex);\n\n    void __RPC_STUB IDispatchEx_DeleteMemberByName_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_DeleteMemberByDispID_Proxy(IDispatchEx*    This,\n                                                             /* [in] */ long id);\n\n    void __RPC_STUB IDispatchEx_DeleteMemberByDispID_Stub(IRpcStubBuffer*    This,\n                                                          IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                          PRPC_MESSAGE       _pRpcMessage,\n                                                          DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_GetMemberProperties_Proxy(IDispatchEx*               This,\n                                                            /* [in] */ long            id,\n                                                            /* [in] */ unsigned long   grfdexFetch,\n                                                            /* [out] */ unsigned long* pgrfdex);\n\n    void __RPC_STUB IDispatchEx_GetMemberProperties_Stub(IRpcStubBuffer*    This,\n                                                         IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                         PRPC_MESSAGE       _pRpcMessage,\n                                                         DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_GetMemberName_Proxy(IDispatchEx*      This,\n                                                      /* [in] */ long   id,\n                                                      /* [out] */ BSTR* pbstrName);\n\n    void __RPC_STUB IDispatchEx_GetMemberName_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_GetNextDispID_Proxy(IDispatchEx*             This,\n                                                      /* [in] */ unsigned long grfdex,\n                                                      /* [in] */ long          id,\n                                                      /* [out] */ long*        pid);\n\n    void __RPC_STUB IDispatchEx_GetNextDispID_Stub(IRpcStubBuffer*    This,\n                                                   IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                   PRPC_MESSAGE       _pRpcMessage,\n                                                   DWORD*             _pdwStubPhase);\n\n    HRESULT __stdcall IDispatchEx_GetNameSpaceParent_Proxy(IDispatchEx*           This,\n                                                           /* [out] */ IUnknown** ppunk);\n\n    void __RPC_STUB IDispatchEx_GetNameSpaceParent_Stub(IRpcStubBuffer*    This,\n                                                        IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                        PRPC_MESSAGE       _pRpcMessage,\n                                                        DWORD*             _pdwStubPhase);\n\n#endif /* __IDispatchEx_INTERFACE_DEFINED__ */\n\n#ifndef __IServiceProvider_INTERFACE_DEFINED__\n#define __IServiceProvider_INTERFACE_DEFINED__\n\n    /* interface IServiceProvider */\n    /* [object][uuid] */\n\n    EXTERN_C const IID IID_IServiceProvider;\n\n#if defined(__cplusplus) && !defined(CINTERFACE)\n\n    MIDL_INTERFACE(\"6D5140C1-7436-11CE-8034-00AA006009FA\")\n    IServiceProvider : public IUnknown\n    {\n      public:\n        virtual HRESULT __stdcall RemoteQueryService(\n            /* [in] */ GUID * guidService,\n            /* [in] */ GUID * riid,\n            /* [out] */ IUnknown * *ppvObject) = 0;\n    };\n\n#else /* C style interface */\n\n    typedef struct IServiceProviderVtbl\n    {\n        BEGIN_INTERFACE\n\n        HRESULT(STDMETHODCALLTYPE* QueryInterface)\n        (IServiceProvider*          This,\n         /* [in] */ REFIID          riid,\n         /* [iid_is][out] */ void** ppvObject);\n\n        ULONG(STDMETHODCALLTYPE* AddRef)(IServiceProvider* This);\n\n        ULONG(STDMETHODCALLTYPE* Release)(IServiceProvider* This);\n\n        HRESULT(__stdcall* RemoteQueryService)\n        (IServiceProvider*      This,\n         /* [in] */ GUID*       guidService,\n         /* [in] */ GUID*       riid,\n         /* [out] */ IUnknown** ppvObject);\n\n        END_INTERFACE\n    } IServiceProviderVtbl;\n\n    interface IServiceProvider { CONST_VTBL struct IServiceProviderVtbl* lpVtbl; };\n\n#ifdef COBJMACROS\n\n#define IServiceProvider_QueryInterface(This, riid, ppvObject) (This)->lpVtbl->QueryInterface(This, riid, ppvObject)\n\n#define IServiceProvider_AddRef(This) (This)->lpVtbl->AddRef(This)\n\n#define IServiceProvider_Release(This) (This)->lpVtbl->Release(This)\n\n#define IServiceProvider_RemoteQueryService(This, guidService, riid, ppvObject)                                        \\\n    (This)->lpVtbl->RemoteQueryService(This, guidService, riid, ppvObject)\n\n#endif /* COBJMACROS */\n\n#endif /* C style interface */\n\n    HRESULT __stdcall IServiceProvider_RemoteQueryService_Proxy(IServiceProvider*      This,\n                                                                /* [in] */ GUID*       guidService,\n                                                                /* [in] */ GUID*       riid,\n                                                                /* [out] */ IUnknown** ppvObject);\n\n    void __RPC_STUB IServiceProvider_RemoteQueryService_Stub(IRpcStubBuffer*    This,\n                                                             IRpcChannelBuffer* _pRpcChannelBuffer,\n                                                             PRPC_MESSAGE       _pRpcMessage,\n                                                             DWORD*             _pdwStubPhase);\n\n#endif /* __IServiceProvider_INTERFACE_DEFINED__ */\n\n    EXTERN_C const CLSID CLSID_ShockwaveFlash;\n\n#ifdef __cplusplus\n\n    class DECLSPEC_UUID(\"D27CDB6E-AE6D-11CF-96B8-444553540000\") ShockwaveFlash;\n#endif\n\n    EXTERN_C const CLSID CLSID_FlashObjectInterface;\n\n#ifdef __cplusplus\n\n    class DECLSPEC_UUID(\"D27CDB71-AE6D-11CF-96B8-444553540000\") FlashObjectInterface;\n#endif\n#endif /* __ShockwaveFlashObjects_LIBRARY_DEFINED__ */\n\n    /* Additional Prototypes for ALL interfaces */\n\n    /* end of Additional Prototypes */\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "src/modules/flash/producer/FlashAxContainer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#include \"../stdafx.h\"\n\n#include \"../interop/TimerHelper.h\"\n#include \"FlashAxContainer.h\"\n\n#include <common/log.h>\n\n#pragma warning(push, 2) // TODO\n\nusing namespace ATL;\n\nnamespace caspar { namespace flash {\n\nCComBSTR FlashAxContainer::flashGUID_(_T(\"{D27CDB6E-AE6D-11CF-96B8-444553540000}\"));\n\n_ATL_FUNC_INFO fnInfoFlashCallEvent        = {CC_STDCALL, VT_EMPTY, 1, {VT_BSTR}};\n_ATL_FUNC_INFO fnInfoReadyStateChangeEvent = {CC_STDCALL, VT_EMPTY, 1, {VT_I4}};\n\nFlashAxContainer::FlashAxContainer()\n    : pTimerHelper(nullptr)\n    , bInvalidRect_(false)\n    , bReadyToRender_(false)\n    , bIsEmpty_(true)\n    , bHasNewTiming_(false)\n    , m_lpDD4(nullptr)\n    , timerCount_(0)\n    , bInPlaceActive_(FALSE)\n{\n}\nFlashAxContainer::~FlashAxContainer()\n{\n    if (m_lpDD4) {\n        m_lpDD4->Release();\n        delete m_lpDD4;\n    }\n\n    if (pTimerHelper != nullptr)\n        delete pTimerHelper;\n}\n\n/////////\n// IObjectWithSite\n/////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::SetSite(IUnknown* pUnkSite)\n{\n    ATLTRACE(_T(\"IObjectWithSite::SetSite\\n\"));\n    HRESULT hr = IObjectWithSiteImpl<FlashAxContainer>::SetSite(pUnkSite);\n\n    if (SUCCEEDED(hr) && m_spUnkSite) {\n        // Look for \"outer\" IServiceProvider\n        hr = m_spUnkSite->QueryInterface(__uuidof(IServiceProvider), (void**)&m_spServices);\n        ATLASSERT(!hr && _T(\"No ServiceProvider!\"));\n    }\n\n    if (pUnkSite == nullptr)\n        m_spServices.Release();\n\n    return hr;\n}\n\n/////////\n// IOleClientSite\n/////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::SaveObject() { ATLTRACENOTIMPL(_T(\"IOleClientSite::SaveObject\")); }\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetMoniker(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk)\n{\n    /*\tif(*ppmk != NULL) {\n            if(m_spMyMoniker == NULL) {\n                ATL::CComObject<MyMoniker>* pMoniker = NULL;\n                HRESULT hr = ATL::CComObject<MyMoniker>::CreateInstance(&pMoniker);\n                if(SUCCEEDED(hr))\n                    m_spMyMoniker = pMoniker;\n            }\n\n            if(m_spMyMoniker != NULL) {\n                *ppmk = m_spMyMoniker;\n                (*ppmk)->AddRef();\n                return S_OK;\n            }\n        }\n    */\n    if (ppmk != nullptr)\n        *ppmk = nullptr;\n    return E_FAIL;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetContainer(IOleContainer** ppContainer)\n{\n    ATLTRACE(_T(\"IOleClientSite::GetContainer\\n\"));\n    *ppContainer = nullptr;\n    return E_NOINTERFACE;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::ShowObject()\n{\n    ATLTRACE(_T(\"IOleClientSite::ShowObject\\n\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnShowWindow(BOOL fShow)\n{\n    ATLTRACE(_T(\"IOleClientSite::OnShowWindow\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::RequestNewObjectLayout()\n{\n    ATLTRACE(_T(\"IOleClientSite::RequestNewObjectLayout\"));\n    return S_OK;\n}\n\n/////////\n// IOleInPlaceSite\n/////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindow(HWND* pHwnd)\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::GetWindow\\n\"));\n    *pHwnd = nullptr; // GetApplication()->GetMainWindow()->getHwnd();\n    return E_FAIL;\n}\nHRESULT STDMETHODCALLTYPE FlashAxContainer::ContextSensitiveHelp(BOOL fEnterMode)\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::ContextSensitiveHelp\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::CanInPlaceActivate()\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::CanInPlaceActivate\\n\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivate()\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::OnInPlaceActivate\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIActivate()\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::OnUIActivate\\n\"));\n    bUIActive_ = TRUE;\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetWindowContext(IOleInPlaceFrame**    ppFrame,\n                                                             IOleInPlaceUIWindow** ppDoc,\n                                                             LPRECT                lprcPosRect,\n                                                             LPRECT                lprcClipRect,\n                                                             LPOLEINPLACEFRAMEINFO pFrameInfo)\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::GetWindowContext\\n\"));\n    if (ppFrame != nullptr)\n        *ppFrame = nullptr;\n    if (ppDoc != nullptr)\n        *ppDoc = nullptr;\n\n    if (ppFrame == nullptr || ppDoc == nullptr || lprcPosRect == nullptr || lprcClipRect == nullptr)\n        return E_POINTER;\n\n    pFrameInfo->fMDIApp       = FALSE;\n    pFrameInfo->haccel        = nullptr;\n    pFrameInfo->cAccelEntries = 0;\n    pFrameInfo->hwndFrame     = nullptr;\n\n    lprcPosRect->top    = m_rcPos.top;\n    lprcPosRect->left   = m_rcPos.left;\n    lprcPosRect->right  = m_rcPos.right;\n    lprcPosRect->bottom = m_rcPos.bottom;\n\n    lprcClipRect->top    = m_rcPos.top;\n    lprcClipRect->left   = m_rcPos.left;\n    lprcClipRect->right  = m_rcPos.right;\n    lprcClipRect->bottom = m_rcPos.bottom;\n\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::Scroll(SIZE scrollExtant)\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::Scroll\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnUIDeactivate(BOOL fUndoable)\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::OnUIDeactivate\\n\"));\n    bUIActive_ = FALSE;\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivate()\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::OnInPlaceDeactivate\\n\"));\n    bInPlaceActive_ = FALSE;\n    m_spInPlaceObjectWindowless.Release();\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::DiscardUndoState()\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::DiscardUndoState\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::DeactivateAndUndo()\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::DeactivateAndUndo\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnPosRectChange(LPCRECT lprcPosRect)\n{\n    ATLTRACE(_T(\"IOleInPlaceSite::OnPosRectChange\"));\n    return S_OK;\n}\n\n//////////\n// IOleInPlaceSiteEx\n//////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceActivateEx(BOOL* pfNoRedraw, DWORD dwFlags)\n{\n    // should only be called once the first time control is inplace-activated\n    ATLTRACE(_T(\"IOleInPlaceSiteEx::OnInPlaceActivateEx\\n\"));\n    ATLASSERT(bInPlaceActive_ == FALSE);\n    ATLASSERT(m_spInPlaceObjectWindowless == NULL);\n\n    bInPlaceActive_ = TRUE;\n    OleLockRunning(m_spOleObject, TRUE, FALSE);\n    HRESULT hr = E_FAIL;\n    if (dwFlags & ACTIVATE_WINDOWLESS) {\n        hr = m_spOleObject->QueryInterface(__uuidof(IOleInPlaceObjectWindowless), (void**)&m_spInPlaceObjectWindowless);\n\n        if (m_spInPlaceObjectWindowless != nullptr)\n            m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\n    }\n\n    return m_spInPlaceObjectWindowless != nullptr ? S_OK : E_FAIL;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnInPlaceDeactivateEx(BOOL fNoRedraw)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteEx::OnInPlaceDeactivateEx\\n\"));\n    bInPlaceActive_ = FALSE;\n    m_spInPlaceObjectWindowless.Release();\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::RequestUIActivate()\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteEx::RequestUIActivate\\n\"));\n    return S_OK;\n}\n\n//////////////\n// IOleInPlaceSiteWindowless\n//////////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::CanWindowlessActivate()\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::CanWindowlessActivate\\n\"));\n    return S_OK;\n    //\treturn S_FALSE;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetCapture()\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::GetCapture\\n\"));\n    return bCapture_ ? S_OK : S_FALSE;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::SetCapture(BOOL fCapture)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::SetCapture\\n\"));\n    bCapture_ = fCapture;\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetFocus()\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::GetFocus\\n\"));\n    return bHaveFocus_ ? S_OK : S_FALSE;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::SetFocus(BOOL fGotFocus)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::SetFocus\\n\"));\n    bHaveFocus_ = fGotFocus;\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetDC(LPCRECT pRect, DWORD grfFlags, HDC* phDC)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::GetDC\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::ReleaseDC(HDC hDC)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::ReleaseDC\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRect(LPCRECT pRect, BOOL fErase)\n{\n    //\tATLTRACE(_T(\"IOleInPlaceSiteWindowless::InvalidateRect\\n\"));\n\n    bInvalidRect_ = true;\n\n    /*\t//Keep a list of dirty rectangles in order to be able to redraw only them\n        if(pRect != NULL) {\n            bDirtyRects_.push_back(DirtyRect(*pRect, fErase != 0));\n        }\n        else {\n            bDirtyRects_.push_back(DirtyRect(true));\n        }\n    */\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::InvalidateRgn(HRGN hRGN, BOOL fErase)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::InvalidateRng\\n\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::ScrollRect(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::ScrollRect\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::AdjustRect(LPRECT prc)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::AdjustRect\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnDefWindowMessage(UINT     msg,\n                                                               WPARAM   wParam,\n                                                               LPARAM   lParam,\n                                                               LRESULT* plResult)\n{\n    ATLTRACE(_T(\"IOleInPlaceSiteWindowless::OnDefWindowMessage\"));\n    return S_OK;\n}\n\n/////////\n// IOleControlSite\n/////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnControlInfoChanged()\n{\n    ATLTRACE(_T(\"IOleControlSite::OnControlInfoChanged\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::LockInPlaceActive(BOOL fLock)\n{\n    ATLTRACE(_T(\"IOleControlSite::LockInPlaceActive\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetExtendedControl(IDispatch** ppDisp)\n{\n    ATLTRACE(_T(\"IOleControlSite::GetExtendedControl\"));\n\n    if (ppDisp == nullptr)\n        return E_POINTER;\n    return m_spOleObject.QueryInterface(ppDisp);\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::TransformCoords(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags)\n{\n    ATLTRACE(_T(\"IOleControlSite::TransformCoords\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::TranslateAccelerator(LPMSG lpMsg, DWORD grfModifiers)\n{\n    ATLTRACE(_T(\"IOleControlSite::TranslateAccelerator\"));\n    return S_FALSE;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::OnFocus(BOOL fGotFocus)\n{\n    bHaveFocus_ = fGotFocus;\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::ShowPropertyFrame()\n{\n    ATLTRACE(_T(\"IOleControlSite::ShowPropertyFrame\"));\n    return S_OK;\n}\n\n/////////\n// IAdviseSink\n/////////\nvoid STDMETHODCALLTYPE FlashAxContainer::OnDataChange(FORMATETC* pFormatetc, STGMEDIUM* pStgmed)\n{\n    ATLTRACE(_T(\"IAdviseSink::OnDataChange\\n\"));\n}\n\nvoid STDMETHODCALLTYPE FlashAxContainer::OnViewChange(DWORD dwAspect, LONG lindex)\n{\n    ATLTRACE(_T(\"IAdviseSink::OnViewChange\\n\"));\n}\n\nvoid STDMETHODCALLTYPE FlashAxContainer::OnRename(IMoniker* pmk) { ATLTRACE(_T(\"IAdviseSink::OnRename\\n\")); }\n\nvoid STDMETHODCALLTYPE FlashAxContainer::OnSave() { ATLTRACE(_T(\"IAdviseSink::OnSave\\n\")); }\n\nvoid STDMETHODCALLTYPE FlashAxContainer::OnClose() { ATLTRACE(_T(\"IAdviseSink::OnClose\\n\")); }\n\n// DirectDraw GUIDS\n\nDEFINE_GUID2(CLSID_DirectDraw, 0xD7B70EE0, 0x4340, 0x11CF, 0xB0, 0x63, 0x00, 0x20, 0xAF, 0xC2, 0xCD, 0x35);\nDEFINE_GUID2(CLSID_DirectDraw7, 0x3c305196, 0x50db, 0x11d3, 0x9c, 0xfe, 0x00, 0xc0, 0x4f, 0xd9, 0x30, 0xc5);\n\nDEFINE_GUID2(IID_IDirectDraw, 0x6C14DB80, 0xA733, 0x11CE, 0xA5, 0x21, 0x00, 0x20, 0xAF, 0x0B, 0xE5, 0x60);\nDEFINE_GUID2(IID_IDirectDraw3, 0x618f8ad4, 0x8b7a, 0x11d0, 0x8f, 0xcc, 0x0, 0xc0, 0x4f, 0xd9, 0x18, 0x9d);\nDEFINE_GUID2(IID_IDirectDraw4, 0x9c59509a, 0x39bd, 0x11d1, 0x8c, 0x4a, 0x00, 0xc0, 0x4f, 0xd9, 0x30, 0xc5);\nDEFINE_GUID2(IID_IDirectDraw7, 0x15e65ec0, 0x3b9c, 0x11d2, 0xb9, 0x2f, 0x00, 0x60, 0x97, 0x97, 0xea, 0x5b);\n\n/////////\n// IServiceProvider\n/////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::QueryService(REFGUID rsid, REFIID riid, void** ppvObj)\n{\n    //\tATLTRACE(_T(\"IServiceProvider::QueryService\\n\"));\n    // the flashcontrol asks for an interface {618F8AD4-8B7A-11D0-8FCC-00C04FD9189D}, this is IID for a DirectDraw3\n    // object\n\n    ATLASSERT(ppvObj != NULL);\n    if (ppvObj == nullptr)\n        return E_POINTER;\n    *ppvObj = nullptr;\n\n    HRESULT hr;\n    // Author: Makarov Igor\n    // Transparent Flash Control in Plain C++\n    // http://www.codeproject.com/KB/COM/flashcontrol.aspx\n    if (IsEqualGUID(rsid, IID_IDirectDraw3)) {\n        if (!m_lpDD4) {\n            m_lpDD4 = new IDirectDraw4Ptr;\n            hr      = m_lpDD4->CreateInstance(CLSID_DirectDraw, nullptr, CLSCTX_INPROC_SERVER);\n            if (FAILED(hr)) {\n                delete m_lpDD4;\n                m_lpDD4 = nullptr;\n                CASPAR_LOG(info) << print_() << \" DirectDraw not installed. Running without DirectDraw.\";\n                return E_NOINTERFACE;\n            }\n        }\n        if (m_lpDD4 && m_lpDD4->GetInterfacePtr()) {\n            *ppvObj = m_lpDD4->GetInterfacePtr();\n            m_lpDD4->AddRef();\n            return S_OK;\n        }\n    }\n\n    // TODO: The fullscreen-consumer requires that this does NOT return an ITimerService\n    hr = QueryInterface(riid, ppvObj); // E_NOINTERFACE;\n\n    return hr;\n}\n\n/////////\n// ITimerService\n/////////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::CreateTimer(ITimer* pReferenceTimer, ITimer** ppNewTimer)\n{\n    ATLTRACE(_T(\"ITimerService::CreateTimer\\n\"));\n    if (pTimerHelper != nullptr) {\n        delete pTimerHelper;\n        pTimerHelper = nullptr;\n    }\n    pTimerHelper = new TimerHelper();\n    return QueryInterface(__uuidof(ITimer), (void**)ppNewTimer);\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetNamedTimer(REFGUID rguidName, ITimer** ppTimer)\n{\n    ATLTRACE(_T(\"ITimerService::GetNamedTimer\"));\n    if (ppTimer == nullptr)\n        return E_POINTER;\n    *ppTimer = nullptr;\n\n    return E_FAIL;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::SetNamedTimerReference(REFGUID rguidName, ITimer* pReferenceTimer)\n{\n    ATLTRACE(_T(\"ITimerService::SetNamedTimerReference\"));\n    return S_OK;\n}\n\n//////\n// ITimer\n//////\nHRESULT STDMETHODCALLTYPE FlashAxContainer::Advise(VARIANT     vtimeMin,\n                                                   VARIANT     vtimeMax,\n                                                   VARIANT     vtimeInterval,\n                                                   DWORD       dwFlags,\n                                                   ITimerSink* pTimerSink,\n                                                   DWORD*      pdwCookie)\n{\n    ATLTRACE(_T(\"Timer::Advise\\n\"));\n\n    if (pdwCookie == nullptr)\n        return E_POINTER;\n\n    if (pTimerHelper != nullptr) {\n        // static tbb::atomic<DWORD> NEXT_ID;\n        pTimerHelper->Setup(0, vtimeMin.ulVal, vtimeInterval.ulVal, pTimerSink);\n        *pdwCookie     = pTimerHelper->ID;\n        bHasNewTiming_ = true;\n\n        return S_OK;\n    }\n    return E_OUTOFMEMORY;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::Unadvise(/* [in] */ DWORD dwCookie)\n{\n    ATLTRACE(_T(\"Timer::Unadvice\\n\"));\n    if (pTimerHelper != nullptr) {\n        pTimerHelper->pTimerSink = nullptr;\n        return S_OK;\n    }\n    return E_FAIL;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::Freeze(/* [in] */ BOOL fFreeze)\n{\n    ATLTRACE(_T(\"Timer::Freeze\\n\"));\n    return S_OK;\n}\n\nHRESULT STDMETHODCALLTYPE FlashAxContainer::GetTime(/* [out] */ VARIANT* pvtime)\n{\n    ATLTRACE(_T(\"Timer::GetTime\\n\"));\n    if (pvtime == nullptr)\n        return E_POINTER;\n\n    //\treturn E_NOTIMPL;\n    pvtime->lVal = 0;\n    return S_OK;\n}\n\ndouble FlashAxContainer::GetFPS()\n{\n    if (pTimerHelper != nullptr && pTimerHelper->interval > 0)\n        return 1000.0 / static_cast<double>(pTimerHelper->interval);\n\n    return 0.0;\n}\n\nbool FlashAxContainer::IsReadyToRender() const { return bReadyToRender_; }\n\nvoid FlashAxContainer::EnterFullscreen()\n{\n    if (m_spInPlaceObjectWindowless != nullptr) {\n        LRESULT result;\n        m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONDOWN, 0, MAKELPARAM(1, 1), &result);\n        m_spInPlaceObjectWindowless->OnWindowMessage(WM_LBUTTONUP, 0, MAKELPARAM(1, 1), &result);\n    }\n}\n\nvoid STDMETHODCALLTYPE FlashAxContainer::OnFlashCall(BSTR request)\n{\n    std::wstring str(request);\n    if (str.find(L\"DisplayedTemplate\") != std::wstring::npos) {\n        ATLTRACE(_T(\"ShockwaveFlash::DisplayedTemplate\\n\"));\n        bReadyToRender_ = true;\n    } else if (str.find(L\"OnCommand\") != std::wstring::npos) {\n        // this is how templatehost 1.8 reports that a command has been received\n        CASPAR_LOG(debug) << print_() << L\" [command]      \" << str;\n        bCallSuccessful_ = true;\n    } else if (str.find(L\"Activity\") != std::wstring::npos) {\n        CASPAR_LOG(debug) << print_() << L\" [activity]     \" << str;\n\n        // this is how templatehost 1.7 reports that a command has been received\n        // typos: ignore-next\n        if (str.find(L\"Command recieved\") != std::wstring::npos || str.find(L\"Command received\") != std::wstring::npos)\n            bCallSuccessful_ = true;\n\n        /*if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\n            std::wstring::size_type pos = str.find(TEXT('@'));\n            if(pos != std::wstring::npos)\n                pFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\n        }*/\n    } else if (str.find(L\"OnNotify\") != std::wstring::npos) {\n        CASPAR_LOG(info) << print_() << L\" [notification] \" << str;\n\n        // if(pFlashProducer_ != 0 && pFlashProducer_->pMonitor_) {\n        //\tstd::wstring::size_type pos = str.find(TEXT('@'));\n        //\tif(pos != std::wstring::npos)\n        //\t\tpFlashProducer_->pMonitor_->Inform(str.substr(pos, str.find(TEXT('<'), pos)-pos));\n        //}\n    } else if (str.find(L\"IsEmpty\") != std::wstring::npos) {\n        CASPAR_LOG(debug) << print_() << L\" Empty.\";\n        ATLTRACE(_T(\"ShockwaveFlash::IsEmpty\\n\"));\n        bIsEmpty_ = true;\n    } else if (str.find(L\"OnError\") != std::wstring::npos) {\n        if (str.find(L\"No template playing on layer\") != std::wstring::npos)\n            CASPAR_LOG(info) << print_() << L\" [info]        \" << str;\n        else\n            CASPAR_LOG(error) << print_() << L\" [error]        \" << str;\n    } else if (str.find(L\"OnDebug\") != std::wstring::npos) {\n        CASPAR_LOG(debug) << print_() << L\" [debug]        \" << str;\n    }\n    // else if(str.find(TEXT(\"OnTemplateDescription\")) != std::wstring::npos)\n    //{\n    //\tCASPAR_LOG(error) << print_() << L\" TemplateDescription: \\n-------------------------------------------\\n\" << str\n    //<<\n    // L\"\\n-------------------------------------------\";\n    //}\n    // else if(str.find(TEXT(\"OnGetInfo\")) != std::wstring::npos)\n    //{\n    //\tCASPAR_LOG(error) << print_() << L\" Info: \\n-------------------------------------------\\n\" << str <<\n    // L\"\\n-------------------------------------------\";\n    //}\n    // else\n    //{\n    //\tCASPAR_LOG(error) << print_() << L\" Unknown: \\n-------------------------------------------\\n\" << str <<\n    // L\"\\n-------------------------------------------\";\n    //}\n\n    CComPtr<IShockwaveFlash> spFlash;\n    HRESULT                  hr = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**)&spFlash);\n    if (hr == S_OK && spFlash) {\n        hr = spFlash->SetReturnValue(SysAllocString(L\"<null/>\"));\n    }\n}\n\nvoid STDMETHODCALLTYPE FlashAxContainer::OnReadyStateChange(long newState)\n{\n    if (newState == 4)\n        bReadyToRender_ = true;\n}\n\nvoid FlashAxContainer::DestroyAxControl()\n{\n    GetControllingUnknown()->AddRef();\n\n    if (!m_spViewObject == false)\n        m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, nullptr);\n\n    if (!m_spOleObject == false) {\n        DispEventUnadvise(m_spOleObject, &DIID__IShockwaveFlashEvents);\n        m_spOleObject->Unadvise(m_dwOleObject);\n        m_spOleObject->Close(OLECLOSE_NOSAVE);\n        m_spOleObject->SetClientSite(nullptr);\n    }\n\n    if (!m_spUnknown == false) {\n        CComPtr<IObjectWithSite> spSite;\n        m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\n        if (spSite != nullptr)\n            spSite->SetSite(nullptr);\n    }\n\n    if (!m_spViewObject == false)\n        m_spViewObject.Release();\n\n    if (!m_spInPlaceObjectWindowless == false)\n        m_spInPlaceObjectWindowless.Release();\n\n    if (!m_spOleObject == false)\n        m_spOleObject.Release();\n\n    if (!m_spUnknown == false)\n        m_spUnknown.Release();\n}\n\nbool FlashAxContainer::CheckForFlashSupport()\n{\n    CLSID clsid;\n    return SUCCEEDED(CLSIDFromString((LPOLESTR)flashGUID_, &clsid));\n}\n\nHRESULT\nFlashAxContainer::CreateAxControl()\n{\n    CLSID   clsid;\n    HRESULT hr = CLSIDFromString((LPOLESTR)flashGUID_, &clsid);\n    if (SUCCEEDED(hr))\n        hr = CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IUnknown), (void**)&m_spUnknown);\n\n    // Start ActivateAx\n    if (SUCCEEDED(hr)) {\n        m_spUnknown->QueryInterface(__uuidof(IOleObject), (void**)&m_spOleObject);\n        if (m_spOleObject) {\n            m_spOleObject->GetMiscStatus(DVASPECT_CONTENT, &m_dwMiscStatus);\n            if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST) {\n                CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\n                m_spOleObject->SetClientSite(spClientSite);\n            }\n\n            // Initialize control\n            CComQIPtr<IPersistStreamInit> spPSI(m_spOleObject);\n            if (spPSI)\n                hr = spPSI->InitNew();\n\n            if (FAILED(hr)) // If the initialization of the control failed...\n            {\n                // Clean up and return\n                if (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)\n                    m_spOleObject->SetClientSite(nullptr);\n\n                m_dwMiscStatus = 0;\n                m_spOleObject.Release();\n                m_spUnknown.Release();\n\n                return hr;\n            }\n            // end Initialize object\n\n            if (0 == (m_dwMiscStatus & OLEMISC_SETCLIENTSITEFIRST)) {\n                CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\n                m_spOleObject->SetClientSite(spClientSite);\n            }\n\n            CComPtr<IShockwaveFlash> spFlash;\n            HRESULT                  hr2 = m_spOleObject->QueryInterface(__uuidof(IShockwaveFlash), (void**)&spFlash);\n            if (hr2 == S_OK && spFlash) {\n                if (FAILED(spFlash->put_WMode(SysAllocString(L\"Transparent\"))))\n                    CASPAR_LOG(warning) << print_() << L\" Failed to set flash container to transparent mode.\";\n                // spFlash->put_WMode(TEXT(\"ogl\"));\n                HRESULT hResultQuality = spFlash->put_Quality2(SysAllocString(L\"Best\"));\n            }\n            if (SUCCEEDED(DispEventAdvise(spFlash, &DIID__IShockwaveFlashEvents))) {\n            }\n\n            HRESULT hrView = m_spOleObject->QueryInterface(__uuidof(IViewObjectEx), (void**)&m_spViewObject);\n\n            CComQIPtr<IAdviseSink> spAdviseSink(GetControllingUnknown());\n            m_spOleObject->Advise(spAdviseSink, &m_dwOleObject);\n            if (m_spViewObject)\n                m_spViewObject->SetAdvise(DVASPECT_CONTENT, 0, spAdviseSink);\n\n            if ((m_dwMiscStatus & OLEMISC_INVISIBLEATRUNTIME) == 0) {\n                // Initialize window to some dummy size\n                m_rcPos.top    = 0;\n                m_rcPos.left   = 0;\n                m_rcPos.right  = 720;\n                m_rcPos.bottom = 576;\n\n                m_pxSize.cx = m_rcPos.right - m_rcPos.left;\n                m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\n                AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\n                m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\n                m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\n                AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\n                m_rcPos.right  = m_rcPos.left + m_pxSize.cx;\n                m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\n\n                CComQIPtr<IOleClientSite> spClientSite(GetControllingUnknown());\n                hr = m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, nullptr, spClientSite, 0, nullptr, &m_rcPos);\n            }\n        }\n        CComPtr<IObjectWithSite> spSite;\n        m_spUnknown->QueryInterface(__uuidof(IObjectWithSite), (void**)&spSite);\n        if (spSite != nullptr)\n            spSite->SetSite(GetControllingUnknown());\n    }\n    // End ActivateAx\n\n    //\thr = E_FAIL;\n    if (FAILED(hr) || m_spUnknown == nullptr) {\n        return E_FAIL;\n        // We don't have a control or something failed so release\n        //\t\tReleaseAll();\n    }\n\n    return S_OK;\n}\n\nvoid FlashAxContainer::SetSize(size_t width, size_t height)\n{\n    if (m_spInPlaceObjectWindowless != nullptr) {\n        m_rcPos.top    = 0;\n        m_rcPos.left   = 0;\n        m_rcPos.right  = width;\n        m_rcPos.bottom = height;\n\n        m_pxSize.cx = m_rcPos.right - m_rcPos.left;\n        m_pxSize.cy = m_rcPos.bottom - m_rcPos.top;\n        AtlPixelToHiMetric(&m_pxSize, &m_hmSize);\n        m_spOleObject->SetExtent(DVASPECT_CONTENT, &m_hmSize);\n        m_spOleObject->GetExtent(DVASPECT_CONTENT, &m_hmSize);\n        AtlHiMetricToPixel(&m_hmSize, &m_pxSize);\n        m_rcPos.right  = m_rcPos.left + m_pxSize.cx;\n        m_rcPos.bottom = m_rcPos.top + m_pxSize.cy;\n\n        m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\n        bInvalidRect_ = true;\n    }\n}\n\nHRESULT\nFlashAxContainer::QueryControl(REFIID iid, void** ppUnk)\n{\n    ATLASSERT(ppUnk != NULL);\n    if (ppUnk == nullptr)\n        return E_POINTER;\n    HRESULT hr = m_spOleObject->QueryInterface(iid, ppUnk);\n    return hr;\n}\n\nbool FlashAxContainer::DrawControl(HDC targetDC)\n{\n    //\tATLTRACE(_T(\"FlashAxContainer::DrawControl\\n\"));\n    DVASPECTINFO aspectInfo = {sizeof(DVASPECTINFO), DVASPECTINFOFLAG_CANOPTIMIZE};\n    HRESULT      hr         = m_spViewObject->Draw(\n        DVASPECT_CONTENT, -1, &aspectInfo, nullptr, nullptr, targetDC, nullptr, nullptr, nullptr, NULL);\n    bInvalidRect_ = false;\n    /*\tconst video_format_desc& fmtDesc = video_format_desc::FormatDescriptions[format_];\n\n        //Trying to redraw just the dirty rectangles. Doesn't seem to work when the movie uses \"filters\", such as glow,\n       dropshadow etc. std::vector<flash::DirtyRect>::iterator it = bDirtyRects_.begin();\n        std::vector<flash::DirtyRect>::iterator end = bDirtyRects_.end();\n        for(; it != end; ++it) {\n            flash::DirtyRect& dirtyRect = (*it);\n            if(dirtyRect.bWhole || dirtyRect.rect.right >= fmtDesc.width || dirtyRect.rect.bottom >= fmtDesc.height) {\n                m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &m_rcPos);\n                hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL);\n                break;\n            }\n            else {\n                m_spInPlaceObjectWindowless->SetObjectRects(&m_rcPos, &(dirtyRect.rect));\n                hr = m_spViewObject->Draw(DVASPECT_OPAQUE, -1, NULL, NULL, NULL, targetDC, NULL, NULL, NULL, NULL);\n            }\n        }\n        bDirtyRects_.clear();\n    */\n\n    return hr == S_OK;\n}\n\nvoid FlashAxContainer::Tick()\n{\n    if (pTimerHelper) {\n        DWORD time = pTimerHelper->Invoke(); // Tick flash\n        if (time - timerCount_ >= 400) {\n            timerCount_ = time;\n            LRESULT hr;\n            m_spInPlaceObjectWindowless->OnWindowMessage(WM_TIMER, 3, 0, &hr);\n        }\n    }\n}\n\nbool FlashAxContainer::FlashCall(const std::wstring& str, std::wstring& result2)\n{\n    CComBSTR                 result;\n    CComPtr<IShockwaveFlash> spFlash;\n    QueryControl(&spFlash);\n    CComBSTR request(str.c_str());\n\n    bIsEmpty_        = false;\n    bCallSuccessful_ = false;\n    for (size_t retries = 0; !bCallSuccessful_ && retries < 4; ++retries)\n        spFlash->CallFunction(request, &result);\n\n    if (bCallSuccessful_)\n        result2 = result;\n\n    return bCallSuccessful_;\n}\n\n}} // namespace caspar::flash\n"
  },
  {
    "path": "src/modules/flash/producer/FlashAxContainer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#ifndef _FLASHAXCONTAINER_H__\n#define _FLASHAXCONTAINER_H__\n\n#pragma once\n\n#include <atlbase.h>\n#include <atlcom.h>\n#include <atlhost.h>\n#include <ocmm.h>\n\n#include <functional>\n\n#include \"../interop/axflash.h\"\n#include <core/video_format.h>\n// #import \"progid:ShockwaveFlash.ShockwaveFlash.9\" no_namespace, named_guids\n\n#include <comdef.h>\n\n#include <InitGuid.h>\n#include <ddraw.h>\n\n#ifndef DEFINE_GUID2\n#define DEFINE_GUID2(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)                                                  \\\n    const GUID name = {l, w1, w2, {b1, b2, b3, b4, b5, b6, b7, b8}}\n#endif\n\n_COM_SMARTPTR_TYPEDEF(IDirectDraw4, IID_IDirectDraw4);\n\nnamespace caspar { namespace flash {\n\nclass TimerHelper;\n/*struct DirtyRect {\n    DirtyRect(LONG l, LONG t, LONG r, LONG b, bool e) : bErase(e), bWhole(false) {\n        rect.left = l;\n        rect.top = t;\n        rect.right = r;\n        rect.bottom = b;\n    }\n    DirtyRect(const RECT& rc, bool e) : bErase(e), bWhole(false)  {\n        rect.left = rc.left;\n        rect.top = rc.top;\n        rect.right = rc.right;\n        rect.bottom = rc.bottom;\n    }\n    explicit DirtyRect(bool b) : bWhole(b) {}\n\n    RECT\trect;\n    bool\tbErase;\n    bool\tbWhole;\n};*/\n\nextern _ATL_FUNC_INFO fnInfoFlashCallEvent;\nextern _ATL_FUNC_INFO fnInfoReadyStateChangeEvent;\n\nclass ATL_NO_VTABLE FlashAxContainer\n    : public ATL::CComCoClass<FlashAxContainer, &CLSID_NULL>\n    , public ATL::CComObjectRootEx<ATL::CComMultiThreadModel>\n    , public IOleClientSite\n    , public IOleContainer\n    , public IOleControlSite\n    , public IOleInPlaceSiteWindowless\n    , public IObjectWithSiteImpl<FlashAxContainer>\n    , public IServiceProvider\n    , public IAdviseSink\n    , public ITimerService\n    , public ITimer\n    , public IDispatchImpl<IDispatch>\n    , public IDispEventSimpleImpl<0, FlashAxContainer, &DIID__IShockwaveFlashEvents>\n{\n  public:\n    FlashAxContainer();\n    virtual ~FlashAxContainer();\n\n    DECLARE_NO_REGISTRY()\n    DECLARE_POLY_AGGREGATABLE(FlashAxContainer)\n    DECLARE_GET_CONTROLLING_UNKNOWN()\n\n    BEGIN_COM_MAP(FlashAxContainer)\n    COM_INTERFACE_ENTRY(IDispatch)\n    COM_INTERFACE_ENTRY(IOleClientSite)\n    COM_INTERFACE_ENTRY(IObjectWithSite)\n    COM_INTERFACE_ENTRY(IOleControlSite)\n    COM_INTERFACE_ENTRY(IOleContainer)\n\n    COM_INTERFACE_ENTRY(IOleInPlaceSiteWindowless)\n    COM_INTERFACE_ENTRY(IOleInPlaceSiteEx)\n    COM_INTERFACE_ENTRY(IOleInPlaceSite)\n    COM_INTERFACE_ENTRY(IOleWindow)\n\n    COM_INTERFACE_ENTRY(IServiceProvider)\n\n    COM_INTERFACE_ENTRY(IAdviseSink)\n\n    COM_INTERFACE_ENTRY(ITimerService)\n\n    COM_INTERFACE_ENTRY(ITimer)\n    END_COM_MAP()\n\n    BEGIN_SINK_MAP(FlashAxContainer)\n    SINK_ENTRY_INFO(0, DIID__IShockwaveFlashEvents, static_cast<DISPID>(0xc5), OnFlashCall, &fnInfoFlashCallEvent)\n    SINK_ENTRY_INFO(0,\n                    DIID__IShockwaveFlashEvents,\n                    static_cast<DISPID>(0xfffffd9f),\n                    OnReadyStateChange,\n                    &fnInfoReadyStateChangeEvent)\n    END_SINK_MAP()\n\n    void STDMETHODCALLTYPE OnFlashCall(BSTR request);\n    void STDMETHODCALLTYPE OnReadyStateChange(long newState);\n\n    // IObjectWithSite\n    STDMETHOD(SetSite)(IUnknown* pUnkSite) override;\n\n    // IOleClientSite\n    STDMETHOD(SaveObject)() override;\n    STDMETHOD(GetMoniker)(DWORD dwAssign, DWORD dwWhichMoniker, IMoniker** ppmk) override;\n    STDMETHOD(GetContainer)(IOleContainer** ppContainer) override;\n    STDMETHOD(ShowObject)() override;\n    STDMETHOD(OnShowWindow)(BOOL fShow) override;\n    STDMETHOD(RequestNewObjectLayout)() override;\n\n    // IOleInPlaceSite\n    STDMETHOD(GetWindow)(HWND* pHwnd) override;\n    STDMETHOD(ContextSensitiveHelp)(BOOL fEnterMode) override;\n    STDMETHOD(CanInPlaceActivate)() override;\n    STDMETHOD(OnInPlaceActivate)() override;\n    STDMETHOD(OnInPlaceDeactivate)() override;\n    STDMETHOD(OnUIActivate)() override;\n    STDMETHOD(OnUIDeactivate)(BOOL fUndoable) override;\n    STDMETHOD(GetWindowContext)\n    (IOleInPlaceFrame**    ppFrame,\n     IOleInPlaceUIWindow** ppDoc,\n     LPRECT                lprcPosRect,\n     LPRECT                lprcClipRect,\n     LPOLEINPLACEFRAMEINFO pFrameInfo) override;\n    STDMETHOD(Scroll)(SIZE scrollExtant) override;\n    STDMETHOD(DiscardUndoState)() override;\n    STDMETHOD(DeactivateAndUndo)() override;\n    STDMETHOD(OnPosRectChange)(LPCRECT lprcPosRect) override;\n\n    // IOleInPlaceSiteEx\n    STDMETHOD(OnInPlaceActivateEx)(BOOL* pfNoRedraw, DWORD dwFlags) override;\n    STDMETHOD(OnInPlaceDeactivateEx)(BOOL fNoRedraw) override;\n    STDMETHOD(RequestUIActivate)() override;\n\n    // IOleInPlaceSiteWindowless\n    STDMETHOD(CanWindowlessActivate)() override;\n    STDMETHOD(GetCapture)() override;\n    STDMETHOD(SetCapture)(BOOL fCapture) override;\n    STDMETHOD(GetFocus)() override;\n    STDMETHOD(SetFocus)(BOOL fGotFocus) override;\n    STDMETHOD(GetDC)(LPCRECT pRect, DWORD grfFlags, HDC* phDC) override;\n    STDMETHOD(ReleaseDC)(HDC hDC) override;\n    STDMETHOD(InvalidateRect)(LPCRECT pRect, BOOL fErase) override;\n    STDMETHOD(InvalidateRgn)(HRGN hRGN, BOOL fErase) override;\n    STDMETHOD(ScrollRect)(INT dx, INT dy, LPCRECT pRectScroll, LPCRECT pRectClip) override;\n    STDMETHOD(AdjustRect)(LPRECT prc) override;\n    STDMETHOD(OnDefWindowMessage)(UINT msg, WPARAM wParam, LPARAM lParam, LRESULT* plResult) override;\n\n    // IOleControlSite\n    STDMETHOD(OnControlInfoChanged)() override;\n    STDMETHOD(LockInPlaceActive)(BOOL fLock) override;\n    STDMETHOD(GetExtendedControl)(IDispatch** ppDisp) override;\n    STDMETHOD(TransformCoords)(POINTL* pPtlHimetric, POINTF* pPtfContainer, DWORD dwFlags) override;\n    STDMETHOD(TranslateAccelerator)(LPMSG lpMsg, DWORD grfModifiers);\n    STDMETHOD(OnFocus)(BOOL fGotFocus) override;\n    STDMETHOD(ShowPropertyFrame)() override;\n\n    // IAdviseSink\n    STDMETHOD_(void, OnDataChange)(FORMATETC* pFormatetc, STGMEDIUM* pStgmed) override;\n    STDMETHOD_(void, OnViewChange)(DWORD dwAspect, LONG lindex) override;\n    STDMETHOD_(void, OnRename)(IMoniker* pmk) override;\n    STDMETHOD_(void, OnSave)() override;\n    STDMETHOD_(void, OnClose)() override;\n\n    // IServiceProvider\n    STDMETHOD(QueryService)(REFGUID rsid, REFIID riid, void** ppvObj) override;\n\n    // IOleContainer\n    STDMETHOD(ParseDisplayName)(IBindCtx*, LPOLESTR, ULONG*, IMoniker**) override\n    {\n        ATLTRACENOTIMPL(_T(\"IOleContainer::ParseDisplayName\"));\n    }\n    STDMETHOD(EnumObjects)(DWORD, IEnumUnknown** ppenum) override\n    {\n        if (ppenum == nullptr)\n            return E_POINTER;\n        *ppenum = nullptr;\n        using enumunk =\n            CComObject<CComEnum<IEnumUnknown, &__uuidof(IEnumUnknown), IUnknown*, _CopyInterface<IUnknown>>>;\n        enumunk* p = nullptr;\n        ATLTRY(p = new enumunk);\n        if (p == nullptr)\n            return E_OUTOFMEMORY;\n        IUnknown* pTemp = m_spUnknown;\n        // There is always only one object.\n        HRESULT hRes = p->Init(reinterpret_cast<IUnknown**>(&pTemp),\n                               reinterpret_cast<IUnknown**>(&pTemp + 1),\n                               GetControllingUnknown(),\n                               AtlFlagCopy);\n        if (SUCCEEDED(hRes))\n            hRes = p->QueryInterface(__uuidof(IEnumUnknown), (void**)ppenum);\n        if (FAILED(hRes))\n            delete p;\n        return hRes;\n    }\n    STDMETHOD(LockContainer)(BOOL) override { ATLTRACENOTIMPL(_T(\"IOleContainer::LockContainer\")); }\n\n    // ITimerService\n    STDMETHOD(CreateTimer)(ITimer* pReferenceTimer, ITimer** ppNewTimer) override;\n    STDMETHOD(GetNamedTimer)(REFGUID rguidName, ITimer** ppTimer) override;\n    STDMETHOD(SetNamedTimerReference)(REFGUID rguidName, ITimer* pReferenceTimer) override;\n\n    // ITimer\n    STDMETHOD(Advise)\n    (VARIANT vtimeMin, VARIANT vtimeMax, VARIANT vtimeInterval, DWORD dwFlags, ITimerSink* pTimerSink, DWORD* pdwCookie)\n        override;\n    STDMETHOD(Unadvise)(DWORD dwCookie) override;\n    STDMETHOD(Freeze)(BOOL fFreeze) override;\n    STDMETHOD(GetTime)(VARIANT* pvtime) override;\n    double GetFPS();\n\n    void set_print(const std::function<std::wstring()>& print) { print_ = print; }\n\n    HRESULT\n    CreateAxControl();\n    void DestroyAxControl();\n    HRESULT\n    QueryControl(REFIID iid, void** ppUnk);\n\n    template <class Q>\n    HRESULT QueryControl(Q** ppUnk)\n    {\n        return QueryControl(__uuidof(Q), (void**)ppUnk);\n    }\n\n    //\tstatic ATL::CComObject<FlashAxContainer>* CreateInstance();\n\n    void Tick();\n    bool FlashCall(const std::wstring& str, std::wstring& result);\n    bool DrawControl(HDC targetDC);\n    bool InvalidRect() const { return bInvalidRect_; }\n    bool IsEmpty() const { return bIsEmpty_; }\n\n    void SetSize(size_t width, size_t height);\n    bool IsReadyToRender() const;\n    void EnterFullscreen();\n\n    static bool CheckForFlashSupport();\n\n    ATL::CComPtr<IOleInPlaceObjectWindowless> m_spInPlaceObjectWindowless;\n\n  private:\n    std::function<std::wstring()> print_;\n    TimerHelper*                  pTimerHelper;\n    volatile bool                 bInvalidRect_;\n    volatile bool                 bCallSuccessful_;\n    volatile bool                 bReadyToRender_;\n    volatile bool                 bIsEmpty_;\n    volatile bool                 bHasNewTiming_;\n    // std::vector<DirtyRect> bDirtyRects_;\n\n    IDirectDraw4Ptr* m_lpDD4;\n    static CComBSTR  flashGUID_;\n\n    DWORD timerCount_;\n\n    //\tstate\n    bool          bUIActive_;\n    bool          bInPlaceActive_;\n    unsigned long bHaveFocus_ : 1;\n    unsigned long bCapture_ : 1;\n\n    DWORD m_dwOleObject;\n    DWORD m_dwMiscStatus;\n    SIZEL m_hmSize;\n    SIZEL m_pxSize;\n    RECT  m_rcPos;\n\n    ATL::CComPtr<IUnknown>      m_spUnknown;\n    ATL::CComPtr<IOleObject>    m_spServices;\n    ATL::CComPtr<IOleObject>    m_spOleObject;\n    ATL::CComPtr<IViewObjectEx> m_spViewObject;\n\n    //\tATL::CComPtr<ATL::CComObject<MyMoniker> > m_spMyMoniker;\n};\n\n}} // namespace caspar::flash\n\n#endif //_FLASHAXCONTAINER_H__\n"
  },
  {
    "path": "src/modules/flash/producer/flash_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../stdafx.h\"\n\n#include \"WinInet.h\"\n#include \"shlwapi.h\"\n#include \"winerror.h\"\n\n#include \"FlashAxContainer.h\"\n#include \"flash_producer.h\"\n\n#include \"../util/swf.h\"\n\n#include <core/video_format.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/pixel_format.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <common/array.h>\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/executor.h>\n#include <common/future.h>\n#include <common/prec_timer.h>\n#include <common/scope_exit.h>\n#include <common/timer.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/filesystem.hpp>\n\nnamespace caspar { namespace flash {\n\nclass bitmap\n{\n  public:\n    bitmap(int width, int height)\n        : bmp_data_(nullptr)\n        , hdc_(CreateCompatibleDC(nullptr), DeleteDC)\n    {\n        BITMAPINFO info;\n        std::memset(&info, 0, sizeof(BITMAPINFO));\n        info.bmiHeader.biBitCount    = 32;\n        info.bmiHeader.biCompression = BI_RGB;\n        info.bmiHeader.biHeight      = static_cast<LONG>(-height);\n        info.bmiHeader.biPlanes      = 1;\n        info.bmiHeader.biSize        = sizeof(BITMAPINFO);\n        info.bmiHeader.biWidth       = static_cast<LONG>(width);\n\n        bmp_.reset(\n            CreateDIBSection(\n                static_cast<HDC>(hdc_.get()), &info, DIB_RGB_COLORS, reinterpret_cast<void**>(&bmp_data_), nullptr, 0),\n            DeleteObject);\n        SelectObject(static_cast<HDC>(hdc_.get()), bmp_.get());\n\n        if (!bmp_data_)\n            CASPAR_THROW_EXCEPTION(bad_alloc());\n    }\n\n    operator HDC() { return static_cast<HDC>(hdc_.get()); }\n\n    BYTE*       data() { return bmp_data_; }\n    const BYTE* data() const { return bmp_data_; }\n\n  private:\n    BYTE*                 bmp_data_;\n    std::shared_ptr<void> hdc_;\n    std::shared_ptr<void> bmp_;\n};\n\nstruct template_host\n{\n    std::wstring video_mode;\n    std::wstring filename;\n    int          width;\n    int          height;\n};\n\ntemplate_host get_template_host(const core::video_format_desc& desc)\n{\n    try {\n        std::vector<template_host> template_hosts;\n        auto template_hosts_element = env::properties().get_child_optional(L\"configuration.template-hosts\");\n\n        if (template_hosts_element) {\n            for (auto& xml_mapping : *template_hosts_element) {\n                try {\n                    template_host template_host;\n                    template_host.video_mode = xml_mapping.second.get(L\"video-mode\", L\"\");\n                    template_host.filename   = xml_mapping.second.get(L\"filename\", L\"cg.fth\");\n                    template_host.width      = xml_mapping.second.get(L\"width\", desc.width);\n                    template_host.height     = xml_mapping.second.get(L\"height\", desc.height);\n                    template_hosts.push_back(template_host);\n                } catch (...) {\n                }\n            }\n        }\n\n        auto template_host_it = boost::find_if(\n            template_hosts, [&](template_host template_host) { return template_host.video_mode == desc.name; });\n        if (template_host_it == template_hosts.end())\n            template_host_it = boost::find_if(\n                template_hosts, [&](template_host template_host) { return template_host.video_mode.empty(); });\n\n        if (template_host_it != template_hosts.end())\n            return *template_host_it;\n    } catch (...) {\n    }\n\n    template_host template_host;\n    template_host.filename = L\"cg.fth\";\n\n    for (auto it = boost::filesystem::directory_iterator(env::template_folder());\n         it != boost::filesystem::directory_iterator();\n         ++it) {\n        if (boost::iequals(it->path().extension().wstring(), L\".\" + desc.name)) {\n            template_host.filename = it->path().filename().wstring();\n            break;\n        }\n    }\n\n    template_host.width  = desc.square_width;\n    template_host.height = desc.square_height;\n    return template_host;\n}\n\nstd::mutex& get_global_init_destruct_mutex()\n{\n    static std::mutex m;\n\n    return m;\n}\n\nstd::wstring url_from_path(std::wstring in)\n{\n    DWORD out_length = INTERNET_MAX_URL_LENGTH * 2;\n    PWSTR out_buf    = (PWSTR)malloc(out_length + 4);\n    CASPAR_SCOPE_EXIT { free(out_buf); };\n    HRESULT ret = UrlCreateFromPathW(in.c_str(), out_buf, &out_length, NULL);\n    if (SUCCEEDED(ret)) {\n        return std::wstring(out_buf);\n    } else {\n        return in;\n    }\n}\n\nclass flash_renderer\n{\n    struct com_init\n    {\n        HRESULT result_ = CoInitialize(nullptr);\n\n        com_init()\n        {\n            if (FAILED(result_))\n                CASPAR_THROW_EXCEPTION(caspar_exception()\n                                       << msg_info(\"Failed to initialize com-context for flash-player\"));\n        }\n\n        ~com_init()\n        {\n            if (SUCCEEDED(result_))\n                ::CoUninitialize();\n        }\n    } com_init_;\n\n    const std::wstring filename_;\n    const int          width_;\n    const int          height_;\n\n    const std::shared_ptr<core::frame_factory> frame_factory_;\n\n    CComObject<caspar::flash::FlashAxContainer>* ax_ = nullptr;\n    core::draw_frame                             head_;\n    bitmap                                       bmp_{width_, height_};\n    prec_timer                                   timer_;\n    caspar::timer                                tick_timer_;\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n\n  public:\n    flash_renderer(const spl::shared_ptr<diagnostics::graph>&  graph,\n                   const std::shared_ptr<core::frame_factory>& frame_factory,\n                   const std::wstring&                         filename,\n                   int                                         width,\n                   int                                         height)\n        : filename_(filename)\n        , width_(width)\n        , height_(height)\n        , frame_factory_(frame_factory)\n        , bmp_(width, height)\n        , graph_(graph)\n    {\n        graph_->set_color(\"frame-time\", diagnostics::color(0.1f, 1.0f, 0.1f));\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"param\", diagnostics::color(1.0f, 0.5f, 0.0f));\n\n        if (FAILED(CComObject<caspar::flash::FlashAxContainer>::CreateInstance(&ax_)))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to create FlashAxContainer\"));\n\n        if (FAILED(ax_->CreateAxControl()))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to Create FlashAxControl\"));\n\n        ax_->set_print([this] { return print(); });\n\n        CComPtr<IShockwaveFlash> spFlash;\n        if (FAILED(ax_->QueryControl(&spFlash)))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to Query FlashAxControl\"));\n\n        if (FAILED(spFlash->put_Playing(VARIANT_TRUE)))\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to start playing Flash\"));\n\n        // Concurrent initialization of two template hosts causes a\n        // SecurityException later when CG ADD is performed. Initialization is\n        // therefore serialized via a global mutex.\n        {\n            std::lock_guard<std::mutex> lock(get_global_init_destruct_mutex());\n            if (FAILED(spFlash->put_Movie(CComBSTR(filename.c_str()))))\n                CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to Load Template Host\"));\n        }\n\n        if (FAILED(spFlash->put_ScaleMode(2))) // Exact fit. Scale without respect to the aspect ratio.\n            CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(print() + L\" Failed to Set Scale Mode\"));\n\n        ax_->SetSize(width_, height_);\n        render_frame(0.0);\n\n        CASPAR_LOG(info) << print() << L\" Initialized.\";\n    }\n\n    ~flash_renderer()\n    {\n        if (ax_) {\n            ax_->DestroyAxControl();\n            ax_->Release();\n        }\n        graph_->set_value(\"tick-time\", 0.0f);\n        graph_->set_value(\"frame-time\", 0.0f);\n        CASPAR_LOG(info) << print() << L\" Uninitialized.\";\n    }\n\n    std::wstring call(const std::wstring& param)\n    {\n        std::wstring result;\n\n        CASPAR_LOG(debug) << print() << \" Call: \" << param;\n\n        if (!ax_->FlashCall(param, result))\n            CASPAR_LOG(warning) << print() << L\" Flash call failed:\"\n                                << param; // CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(\"Flash function call\n                                          // failed.\") << arg_name_info(\"param\") << arg_value_info(narrow(param)));\n\n        if (boost::starts_with(result, L\"<exception>\"))\n            CASPAR_LOG(warning) << print() << L\" Flash call failed:\" << result;\n\n        graph_->set_tag(diagnostics::tag_severity::INFO, \"param\");\n\n        return result;\n    }\n\n    core::draw_frame render_frame(double sync)\n    {\n        const float frame_time = 1.0f / fps();\n\n        if (!ax_->IsReadyToRender()) {\n            return head_;\n        }\n\n        if (is_empty()) {\n            return core::draw_frame::empty();\n        }\n\n        if (sync > 0.00001)\n            timer_.tick(frame_time * sync); // This will block the thread.\n\n        graph_->set_value(\"tick-time\", static_cast<float>(tick_timer_.elapsed() / frame_time) * 0.5f);\n        tick_timer_.restart();\n        caspar::timer frame_timer;\n        ax_->Tick();\n\n        if (ax_->InvalidRect()) {\n            core::pixel_format_desc desc = core::pixel_format_desc(core::pixel_format::bgra);\n            desc.planes.push_back(core::pixel_format_desc::plane(width_, height_, 4));\n            auto frame = frame_factory_->create_frame(this, desc);\n\n            std::memset(bmp_.data(), 0, width_ * height_ * 4);\n            ax_->DrawControl(bmp_);\n\n            std::memcpy(frame.image_data(0).begin(), bmp_.data(), width_ * height_ * 4);\n            head_ = core::draw_frame(std::move(frame));\n        }\n\n        MSG msg;\n        while (PeekMessage(&msg,\n                           nullptr,\n                           NULL,\n                           NULL,\n                           PM_REMOVE)) // DO NOT REMOVE THE MESSAGE DISPATCH LOOP. Without this some stuff doesn't work!\n        {\n            if (msg.message == WM_TIMER && msg.wParam == 3 && msg.lParam == 0) // We tick this inside FlashAxContainer\n                continue;\n\n            TranslateMessage(&msg);\n            DispatchMessage(&msg);\n        }\n\n        graph_->set_value(\"frame-time\", static_cast<float>(frame_timer.elapsed() / frame_time) * 0.5f);\n        return head_;\n    }\n\n    bool is_empty() const { return ax_->IsEmpty(); }\n\n    double fps() const { return ax_->GetFPS(); }\n\n    std::wstring print()\n    {\n        return L\"flash-player[\" + boost::filesystem::path(filename_).filename().wstring() + L\"|\" +\n               std::to_wstring(width_) + L\"x\" + std::to_wstring(height_) + L\"]\";\n    }\n};\n\nstruct flash_producer : public core::frame_producer\n{\n    core::monitor::state                       state_;\n    const std::wstring                         filename_;\n    const spl::shared_ptr<core::frame_factory> frame_factory_;\n    const core::video_format_desc              format_desc_;\n    const int                                  width_;\n    const int                                  height_;\n    const int                                  buffer_size_ =\n        env::properties().get(L\"configuration.flash.buffer-depth\", format_desc_.fps > 30.0 ? 4 : 2);\n\n    std::atomic<int> fps_;\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n\n    std::queue<core::draw_frame>                    frame_buffer_;\n    tbb::concurrent_bounded_queue<core::draw_frame> output_buffer_;\n\n    core::draw_frame last_frame_;\n\n    std::unique_ptr<flash_renderer> renderer_;\n    std::atomic<bool>               has_renderer_;\n\n    executor executor_ = executor(L\"flash_producer\");\n\n  public:\n    flash_producer(const spl::shared_ptr<core::frame_factory>& frame_factory,\n                   const core::video_format_desc&              format_desc,\n                   const std::wstring&                         filename,\n                   int                                         width,\n                   int                                         height)\n        : filename_(filename)\n        , frame_factory_(frame_factory)\n        , format_desc_(format_desc)\n        , width_(width > 0 ? width : format_desc.width)\n        , height_(height > 0 ? height : format_desc.height)\n    {\n        fps_ = 0;\n\n        graph_->set_color(\"buffered\", diagnostics::color(1.0f, 1.0f, 0.0f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.9f));\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        has_renderer_ = false;\n\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    ~flash_producer()\n    {\n        executor_.invoke([this] { renderer_.reset(); });\n    }\n\n    // frame_producer\n\n    void log_buffered()\n    {\n        double buffered = output_buffer_.size();\n        auto   ratio    = buffered / buffer_size_;\n        graph_->set_value(\"buffered\", ratio);\n    }\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        auto frame = last_frame_;\n\n        double buffered = output_buffer_.size();\n        auto   ratio    = buffered / buffer_size_;\n        graph_->set_value(\"buffered\", ratio);\n\n        if (output_buffer_.try_pop(frame))\n            last_frame_ = frame;\n        else\n            graph_->set_tag(diagnostics::tag_severity::WARNING, \"late-frame\");\n\n        fill_buffer();\n\n        state_[\"host/path\"]   = filename_;\n        state_[\"host/width\"]  = width_;\n        state_[\"host/height\"] = height_;\n        state_[\"host/fps\"]    = fps_;\n        state_[\"buffer\"]      = output_buffer_.size() % buffer_size_;\n\n        return frame;\n    }\n\n    bool is_ready() override { return !output_buffer_.empty() || last_frame_; }\n\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        auto param = boost::algorithm::join(params, L\" \");\n\n        if (param == L\"?\")\n            return make_ready_future(std::wstring(has_renderer_ ? L\"1\" : L\"0\"));\n\n        return executor_.begin_invoke([this, param]() -> std::wstring {\n            try {\n                bool initialize_renderer = !renderer_;\n\n                if (initialize_renderer) {\n                    renderer_.reset(new flash_renderer(graph_, frame_factory_, filename_, width_, height_));\n\n                    has_renderer_ = true;\n                }\n\n                std::wstring result = param == L\"start_rendering\" ? L\"\" : renderer_->call(param);\n\n                if (initialize_renderer) {\n                    do_fill_buffer(true);\n                }\n\n                return result;\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n                renderer_.reset(nullptr);\n                has_renderer_ = false;\n            }\n\n            return L\"\";\n        });\n    }\n\n    std::wstring print() const override\n    {\n        return L\"flash[\" + boost::filesystem::path(filename_).wstring() + L\"|\" + std::to_wstring(fps_) + L\"]\";\n    }\n\n    std::wstring name() const override { return L\"flash\"; }\n\n    core::monitor::state state() const override { return state_; }\n\n    // flash_producer\n\n    void fill_buffer()\n    {\n        if (executor_.size() > 0)\n            return;\n\n        executor_.begin_invoke([this] { do_fill_buffer(false); });\n    }\n\n    void do_fill_buffer(bool initial_buffer_fill)\n    {\n        int       nothing_rendered             = 0;\n        const int MAX_NOTHING_RENDERED_RETRIES = 4;\n\n        auto to_render              = buffer_size_ - output_buffer_.size();\n        bool allow_faster_rendering = !initial_buffer_fill;\n        int  rendered               = 0;\n\n        while (rendered < to_render) {\n            bool was_rendered = next(allow_faster_rendering);\n            log_buffered();\n\n            if (was_rendered) {\n                ++rendered;\n            } else {\n                if (nothing_rendered++ < MAX_NOTHING_RENDERED_RETRIES) {\n                    // Flash player not ready with first frame, sleep to not busy-loop;\n                    std::this_thread::sleep_for(std::chrono::milliseconds(10));\n                    std::this_thread::yield();\n                } else\n                    return;\n            }\n\n            // TODO yield\n        }\n    }\n\n    bool next(bool allow_faster_rendering)\n    {\n        if (!renderer_)\n            frame_buffer_.push(core::draw_frame{});\n\n        if (frame_buffer_.empty()) {\n            if (abs(renderer_->fps() - format_desc_.fps / 2.0) < 2.0) // format == 2 * flash -> duplicate\n            {\n                auto frame = render_frame(allow_faster_rendering);\n                if (frame) {\n                    frame_buffer_.push(frame);\n                    frame_buffer_.push(frame);\n                }\n            } else // if(abs(renderer_->fps() - format_desc_.fps) < 0.1) // format == flash -> simple\n            {\n                auto frame = render_frame(allow_faster_rendering);\n                if (frame) {\n                    frame_buffer_.push(frame);\n                }\n            }\n\n            fps_ = static_cast<int>(renderer_->fps() * 100.0);\n            graph_->set_text(print());\n\n            if (renderer_->is_empty()) {\n                renderer_.reset();\n                has_renderer_ = false;\n            }\n        }\n\n        if (frame_buffer_.empty()) {\n            return false;\n        }\n        output_buffer_.push(std::move(frame_buffer_.front()));\n        frame_buffer_.pop();\n        return true;\n    }\n\n    core::draw_frame render_frame(bool allow_faster_rendering)\n    {\n        double sync;\n\n        if (allow_faster_rendering) {\n            double ratio = std::min(\n                1.0, static_cast<double>(output_buffer_.size()) / static_cast<double>(std::max(1, buffer_size_ - 1)));\n            sync = 2 * ratio - ratio * ratio;\n        } else {\n            sync = 1.0;\n        }\n\n        return renderer_->render_frame(sync);\n    }\n};\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params)\n{\n    auto template_host = get_template_host(dependencies.format_desc);\n\n    auto filename = env::template_folder() + template_host.filename;\n\n    if (!boost::filesystem::exists(filename))\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L\"Could not open flash movie \" + filename));\n\n    const auto url = url_from_path(filename);\n    return spl::make_shared<flash_producer>(\n        dependencies.frame_factory, dependencies.format_desc, url, template_host.width, template_host.height);\n}\n\nspl::shared_ptr<core::frame_producer> create_swf_producer(const core::frame_producer_dependencies& dependencies,\n                                                          const std::vector<std::wstring>&         params)\n{\n    auto filename = env::media_folder() + params.at(0) + L\".swf\";\n\n    if (!boost::filesystem::exists(filename))\n        return core::frame_producer::empty();\n\n    swf_t::header_t header(filename);\n\n    const auto url      = url_from_path(filename);\n    auto       producer = spl::make_shared<flash_producer>(\n        dependencies.frame_factory, dependencies.format_desc, url, header.frame_width, header.frame_height);\n\n    producer->call({L\"start_rendering\"}).get();\n\n    return producer;\n}\n\nstd::wstring find_template(const std::wstring& template_name)\n{\n    if (boost::filesystem::exists(template_name + L\".ft\"))\n        return url_from_path(template_name + L\".ft\");\n\n    if (boost::filesystem::exists(template_name + L\".ct\"))\n        return url_from_path(template_name + L\".ct\");\n\n    if (boost::filesystem::exists(template_name + L\".swf\"))\n        return url_from_path(template_name + L\".swf\");\n\n    return L\"\";\n}\n\n}} // namespace caspar::flash\n"
  },
  {
    "path": "src/modules/flash/producer/flash_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/fwd.h>\n\n#include <common/memory.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace flash {\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params);\nspl::shared_ptr<core::frame_producer> create_swf_producer(const core::frame_producer_dependencies& dependencies,\n                                                          const std::vector<std::wstring>&         params);\n\nstd::wstring find_template(const std::wstring& templateName);\n\n}} // namespace caspar::flash"
  },
  {
    "path": "src/modules/flash/util/swf.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"swf.h\"\n\n#include <common/except.h>\n\n#include <zlib.h>\n\n#include <fstream>\n#include <streambuf>\n\nnamespace caspar { namespace flash {\n\nswf_t::header_t::header_t(const std::wstring& filename)\n    : valid(false)\n{\n    auto stream = std::fstream();\n    stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\n    stream.open(filename, std::ios::in | std::ios::binary);\n    stream.read(reinterpret_cast<char*>(this), 8);\n\n    const std::array<std::uint8_t, 3> s1 = {'F', 'W', 'S'};\n    const std::array<std::uint8_t, 3> s2 = {'C', 'W', 'S'};\n\n    if (this->signature != s1 && this->signature != s2)\n        return;\n\n    //_byteswap_ulong(this->file_length);\n\n    std::vector<char> file_data;\n    std::copy(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>(), std::back_inserter(file_data));\n\n    std::array<char, 32> uncompressed_data;\n    uLongf               file_size = 32;\n    auto                 ret       = uncompress(reinterpret_cast<Bytef*>(uncompressed_data.data()),\n                          &file_size,\n                          reinterpret_cast<const Bytef*>(file_data.data()),\n                          static_cast<uLong>(file_data.size()));\n\n    if (ret == Z_DATA_ERROR)\n        CASPAR_THROW_EXCEPTION(io_error());\n\n    // http://thenobody.blog.matfyz.sk/p13084-how-to-get-dimensions-of-a-swf-file\n\n    unsigned char nbits = reinterpret_cast<unsigned char*>(uncompressed_data.data())[0];\n\n    unsigned int size = nbits >> 3; // remove overlapping 3 bits\n\n    unsigned long dims[4]  = {};\n    unsigned long neg_root = 1 << (size - 1); // numbers are signed, i.e. leftmost bit denotes -\n\n    unsigned int  bi_offset = size % 8 ? 8 - size % 8 : 0; // offset of bit numbers depending on specified size\n    unsigned int  by_offset = (size + bi_offset) / 8;      // offset of bytes\n    unsigned long ibuf      = (unsigned long)(nbits % 8);  // actual result - starts with last 3 bits of first byte\n\n    for (auto i = 0; i < 4; ++i) {\n        unsigned int ioffset = by_offset * i;\n\n        for (unsigned int j = 0; j < by_offset; ++j) {\n            ibuf <<= 8;\n            ibuf += reinterpret_cast<unsigned char*>(uncompressed_data.data())[1 + ioffset + j];\n        }\n\n        dims[i] = (ibuf >> (3 + bi_offset + (i * bi_offset))) / 20; // coordinates in twips, so divide by 20 for pixels\n\n        if (dims[i] >= neg_root)                              // if the leftmost bit is 1 number is negative\n            dims[i] = -1 * (neg_root - (dims[i] - neg_root)); // convert to negative number\n\n        int expn = 3 + bi_offset + i * bi_offset; // bit divider for ...\n        ibuf     = ibuf % (1 << (expn - 1));      // ... buffered number\n    }\n\n    this->frame_width  = dims[1] - dims[0]; // max - mix\n    this->frame_height = dims[3] - dims[2];\n\n    this->valid = true;\n}\n\nswf_t::swf_t(const std::wstring& filename)\n    : header(filename)\n{\n    auto stream = std::fstream();\n    stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);\n    stream.open(filename, std::ios::in | std::ios::binary);\n    stream.seekg(8, std::fstream::beg);\n\n    this->data.resize(this->header.file_length - 8);\n\n    std::vector<char> file_data;\n    std::copy(std::istreambuf_iterator<char>(stream), std::istreambuf_iterator<char>(), std::back_inserter(file_data));\n\n    uLongf file_size = this->header.file_length;\n    auto   ret       = uncompress(reinterpret_cast<Bytef*>(this->data.data()),\n                          &file_size,\n                          reinterpret_cast<const Bytef*>(file_data.data()),\n                          static_cast<uLong>(file_data.size()));\n\n    if (ret != Z_OK)\n        CASPAR_THROW_EXCEPTION(io_error());\n}\n\n}} // namespace caspar::flash\n"
  },
  {
    "path": "src/modules/flash/util/swf.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <array>\n#include <cstdint>\n#include <string>\n\nnamespace caspar { namespace flash {\n\nstruct swf_t\n{\n    struct header_t\n    {\n        header_t(const std::wstring& filename);\n\n        std::array<std::uint8_t, 3> signature;\n        std::uint8_t                version;\n        std::uint32_t               file_length;\n        std::uint32_t               frame_width;\n        std::uint32_t               frame_height;\n        std::uint16_t               frame_rate;\n        std::uint16_t               frame_count;\n\n        bool valid;\n\n    } header;\n\n    std::vector<char> data;\n\n    swf_t(const std::wstring& filename);\n};\n\n}} // namespace caspar::flash\n"
  },
  {
    "path": "src/modules/html/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (html)\n\nset(SOURCES\n\t\tproducer/html_cg_proxy.cpp\n\t\tproducer/html_cg_proxy.h\n\t\tproducer/html_producer.cpp\n\t\tproducer/html_producer.h\n\n\t\thtml.cpp\n\t\thtml.h\n\t\tutil.h\n)\n\ncasparcg_add_module_project(html\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"html::init\"\n\tUNINIT_FUNCTION \"html::uninit\"\n\tCLI_INTERCEPTOR \"html::intercept_command_line\"\n)\ntarget_link_libraries(html PRIVATE ffmpeg CEF::CEF)\n\ntarget_include_directories(html PRIVATE\n    ..\n\t${FFMPEG_INCLUDE_PATH}\n)\n\nset_target_properties(html PROPERTIES FOLDER modules)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources ./*)\n"
  },
  {
    "path": "src/modules/html/html.cpp",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"html.h\"\n#include \"util.h\"\n\n#include \"producer/html_cg_proxy.h\"\n#include \"producer/html_producer.h\"\n\n#include <common/env.h>\n#include <common/executor.h>\n#include <common/future.h>\n\n#include <core/producer/cg_proxy.h>\n\n#include <boost/asio.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/log/trivial.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/range/algorithm/remove_if.hpp>\n\n#include <memory>\n#include <utility>\n\n#include <include/cef_app.h>\n#include <include/cef_version.h>\n\n#ifdef WIN32\n#include <accelerator/d3d/d3d_device.h>\n#endif\n\nnamespace caspar::html {\n\nstd::unique_ptr<executor> g_cef_executor;\n\nvoid caspar_log(const CefRefPtr<CefBrowser>&        browser,\n                boost::log::trivial::severity_level level,\n                const std::string&                  message)\n{\n    if (browser != nullptr) {\n        auto msg = CefProcessMessage::Create(LOG_MESSAGE_NAME);\n        msg->GetArgumentList()->SetInt(0, level);\n        msg->GetArgumentList()->SetString(1, message);\n\n        CefRefPtr<CefFrame> mainFrame = browser->GetMainFrame();\n        if (mainFrame) {\n            mainFrame->SendProcessMessage(PID_BROWSER, msg);\n        }\n    }\n}\n\nclass remove_handler : public CefV8Handler\n{\n    CefRefPtr<CefBrowser> browser_;\n\n  public:\n    explicit remove_handler(const CefRefPtr<CefBrowser>& browser)\n        : browser_(browser)\n    {\n    }\n\n    bool Execute(const CefString&       name,\n                 CefRefPtr<CefV8Value>  object,\n                 const CefV8ValueList&  arguments,\n                 CefRefPtr<CefV8Value>& retval,\n                 CefString&             exception) override\n    {\n        if (!CefCurrentlyOn(TID_RENDERER)) {\n            return false;\n        }\n\n        CefRefPtr<CefFrame> mainFrame = browser_->GetMainFrame();\n        if (mainFrame) {\n            mainFrame->SendProcessMessage(PID_BROWSER, CefProcessMessage::Create(REMOVE_MESSAGE_NAME));\n        }\n\n        return true;\n    }\n\n    IMPLEMENT_REFCOUNTING(remove_handler);\n};\n\nclass renderer_application\n    : public CefApp\n    , CefRenderProcessHandler\n{\n    std::vector<CefRefPtr<CefV8Context>> contexts_;\n    const bool                           enable_gpu_;\n    const bool                           shared_texture_;\n\n  public:\n    explicit renderer_application(const bool enable_gpu, const bool shared_texture)\n        : enable_gpu_(enable_gpu)\n        , shared_texture_(shared_texture)\n    {\n    }\n\n    CefRefPtr<CefRenderProcessHandler> GetRenderProcessHandler() override { return this; }\n\n    void\n    OnContextCreated(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context) override\n    {\n        if (!frame->IsMain())\n            return;\n\n        caspar_log(\n            browser, boost::log::trivial::trace, \"context for frame \" + frame->GetIdentifier().ToString() + \" created\");\n        contexts_.push_back(context);\n\n        auto window = context->GetGlobal();\n\n        window->SetValue(\n            \"remove\", CefV8Value::CreateFunction(\"remove\", new remove_handler(browser)), V8_PROPERTY_ATTRIBUTE_NONE);\n\n        CefRefPtr<CefV8Value>     ret;\n        CefRefPtr<CefV8Exception> exception;\n        bool                      injected = context->Eval(R\"(\n            window.caspar = window.casparcg = {};\n\t\t)\",\n                                      CefString(),\n                                      1,\n                                      ret,\n                                      exception);\n\n        if (!injected) {\n            caspar_log(browser, boost::log::trivial::error, \"Could not inject javascript animation code.\");\n        }\n    }\n\n    void OnContextReleased(CefRefPtr<CefBrowser>   browser,\n                           CefRefPtr<CefFrame>     frame,\n                           CefRefPtr<CefV8Context> context) override\n    {\n        if (!frame->IsMain())\n            return;\n\n        auto removed =\n            boost::remove_if(contexts_, [&](const CefRefPtr<CefV8Context>& c) { return c->IsSame(context); });\n\n        if (removed != contexts_.end()) {\n            caspar_log(browser,\n                       boost::log::trivial::trace,\n                       \"context for frame \" + frame->GetIdentifier().ToString() + \" released\");\n        } else {\n            caspar_log(browser,\n                       boost::log::trivial::warning,\n                       \"context for frame \" + frame->GetIdentifier().ToString() + \" released, but not found\");\n        }\n    }\n\n    void OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) override { contexts_.clear(); }\n\n    void OnBeforeCommandLineProcessing(const CefString& process_type, CefRefPtr<CefCommandLine> command_line) override\n    {\n        if (enable_gpu_) {\n            command_line->AppendSwitch(\"enable-webgl\");\n\n            auto default_backend = L\"\"; // Let CEF choose what is best\n#if __unix__\n            // If there is no X server, Chromium requires us to force it to the angle backend\n            if (getenv(\"DISPLAY\") == nullptr)\n                default_backend = L\"vulkan\";\n#endif\n\n            // This gives better performance on the gpu->cpu readback, but can perform worse with intense templates\n            auto backend = env::properties().get(L\"configuration.html.angle-backend\", default_backend);\n            if (backend.size() > 0) {\n                command_line->AppendSwitchWithValue(\"use-angle\", backend);\n            }\n        }\n\n#if __unix__\n        if (getenv(\"DISPLAY\") == nullptr) {\n            command_line->AppendSwitchWithValue(\"ozone-platform\", \"headless\");\n        }\n#endif\n\n        command_line->AppendSwitch(\"disable-web-security\");\n        command_line->AppendSwitch(\"enable-begin-frame-scheduling\");\n        command_line->AppendSwitch(\"enable-media-stream\");\n        command_line->AppendSwitch(\"use-fake-ui-for-media-stream\");\n        command_line->AppendSwitchWithValue(\"autoplay-policy\", \"no-user-gesture-required\");\n        command_line->AppendSwitchWithValue(\"remote-allow-origins\", \"*\");\n\n        if (process_type.empty() && !enable_gpu_) {\n            // This gives more performance, but disabled gpu effects. Without it a single 1080p producer cannot be run\n            // smoothly\n\n            command_line->AppendSwitch(\"disable-gpu\");\n            command_line->AppendSwitch(\"disable-gpu-compositing\");\n            command_line->AppendSwitchWithValue(\"disable-gpu-vsync\", \"gpu\");\n        }\n    }\n\n    IMPLEMENT_REFCOUNTING(renderer_application);\n};\n\nbool intercept_command_line(int argc, char** argv)\n{\n#ifdef _WIN32\n    CefMainArgs main_args;\n#else\n    CefMainArgs main_args(argc, argv);\n#endif\n\n    return CefExecuteProcess(main_args, CefRefPtr<CefApp>(new renderer_application(false, false)), nullptr) >= 0;\n}\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    dependencies.producer_registry->register_producer_factory(L\"HTML Producer\", html::create_producer);\n\n    CefMainArgs main_args;\n    g_cef_executor = std::make_unique<executor>(L\"cef\");\n    bool result    = g_cef_executor->invoke([&] {\n#ifdef WIN32\n        SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);\n#endif\n        const auto gpu = is_gpu_shared_texture_enabled();\n\n        CefSettings settings;\n        settings.command_line_args_disabled   = false;\n        settings.no_sandbox                   = true;\n        settings.remote_debugging_port        = env::properties().get(L\"configuration.html.remote-debugging-port\", 0);\n        settings.windowless_rendering_enabled = true;\n\n        auto cache_path = env::properties().get(L\"configuration.html.cache-path\", L\"cef-cache\");\n        if (!cache_path.empty()) {\n            if (!boost::filesystem::path(cache_path).is_absolute()) {\n                cache_path = caspar::env::initial_folder() + L\"/\" + cache_path;\n            }\n            CASPAR_LOG(info) << L\"[html] Using CEF cache path: \" << cache_path;\n            CefString(&settings.cache_path).FromWString(cache_path);\n        }\n\n        return CefInitialize(\n            main_args, settings, CefRefPtr<CefApp>(new renderer_application(gpu.first, gpu.second)), nullptr);\n    });\n\n    if (!result) {\n        CASPAR_LOG(error) << \"[html] Failed to initialize CEF\";\n        return;\n    }\n\n    g_cef_executor->begin_invoke([&] { CefRunMessageLoop(); });\n    dependencies.cg_registry->register_cg_producer(\n        L\"html\",\n        {L\".html\"},\n        [](const spl::shared_ptr<core::frame_producer>& producer) { return spl::make_shared<html_cg_proxy>(producer); },\n        [](const core::frame_producer_dependencies& dependencies, const std::wstring& filename) {\n            return html::create_cg_producer(dependencies, {filename});\n        },\n        false);\n}\n\nvoid uninit()\n{\n    if (!g_cef_executor)\n        return;\n\n    invoke([] { CefQuitMessageLoop(); });\n    g_cef_executor->begin_invoke([&] { CefShutdown(); });\n    g_cef_executor.reset();\n}\n\nclass cef_task : public CefTask\n{\n  private:\n    std::promise<void>    promise_;\n    std::function<void()> function_;\n\n  public:\n    explicit cef_task(std::function<void()> function)\n        : function_(std::move(function))\n    {\n    }\n\n    void Execute() override\n    {\n        CASPAR_LOG(trace) << \"[cef_task] executing task\";\n\n        try {\n            function_();\n            promise_.set_value();\n            CASPAR_LOG(trace) << \"[cef_task] task succeeded\";\n        } catch (...) {\n            promise_.set_exception(std::current_exception());\n            CASPAR_LOG(warning) << \"[cef_task] task failed\";\n        }\n    }\n\n    std::future<void> future() { return promise_.get_future(); }\n\n    IMPLEMENT_REFCOUNTING(cef_task);\n};\n\nvoid invoke(const std::function<void()>& func) { begin_invoke(func).get(); }\n\nstd::future<void> begin_invoke(const std::function<void()>& func)\n{\n    CefRefPtr<cef_task> task = new cef_task(func);\n\n    if (CefCurrentlyOn(TID_UI)) {\n        // Avoid deadlock.\n        task->Execute();\n        return task->future();\n    }\n\n    if (CefPostTask(TID_UI, task.get())) {\n        return task->future();\n    }\n    CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"[cef_executor] Could not post task\"));\n}\n\nstd::pair<bool, bool> is_gpu_shared_texture_enabled()\n{\n    const bool enable_gpu            = env::properties().get(L\"configuration.html.enable-gpu\", false);\n    bool       shared_texture_enable = false;\n\n#ifdef WIN32\n    if (enable_gpu) {\n        auto dev = accelerator::d3d::d3d_device::get_device();\n        if (!dev) {\n            CASPAR_LOG(warning) << L\"Failed to create directX device for cef gpu acceleration\";\n        } else {\n            shared_texture_enable = true;\n        }\n    }\n#else\n    // It would be nice to support this on linux, but it needs some investigation and work\n    // Test results (March 2026) suggest that linux without shared-texture is more performant than windows with or\n    // without\n#endif\n\n    return std::make_pair(enable_gpu, shared_texture_enable);\n}\n\n} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/html/html.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <functional>\n#include <future>\n#include <string>\n\n#include <core/module_dependencies.h>\n\nnamespace caspar::html {\n\nbool intercept_command_line(int argc, char** argv);\nvoid init(const core::module_dependencies& dependencies);\nvoid uninit();\n\n} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/html/producer/html_cg_proxy.cpp",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"html_cg_proxy.h\"\n\n#include <future>\n\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/algorithm/string/replace.hpp>\n#include <boost/algorithm/string/trim.hpp>\n#include <boost/format.hpp>\n\nnamespace caspar { namespace html {\n\nhtml_cg_proxy::html_cg_proxy(const spl::shared_ptr<core::frame_producer>& producer)\n    : producer_(producer)\n{\n}\n\nhtml_cg_proxy::~html_cg_proxy() {}\n\nvoid html_cg_proxy::add(int                 layer,\n                        const std::wstring& template_name,\n                        bool                play_on_load,\n                        const std::wstring& start_from_label,\n                        const std::wstring& data)\n{\n    update(layer, data);\n\n    if (play_on_load)\n        play(layer);\n}\n\nvoid html_cg_proxy::remove(int layer) { producer_->call({L\"remove()\"}); }\n\nvoid html_cg_proxy::play(int layer) { producer_->call({L\"play()\"}); }\n\nvoid html_cg_proxy::stop(int layer) { producer_->call({L\"stop()\"}); }\n\nvoid html_cg_proxy::next(int layer) { producer_->call({L\"next()\"}); }\n\nvoid html_cg_proxy::update(int layer, const std::wstring& data)\n{\n    auto escaped =\n        boost::algorithm::replace_all_copy(boost::algorithm::trim_copy_if(data, boost::is_any_of(\" \\\"\")), \"\\\"\", \"\\\\\\\"\");\n    producer_->call({L\"update(\\\"\" + escaped + L\"\\\")\"});\n}\n\nstd::wstring html_cg_proxy::invoke(int layer, const std::wstring& label)\n{\n    auto function_call = boost::algorithm::trim_copy_if(label, boost::is_any_of(\" \\\"\"));\n\n    // Append empty () if no parameter list has been given\n    auto javascript = boost::ends_with(function_call, \")\") ? function_call : function_call + L\"()\";\n    return producer_->call({javascript}).get();\n}\n\n}} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/html/producer/html_cg_proxy.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include <core/producer/cg_proxy.h>\n\nnamespace caspar { namespace html {\n\nclass html_cg_proxy : public core::cg_proxy\n{\n  public:\n    explicit html_cg_proxy(const spl::shared_ptr<core::frame_producer>& producer);\n    ~html_cg_proxy();\n\n    void         add(int                 layer,\n                     const std::wstring& template_name,\n                     bool                play_on_load,\n                     const std::wstring& start_from_label,\n                     const std::wstring& data) override;\n    void         remove(int layer) override;\n    void         play(int layer) override;\n    void         stop(int layer) override;\n    void         next(int layer) override;\n    void         update(int layer, const std::wstring& data) override;\n    std::wstring invoke(int layer, const std::wstring& label) override;\n\n  private:\n    spl::shared_ptr<core::frame_producer> producer_;\n};\n\n}} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/html/producer/html_producer.cpp",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"html_producer.h\"\n\n#include <core/video_format.h>\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/frame_transform.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <common/assert.h>\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/future.h>\n#include <common/os/filesystem.h>\n#include <common/timer.h>\n\n#if defined(__GNUC__) && __GNUC__ == 14\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n#endif\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/log/trivial.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/regex.hpp>\n#if defined(__GNUC__) && __GNUC__ == 14\n#pragma GCC diagnostic pop\n#endif\n\n#include <tbb/concurrent_queue.h>\n#include <tbb/parallel_for.h>\n\n#include <mutex>\n\n#include <include/cef_app.h>\n#include <include/cef_client.h>\n#include <include/cef_render_handler.h>\n\n#include <optional>\n#include <queue>\n#include <utility>\n\n#include <ffmpeg/util/audio_resampler.h>\n\n#include \"../html.h\"\n#include \"../util.h\"\n\n#ifdef WIN32\n#include <accelerator/d3d/d3d_device.h>\n#include <accelerator/d3d/d3d_device_context.h>\n#include <accelerator/d3d/d3d_texture2d.h>\n#endif\n\nnamespace caspar { namespace html {\n\ninline std::int_least64_t now()\n{\n    return std::chrono::duration_cast<std::chrono::milliseconds>(\n               std::chrono::high_resolution_clock::now().time_since_epoch())\n        .count();\n}\n\nstruct presentation_frame\n{\n    std::int_least64_t timestamp;\n    core::draw_frame   frame;\n\n    explicit presentation_frame(core::draw_frame frame = {}, std::int_least64_t ts = now()) noexcept\n        : timestamp(ts)\n        , frame(std::move(frame))\n    {\n    }\n\n    presentation_frame(presentation_frame&& other) noexcept\n        : timestamp(other.timestamp)\n        , frame(std::move(other.frame))\n    {\n    }\n\n    presentation_frame(const presentation_frame&)            = delete;\n    presentation_frame& operator=(const presentation_frame&) = delete;\n\n    presentation_frame& operator=(presentation_frame&& rhs) noexcept\n    {\n        timestamp = rhs.timestamp;\n        frame     = std::move(rhs.frame);\n        return *this;\n    }\n\n    ~presentation_frame() {}\n};\n\nclass html_client\n    : public CefClient\n    , public CefRenderHandler\n    , public CefAudioHandler\n    , public CefLifeSpanHandler\n    , public CefLoadHandler\n    , public CefDisplayHandler\n{\n    std::wstring                        url_;\n    spl::shared_ptr<diagnostics::graph> graph_;\n    core::monitor::state                state_;\n    mutable std::mutex                  state_mutex_;\n    caspar::timer                       tick_timer_;\n    caspar::timer                       frame_timer_;\n    caspar::timer                       paint_timer_;\n    caspar::timer                       test_timer_;\n\n    spl::shared_ptr<core::frame_factory> frame_factory_;\n    core::video_format_desc              format_desc_;\n    bool                                 gpu_enabled_;\n    bool                                 shared_texture_enable_;\n    tbb::concurrent_queue<std::wstring>  javascript_before_load_;\n    std::atomic<bool>                    loaded_;\n    std::atomic<bool>                    not_found_;\n    std::queue<presentation_frame>       frames_;\n    std::queue<presentation_frame>       audio_frames_;\n    mutable std::mutex                   frames_mutex_;\n    mutable std::mutex                   audio_frames_mutex_;\n    const size_t                         frames_max_size_ = 4;\n    std::atomic<bool>                    closing_;\n\n    std::unique_ptr<ffmpeg::AudioResampler> audioResampler_;\n\n    core::draw_frame   last_video_frame_;\n    core::draw_frame   last_frame_;\n    std::int_least64_t last_frame_time_;\n\n    CefRefPtr<CefBrowser> browser_;\n\n#ifdef WIN32\n    std::shared_ptr<accelerator::d3d::d3d_device> const d3d_device_;\n    std::shared_ptr<accelerator::d3d::d3d_texture2d>    d3d_shared_buffer_;\n#endif\n\n  public:\n    html_client(spl::shared_ptr<core::frame_factory>       frame_factory,\n                const spl::shared_ptr<diagnostics::graph>& graph,\n                core::video_format_desc                    format_desc,\n                bool                                       gpu_enabled,\n                bool                                       shared_texture_enable,\n                std::wstring                               url)\n        : url_(std::move(url))\n        , graph_(graph)\n        , frame_factory_(std::move(frame_factory))\n        , format_desc_(std::move(format_desc))\n        , gpu_enabled_(gpu_enabled)\n        , shared_texture_enable_(shared_texture_enable)\n#ifdef WIN32\n        , d3d_device_(accelerator::d3d::d3d_device::get_device())\n#endif\n    {\n        graph_->set_color(\"browser-tick-time\", diagnostics::color(0.1f, 1.0f, 0.1f));\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.1f, 0.1f));\n        graph_->set_color(\"overload\", diagnostics::color(0.6f, 0.6f, 0.3f));\n        graph_->set_color(\"buffered-frames\", diagnostics::color(0.2f, 0.9f, 0.9f));\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n        {\n            std::lock_guard<std::mutex> lock(state_mutex_);\n            state_[\"file/path\"] = u8(url_);\n        }\n\n        loaded_    = false;\n        not_found_ = false;\n        closing_   = false;\n    }\n\n    void reload()\n    {\n        html::begin_invoke([this] {\n            if (browser_ != nullptr)\n                browser_->Reload();\n        });\n    }\n\n    void close()\n    {\n        closing_ = true;\n\n        html::invoke([this] {\n            if (browser_ != nullptr) {\n                browser_->GetHost()->CloseBrowser(true);\n            }\n        });\n    }\n\n    bool try_pop(const core::video_field field)\n    {\n        bool                        result = false;\n        std::lock_guard<std::mutex> lock(frames_mutex_);\n\n        core::draw_frame audio_frame;\n        uint64_t         audio_frame_timestamp = 0;\n\n        {\n            std::lock_guard<std::mutex> audio_lock(audio_frames_mutex_);\n            if (!audio_frames_.empty()) {\n                audio_frame_timestamp = audio_frames_.front().timestamp;\n                audio_frame           = core::draw_frame(std::move(audio_frames_.front().frame));\n                audio_frames_.pop();\n            }\n        }\n\n        if (!frames_.empty()) {\n            /*\n             * CEF in gpu-enabled mode only sends frames when something changes, and interlaced channels\n             * consume two frames in a short time span.\n             * This can interact poorly and cause the second\n             * field of an animation repeat the first.\n             * If there is a single field in the buffer, it may\n             * want delaying to avoid this stutter.\n             * The hazard here is that sometimes animations will\n             * start a field later than intended.\n             */\n            if (field == core::video_field::a && frames_.size() == 1) {\n                auto now_time = now();\n\n                // Make sure there has been a gap before this pop, of at least a couple of frames\n                auto follows_gap_in_frames = (now_time - last_frame_time_) > 100;\n\n                // Check if the sole buffered frame is too young to have a partner field generated (with a tolerance)\n                auto time_per_frame           = (1000 * 1.5) / format_desc_.fps;\n                auto front_frame_is_too_young = (now_time - frames_.front().timestamp) < time_per_frame;\n\n                if (follows_gap_in_frames && front_frame_is_too_young) {\n                    return false;\n                }\n            }\n\n            last_frame_time_  = frames_.front().timestamp;\n            last_video_frame_ = std::move(frames_.front().frame);\n            last_frame_       = last_video_frame_;\n            frames_.pop();\n\n            graph_->set_value(\"buffered-frames\", (double)frames_.size() / frames_max_size_);\n\n            result = true;\n        }\n\n        if (audio_frame) {\n            last_frame_time_ = audio_frame_timestamp;\n            last_frame_      = core::draw_frame::over(last_video_frame_, audio_frame);\n            result           = true;\n        }\n\n        return result;\n    }\n\n    core::draw_frame receive(const core::video_field field)\n    {\n        if (!try_pop(field)) {\n            graph_->set_tag(diagnostics::tag_severity::SILENT, \"late-frame\");\n            return core::draw_frame::still(last_frame_);\n        } else {\n            return last_frame_;\n        }\n    }\n\n    core::draw_frame last_frame() const { return core::draw_frame::still(last_frame_); }\n\n    bool is_ready() const\n    {\n        std::lock_guard<std::mutex> lock(frames_mutex_);\n        return !frames_.empty() || last_frame_;\n    }\n\n    void execute_javascript(const std::wstring& javascript)\n    {\n        if (!loaded_) {\n            javascript_before_load_.push(javascript);\n        } else {\n            execute_queued_javascript();\n            do_execute_javascript(javascript);\n        }\n    }\n\n    bool OnBeforePopup(CefRefPtr<CefBrowser>          browser,\n                       CefRefPtr<CefFrame>            frame,\n                       int                            popup_id,\n                       const CefString&               target_url,\n                       const CefString&               target_frame_name,\n                       WindowOpenDisposition          target_disposition,\n                       bool                           user_gesture,\n                       const CefPopupFeatures&        popupFeatures,\n                       CefWindowInfo&                 windowInfo,\n                       CefRefPtr<CefClient>&          client,\n                       CefBrowserSettings&            settings,\n                       CefRefPtr<CefDictionaryValue>& dict,\n                       bool*                          no_javascript_access) override\n    {\n        // This blocks popup windows from opening, as they dont make sense and hit an exception in get_browser_host upon\n        // closing\n        return true;\n    }\n\n    CefRefPtr<CefBrowserHost> get_browser_host() const\n    {\n        if (browser_ != nullptr)\n            return browser_->GetHost();\n        return nullptr;\n    }\n\n    core::monitor::state state() const\n    {\n        std::lock_guard<std::mutex> lock(state_mutex_);\n        return state_;\n    }\n\n  private:\n    void GetViewRect(CefRefPtr<CefBrowser> browser, CefRect& rect) override\n    {\n        CASPAR_ASSERT(CefCurrentlyOn(TID_UI));\n\n        rect = CefRect(0, 0, format_desc_.square_width, format_desc_.square_height);\n    }\n\n    void OnPaint(CefRefPtr<CefBrowser> browser,\n                 PaintElementType      type,\n                 const RectList&       dirtyRects,\n                 const void*           buffer,\n                 int                   width,\n                 int                   height) override\n    {\n        if (shared_texture_enable_ || closing_ || not_found_)\n            return;\n\n        graph_->set_value(\"browser-tick-time\", paint_timer_.elapsed() * format_desc_.fps * 0.5);\n        paint_timer_.restart();\n        CASPAR_ASSERT(CefCurrentlyOn(TID_UI));\n\n        if (type != PET_VIEW)\n            return;\n\n        core::pixel_format_desc pixel_desc(core::pixel_format::bgra);\n        pixel_desc.planes.emplace_back(width, height, 4);\n\n        core::mutable_frame frame = frame_factory_->create_frame(this, pixel_desc);\n        char*               src   = (char*)buffer;\n        char*               dst   = reinterpret_cast<char*>(frame.image_data(0).begin());\n        test_timer_.restart();\n\n#ifdef WIN32\n        if (gpu_enabled_) {\n            int chunksize = height * width;\n            tbb::parallel_for(0, 4, [&](int y) { std::memcpy(dst + y * chunksize, src + y * chunksize, chunksize); });\n        } else {\n            std::memcpy(dst, src, width * height * 4);\n        }\n#else\n        // On my one test linux machine, doing a single memcpy doesn't have the same cost as windows,\n        // making using tbb excessive\n        std::memcpy(dst, src, width * height * 4);\n#endif\n\n        graph_->set_value(\"memcpy\", test_timer_.elapsed() * format_desc_.fps * 0.5 * 5);\n\n        {\n            std::lock_guard<std::mutex> lock(frames_mutex_);\n\n            core::draw_frame new_frame = core::draw_frame(std::move(frame));\n\n            frames_.push(presentation_frame(std::move(new_frame)));\n            while (frames_.size() > frames_max_size_) {\n                frames_.pop();\n                graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n            }\n            graph_->set_value(\"buffered-frames\", (double)frames_.size() / frames_max_size_);\n        }\n    }\n\n#ifdef WIN32\n    void OnAcceleratedPaint(CefRefPtr<CefBrowser>          browser,\n                            PaintElementType               type,\n                            const RectList&                dirtyRects,\n                            const CefAcceleratedPaintInfo& info) override\n    {\n        try {\n            if (!shared_texture_enable_ || closing_ || not_found_)\n                return;\n\n            graph_->set_value(\"browser-tick-time\", paint_timer_.elapsed() * format_desc_.fps * 0.5);\n            paint_timer_.restart();\n            CASPAR_ASSERT(CefCurrentlyOn(TID_UI));\n\n            if (type != PET_VIEW)\n                return;\n\n            if (d3d_shared_buffer_) {\n                if (info.shared_texture_handle != d3d_shared_buffer_->share_handle())\n                    d3d_shared_buffer_.reset();\n            }\n\n            if (!d3d_shared_buffer_) {\n                d3d_shared_buffer_ = d3d_device_->open_shared_texture(info.shared_texture_handle);\n                if (!d3d_shared_buffer_)\n                    CASPAR_LOG(error) << print() << L\" could not open shared texture!\";\n            }\n\n            if (d3d_shared_buffer_) {\n                core::pixel_format format = core::pixel_format::invalid;\n                if (d3d_shared_buffer_->format() == DXGI_FORMAT_B8G8R8A8_UNORM) {\n                    format = core::pixel_format::bgra;\n                } else if (d3d_shared_buffer_->format() == DXGI_FORMAT_R8G8B8A8_UNORM) {\n                    format = core::pixel_format::rgba;\n                }\n\n                if (format != core::pixel_format::invalid) {\n                    auto frame =\n                        frame_factory_->import_d3d_texture(this, d3d_shared_buffer_, format, common::bit_depth::bit8);\n                    core::draw_frame dframe(std::move(frame));\n\n                    {\n                        std::lock_guard<std::mutex> lock(frames_mutex_);\n\n                        frames_.push(presentation_frame(std::move(dframe)));\n                        while (frames_.size() > 4) {\n                            frames_.pop();\n                            graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n                        }\n                        graph_->set_value(\"buffered-frames\", (double)frames_.size() / frames_max_size_);\n                    }\n                }\n            }\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n    }\n#endif\n\n    void OnAfterCreated(CefRefPtr<CefBrowser> browser) override\n    {\n        CASPAR_ASSERT(CefCurrentlyOn(TID_UI));\n\n        browser_ = std::move(browser);\n    }\n\n    void OnBeforeClose(CefRefPtr<CefBrowser> browser) override\n    {\n        CASPAR_ASSERT(CefCurrentlyOn(TID_UI));\n\n        browser_ = nullptr;\n    }\n\n    bool DoClose(CefRefPtr<CefBrowser> browser) override\n    {\n        CASPAR_ASSERT(CefCurrentlyOn(TID_UI));\n\n        return false;\n    }\n\n    bool OnConsoleMessage(CefRefPtr<CefBrowser> browser,\n                          cef_log_severity_t    level,\n                          const CefString&      message,\n                          const CefString&      source,\n                          int                   line) override\n    {\n        auto msg = log::replace_nonprintable_copy(message.ToWString(), L'?');\n        if (level == cef_log_severity_t::LOGSEVERITY_DEBUG)\n            CASPAR_LOG(debug) << print() << L\" Log: \" << msg;\n        else if (level == cef_log_severity_t::LOGSEVERITY_WARNING)\n            CASPAR_LOG(warning) << print() << L\" Log: \" << msg;\n        else if (level == cef_log_severity_t::LOGSEVERITY_ERROR)\n            CASPAR_LOG(error) << print() << L\" Log: \" << msg;\n        else if (level == cef_log_severity_t::LOGSEVERITY_FATAL)\n            CASPAR_LOG(fatal) << print() << L\" Log: \" << msg;\n        else\n            CASPAR_LOG(info) << print() << L\" Log: \" << msg;\n        return true;\n    }\n\n    CefRefPtr<CefRenderHandler> GetRenderHandler() override { return this; }\n\n    CefRefPtr<CefAudioHandler> GetAudioHandler() override { return this; }\n\n    CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }\n\n    CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }\n\n    CefRefPtr<CefDisplayHandler> GetDisplayHandler() override { return this; }\n\n    void OnLoadError(CefRefPtr<CefBrowser> browser,\n                     CefRefPtr<CefFrame>   frame,\n                     ErrorCode             errorCode,\n                     const CefString&      errorText,\n                     const CefString&      failedUrl) override\n    {\n        not_found_ = true;\n        CASPAR_LOG(warning) << \"[html_producer] \" << errorText.ToString() << \" while loading url: \\\"\"\n                            << failedUrl.ToString() << \"\\\"\";\n\n        // Stop producing if the page fails to load\n        {\n            std::lock_guard<std::mutex> lock(frames_mutex_);\n            frames_.push(presentation_frame());\n        }\n\n        {\n            std::lock_guard<std::mutex> lock(state_mutex_);\n            state_ = {};\n        }\n    }\n\n    void OnLoadEnd(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, int httpStatusCode) override\n    {\n        if (not_found_)\n            return;\n\n        loaded_ = true;\n        execute_queued_javascript();\n    }\n\n    bool OnProcessMessageReceived(CefRefPtr<CefBrowser>        browser,\n                                  CefRefPtr<CefFrame>          frame,\n                                  CefProcessId                 source_process,\n                                  CefRefPtr<CefProcessMessage> message) override\n    {\n        auto name = message->GetName().ToString();\n\n        if (name == REMOVE_MESSAGE_NAME) {\n            // TODO fully remove producer\n            this->close();\n\n            {\n                std::lock_guard<std::mutex> lock(frames_mutex_);\n                frames_.push(presentation_frame());\n            }\n\n            {\n                std::lock_guard<std::mutex> lock(state_mutex_);\n                state_ = {};\n            }\n\n            return true;\n        }\n        if (name == LOG_MESSAGE_NAME) {\n            auto args     = message->GetArgumentList();\n            auto severity = static_cast<boost::log::trivial::severity_level>(args->GetInt(0));\n            auto msg      = log::replace_nonprintable_copy(args->GetString(1).ToWString(), L'?');\n\n            BOOST_LOG_SEV(log::logger::get(), severity) << print() << L\" [renderer_process] \" << msg;\n        }\n\n        return false;\n    }\n\n    bool GetAudioParameters(CefRefPtr<CefBrowser> browser, CefAudioParameters& params) override\n    {\n        params.channel_layout    = CEF_CHANNEL_LAYOUT_7_1;\n        params.sample_rate       = format_desc_.audio_sample_rate;\n        params.frames_per_buffer = format_desc_.audio_cadence[0];\n        return format_desc_.audio_cadence.size() == 1; // TODO - handle 59.94\n    }\n\n    void OnAudioStreamStarted(CefRefPtr<CefBrowser> browser, const CefAudioParameters& params, int channels) override\n    {\n        audioResampler_ = std::make_unique<ffmpeg::AudioResampler>(params.sample_rate, AV_SAMPLE_FMT_FLTP);\n    }\n    void OnAudioStreamPacket(CefRefPtr<CefBrowser> browser, const float** data, int samples, int64_t pts) override\n    {\n        if (!audioResampler_)\n            return;\n\n        auto audio       = audioResampler_->convert(samples, reinterpret_cast<const void**>(data));\n        auto audio_frame = core::mutable_frame(this, {}, std::move(audio), core::pixel_format_desc());\n\n        {\n            std::lock_guard<std::mutex> lock(audio_frames_mutex_);\n            while (audio_frames_.size() >= frames_max_size_) {\n                audio_frames_.pop();\n            }\n            audio_frames_.push(presentation_frame(core::draw_frame(std::move(audio_frame))));\n        }\n    }\n    void OnAudioStreamStopped(CefRefPtr<CefBrowser> browser) override { audioResampler_ = nullptr; }\n    void OnAudioStreamError(CefRefPtr<CefBrowser> browser, const CefString& message) override\n    {\n        CASPAR_LOG(info) << \"[html_producer] OnAudioStreamError: \\\"\" << message.ToString() << \"\\\"\";\n        audioResampler_ = nullptr;\n    }\n\n    void do_execute_javascript(const std::wstring& javascript)\n    {\n        html::begin_invoke([this, javascript] {\n            if (browser_ != nullptr)\n                browser_->GetMainFrame()->ExecuteJavaScript(\n                    u8(javascript).c_str(), browser_->GetMainFrame()->GetURL(), 0);\n        });\n    }\n\n    void execute_queued_javascript()\n    {\n        std::wstring javascript;\n\n        while (javascript_before_load_.try_pop(javascript))\n            do_execute_javascript(javascript);\n    }\n\n    std::wstring print() const\n    {\n        return L\"html[\" + url_ + L\"]\" + L\" \" + std::to_wstring(format_desc_.square_width) + L\" \" +\n               std::to_wstring(format_desc_.square_height) + L\" \" + std::to_wstring(format_desc_.fps);\n    }\n\n    IMPLEMENT_REFCOUNTING(html_client);\n};\n\nclass html_producer : public core::frame_producer\n{\n    core::video_format_desc             format_desc_;\n    const std::wstring                  url_;\n    spl::shared_ptr<diagnostics::graph> graph_;\n\n    CefRefPtr<html_client> client_;\n\n  public:\n    html_producer(const spl::shared_ptr<core::frame_factory>& frame_factory,\n                  const core::video_format_desc&              format_desc,\n                  const std::wstring&                         url)\n        : format_desc_(format_desc)\n        , url_(url)\n    {\n        html::invoke([&] {\n            auto gpu = is_gpu_shared_texture_enabled();\n\n            client_ = new html_client(frame_factory, graph_, format_desc, gpu.first, gpu.second, url_);\n\n            CefWindowInfo window_info;\n            window_info.bounds.width                 = format_desc.square_width;\n            window_info.bounds.height                = format_desc.square_height;\n            window_info.windowless_rendering_enabled = true;\n            window_info.shared_texture_enabled       = gpu.second;\n\n            CefBrowserSettings browser_settings;\n            browser_settings.webgl = gpu.first ? cef_state_t::STATE_ENABLED : cef_state_t::STATE_DISABLED;\n            double fps             = format_desc.fps;\n            browser_settings.windowless_frame_rate = int(ceil(fps));\n            CefBrowserHost::CreateBrowser(window_info, client_.get(), url, browser_settings, nullptr, nullptr);\n        });\n    }\n\n    ~html_producer() override\n    {\n        if (client_ != nullptr)\n            client_->close();\n    }\n\n    // frame_producer\n\n    std::wstring name() const override { return L\"html\"; }\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        if (client_ != nullptr) {\n            return client_->receive(field);\n        }\n\n        return core::draw_frame::empty();\n    }\n\n    core::draw_frame first_frame(const core::video_field field) override { return receive_impl(field, 0); }\n\n    bool is_ready() override\n    {\n        if (client_ != nullptr) {\n            return client_->is_ready();\n        }\n        return false;\n    }\n\n    core::draw_frame last_frame(const core::video_field field) override\n    {\n        if (client_ != nullptr) {\n            return client_->last_frame();\n        }\n\n        return core::draw_frame::empty();\n    }\n\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        if (client_ == nullptr)\n            return make_ready_future(std::wstring());\n\n        auto javascript = params.at(0);\n\n        if (javascript == L\"RELOAD\") {\n            client_->reload();\n        } else {\n            client_->execute_javascript(javascript);\n        }\n\n        return make_ready_future(std::wstring());\n    }\n\n    std::wstring print() const override { return L\"html[\" + url_ + L\"]\"; }\n\n    core::monitor::state state() const override\n    {\n        if (client_ != nullptr) {\n            return client_->state();\n        }\n\n        static const core::monitor::state empty;\n        return empty;\n    }\n};\n\nspl::shared_ptr<core::frame_producer> create_cg_producer(const core::frame_producer_dependencies& dependencies,\n                                                         const std::vector<std::wstring>&         params)\n{\n    const auto html_prefix    = boost::iequals(params.at(0), L\"[HTML]\");\n    const auto param_url      = html_prefix ? params.at(1) : params.at(0);\n    const auto filename       = env::template_folder() + param_url + L\".html\";\n    const auto found_filename = find_case_insensitive(filename);\n    const auto http_prefix =\n        boost::algorithm::istarts_with(param_url, L\"http:\") || boost::algorithm::istarts_with(param_url, L\"https:\");\n\n    if (!found_filename && !http_prefix && !html_prefix)\n        return core::frame_producer::empty();\n\n    const auto url = found_filename ? L\"file://\" + *found_filename : param_url;\n\n    std::optional<int> width;\n    std::optional<int> height;\n    {\n        auto u8_url = u8(url);\n\n        boost::smatch what;\n        if (boost::regex_search(u8_url, what, boost::regex(\"width=([0-9]+)\"))) {\n            width = std::stoi(what[1].str());\n        }\n\n        if (boost::regex_search(u8_url, what, boost::regex(\"height=([0-9]+)\"))) {\n            height = std::stoi(what[1].str());\n        }\n    }\n\n    auto format_desc = dependencies.format_desc;\n    if (width && height) {\n        format_desc.width         = *width;\n        format_desc.square_width  = *width;\n        format_desc.height        = *height;\n        format_desc.square_height = *height;\n    }\n\n    return spl::make_shared<html_producer>(dependencies.frame_factory, format_desc, url);\n}\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params)\n{\n    return create_cg_producer(dependencies, params);\n}\n\n}} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/html/producer/html_producer.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace html {\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params);\nspl::shared_ptr<core::frame_producer> create_cg_producer(const core::frame_producer_dependencies& dependencies,\n                                                         const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/html/util.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@supergly.tv\n */\n\n#pragma once\n\n#include <functional>\n#include <future>\n#include <string>\n\nnamespace caspar::html {\n\nconst std::string REMOVE_MESSAGE_NAME = \"CasparCGRemove\";\nconst std::string LOG_MESSAGE_NAME    = \"CasparCGLog\";\n\nvoid              invoke(const std::function<void()>& func);\nstd::future<void> begin_invoke(const std::function<void()>& func);\n\nstd::pair<bool, bool> is_gpu_shared_texture_enabled();\n\n} // namespace caspar::html\n"
  },
  {
    "path": "src/modules/image/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (image)\n\nset(SOURCES\n\t\tconsumer/image_consumer.cpp\n\t\tconsumer/image_consumer.h\n\n\t\tproducer/image_producer.cpp\n\t\tproducer/image_producer.h\n\n\t\tproducer/image_scroll_producer.cpp\n\t\tproducer/image_scroll_producer.h\n\n\t\tutil/image_algorithms.cpp\n\t\tutil/image_algorithms.h\n\t\tutil/image_converter.cpp\n\t\tutil/image_converter.h\n\t\tutil/image_loader.cpp\n\t\tutil/image_loader.h\n\t\tutil/image_view.h\n\n\t\timage.cpp\n\t\timage.h\n)\n\ncasparcg_add_module_project(image\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"image::init\"\n)\ntarget_include_directories(image PRIVATE\n\t..\n\t${FFMPEG_INCLUDE_PATH}\n    )\n\nset_target_properties(image PROPERTIES FOLDER modules)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources\\\\util util/*)\nsource_group(sources ./*)\n\ntarget_link_libraries(image PRIVATE\n\tffmpeg\n)\n\n"
  },
  {
    "path": "src/modules/image/consumer/image_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"image_consumer.h\"\n\n#include <common/array.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/future.h>\n\n#include <core/consumer/channel_info.h>\n#include <core/frame/frame.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/date_time/posix_time/posix_time.hpp>\n\n#include <fstream>\n#include <utility>\n#include <vector>\n\n#include <ffmpeg/util/av_assert.h>\n#include <ffmpeg/util/av_util.h>\n\n#include \"../util/image_algorithms.h\"\n#include \"../util/image_converter.h\"\n#include \"../util/image_view.h\"\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavcodec/avcodec.h>\n#include <libavformat/avformat.h>\n#include <libavutil/imgutils.h>\n#include <libavutil/pixfmt.h>\n}\n\nnamespace caspar::image {\n\nstruct image_consumer : public core::frame_consumer\n{\n    const std::wstring filename_;\n\n    explicit image_consumer(std::wstring filename)\n        : filename_(std::move(filename))\n    {\n    }\n\n    void initialize(const core::video_format_desc& /*format_desc*/,\n                    const core::channel_info& channel_info,\n                    int                       port_index) override\n    {\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        auto filename = filename_;\n\n        std::thread async([frame, filename] {\n            try {\n                std::string filename2;\n\n                if (frame.pixel_format_desc().format != core::pixel_format::bgra)\n                    CASPAR_THROW_EXCEPTION(caspar_exception()\n                                           << msg_info(\"image_consumer received frame with wrong format\"));\n\n                if (filename.empty())\n                    filename2 =\n                        u8(env::media_folder() +\n                           boost::posix_time::to_iso_wstring(boost::posix_time::second_clock::local_time()) + L\".png\");\n                else\n                    filename2 = u8(env::media_folder() + filename + L\".png\");\n\n                std::fstream file_stream(filename2, std::fstream::out | std::fstream::trunc | std::fstream::binary);\n                if (!file_stream)\n                    FF_RET(AVERROR(EINVAL), \"fstream_open\");\n\n                const AVCodec* codec = avcodec_find_encoder(AV_CODEC_ID_PNG);\n                if (!codec)\n                    FF_RET(AVERROR(EINVAL), \"avcodec_find_encoder\");\n\n                auto ctx = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(codec),\n                                                           [](AVCodecContext* ptr) { avcodec_free_context(&ptr); });\n\n                ctx->width     = static_cast<int>(frame.width());\n                ctx->height    = static_cast<int>(frame.height());\n                ctx->pix_fmt   = AV_PIX_FMT_RGBA;\n                ctx->time_base = {1, 1};\n                ctx->framerate = {0, 1};\n\n                FF(avcodec_open2(ctx.get(), codec, nullptr));\n\n                auto av_frame         = ffmpeg::alloc_frame();\n                av_frame->width       = static_cast<int>(frame.width());\n                av_frame->height      = static_cast<int>(frame.height());\n                av_frame->format      = AV_PIX_FMT_BGRA;\n                av_frame->pts         = 0;\n                av_frame->linesize[0] = static_cast<int>(frame.width()) * 4;\n                av_frame->data[0]     = const_cast<uint8_t*>(frame.image_data(0).data());\n\n                // The png encoder requires RGB ordering, the mixer producers BGR.\n                auto av_frame2 = convert_image_frame(av_frame, AV_PIX_FMT_RGBA);\n                // Also straighten the alpha, as png is always straight, and the mixer produces premultiplied\n                image_view<bgra_pixel> original_view(av_frame2->data[0], av_frame2->width, av_frame2->height);\n                unmultiply(original_view);\n\n                FF(avcodec_send_frame(ctx.get(), av_frame2.get()));\n                FF(avcodec_send_frame(ctx.get(), nullptr));\n\n                auto pkt = std::shared_ptr<AVPacket>(av_packet_alloc(), [](AVPacket* ptr) { av_packet_free(&ptr); });\n                int  ret = 0;\n                while (ret >= 0) {\n                    ret = avcodec_receive_packet(ctx.get(), pkt.get());\n                    if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)\n                        break;\n                    FF_RET(ret, \"avcodec_receive_packet\");\n\n                    file_stream.write(reinterpret_cast<const char*>(pkt->data), pkt->size);\n                    av_packet_unref(pkt.get());\n                }\n\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION()\n            }\n        });\n        async.detach();\n\n        return make_ready_future(false);\n    }\n\n    std::wstring print() const override { return L\"image[]\"; }\n\n    std::wstring name() const override { return L\"image\"; }\n\n    int index() const override { return 100; }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"image/filename\"] = u8(filename_);\n        return state;\n    }\n};\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info)\n{\n    if (params.empty() || !boost::iequals(params.at(0), L\"IMAGE\"))\n        return core::frame_consumer::empty();\n\n    if (channel_info.depth != common::bit_depth::bit8)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Image consumer only supports 8-bit color depth.\"));\n\n    std::wstring filename;\n\n    if (params.size() > 1)\n        filename = params.at(1);\n\n    return spl::make_shared<image_consumer>(filename);\n}\n\n} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/consumer/image_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <core/consumer/frame_consumer.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace image {\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info);\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/image.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"image.h\"\n\n#include \"consumer/image_consumer.h\"\n#include \"producer/image_producer.h\"\n#include \"producer/image_scroll_producer.h\"\n\n#include <common/utf.h>\n\nnamespace caspar { namespace image {\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    dependencies.producer_registry->register_producer_factory(L\"Image Scroll Producer\", create_scroll_producer);\n    dependencies.producer_registry->register_producer_factory(L\"Image Producer\", create_producer);\n    dependencies.consumer_registry->register_consumer_factory(L\"Image Consumer\", create_consumer);\n}\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/image.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace image {\n\nvoid init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/producer/image_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"image_producer.h\"\n\n#include \"../util/image_converter.h\"\n#include \"../util/image_loader.h\"\n\n#include <common/base64.h>\n#include <common/env.h>\n#include <common/filesystem.h>\n#include <common/param.h>\n\n#include <boost/algorithm/string.hpp>\n\n#include <utility>\n\nnamespace caspar { namespace image {\n\nstruct image_producer : public core::frame_producer\n{\n    core::monitor::state                       state_;\n    const std::wstring                         description_;\n    const spl::shared_ptr<core::frame_factory> frame_factory_;\n    const uint32_t                             length_ = 0;\n    core::draw_frame                           frame_;\n\n    image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory,\n                   std::wstring                                description,\n                   uint32_t                                    length,\n                   core::frame_geometry::scale_mode            scale_mode)\n        : description_(std::move(description))\n        , frame_factory_(frame_factory)\n        , length_(length)\n    {\n        auto av_frame = load_image(description_);\n        if (!is_frame_compatible_with_mixer(av_frame))\n            av_frame = convert_image_frame(av_frame, AV_PIX_FMT_BGRA);\n\n        auto frame =\n            ffmpeg::make_frame(this, *frame_factory, av_frame, nullptr, core::color_space::bt709, scale_mode, true);\n        frame_ = core::draw_frame(std::move(frame));\n\n        state_[\"file/path\"] = description_;\n\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    image_producer(const spl::shared_ptr<core::frame_factory>& frame_factory,\n                   std::vector<unsigned char>                  image_data,\n                   uint32_t                                    length,\n                   core::frame_geometry::scale_mode            scale_mode)\n        : description_(L\"base64 image from memory\")\n        , frame_factory_(frame_factory)\n        , length_(length)\n    {\n        auto av_frame = load_from_memory(std::move(image_data));\n        if (!is_frame_compatible_with_mixer(av_frame))\n            av_frame = convert_image_frame(av_frame, AV_PIX_FMT_BGRA);\n\n        auto frame =\n            ffmpeg::make_frame(this, *frame_factory, av_frame, nullptr, core::color_space::bt709, scale_mode, true);\n        frame_ = core::draw_frame(std::move(frame));\n\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    // frame_producer\n\n    core::draw_frame last_frame(const core::video_field field) override { return frame_; }\n\n    core::draw_frame first_frame(const core::video_field field) override { return frame_; }\n\n    bool is_ready() override { return true; }\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override { return frame_; }\n\n    uint32_t nb_frames() const override { return length_; }\n\n    std::wstring print() const override { return L\"image_producer[\" + description_ + L\"]\"; }\n\n    std::wstring name() const override { return L\"image\"; }\n\n    core::monitor::state state() const override { return state_; }\n};\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params)\n{\n    if (boost::contains(params.at(0), L\"://\")) {\n        return core::frame_producer::empty();\n    }\n\n    auto length     = get_param(L\"LENGTH\", params, std::numeric_limits<uint32_t>::max());\n    auto scale_mode = core::scale_mode_from_string(get_param(L\"SCALE_MODE\", params, L\"STRETCH\"));\n\n    //    if (boost::iequals(params.at(0), L\"[PNG_BASE64]\")) {\n    //        if (params.size() < 2)\n    //            return core::frame_producer::empty();\n    //\n    //        auto png_data = from_base64(u8(params.at(1)));\n    //\n    //        return spl::make_shared<image_producer>(dependencies.frame_factory, std::move(png_data), length,\n    //        scale_mode);\n    //    }\n\n    auto filename = find_file_within_dir_or_absolute(env::media_folder(), params.at(0), is_valid_file);\n    if (!filename) {\n        return core::frame_producer::empty();\n    }\n\n    return spl::make_shared<image_producer>(dependencies.frame_factory, filename->wstring(), length, scale_mode);\n}\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/producer/image_producer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/producer/frame_producer.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace image {\n\nspl::shared_ptr<core::frame_producer> create_producer(const core::frame_producer_dependencies& dependencies,\n                                                      const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::image"
  },
  {
    "path": "src/modules/image/producer/image_scroll_producer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"image_scroll_producer.h\"\n\n#include \"../util/image_algorithms.h\"\n#include \"../util/image_converter.h\"\n#include \"../util/image_loader.h\"\n#include \"../util/image_view.h\"\n\n#include <core/frame/frame_transform.h>\n\n#include <common/env.h>\n#include <common/filesystem.h>\n#include <common/future.h>\n#include <common/param.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/date_time.hpp>\n#include <boost/date_time/posix_time/ptime.hpp>\n#include <boost/lexical_cast.hpp>\n#include <boost/scoped_array.hpp>\n\n#include <algorithm>\n#include <array>\n#include <cstdint>\n#include <optional>\n#include <utility>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavutil/frame.h>\n}\n\nnamespace caspar { namespace image {\n\n// Like tweened_transform but for speed\nclass speed_tweener\n{\n    double  source_   = 0.0;\n    double  dest_     = 0.0;\n    int     duration_ = 0;\n    int     time_     = 0;\n    tweener tweener_;\n\n  public:\n    speed_tweener() = default;\n    speed_tweener(double source, double dest, int duration, tweener tween)\n        : source_(source)\n        , dest_(dest)\n        , duration_(duration)\n        , time_(0)\n        , tweener_(std::move(tween))\n    {\n    }\n\n    double dest() const { return dest_; }\n\n    double fetch() const\n    {\n        if (time_ == duration_)\n            return dest_;\n\n        double delta  = dest_ - source_;\n        double result = tweener_(time_, source_, delta, duration_);\n\n        return result;\n    }\n\n    double fetch_and_tick()\n    {\n        time_ = std::min(time_ + 1, duration_);\n        return fetch();\n    }\n};\n\nstruct image_scroll_producer : public core::frame_producer\n{\n    core::monitor::state state_;\n\n    const std::wstring            filename_;\n    std::vector<core::draw_frame> frames_;\n    core::video_format_desc       format_desc_;\n    int                           width_;\n    int                           height_;\n\n    double                                  delta_ = 0.0;\n    speed_tweener                           speed_;\n    std::optional<boost::posix_time::ptime> end_time_;\n    core::draw_frame                        frame_;\n\n    int start_offset_x_ = 0;\n    int start_offset_y_ = 0;\n\n    explicit image_scroll_producer(const spl::shared_ptr<core::frame_factory>& frame_factory,\n                                   core::video_format_desc                     format_desc,\n                                   std::wstring                                filename,\n                                   double                                      s,\n                                   double                                      duration,\n                                   std::optional<boost::posix_time::ptime>     end_time,\n                                   int                                         motion_blur_px         = 0,\n                                   bool                                        premultiply_with_alpha = false)\n        : filename_(std::move(filename))\n        , format_desc_(std::move(format_desc))\n        , end_time_(std::move(end_time))\n    {\n        double speed = s;\n\n        if (end_time_)\n            speed = -1.0;\n\n        auto av_frame = convert_image_frame(load_image(filename_), AV_PIX_FMT_BGRA);\n\n        width_  = av_frame->width;\n        height_ = av_frame->height;\n\n        bool vertical   = width_ == format_desc_.width;\n        bool horizontal = height_ == format_desc_.height;\n\n        if (!vertical && !horizontal)\n            CASPAR_THROW_EXCEPTION(caspar::user_error()\n                                   << msg_info(\"Neither width nor height matched the video resolution\"));\n\n        if (duration != 0.0)\n            speed = speed_from_duration(duration);\n\n        if (vertical) {\n            if (speed < 0.0) {\n                start_offset_y_ = height_ + format_desc_.height;\n            }\n        } else {\n            if (speed > 0.0)\n                start_offset_x_ = format_desc_.width - (width_ % format_desc_.width);\n            else\n                start_offset_x_ = format_desc_.width - (width_ % format_desc_.width) + width_ + format_desc_.width;\n        }\n\n        speed_ = speed_tweener(speed, speed, 0, tweener(L\"linear\"));\n\n        auto                   bytes = av_frame->data[0];\n        auto                   count = width_ * height_ * 4;\n        image_view<bgra_pixel> original_view(bytes, width_, height_);\n\n        // This needs to be performed before being the blur is applied\n        if (premultiply_with_alpha)\n            premultiply(original_view);\n\n        boost::scoped_array<uint8_t> blurred_copy;\n\n        if (motion_blur_px > 0) {\n            double angle = 3.14159265 / 2; // Up\n\n            if (horizontal && speed < 0)\n                angle *= 2; // Left\n            else if (vertical && speed > 0)\n                angle *= 3; // Down\n            else if (horizontal && speed > 0)\n                angle = 0.0; // Right\n\n            blurred_copy.reset(new uint8_t[count]);\n            image_view<bgra_pixel> blurred_view(blurred_copy.get(), width_, height_);\n            caspar::tweener        blur_tweener(L\"easeInQuad\");\n            blur(original_view, blurred_view, angle, motion_blur_px, blur_tweener);\n            bytes = blurred_copy.get();\n        }\n\n        if (vertical) {\n            int n = 1;\n\n            while (count > 0) {\n                core::pixel_format_desc desc = core::pixel_format_desc(core::pixel_format::bgra);\n                desc.planes.emplace_back(width_, format_desc_.height, 4);\n                auto frame = frame_factory->create_frame(this, desc);\n\n                if (count >= frame.image_data(0).size()) {\n                    std::copy_n(bytes + count - frame.image_data(0).size(),\n                                frame.image_data(0).size(),\n                                frame.image_data(0).begin());\n                    count -= static_cast<int>(frame.image_data(0).size());\n                } else {\n                    memset(frame.image_data(0).begin(), 0, frame.image_data(0).size());\n                    std::copy_n(bytes, count, frame.image_data(0).begin() + format_desc_.size - count);\n                    count = 0;\n                }\n\n                core::draw_frame draw_frame(std::move(frame));\n\n                // Set the relative position to the other image fragments\n                draw_frame.transform().image_transform.fill_translation[1] = -n++;\n\n                frames_.push_back(draw_frame);\n            }\n        } else if (horizontal) {\n            int i = 0;\n            while (count > 0) {\n                core::pixel_format_desc desc = core::pixel_format_desc(core::pixel_format::bgra);\n                desc.planes.emplace_back(format_desc_.width, height_, 4);\n                auto frame = frame_factory->create_frame(this, desc);\n                if (count >= frame.image_data(0).size()) {\n                    for (int y = 0; y < height_; ++y)\n                        std::copy_n(bytes + i * format_desc_.width * 4 + y * width_ * 4,\n                                    format_desc_.width * 4,\n                                    frame.image_data(0).begin() + y * format_desc_.width * 4);\n\n                    ++i;\n                    count -= static_cast<int>(frame.image_data(0).size());\n                } else {\n                    memset(frame.image_data(0).begin(), 0, frame.image_data(0).size());\n                    auto width2 = width_ % format_desc_.width;\n                    for (int y = 0; y < height_; ++y)\n                        std::copy_n(bytes + i * format_desc_.width * 4 + y * width_ * 4,\n                                    width2 * 4,\n                                    frame.image_data(0).begin() + y * format_desc_.width * 4);\n\n                    count = 0;\n                }\n\n                frames_.emplace_back(std::move(frame));\n            }\n\n            std::reverse(frames_.begin(), frames_.end());\n\n            // Set the relative positions of the image fragments.\n            for (size_t n = 0; n < frames_.size(); ++n) {\n                double translation                                         = -(static_cast<double>(n) + 1.0);\n                frames_[n].transform().image_transform.fill_translation[0] = translation;\n            }\n        }\n\n        CASPAR_LOG(info) << print() << L\" Initialized\";\n    }\n\n    double get_total_num_pixels() const\n    {\n        bool vertical = width_ == format_desc_.width;\n\n        if (vertical)\n            return height_ + format_desc_.height;\n        else\n            return width_ + format_desc_.width;\n    }\n\n    double speed_from_duration(double duration_seconds) const\n    {\n        return get_total_num_pixels() / (duration_seconds * format_desc_.fps);\n    }\n\n    std::future<std::wstring> call(const std::vector<std::wstring>& params) override\n    {\n        auto cmd = params.at(0);\n\n        if (boost::iequals(cmd, L\"SPEED\")) {\n            if (params.size() == 1)\n                return make_ready_future(boost::lexical_cast<std::wstring>(-speed_.fetch()));\n\n            auto         val      = boost::lexical_cast<double>(params.at(1));\n            int          duration = params.size() > 2 ? boost::lexical_cast<int>(params.at(2)) : 0;\n            std::wstring tween    = params.size() > 3 ? params.at(3) : L\"linear\";\n            speed_                = speed_tweener(speed_.fetch(), -val, duration, tween);\n        }\n\n        return make_ready_future<std::wstring>(L\"\");\n    }\n\n    std::vector<core::draw_frame> get_visible()\n    {\n        std::vector<core::draw_frame> result;\n        result.reserve(frames_.size());\n\n        for (auto& frame : frames_) {\n            auto& fill_translation = frame.transform().image_transform.fill_translation;\n\n            if (width_ == format_desc_.width) {\n                auto motion_offset_in_screens =\n                    (static_cast<double>(start_offset_y_) + delta_) / static_cast<double>(format_desc_.height);\n                auto vertical_offset = fill_translation[1] + motion_offset_in_screens;\n\n                if (vertical_offset < -1.0 || vertical_offset > 1.0) {\n                    continue;\n                }\n            } else {\n                auto motion_offset_in_screens =\n                    (static_cast<double>(start_offset_x_) + delta_) / static_cast<double>(format_desc_.width);\n                auto horizontal_offset = fill_translation[0] + motion_offset_in_screens;\n\n                if (horizontal_offset < -1.0 || horizontal_offset > 1.0) {\n                    continue;\n                }\n            }\n\n            result.push_back(frame);\n        }\n\n        return std::move(result);\n    }\n\n    // frame_producer\n    core::draw_frame render_frame(bool allow_eof)\n    {\n        if (frames_.empty())\n            return core::draw_frame::empty();\n\n        core::draw_frame result(get_visible());\n        auto&            fill_translation = result.transform().image_transform.fill_translation;\n\n        if (width_ == format_desc_.width) {\n            if (static_cast<size_t>(std::abs(delta_)) >= height_ + format_desc_.height && allow_eof)\n                return core::draw_frame::empty();\n\n            fill_translation[1] = static_cast<double>(start_offset_y_) / static_cast<double>(format_desc_.height) +\n                                  delta_ / static_cast<double>(format_desc_.height);\n        } else {\n            if (static_cast<size_t>(std::abs(delta_)) >= width_ + format_desc_.width && allow_eof)\n                return core::draw_frame::empty();\n\n            fill_translation[0] = static_cast<double>(start_offset_x_) / static_cast<double>(format_desc_.width) +\n                                  (delta_) / static_cast<double>(format_desc_.width);\n        }\n\n        return result;\n    }\n\n    core::draw_frame render_frame(bool allow_eof, bool advance_delta)\n    {\n        auto result = render_frame(allow_eof);\n\n        if (advance_delta) {\n            advance();\n        }\n\n        return result;\n    }\n\n    void advance()\n    {\n        if (end_time_) {\n            boost::posix_time::ptime now(boost::posix_time::second_clock::local_time());\n\n            auto diff    = *end_time_ - now;\n            auto seconds = diff.total_seconds();\n\n            set_speed(-speed_from_duration(static_cast<double>(seconds)));\n            end_time_ = {};\n        } else\n            delta_ += speed_.fetch_and_tick();\n    }\n\n    void set_speed(double speed) { speed_ = speed_tweener(speed, speed, 0, tweener(L\"linear\")); }\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        frame_ = render_frame(true, true);\n        return frame_;\n    }\n\n    std::wstring print() const override { return L\"image_scroll_producer[\" + filename_ + L\"]\"; }\n\n    std::wstring name() const override { return L\"image-scroll\"; }\n\n    uint32_t nb_frames() const override\n    {\n        if (width_ == format_desc_.width) {\n            auto length = (height_ + format_desc_.height * 2);\n            return static_cast<uint32_t>(length / std::abs(speed_.fetch())); // + length % std::abs(delta_));\n        } else {\n            auto length = (width_ + format_desc_.width * 2);\n            return static_cast<uint32_t>(length / std::abs(speed_.fetch())); // + length % std::abs(delta_));\n        }\n    }\n\n    core::monitor::state state() const override { return state_; }\n\n    bool is_ready() override { return !frames_.empty(); }\n};\n\nspl::shared_ptr<core::frame_producer> create_scroll_producer(const core::frame_producer_dependencies& dependencies,\n                                                             const std::vector<std::wstring>&         params)\n{\n    if (boost::contains(params.at(0), L\"://\")) {\n        return core::frame_producer::empty();\n    }\n\n    std::optional<boost::filesystem::path> filename =\n        find_file_within_dir_or_absolute(env::media_folder(), params.at(0), is_valid_file);\n    if (!filename) {\n        return core::frame_producer::empty();\n    }\n\n    double                                  duration = 0.0;\n    double                                  speed    = get_param(L\"SPEED\", params, 0.0);\n    std::optional<boost::posix_time::ptime> end_time;\n\n    if (speed == 0)\n        duration = get_param(L\"DURATION\", params, 0.0);\n\n    if (duration == 0) {\n        auto end_time_str = get_param(L\"END_TIME\", params);\n\n        if (!end_time_str.empty()) {\n            end_time = boost::posix_time::time_from_string(u8(end_time_str));\n        }\n    }\n\n    if (speed == 0 && duration == 0 && !end_time)\n        return core::frame_producer::empty();\n\n    int motion_blur_px = get_param(L\"BLUR\", params, 0);\n\n    bool premultiply_with_alpha = contains_param(L\"PREMULTIPLY\", params);\n\n    return spl::make_shared<image_scroll_producer>(dependencies.frame_factory,\n                                                   dependencies.format_desc,\n                                                   filename->wstring(),\n                                                   -speed,\n                                                   -duration,\n                                                   end_time,\n                                                   motion_blur_px,\n                                                   premultiply_with_alpha);\n}\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/producer/image_scroll_producer.h",
    "content": "#pragma once\n/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/producer/frame_producer.h>\n\n#include <string>\n#include <vector>\n\nnamespace caspar { namespace image {\n\nspl::shared_ptr<core::frame_producer> create_scroll_producer(const core::frame_producer_dependencies& dependencies,\n                                                             const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/util/image_algorithms.cpp",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se.com\n */\n\n#include \"image_algorithms.h\"\n\n#include <algorithm>\n#include <cmath>\n#include <vector>\n\nnamespace caspar { namespace image {\n\nstd::vector<std::pair<int, int>> get_line_points(int num_pixels, double angle_radians)\n{\n    std::vector<std::pair<int, int>> line_points;\n    line_points.reserve(num_pixels);\n\n    double delta_x       = std::cos(angle_radians);\n    double delta_y       = -std::sin(angle_radians); // In memory is revered\n    double max_delta     = std::max(std::abs(delta_x), std::abs(delta_y));\n    double amplification = 1.0 / max_delta;\n    delta_x *= amplification;\n    delta_y *= amplification;\n\n    for (int i = 1; i <= num_pixels; ++i)\n        line_points.push_back(std::make_pair(static_cast<int>(std::floor(delta_x * static_cast<double>(i) + 0.5)),\n                                             static_cast<int>(std::floor(delta_y * static_cast<double>(i) + 0.5))));\n\n    return std::move(line_points);\n}\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/util/image_algorithms.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <common/tweener.h>\n\n#include <algorithm>\n#include <cstdint>\n\nnamespace caspar { namespace image {\n\n/**\n * Helper for calculating the color of a pixel given any number of of other\n * pixels (each with their own weight).\n */\nclass rgba_weighting\n{\n    int r            = 0;\n    int g            = 0;\n    int b            = 0;\n    int a            = 0;\n    int total_weight = 0;\n\n  public:\n    template <class RGBAPixel>\n    void add_pixel(const RGBAPixel& pixel, uint8_t weight)\n    {\n        r += pixel.r() * weight;\n        g += pixel.g() * weight;\n        b += pixel.b() * weight;\n        a += pixel.a() * weight;\n\n        total_weight += weight;\n    }\n\n    template <class RGBAPixel>\n    void store_result(RGBAPixel& pixel)\n    {\n        pixel.r() = static_cast<uint8_t>(r / total_weight);\n        pixel.g() = static_cast<uint8_t>(g / total_weight);\n        pixel.b() = static_cast<uint8_t>(b / total_weight);\n        pixel.a() = static_cast<uint8_t>(a / total_weight);\n    }\n};\n\ntemplate <class T>\nstd::vector<T> get_tweened_values(const caspar::tweener& tweener, size_t num_values, T from, T to)\n{\n    std::vector<T> result;\n    result.reserve(num_values);\n\n    double start    = static_cast<double>(from);\n    double delta    = static_cast<double>(to - from);\n    double duration = static_cast<double>(num_values);\n\n    for (double t = 0; t < duration; ++t) {\n        result.push_back(static_cast<T>(tweener(t, start, delta, duration - 1.0)));\n    }\n\n    return std::move(result);\n}\n\n/**\n * Blur a source image and store the blurred result in a destination image.\n * <p>\n * The blur is done by weighting each relative pixel from a destination pixel\n * position using a vector of relative x-y pairs. The further away a related\n * pixel is the less weight it gets. A tweener is used to calculate the actual\n * weights of each related pixel.\n *\n * @param src                      The source view. Has to model the ImageView\n *                                 concept and have a pixel type modelling the\n *                                 RGBAPixel concept.\n * @param dst                      The destination view. Has to model the\n *                                 ImageView concept and have a pixel type\n *                                 modelling the RGBAPixel concept.\n * @param motion_trail_coordinates The relative x-y positions to weight in for\n *                                 each pixel.\n * @param tweener                  The tweener to use for calculating the\n *                                 weights of each relative position in the\n *                                 motion trail.\n */\ntemplate <class SrcView, class DstView>\nvoid blur(const SrcView&                          src,\n          DstView&                                dst,\n          const std::vector<std::pair<int, int>>& motion_trail_coordinates,\n          const caspar::tweener&                  tweener)\n{\n    auto blur_px           = motion_trail_coordinates.size();\n    auto tweened_weights_y = get_tweened_values<uint8_t>(tweener, blur_px + 2, 255, 0);\n    tweened_weights_y.pop_back();\n    tweened_weights_y.erase(tweened_weights_y.begin());\n\n    auto src_end  = src.end();\n    auto dst_iter = dst.begin();\n\n    for (auto src_iter = src.begin(); src_iter != src_end; ++src_iter, ++dst_iter) {\n        rgba_weighting w;\n\n        for (int i = 0; i < blur_px; ++i) {\n            auto& coordinate  = motion_trail_coordinates[i];\n            auto  other_pixel = src.relative(src_iter, coordinate.first, coordinate.second);\n\n            if (other_pixel == nullptr)\n                break;\n\n            w.add_pixel(*other_pixel, tweened_weights_y[i]);\n        }\n\n        w.add_pixel(*src_iter, 255);\n        w.store_result(*dst_iter);\n    }\n}\n\n/**\n * Calculate relative x-y coordinates of a straight line with a given angle and\n * a given number of points.\n *\n * @param num_pixels    The number of pixels/points to create.\n * @param angle_radians The angle of the line in radians.\n *\n * @return the x-y pairs.\n */\nstd::vector<std::pair<int, int>> get_line_points(int num_pixels, double angle_radians);\n\n/**\n * Directionally blur a source image modelling the ImageView concept and store\n * the blurred image to a destination image also modelling the ImageView\n * concept.\n * <p>\n * The pixel type of the views must model the RGBAPixel concept.\n *\n * @param src           The source image view. Has to model the ImageView\n *                      concept and have a pixel type that models RGBAPixel.\n * @param dst           The destination image view. Has to model the ImageView\n *                      concept and have a pixel type that models RGBAPixel.\n * @param angle_radians The angle in radians to directionally blur the image.\n * @param blur_px       The number of pixels of the blur.\n * @param tweener       The tweener to use to create a pixel weighting curve\n *                      with.\n */\ntemplate <class SrcView, class DstView>\nvoid blur(const SrcView& src, DstView& dst, double angle_radians, int blur_px, const caspar::tweener& tweener)\n{\n    auto motion_trail = get_line_points(blur_px, angle_radians);\n\n    blur(src, dst, motion_trail, tweener);\n}\n\n/**\n * Premultiply with alpha for each pixel in an ImageView. The modifications is\n * done in place. The pixel type of the ImageView must model the RGBAPixel\n * concept.\n *\n * @param view_to_modify The image view to premultiply in place. Has to model\n *                       the ImageView concept and have a pixel type that\n *                       models RGBAPixel.\n */\ntemplate <class SrcDstView>\nvoid premultiply(SrcDstView& view_to_modify)\n{\n    std::for_each(view_to_modify.begin(), view_to_modify.end(), [&](typename SrcDstView::pixel_type& pixel) {\n        int alpha = static_cast<int>(pixel.a());\n\n        if (alpha != 255) // Performance optimization\n        {\n            // We don't event try to premultiply 0 since it will be unaffected.\n            if (pixel.r())\n                pixel.r() = static_cast<uint8_t>(static_cast<int>(pixel.r()) * alpha / 255);\n\n            if (pixel.g())\n                pixel.g() = static_cast<uint8_t>(static_cast<int>(pixel.g()) * alpha / 255);\n\n            if (pixel.b())\n                pixel.b() = static_cast<uint8_t>(static_cast<int>(pixel.b()) * alpha / 255);\n        }\n    });\n}\n\n/**\n * Un-multiply with alpha for each pixel in an ImageView. The modifications is\n * done in place. The pixel type of the ImageView must model the RGBAPixel\n * concept.\n *\n * @param view_to_modify The image view to unmultiply in place. Has to model\n *                       the ImageView concept and have a pixel type that\n *                       models RGBAPixel.\n */\ntemplate <class SrcDstView>\nvoid unmultiply(SrcDstView& view_to_modify)\n{\n    std::for_each(view_to_modify.begin(), view_to_modify.end(), [&](typename SrcDstView::pixel_type& pixel) {\n        int alpha = static_cast<int>(pixel.a());\n\n        if (alpha != 0 && alpha != 255) {\n            // We don't event try to premultiply 0 since it will be unaffected.\n            if (pixel.r())\n                pixel.r() = static_cast<uint8_t>(static_cast<int>(pixel.r()) * 255 / alpha);\n\n            if (pixel.g())\n                pixel.g() = static_cast<uint8_t>(static_cast<int>(pixel.g()) * 255 / alpha);\n\n            if (pixel.b())\n                pixel.b() = static_cast<uint8_t>(static_cast<int>(pixel.b()) * 255 / alpha);\n        }\n    });\n}\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/util/image_converter.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"image_converter.h\"\n\n#include <common/except.h>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavformat/avformat.h>\n#include <libavutil/pixfmt.h>\n#include <libswscale/swscale.h>\n}\n\nnamespace caspar::image {\n\nbool is_frame_compatible_with_mixer(const std::shared_ptr<AVFrame>& src)\n{\n    std::vector<int> data_map;\n    auto             sample_pix_desc = ffmpeg::pixel_format_desc(\n        static_cast<AVPixelFormat>(src->format), src->width, src->height, data_map, core::color_space::bt709);\n    return sample_pix_desc.format != core::pixel_format::invalid;\n}\n\nstd::shared_ptr<AVFrame> convert_image_frame(const std::shared_ptr<AVFrame>& src, AVPixelFormat pixFmt)\n{\n    if (src->format == pixFmt)\n        return src;\n\n    auto sws = std::shared_ptr<SwsContext>(sws_getContext(src->width,\n                                                          src->height,\n                                                          static_cast<AVPixelFormat>(src->format),\n                                                          src->width,\n                                                          src->height,\n                                                          pixFmt,\n                                                          0,\n                                                          nullptr,\n                                                          nullptr,\n                                                          nullptr),\n                                           [](SwsContext* ptr) { sws_freeContext(ptr); });\n    if (!sws) {\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Failed to create SwsContext\"));\n    }\n\n    auto dest                 = ffmpeg::alloc_frame();\n    dest->sample_aspect_ratio = src->sample_aspect_ratio;\n    dest->width               = src->width;\n    dest->height              = src->height;\n    dest->format              = pixFmt;\n    dest->colorspace          = AVCOL_SPC_BT709;\n    av_frame_get_buffer(dest.get(), 64);\n\n    sws_scale(sws.get(), src->data, src->linesize, 0, src->height, dest->data, dest->linesize);\n\n    return dest;\n}\n\n} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/util/image_converter.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include <ffmpeg/util/av_util.h>\n\n#include <memory>\n\nnamespace caspar::image {\n\nbool is_frame_compatible_with_mixer(const std::shared_ptr<AVFrame>& src);\n\nstd::shared_ptr<AVFrame> convert_image_frame(const std::shared_ptr<AVFrame>& src, AVPixelFormat pixFmt);\n\n} // namespace caspar::image"
  },
  {
    "path": "src/modules/image/util/image_loader.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"image_loader.h\"\n#include \"image_algorithms.h\"\n\n#include <common/except.h>\n#include \"common/scope_exit.h\"\n\n#include <ffmpeg/util/av_assert.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/exception/errinfo_file_name.hpp>\n#include <boost/filesystem.hpp>\n\n#include <set>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavcodec/avcodec.h>\n#include <libavformat/avformat.h>\n#include <libavutil/dict.h>\n#include <libavutil/imgutils.h>\n#include <libswscale/swscale.h>\n}\n\nnamespace caspar { namespace image {\n\n// Based on: https://github.com/FFmpeg/FFmpeg/blob/master/libavfilter/lavfutils.c\nstd::shared_ptr<AVFrame> ff_load_image(const char* filename, AVFormatContext* format_ctx)\n{\n    auto frame = ffmpeg::alloc_frame();\n\n    bool has_input_format_ctx = format_ctx != nullptr;\n\n    const AVInputFormat* input_format = av_find_input_format(\"image2pipe\");\n    FF(avformat_open_input(&format_ctx, filename, input_format, nullptr));\n    CASPAR_SCOPE_EXIT\n    {\n        if (!has_input_format_ctx)\n            avformat_close_input(&format_ctx);\n    };\n\n    FF(avformat_find_stream_info(format_ctx, nullptr));\n\n    const AVCodecParameters* par   = format_ctx->streams[0]->codecpar;\n    const AVCodec*           codec = avcodec_find_decoder(par->codec_id);\n    if (!codec) {\n        FF_RET(AVERROR(EINVAL), \"avcodec_find_decoder\");\n    }\n\n    auto codec_ctx = std::shared_ptr<AVCodecContext>(avcodec_alloc_context3(codec),\n                                                     [](AVCodecContext* ptr) { avcodec_free_context(&ptr); });\n    if (!codec_ctx) {\n        FF_RET(AVERROR(ENOMEM), \"avcodec_alloc_context3\");\n    }\n\n    FF(avcodec_parameters_to_context(codec_ctx.get(), par));\n\n    AVDictionary* opt = nullptr;\n    CASPAR_SCOPE_EXIT { av_dict_free(&opt); };\n\n    av_dict_set(&opt, \"thread_type\", \"slice\", 0);\n    FF(avcodec_open2(codec_ctx.get(), codec, &opt));\n\n    AVPacket pkt;\n    FF(av_read_frame(format_ctx, &pkt));\n\n    const int ret = avcodec_send_packet(codec_ctx.get(), &pkt);\n    av_packet_unref(&pkt);\n    FF_RET(ret, \"avcodec_send_packet\");\n\n    FF(avcodec_receive_frame(codec_ctx.get(), frame.get()));\n\n    return frame;\n}\n\nstd::shared_ptr<AVFrame> load_image(const std::wstring& filename)\n{\n    if (!boost::filesystem::exists(filename))\n        CASPAR_THROW_EXCEPTION(file_not_found() << boost::errinfo_file_name(u8(filename)));\n\n    return ff_load_image(u8(filename).c_str(), nullptr);\n}\n\nstatic int readFunction(void* opaque, uint8_t* buf, int buf_size)\n{\n    auto& data = *static_cast<std::vector<unsigned char>*>(opaque);\n    memcpy(buf, data.data(), buf_size);\n    return static_cast<int>(data.size());\n}\n\nstd::shared_ptr<AVFrame> load_from_memory(std::vector<unsigned char> image_data)\n{\n    const std::shared_ptr<unsigned char> buffer(static_cast<unsigned char*>(av_malloc(image_data.size())), &av_free);\n\n    auto avioContext = std::shared_ptr<AVIOContext>(avio_alloc_context(buffer.get(),\n                                                                       static_cast<int>(image_data.size()),\n                                                                       0,\n                                                                       reinterpret_cast<void*>(&image_data),\n                                                                       &readFunction,\n                                                                       nullptr,\n                                                                       nullptr),\n                                                    [](AVIOContext* ptr) { avio_context_free(&ptr); });\n\n    const auto avFormat = std::shared_ptr<AVFormatContext>(avformat_alloc_context(), &avformat_free_context);\n    avFormat->pb        = avioContext.get();\n\n    return ff_load_image(\"base64\", avFormat.get());\n}\n\nbool is_valid_file(const boost::filesystem::path& filename)\n{\n    static const std::set<std::wstring> extensions = {L\".png\",\n                                                      L\".tga\",\n                                                      L\".bmp\",\n                                                      L\".jpg\",\n                                                      L\".jpeg\",\n                                                      L\".gif\",\n                                                      L\".tiff\",\n                                                      L\".tif\",\n                                                      L\".jp2\",\n                                                      L\".jpx\",\n                                                      L\".j2k\",\n                                                      L\".j2c\",\n                                                      L\".webp\"};\n\n    auto ext = boost::to_lower_copy(boost::filesystem::path(filename).extension().wstring());\n    if (extensions.find(ext) == extensions.end()) {\n        return false;\n    }\n\n    return true;\n}\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/util/image_loader.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <ffmpeg/util/av_util.h>\n\n#include <memory>\n#include <string>\n\n#include <boost/filesystem.hpp>\n\nnamespace caspar { namespace image {\n\nstd::shared_ptr<AVFrame> load_image(const std::wstring& filename);\nstd::shared_ptr<AVFrame> load_from_memory(std::vector<unsigned char> image_data);\n\nbool is_valid_file(const boost::filesystem::path& filename);\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/image/util/image_view.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <boost/iterator/filter_iterator.hpp>\n\nnamespace caspar { namespace image {\n\n/**\n * A POD pixel with a compatible memory layout as a 8bit BGRA pixel (32bits in\n * total).\n * <p>\n * Models the PackedPixel concept used by for example image_view. Also models\n * the RGBAPixel concept which does not care about the order between RGBA but\n * only requires that all 4 channel has accessors.\n */\nclass bgra_pixel\n{\n    uint8_t b_;\n    uint8_t g_;\n    uint8_t r_;\n    uint8_t a_;\n\n  public:\n    bgra_pixel(uint8_t b = 0, uint8_t g = 0, uint8_t r = 0, uint8_t a = 0)\n        : b_(b)\n        , g_(g)\n        , r_(r)\n        , a_(a)\n    {\n    }\n\n    const uint8_t& b() const { return b_; }\n    uint8_t&       b() { return b_; }\n    const uint8_t& g() const { return g_; }\n    uint8_t&       g() { return g_; }\n    const uint8_t& r() const { return r_; }\n    uint8_t&       r() { return r_; }\n    const uint8_t& a() const { return a_; }\n    uint8_t&       a() { return a_; }\n};\n\ntemplate <class PackedPixel>\nclass image_sub_view;\n\n/**\n * An image view abstracting raw packed pixel data\n * <p>\n * This is only a view, it does not own the data.\n * <p>\n * Models the the ImageView concept.\n */\ntemplate <class PackedPixel>\nclass image_view\n{\n  public:\n    using pixel_type = PackedPixel;\n\n    image_view(void* raw_start, int width, int height)\n        : begin_(static_cast<PackedPixel*>(raw_start))\n        , end_(begin_ + width * height)\n        , width_(width)\n        , height_(height)\n    {\n    }\n\n    PackedPixel* begin() { return begin_; }\n\n    const PackedPixel* begin() const { return begin_; }\n\n    PackedPixel* end() { return end_; }\n\n    const PackedPixel* end() const { return end_; }\n\n    template <class PackedPixelIter>\n    PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y)\n    {\n        auto         pixel_distance = delta_x + width_ * delta_y;\n        PackedPixel* to_address     = &(*to);\n        auto         result         = to_address + pixel_distance;\n\n        if (result < begin_ || result >= end_)\n            return nullptr;\n        return result;\n    }\n\n    template <class PackedPixelIter>\n    const PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y) const\n    {\n        auto               pixel_distance = delta_x + width_ * delta_y;\n        const PackedPixel* to_address     = &(*to);\n        auto               result         = to_address + pixel_distance;\n\n        if (result < begin_ || result >= end_)\n            return nullptr;\n        return result;\n    }\n\n    int width() const { return width_; }\n\n    int height() const { return height_; }\n\n    image_sub_view<PackedPixel> subview(int x, int y, int width, int height)\n    {\n        return image_sub_view<PackedPixel>(*this, x, y, width, height);\n    }\n\n    const image_sub_view<PackedPixel> subview(int x, int y, int width, int height) const\n    {\n        return image_sub_view<PackedPixel>(*this, x, y, width, height);\n    }\n\n  private:\n    PackedPixel* begin_;\n    PackedPixel* end_;\n    int          width_;\n    int          height_;\n};\n\ntemplate <class PackedPixel>\nclass is_within_view\n{\n  public:\n    is_within_view(const PackedPixel* begin, int width, int stride)\n        : begin_(begin)\n        , width_(width)\n        , stride_(stride)\n        , no_check_(width == stride)\n    {\n    }\n\n    bool operator()(const PackedPixel& pixel) const\n    {\n        if (no_check_)\n            return true;\n\n        const PackedPixel* position                = &pixel;\n        int                distance_from_row_start = (position - begin_) % stride_;\n\n        return distance_from_row_start < width_;\n    }\n\n  private:\n    const PackedPixel* begin_;\n    int                width_;\n    int                stride_;\n    bool               no_check_;\n};\n\ntemplate <class PackedPixel>\nstruct image_stride_iterator : public boost::filter_iterator<is_within_view<PackedPixel>, PackedPixel*>\n{\n    image_stride_iterator(PackedPixel* begin, PackedPixel* end, int width, int stride)\n        : boost::filter_iterator<is_within_view<PackedPixel>, PackedPixel*>::filter_iterator(\n              is_within_view<PackedPixel>(begin, width, stride),\n              begin,\n              end)\n    {\n    }\n};\n\n/**\n * A sub view created from an image_view.\n * <p>\n * This also models the ImageView concept.\n */\ntemplate <class PackedPixel>\nclass image_sub_view\n{\n  private:\n    image_view<PackedPixel> root_view_;\n    int                     relative_to_root_x_;\n    int                     relative_to_root_y_;\n    int                     width_;\n    int                     height_;\n    PackedPixel* raw_begin_ = root_view_.relative(root_view_.begin(), relative_to_root_x_, relative_to_root_y_);\n    PackedPixel* raw_end_   = root_view_.relative(raw_begin_, width_ - 1, height_ - 1) + 1;\n\n  public:\n    using pixel_type = PackedPixel;\n\n    image_sub_view(image_view<PackedPixel>& root_view, int x, int y, int width, int height)\n        : root_view_(root_view)\n        , relative_to_root_x_(x)\n        , relative_to_root_y_(y)\n        , width_(width)\n        , height_(height)\n    {\n    }\n\n    image_stride_iterator<PackedPixel> begin()\n    {\n        return image_stride_iterator<PackedPixel>(raw_begin_, raw_end_, width_, root_view_.width());\n    }\n\n    image_stride_iterator<const PackedPixel> begin() const\n    {\n        return image_stride_iterator<const PackedPixel>(raw_begin_, raw_end_, width_, root_view_.width());\n    }\n\n    image_stride_iterator<PackedPixel> end()\n    {\n        return image_stride_iterator<PackedPixel>(raw_end_, raw_end_, width_, root_view_.width());\n    }\n\n    image_stride_iterator<const PackedPixel> end() const\n    {\n        return image_stride_iterator<const PackedPixel>(raw_end_, raw_end_, width_, root_view_.width());\n    }\n\n    template <class PackedPixelIter>\n    PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y)\n    {\n        return root_view_.relative(to, delta_x, delta_y);\n    }\n\n    template <class PackedPixelIter>\n    const PackedPixel* relative(PackedPixelIter to, int delta_x, int delta_y) const\n    {\n        return root_view_.relative(to, delta_x, delta_y);\n    }\n\n    int width() const { return width_; }\n\n    int height() const { return height_; }\n\n    image_sub_view<PackedPixel> subview(int x, int y, int width, int height)\n    {\n        return root_view_.subview(relative_to_root_x_ + x, relative_to_root_y_ + y, width, height);\n    }\n\n    const image_sub_view<PackedPixel> subview(int x, int y, int width, int height) const\n    {\n        return root_view_.subview(relative_to_root_x_ + x, relative_to_root_y_ + y, width, height);\n    }\n};\n\n}} // namespace caspar::image\n"
  },
  {
    "path": "src/modules/newtek/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (newtek)\n\nset(SOURCES\n\t\tconsumer/newtek_ndi_consumer.cpp\n\t\tconsumer/newtek_ndi_consumer.h\n\n\t\tproducer/newtek_ndi_producer.cpp\n\t\tproducer/newtek_ndi_producer.h\n\n\t\tutil/ndi.cpp\n\t\tutil/ndi.h\n\n\t\tnewtek.cpp\n\t\tnewtek.h\n\n\t\tinterop/Processing.NDI.compat.h\n\t\tinterop/Processing.NDI.deprecated.h\n\t\tinterop/Processing.NDI.DynamicLoad.h\n\t\tinterop/Processing.NDI.Find.h\n\t\tinterop/Processing.NDI.FrameSync.h\n\t\tinterop/Processing.NDI.Lib.cplusplus.h\n\t\tinterop/Processing.NDI.Lib.h\n\t\tinterop/Processing.NDI.Recv.ex.h\n\t\tinterop/Processing.NDI.Recv.h\n\t\tinterop/Processing.NDI.Routing.h\n\t\tinterop/Processing.NDI.Send.h\n\t\tinterop/Processing.NDI.structs.h\n\t\tinterop/Processing.NDI.utilities.h\n\n\t\tStdAfx.h\n)\n\ncasparcg_add_module_project(newtek\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"newtek::init\"\n)\ntarget_include_directories(newtek PRIVATE\n\t..\n    ${FFMPEG_INCLUDE_PATH}\n    )\ntarget_precompile_headers(newtek PRIVATE \"StdAfx.h\")\n\nset_target_properties(newtek PROPERTIES FOLDER modules)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources\\\\producer producer/*)\nsource_group(sources\\\\interop interop/*)\nsource_group(sources\\\\util util/*)\nsource_group(sources ./*)\n\ntarget_link_libraries(newtek PRIVATE ffmpeg)\n"
  },
  {
    "path": "src/modules/newtek/StdAfx.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#ifdef _DEBUG\n#include <crtdbg.h>\n#endif\n\n#define NOMINMAX\n\n#include <algorithm>\n#include <array>\n#include <deque>\n#include <functional>\n#include <math.h>\n#include <memory>\n#include <queue>\n#include <string>\n#include <vector>\n\n#include <common/memory.h>\n\n#include <common/except.h>\n#include <common/log.h>\n\n#include <assert.h>\n"
  },
  {
    "path": "src/modules/newtek/consumer/newtek_ndi_consumer.cpp",
    "content": "/*\n * Copyright 2018\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Krzysztof Zegzula, zegzulakrzysztof@gmail.com\n * based on work of Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"newtek_ndi_consumer.h\"\n\n#include <boost/thread/exceptions.hpp>\n#include <chrono>\n#include <condition_variable>\n#include <core/consumer/channel_info.h>\n#include <core/consumer/frame_consumer.h>\n#include <core/frame/frame.h>\n#include <core/mixer/audio/audio_util.h>\n#include <core/video_format.h>\n\n#include <common/assert.h>\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/future.h>\n#include <common/param.h>\n#include <common/timer.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/thread.hpp>\n#include <ratio>\n#include <thread>\n\n#include \"../util/ndi.h\"\n\nnamespace caspar { namespace newtek {\n\nstruct newtek_ndi_consumer : public core::frame_consumer\n{\n    static std::atomic<int> instances_;\n    const int               instance_no_;\n    const std::wstring      name_;\n    const bool              allow_fields_;\n    const std::string       discovery_server_url_;\n    const bool              use_advertiser_;\n    const bool              allow_monitoring_;\n\n    core::video_format_desc              format_desc_;\n    int                                  channel_index_;\n    NDIlib_v6*                           ndi_lib_;\n    NDIlib_video_frame_v2_t              ndi_video_frame_;\n    NDIlib_audio_frame_interleaved_32s_t ndi_audio_frame_;\n    std::shared_ptr<uint8_t>             field_data_;\n    spl::shared_ptr<diagnostics::graph>  graph_;\n    caspar::timer                        tick_timer_;\n    caspar::timer                        frame_timer_;\n    caspar::timer                        ndi_timer_;\n    int                                  frame_no_;\n    std::mutex                           buffer_mutex_;\n    std::condition_variable              buffer_cond_;\n    std::condition_variable              worker_cond_;\n    bool                                 ready_for_frame_;\n    std::queue<core::const_frame>        buffer_;\n    boost::thread                        send_thread;\n    executor                             executor_;\n\n    std::unique_ptr<NDIlib_send_instance_t, std::function<void(NDIlib_send_instance_t*)>> ndi_send_instance_;\n    std::unique_ptr<NDIlib_send_advertiser_instance_t, std::function<void(NDIlib_send_advertiser_instance_t*)>>\n        ndi_advertiser_instance_;\n\n  public:\n    newtek_ndi_consumer(std::wstring name,\n                        bool         allow_fields,\n                        std::string  discovery_server_url = \"\",\n                        bool         use_advertiser       = false,\n                        bool         allow_monitoring     = true)\n        : name_(!name.empty() ? name : default_ndi_name())\n        , instance_no_(instances_++)\n        , frame_no_(0)\n        , allow_fields_(allow_fields)\n        , discovery_server_url_(discovery_server_url)\n        , use_advertiser_(use_advertiser)\n        , allow_monitoring_(allow_monitoring)\n        , channel_index_(0)\n        , executor_(L\"ndi_consumer[\" + std::to_wstring(instance_no_) + L\"]\")\n    {\n        ndi_lib_ = ndi::load_library();\n        graph_->set_text(print());\n        graph_->set_color(\"frame-time\", diagnostics::color(0.5f, 1.0f, 0.2f));\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"buffered-frames\", diagnostics::color(0.5f, 0.0f, 0.2f));\n        graph_->set_color(\"ndi-tick\", diagnostics::color(1.0f, 1.0f, 0.1f));\n        diagnostics::register_graph(graph_);\n    }\n\n    ~newtek_ndi_consumer()\n    {\n        if (send_thread.joinable()) {\n            send_thread.interrupt();\n            send_thread.join();\n        }\n    }\n\n    // frame_consumer\n\n    void initialize(const core::video_format_desc& format_desc,\n                    const core::channel_info&      channel_info,\n                    int                            port_index) override\n    {\n        format_desc_   = format_desc;\n        channel_index_ = channel_info.index;\n\n        // Make sure to stop the advertiser before recreating the sender\n        ndi_advertiser_instance_.reset();\n\n        NDIlib_send_create_t NDI_send_create_desc;\n\n        auto tmp_name                   = u8(name_);\n        NDI_send_create_desc.p_ndi_name = tmp_name.c_str();\n        // NDI defaults to clocking on video, however it's very jittery.\n        NDI_send_create_desc.clock_video = false;\n        NDI_send_create_desc.clock_audio = false;\n\n        ndi_send_instance_ = {new NDIlib_send_instance_t(ndi_lib_->send_create(&NDI_send_create_desc)),\n                              [this](auto p) { this->ndi_lib_->send_destroy(*p); }};\n\n        // Create and configure NDI advertiser if enabled\n        if (use_advertiser_) {\n            if (!ndi_lib_->send_advertiser_create) {\n                CASPAR_LOG(warning)\n                    << L\"NDI advertiser requested but not supported by this NDI SDK version (requires NDI 5.5+)\";\n            } else {\n                // Use constructor for proper initialization\n                NDIlib_send_advertiser_create_t advertiser_create_desc(\n                    discovery_server_url_.empty() ? nullptr : discovery_server_url_.c_str());\n\n                auto advertiser_instance = ndi_lib_->send_advertiser_create(&advertiser_create_desc);\n\n                if (!advertiser_instance) {\n                    CASPAR_LOG(warning) << L\"Failed to create NDI advertiser for sender '\" << name_ << L\"'\"\n                                        << (discovery_server_url_.empty()\n                                                ? L\" (using default discovery)\"\n                                                : L\" with server: \" + u16(discovery_server_url_));\n                } else {\n                    ndi_advertiser_instance_ = {\n                        new NDIlib_send_advertiser_instance_t(advertiser_instance), [this](auto p) {\n                            if (p && *p && this->ndi_lib_->send_advertiser_del_sender &&\n                                this->ndi_lib_->send_advertiser_destroy) {\n                                // Remove sender before destroying advertiser\n                                this->ndi_lib_->send_advertiser_del_sender(*p, *ndi_send_instance_);\n                                this->ndi_lib_->send_advertiser_destroy(*p);\n                            }\n                        }};\n\n                    bool added = ndi_lib_->send_advertiser_add_sender(\n                        *ndi_advertiser_instance_, *ndi_send_instance_, allow_monitoring_);\n\n                    if (added) {\n                        CASPAR_LOG(info) << L\"NDI sender '\" << name_ << L\"' registered with discovery server\"\n                                         << (discovery_server_url_.empty() ? L\"\"\n                                                                           : L\" at \" + u16(discovery_server_url_));\n                    } else {\n                        CASPAR_LOG(warning) << L\"Failed to register NDI sender '\" << name_\n                                            << L\"' with advertiser (sender may already be registered)\";\n                    }\n                }\n            }\n        }\n\n        ndi_video_frame_.xres                 = format_desc.width;\n        ndi_video_frame_.yres                 = format_desc.height;\n        ndi_video_frame_.frame_rate_N         = format_desc.framerate.numerator() * format_desc.field_count;\n        ndi_video_frame_.frame_rate_D         = format_desc.framerate.denominator();\n        ndi_video_frame_.FourCC               = NDIlib_FourCC_type_BGRA;\n        ndi_video_frame_.line_stride_in_bytes = format_desc.width * 4;\n        ndi_video_frame_.frame_format_type    = NDIlib_frame_format_type_progressive;\n\n        if (format_desc.field_count == 2 && allow_fields_) {\n            ndi_video_frame_.yres /= 2;\n            ndi_video_frame_.frame_rate_N /= 2;\n            ndi_video_frame_.picture_aspect_ratio = format_desc.width * 1.0f / format_desc.height;\n            field_data_.reset(new uint8_t[ndi_video_frame_.line_stride_in_bytes * ndi_video_frame_.yres],\n                              std::default_delete<uint8_t[]>());\n            ndi_video_frame_.p_data = field_data_.get();\n        }\n\n        ndi_audio_frame_.sample_rate = format_desc_.audio_sample_rate;\n        ndi_audio_frame_.no_channels = format_desc_.audio_channels;\n        ndi_audio_frame_.timecode    = NDIlib_send_timecode_synthesize;\n\n        graph_->set_text(print());\n        // CASPAR_VERIFY(ndi_send_instance_);\n\n        send_thread = boost::thread([this]() {\n            set_thread_realtime_priority();\n            set_thread_name(L\"NDI-SEND: \" + name_);\n            CASPAR_LOG(info) << L\"Starting ndi-send thread for ndi output: \" << name_;\n            try {\n                auto buffer_size = buffer_.size();\n                // Buffer a few frames to keep NDI going when caspar is slow on a few frames\n                // This can be removed when CasparCG doesn't periodally slows down on frames\n                while (!send_thread.interruption_requested()) {\n                    {\n                        std::unique_lock<std::mutex> lock(buffer_mutex_);\n                        worker_cond_.wait(lock, [&] { return buffer_.size() > buffer_size; });\n                        graph_->set_value(\"buffered-frames\", static_cast<double>(buffer_.size() + 0.001) / 8);\n                        buffer_size = buffer_.size();\n                        if (buffer_.size() >= 8) {\n                            break;\n                        }\n                    }\n                }\n\n                // Use steady clock to generate a near perfect NDI tick time.\n                auto frametimeUs = static_cast<int>(1000000 / format_desc_.fps);\n                auto time_point  = std::chrono::steady_clock::now();\n                time_point += std::chrono::microseconds(frametimeUs);\n                while (!send_thread.interruption_requested()) {\n                    core::const_frame frame;\n                    {\n                        std::unique_lock<std::mutex> lock(buffer_mutex_);\n                        worker_cond_.wait(lock, [&] { return !buffer_.empty(); });\n                        graph_->set_value(\"buffered-frames\", static_cast<double>(buffer_.size() + 0.001) / 8);\n                        frame = std::move(buffer_.front());\n                        buffer_.pop();\n                    }\n                    graph_->set_value(\"ndi-tick\", ndi_timer_.elapsed() * format_desc_.fps * 0.5);\n                    ndi_timer_.restart();\n                    frame_timer_.restart();\n                    auto audio_data             = frame.audio_data();\n                    int  audio_data_size        = static_cast<int>(audio_data.size());\n                    ndi_audio_frame_.no_samples = audio_data_size / format_desc_.audio_channels;\n                    ndi_audio_frame_.p_data     = const_cast<int*>(audio_data.data());\n                    ndi_lib_->util_send_send_audio_interleaved_32s(*ndi_send_instance_, &ndi_audio_frame_);\n                    if (format_desc_.field_count == 2 && allow_fields_) {\n                        ndi_video_frame_.frame_format_type =\n                            (frame_no_ % 2 ? NDIlib_frame_format_type_field_1 : NDIlib_frame_format_type_field_0);\n                        for (auto y = 0; y < ndi_video_frame_.yres; ++y) {\n                            std::memcpy(reinterpret_cast<char*>(ndi_video_frame_.p_data) + y * format_desc_.width * 4,\n                                        frame.image_data(0).data() + (y * 2 + frame_no_ % 2) * format_desc_.width * 4,\n                                        format_desc_.width * 4);\n                        }\n                    } else {\n                        ndi_video_frame_.p_data = const_cast<uint8_t*>(frame.image_data(0).begin());\n                    }\n                    ndi_lib_->send_send_video_v2(*ndi_send_instance_, &ndi_video_frame_);\n                    frame_no_++;\n                    graph_->set_value(\"frame-time\", frame_timer_.elapsed() * format_desc_.fps * 0.5);\n                    std::this_thread::sleep_until(time_point);\n                    time_point += std::chrono::microseconds(frametimeUs);\n                }\n            } catch (boost::thread_interrupted) {\n                // NOTHING\n            }\n        });\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        return executor_.begin_invoke([=, this] {\n            graph_->set_value(\"tick-time\", tick_timer_.elapsed() * format_desc_.fps * 0.5);\n            tick_timer_.restart();\n            {\n                std::unique_lock<std::mutex> lock(buffer_mutex_);\n                buffer_.push(std::move(frame));\n            }\n            worker_cond_.notify_all();\n            return true;\n        });\n    }\n\n    std::wstring print() const override\n    {\n        if (channel_index_) {\n            return L\"ndi_consumer[\" + boost::lexical_cast<std::wstring>(channel_index_) + L\"|\" + name_ + L\"]\";\n        } else {\n            return L\"[ndi_consumer]\";\n        }\n    }\n\n    std::wstring name() const override { return L\"ndi\"; }\n\n    std::wstring default_ndi_name() const\n    {\n        return L\"CasparCG\" + (instance_no_ ? L\" \" + boost::lexical_cast<std::wstring>(instance_no_) : L\"\");\n    }\n\n    int index() const override { return 900; }\n\n    bool has_synchronization_clock() const override { return false; }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"ndi/name\"]                 = name_;\n        state[\"ndi/allow_fields\"]         = allow_fields_;\n        state[\"ndi/use_advertiser\"]       = use_advertiser_;\n        state[\"ndi/allow_monitoring\"]     = allow_monitoring_;\n        state[\"ndi/discovery_server_url\"] = discovery_server_url_;\n        return state;\n    }\n};\n\nstd::atomic<int> newtek_ndi_consumer::instances_(0);\n\nspl::shared_ptr<core::frame_consumer>\ncreate_ndi_consumer(const std::vector<std::wstring>&                         params,\n                    const core::video_format_repository&                     format_repository,\n                    const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                    const core::channel_info&                                channel_info)\n{\n    if (params.size() < 1 || !boost::iequals(params.at(0), L\"NDI\"))\n        return core::frame_consumer::empty();\n\n    if (channel_info.depth != common::bit_depth::bit8)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Newtek NDI consumer only supports 8-bit color depth.\"));\n\n    std::wstring name                   = get_param(L\"NAME\", params, L\"\");\n    bool         allow_fields           = contains_param(L\"ALLOW_FIELDS\", params);\n    bool         use_advertiser         = contains_param(L\"USE_ADVERTISER\", params);\n    bool         allow_monitoring       = get_param(L\"ALLOW_MONITORING\", params, true);\n    std::wstring discovery_server_url_w = get_param(L\"DISCOVERY_SERVER\", params, L\"\");\n    if (discovery_server_url_w.empty())\n        discovery_server_url_w = env::properties().get(L\"configuration.ndi.discovery-server\", L\"\");\n    std::string discovery_server_url = ndi::apply_default_discovery_port(u8(discovery_server_url_w));\n\n    return spl::make_shared<newtek_ndi_consumer>(\n        name, allow_fields, discovery_server_url, use_advertiser, allow_monitoring);\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_ndi_consumer(const boost::property_tree::wptree&                      ptree,\n                                  const core::video_format_repository&                     format_repository,\n                                  const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                  const core::channel_info&                                channel_info)\n{\n    auto         name                   = ptree.get(L\"name\", L\"\");\n    bool         allow_fields           = ptree.get(L\"allow-fields\", false);\n    bool         use_advertiser         = ptree.get(L\"use-advertiser\", false);\n    bool         allow_monitoring       = ptree.get(L\"allow-monitoring\", true);\n    std::wstring discovery_server_url_w = ptree.get(L\"discovery-server\", L\"\");\n    if (discovery_server_url_w.empty())\n        discovery_server_url_w = env::properties().get(L\"configuration.ndi.discovery-server\", L\"\");\n    std::string discovery_server_url = ndi::apply_default_discovery_port(u8(discovery_server_url_w));\n\n    if (channel_info.depth != common::bit_depth::bit8)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(\"Newtek NDI consumer only supports 8-bit color depth.\"));\n\n    return spl::make_shared<newtek_ndi_consumer>(\n        name, allow_fields, discovery_server_url, use_advertiser, allow_monitoring);\n}\n\n}} // namespace caspar::newtek\n"
  },
  {
    "path": "src/modules/newtek/consumer/newtek_ndi_consumer.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Krzysztof Zegzula, zegzulakrzysztof@gmail.com\n * based on work of Robert Nagy, ronag89@gmail.com work\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <string>\n\nnamespace caspar { namespace newtek {\n\nspl::shared_ptr<core::frame_consumer>\ncreate_ndi_consumer(const std::vector<std::wstring>&                         params,\n                    const core::video_format_repository&                     format_repository,\n                    const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                    const core::channel_info&                                channel_info);\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_ndi_consumer(const boost::property_tree::wptree&                      ptree,\n                                  const core::video_format_repository&                     format_repository,\n                                  const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                  const core::channel_info&                                channel_info);\n\n}} // namespace caspar::newtek\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.DynamicLoad.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\ntypedef struct NDIlib_v6_3 {\r\n\t// v1.5\r\n\tunion {\r\n\t\tbool (*initialize)(void);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_initialize)(void);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*destroy)(void);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_destroy)(void);\r\n\t};\r\n\tunion {\r\n\t\tconst char* (*version)(void);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* (*NDIlib_version)(void);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*is_supported_CPU)(void);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_is_supported_CPU)(void);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_find_instance_t (*find_create)(const NDIlib_find_create_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_find_instance_t (*NDIlib_find_create)(const NDIlib_find_create_t* p_create_settings);\r\n\t};\r\n\r\n\tunion {\r\n\t\tNDIlib_find_instance_t (*find_create_v2)(const NDIlib_find_create_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_find_instance_t (*NDIlib_find_create_v2)(const NDIlib_find_create_t* p_create_settings);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*find_destroy)(NDIlib_find_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_find_destroy)(NDIlib_find_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tconst NDIlib_source_t* (*find_get_sources)(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const NDIlib_source_t* (*NDIlib_find_get_sources)(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tNDIlib_send_instance_t (*send_create)(const NDIlib_send_create_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_send_instance_t (*NDIlib_send_create)(const NDIlib_send_create_t* p_create_settings);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_destroy)(NDIlib_send_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_destroy)(NDIlib_send_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*send_send_video)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_video)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*send_send_video_async)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_video_async)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*send_send_audio)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_audio)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_send_metadata)(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_metadata)(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t};\r\n\r\n\tunion {\r\n\t\tNDIlib_frame_type_e (*send_capture)(NDIlib_send_instance_t p_instance, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_frame_type_e (*NDIlib_send_capture)(NDIlib_send_instance_t p_instance, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_free_metadata)(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_free_metadata)(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*send_get_tally)(NDIlib_send_instance_t p_instance, NDIlib_tally_t* p_tally, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_send_get_tally)(NDIlib_send_instance_t p_instance, NDIlib_tally_t* p_tally, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tint (*send_get_no_connections)(NDIlib_send_instance_t p_instance, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED int (*NDIlib_send_get_no_connections)(NDIlib_send_instance_t p_instance, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_clear_connection_metadata)(NDIlib_send_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_clear_connection_metadata)(NDIlib_send_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_add_connection_metadata)(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_add_connection_metadata)(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_set_failover)(NDIlib_send_instance_t p_instance, const NDIlib_source_t* p_failover_source);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_set_failover)(NDIlib_send_instance_t p_instance, const NDIlib_source_t* p_failover_source);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_recv_instance_t (*recv_create_v2)(const NDIlib_recv_create_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_recv_instance_t (*NDIlib_recv_create_v2)(const NDIlib_recv_create_t* p_create_settings);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_recv_instance_t (*recv_create)(const NDIlib_recv_create_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_recv_instance_t (*NDIlib_recv_create)(const NDIlib_recv_create_t* p_create_settings);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_destroy)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_destroy)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_frame_type_e (*recv_capture)(NDIlib_recv_instance_t p_instance, NDIlib_video_frame_t* p_video_data, NDIlib_audio_frame_t* p_audio_data, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_frame_type_e (*NDIlib_recv_capture)(NDIlib_recv_instance_t p_instance, NDIlib_video_frame_t* p_video_data, NDIlib_audio_frame_t* p_audio_data, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*recv_free_video)(NDIlib_recv_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_video)(NDIlib_recv_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*recv_free_audio)(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_audio)(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_free_metadata)(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_metadata)(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_send_metadata)(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_send_metadata)(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_set_tally)(NDIlib_recv_instance_t p_instance, const NDIlib_tally_t* p_tally);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_set_tally)(NDIlib_recv_instance_t p_instance, const NDIlib_tally_t* p_tally);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_get_performance)(NDIlib_recv_instance_t p_instance, NDIlib_recv_performance_t* p_total, NDIlib_recv_performance_t* p_dropped);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_get_performance)(NDIlib_recv_instance_t p_instance, NDIlib_recv_performance_t* p_total, NDIlib_recv_performance_t* p_dropped);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_get_queue)(NDIlib_recv_instance_t p_instance, NDIlib_recv_queue_t* p_total);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_get_queue)(NDIlib_recv_instance_t p_instance, NDIlib_recv_queue_t* p_total);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_clear_connection_metadata)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_clear_connection_metadata)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_add_connection_metadata)(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_add_connection_metadata)(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\t};\r\n\r\n\tunion {\r\n\t\tint (*recv_get_no_connections)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED int (*NDIlib_recv_get_no_connections)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tNDIlib_routing_instance_t (*routing_create)(const NDIlib_routing_create_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_routing_instance_t (*NDIlib_routing_create)(const NDIlib_routing_create_t* p_create_settings);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*routing_destroy)(NDIlib_routing_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_routing_destroy)(NDIlib_routing_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*routing_change)(NDIlib_routing_instance_t p_instance, const NDIlib_source_t* p_source);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_routing_change)(NDIlib_routing_instance_t p_instance, const NDIlib_source_t* p_source);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*routing_clear)(NDIlib_routing_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_routing_clear)(NDIlib_routing_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_send_send_audio_interleaved_16s)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_interleaved_16s_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_send_send_audio_interleaved_16s)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_interleaved_16s_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*util_audio_to_interleaved_16s)(const NDIlib_audio_frame_t* p_src, NDIlib_audio_frame_interleaved_16s_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_to_interleaved_16s)(const NDIlib_audio_frame_t* p_src, NDIlib_audio_frame_interleaved_16s_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*util_audio_from_interleaved_16s)(const NDIlib_audio_frame_interleaved_16s_t* p_src, NDIlib_audio_frame_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_from_interleaved_16s)(const NDIlib_audio_frame_interleaved_16s_t* p_src, NDIlib_audio_frame_t* p_dst);\r\n\t};\r\n\r\n\t// v2\r\n\tunion {\r\n\t\tbool (*find_wait_for_sources)(NDIlib_find_instance_t p_instance, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_find_wait_for_sources)(NDIlib_find_instance_t p_instance, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tconst NDIlib_source_t* (*find_get_current_sources)(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const NDIlib_source_t* (*NDIlib_find_get_current_sources)(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*util_audio_to_interleaved_32f)(const NDIlib_audio_frame_t* p_src, NDIlib_audio_frame_interleaved_32f_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_to_interleaved_32f)(const NDIlib_audio_frame_t* p_src, NDIlib_audio_frame_interleaved_32f_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*util_audio_from_interleaved_32f)(const NDIlib_audio_frame_interleaved_32f_t* p_src, NDIlib_audio_frame_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_from_interleaved_32f)(const NDIlib_audio_frame_interleaved_32f_t* p_src, NDIlib_audio_frame_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_send_send_audio_interleaved_32f)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_interleaved_32f_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_send_send_audio_interleaved_32f)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_interleaved_32f_t* p_audio_data);\r\n\t};\r\n\r\n\t// v3\r\n\tunion {\r\n\t\tvoid (*recv_free_video_v2)(NDIlib_recv_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_video_v2)(NDIlib_recv_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_free_audio_v2)(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_v2_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_audio_v2)(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_v2_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tNDIlib_frame_type_e (*recv_capture_v2)(NDIlib_recv_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data, NDIlib_audio_frame_v2_t* p_audio_data, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);             // The amount of time in milliseconds to wait for data.\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_frame_type_e (*NDIlib_recv_capture_v2)(NDIlib_recv_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data, NDIlib_audio_frame_v2_t* p_audio_data, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);             // The amount of time in milliseconds to wait for data.\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_send_video_v2)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_video_v2)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_send_video_async_v2)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_video_async_v2)(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*send_send_audio_v2)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_v2_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_audio_v2)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_v2_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_audio_to_interleaved_16s_v2)(const NDIlib_audio_frame_v2_t* p_src, NDIlib_audio_frame_interleaved_16s_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_to_interleaved_16s_v2)(const NDIlib_audio_frame_v2_t* p_src, NDIlib_audio_frame_interleaved_16s_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_audio_from_interleaved_16s_v2)(const NDIlib_audio_frame_interleaved_16s_t* p_src, NDIlib_audio_frame_v2_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_from_interleaved_16s_v2)(const NDIlib_audio_frame_interleaved_16s_t* p_src, NDIlib_audio_frame_v2_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_audio_to_interleaved_32f_v2)(const NDIlib_audio_frame_v2_t* p_src, NDIlib_audio_frame_interleaved_32f_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_to_interleaved_32f_v2)(const NDIlib_audio_frame_v2_t* p_src, NDIlib_audio_frame_interleaved_32f_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_audio_from_interleaved_32f_v2)(const NDIlib_audio_frame_interleaved_32f_t* p_src, NDIlib_audio_frame_v2_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_from_interleaved_32f_v2)(const NDIlib_audio_frame_interleaved_32f_t* p_src, NDIlib_audio_frame_v2_t* p_dst);\r\n\t};\r\n\r\n\t// V3.01\r\n\tunion {\r\n\t\tvoid (*recv_free_string)(NDIlib_recv_instance_t p_instance, const char* p_string);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_string)(NDIlib_recv_instance_t p_instance, const char* p_string);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_is_supported)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_is_supported)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*recv_recording_is_supported)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_recording_is_supported)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tconst char* (*recv_get_web_control)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* (*NDIlib_recv_get_web_control)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_zoom)(NDIlib_recv_instance_t p_instance, const float zoom_value);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_zoom)(NDIlib_recv_instance_t p_instance, const float zoom_value);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_zoom_speed)(NDIlib_recv_instance_t p_instance, const float zoom_speed);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_zoom_speed)(NDIlib_recv_instance_t p_instance, const float zoom_speed);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_pan_tilt)(NDIlib_recv_instance_t p_instance, const float pan_value, const float tilt_value);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_pan_tilt)(NDIlib_recv_instance_t p_instance, const float pan_value, const float tilt_value);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_pan_tilt_speed)(NDIlib_recv_instance_t p_instance, const float pan_speed, const float tilt_speed);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_pan_tilt_speed)(NDIlib_recv_instance_t p_instance, const float pan_speed, const float tilt_speed);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_store_preset)(NDIlib_recv_instance_t p_instance, const int preset_no);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_store_preset)(NDIlib_recv_instance_t p_instance, const int preset_no);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_recall_preset)(NDIlib_recv_instance_t p_instance, const int preset_no, const float speed);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_recall_preset)(NDIlib_recv_instance_t p_instance, const int preset_no, const float speed);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_auto_focus)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_auto_focus)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_focus)(NDIlib_recv_instance_t p_instance, const float focus_value);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_focus)(NDIlib_recv_instance_t p_instance, const float focus_value);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_focus_speed)(NDIlib_recv_instance_t p_instance, const float focus_speed);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_focus_speed)(NDIlib_recv_instance_t p_instance, const float focus_speed);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_white_balance_auto)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_white_balance_auto)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_white_balance_indoor)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_white_balance_indoor)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_white_balance_outdoor)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_white_balance_outdoor)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_white_balance_oneshot)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_white_balance_oneshot)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_white_balance_manual)(NDIlib_recv_instance_t p_instance, const float red, const float blue);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_white_balance_manual)(NDIlib_recv_instance_t p_instance, const float red, const float blue);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_exposure_auto)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_exposure_auto)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tbool (*recv_ptz_exposure_manual)(NDIlib_recv_instance_t p_instance, const float exposure_level);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_exposure_manual)(NDIlib_recv_instance_t p_instance, const float exposure_level);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*recv_recording_start)(NDIlib_recv_instance_t p_instance, const char* p_filename_hint);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_recording_start)(NDIlib_recv_instance_t p_instance, const char* p_filename_hint);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*recv_recording_stop)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_recording_stop)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*recv_recording_set_audio_level)(NDIlib_recv_instance_t p_instance, const float level_dB);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_recording_set_audio_level)(NDIlib_recv_instance_t p_instance, const float level_dB);\r\n\t};\r\n\r\n\tunion {\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*recv_recording_is_recording)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_recording_is_recording)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* (*recv_recording_get_filename)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* (*NDIlib_recv_recording_get_filename)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* (*recv_recording_get_error)(NDIlib_recv_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* (*NDIlib_recv_recording_get_error)(NDIlib_recv_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\t// This functionality is now provided via external NDI recording, see SDK documentation.\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*recv_recording_get_times)(NDIlib_recv_instance_t p_instance, NDIlib_recv_recording_time_t* p_times);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_recording_get_times)(NDIlib_recv_instance_t p_instance, NDIlib_recv_recording_time_t* p_times);\r\n\t};\r\n\r\n\t// v3.1\r\n\tunion {\r\n\t\tNDIlib_recv_instance_t (*recv_create_v3)(const NDIlib_recv_create_v3_t* p_create_settings);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_recv_instance_t (*NDIlib_recv_create_v3)(const NDIlib_recv_create_v3_t* p_create_settings);\r\n\t};\r\n\r\n\t// v3.5\r\n\tunion {\r\n\t\tvoid (*recv_connect)(NDIlib_recv_instance_t p_instance, const NDIlib_source_t* p_src);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_connect)(NDIlib_recv_instance_t p_instance, const NDIlib_source_t* p_src);\r\n\t};\r\n\r\n\t// v3.6\r\n\tunion {\r\n\t\tNDIlib_framesync_instance_t (*framesync_create)(NDIlib_recv_instance_t p_receiver);\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_framesync_instance_t (*NDIlib_framesync_create)(NDIlib_recv_instance_t p_receiver);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_destroy)(NDIlib_framesync_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_destroy)(NDIlib_framesync_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_capture_audio)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v2_t* p_audio_data, int sample_rate, int no_channels, int no_samples);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_capture_audio)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v2_t* p_audio_data, int sample_rate, int no_channels, int no_samples);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_free_audio)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v2_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_free_audio)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v2_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_capture_video)(NDIlib_framesync_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data, NDIlib_frame_format_type_e field_type);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_capture_video)(NDIlib_framesync_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data, NDIlib_frame_format_type_e field_type);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_free_video)(NDIlib_framesync_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_free_video)(NDIlib_framesync_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_send_send_audio_interleaved_32s)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_interleaved_32s_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_send_send_audio_interleaved_32s)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_interleaved_32s_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_audio_to_interleaved_32s_v2)(const NDIlib_audio_frame_v2_t* p_src, NDIlib_audio_frame_interleaved_32s_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_to_interleaved_32s_v2)(const NDIlib_audio_frame_v2_t* p_src, NDIlib_audio_frame_interleaved_32s_t* p_dst);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_audio_from_interleaved_32s_v2)(const NDIlib_audio_frame_interleaved_32s_t* p_src, NDIlib_audio_frame_v2_t* p_dst);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_audio_from_interleaved_32s_v2)(const NDIlib_audio_frame_interleaved_32s_t* p_src, NDIlib_audio_frame_v2_t* p_dst);\r\n\t};\r\n\r\n\t// v3.8\r\n\tunion {\r\n\t\tconst NDIlib_source_t* (*send_get_source_name)(NDIlib_send_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const NDIlib_source_t* (*NDIlib_send_get_source_name)(NDIlib_send_instance_t p_instance);\r\n\t};\r\n\r\n\t// v4.0\r\n\tunion {\r\n\t\tvoid (*send_send_audio_v3)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_v3_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_send_send_audio_v3)(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_v3_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_V210_to_P216)(const NDIlib_video_frame_v2_t* p_src_v210, NDIlib_video_frame_v2_t* p_dst_p216);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_V210_to_P216)(const NDIlib_video_frame_v2_t* p_src_v210, NDIlib_video_frame_v2_t* p_dst_p216);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*util_P216_to_V210)(const NDIlib_video_frame_v2_t* p_src_p216, NDIlib_video_frame_v2_t* p_dst_v210);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_util_P216_to_V210)(const NDIlib_video_frame_v2_t* p_src_p216, NDIlib_video_frame_v2_t* p_dst_v210);\r\n\t};\r\n\r\n\t// v4.1\r\n\tunion {\r\n\t\tint (*routing_get_no_connections)(NDIlib_routing_instance_t p_instance, uint32_t timeout_in_ms);\r\n\t\tPROCESSINGNDILIB_DEPRECATED int (*NDIlib_routing_get_no_connections)(NDIlib_routing_instance_t p_instance, uint32_t timeout_in_ms);\r\n\t};\r\n\r\n\tunion {\r\n\t\tconst NDIlib_source_t* (*routing_get_source_name)(NDIlib_routing_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED const NDIlib_source_t* (*NDIlib_routing_get_source_name)(NDIlib_routing_instance_t p_instance);\r\n\t};\r\n\r\n\tunion {\r\n\t\tNDIlib_frame_type_e (*recv_capture_v3)(NDIlib_recv_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data, NDIlib_audio_frame_v3_t* p_audio_data, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);             // The amount of time in milliseconds to wait for data.\r\n\t\tPROCESSINGNDILIB_DEPRECATED NDIlib_frame_type_e (*NDIlib_recv_capture_v3)(NDIlib_recv_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data, NDIlib_audio_frame_v3_t* p_audio_data, NDIlib_metadata_frame_t* p_metadata, uint32_t timeout_in_ms);             // The amount of time in milliseconds to wait for data.\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*recv_free_audio_v3)(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_v3_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_recv_free_audio_v3)(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_v3_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_capture_audio_v2)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v3_t* p_audio_data, int sample_rate, int no_channels, int no_samples);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_capture_audio_v2)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v3_t* p_audio_data, int sample_rate, int no_channels, int no_samples);\r\n\t};\r\n\r\n\tunion {\r\n\t\tvoid (*framesync_free_audio_v2)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v3_t* p_audio_data);\r\n\t\tPROCESSINGNDILIB_DEPRECATED void (*NDIlib_framesync_free_audio_v2)(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v3_t* p_audio_data);\r\n\t};\r\n\r\n\tunion {\r\n\t\tint (*framesync_audio_queue_depth)(NDIlib_framesync_instance_t p_instance);\r\n\t\tPROCESSINGNDILIB_DEPRECATED int (*NDIlib_framesync_audio_queue_depth)(NDIlib_framesync_instance_t p_instance);\r\n\t};\r\n\r\n\t// v5\r\n\tunion {\r\n\t\tbool (*recv_ptz_exposure_manual_v2)(NDIlib_recv_instance_t p_instance, const float iris, const float gain, const float shutter_speed);\r\n\t\tPROCESSINGNDILIB_DEPRECATED bool (*NDIlib_recv_ptz_exposure_manual_v2)(NDIlib_recv_instance_t p_instance, const float iris, const float gain, const float shutter_speed);\r\n\t};\r\n\r\n\t// v6.1\r\n\tbool (*util_audio_to_interleaved_16s_v3)(const NDIlib_audio_frame_v3_t* p_src, NDIlib_audio_frame_interleaved_16s_t* p_dst);\r\n\tbool (*util_audio_from_interleaved_16s_v3)(const NDIlib_audio_frame_interleaved_16s_t* p_src, NDIlib_audio_frame_v3_t* p_dst);\r\n\tbool (*util_audio_to_interleaved_32s_v3)(const NDIlib_audio_frame_v3_t* p_src, NDIlib_audio_frame_interleaved_32s_t* p_dst);\r\n\tbool (*util_audio_from_interleaved_32s_v3)(const NDIlib_audio_frame_interleaved_32s_t* p_src, NDIlib_audio_frame_v3_t* p_dst);\r\n\tbool (*util_audio_to_interleaved_32f_v3)(const NDIlib_audio_frame_v3_t* p_src, NDIlib_audio_frame_interleaved_32f_t* p_dst);\r\n\tbool (*util_audio_from_interleaved_32f_v3)(const NDIlib_audio_frame_interleaved_32f_t* p_src, NDIlib_audio_frame_v3_t* p_dst);\r\n\r\n\t// v6.2\r\n\tbool (*recv_get_source_name)(NDIlib_recv_instance_t p_instance, const char** p_source_name, uint32_t timeout_in_ms);\r\n\r\n\tNDIlib_recv_advertiser_instance_t (*recv_advertiser_create)(const NDIlib_recv_advertiser_create_t* p_create_settings);\r\n\tvoid (*recv_advertiser_destroy)(NDIlib_recv_advertiser_instance_t p_instance);\r\n\tbool (*recv_advertiser_add_receiver)(NDIlib_recv_advertiser_instance_t p_instance, NDIlib_recv_instance_t p_receiver, bool allow_controlling, bool allow_monitoring, const char* p_input_group_name);\r\n\tbool (*recv_advertiser_del_receiver)(NDIlib_recv_advertiser_instance_t p_instance, NDIlib_recv_instance_t p_receiver);\r\n\r\n\tNDIlib_recv_listener_instance_t (*recv_listener_create)(const NDIlib_recv_listener_create_t* p_create_settings);\r\n\tvoid (*recv_listener_destroy)(NDIlib_recv_listener_instance_t p_instance);\r\n\tbool (*recv_listener_is_connected)(NDIlib_recv_listener_instance_t p_instance);\r\n\tconst char* (*recv_listener_get_server_url)(NDIlib_recv_listener_instance_t p_instance);\r\n\tconst NDIlib_receiver_t* (*recv_listener_get_receivers)(NDIlib_recv_listener_instance_t p_instance, uint32_t* p_num_receivers);\r\n\tbool (*recv_listener_wait_for_receivers)(NDIlib_recv_listener_instance_t p_instance, uint32_t timeout_in_ms);\r\n\r\n\t// v6.3\r\n\tNDIlib_send_advertiser_instance_t(*send_advertiser_create)(const NDIlib_send_advertiser_create_t* p_create_settings);\r\n\tvoid (*send_advertiser_destroy)(NDIlib_send_advertiser_instance_t p_instance);\r\n\tbool (*send_advertiser_add_sender)(NDIlib_send_advertiser_instance_t p_instance, NDIlib_send_instance_t p_sender, bool allow_monitoring);\r\n\tbool (*send_advertiser_del_sender)(NDIlib_send_advertiser_instance_t p_instance, NDIlib_send_instance_t p_sender);\r\n\r\n\tNDIlib_send_listener_instance_t (*send_listener_create)(const NDIlib_send_listener_create_t* p_create_settings);\r\n\tvoid (*send_listener_destroy)(NDIlib_send_listener_instance_t p_instance);\r\n\tbool (*send_listener_is_connected)(NDIlib_send_listener_instance_t p_instance);\r\n\tconst char* (*send_listener_get_server_url)(NDIlib_send_listener_instance_t p_instance);\r\n\tconst NDIlib_sender_t* (*send_listener_get_senders)(NDIlib_send_listener_instance_t p_instance, uint32_t* p_num_senders);\r\n\tbool (*send_listener_wait_for_senders)(NDIlib_send_listener_instance_t p_instance, uint32_t timeout_in_ms);\r\n} NDIlib_v6_3;\r\n\r\ntypedef struct NDIlib_v6_3 NDIlib_v6;\r\ntypedef struct NDIlib_v6_3 NDIlib_v5;\r\ntypedef struct NDIlib_v6_3 NDIlib_v4_5;\r\ntypedef struct NDIlib_v6_3 NDIlib_v4;\r\ntypedef struct NDIlib_v6_3 NDIlib_v3;\r\ntypedef struct NDIlib_v6_3 NDIlib_v2;\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_v6_3* NDIlib_v6_3_load(void);\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_v6* NDIlib_v6_load(void);\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst NDIlib_v5* NDIlib_v5_load(void);\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst NDIlib_v4_5* NDIlib_v4_5_load(void);\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst NDIlib_v4* NDIlib_v4_load(void);\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst NDIlib_v3* NDIlib_v3_load(void);\r\n\r\n// Load the library.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst NDIlib_v2* NDIlib_v2_load(void);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Find.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// Structures and type definitions required by NDI finding.\r\n// The reference to an instance of the finder.\r\nstruct NDIlib_find_instance_type;\r\ntypedef struct NDIlib_find_instance_type* NDIlib_find_instance_t;\r\n\r\n// The creation structure that is used when you are creating a finder.\r\ntypedef struct NDIlib_find_create_t {\r\n\t// Do we want to include the list of NDI sources that are running on the local machine? If TRUE then\r\n\t// local sources will be visible, if FALSE then they will not.\r\n\tbool show_local_sources;\r\n\r\n\t// Which groups do you want to search in for sources.\r\n\tconst char* p_groups;\r\n\r\n\t// The list of additional IP addresses that exist that we should query for sources on. For instance, if\r\n\t// you want to find the sources on a remote machine that is not on your local sub-net then you can put a\r\n\t// comma separated list of those IP addresses here and those sources will be available locally even\r\n\t// though they are not mDNS discoverable. An example might be \"12.0.0.8,13.0.12.8\". When none is\r\n\t// specified the registry is used.\r\n\t// Default = NULL;\r\n\tconst char* p_extra_ips;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_find_create_t(\r\n\t\tbool show_local_sources_ = true,\r\n\t\tconst char* p_groups_ = NULL,\r\n\t\tconst char* p_extra_ips_ = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_find_create_t;\r\n\r\n//***********************************************************************************************************\r\n// Create a new finder instance. This will return NULL if it fails.\r\nPROCESSINGNDILIB_API\r\nNDIlib_find_instance_t NDIlib_find_create_v2(const NDIlib_find_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// This will destroy an existing finder instance.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_find_destroy(NDIlib_find_instance_t p_instance);\r\n\r\n// This function will recover the current set of sources (i.e. the ones that exist right this second). The\r\n// char* memory buffers returned in NDIlib_source_t are valid until the next call to\r\n// NDIlib_find_get_current_sources or a call to NDIlib_find_destroy. For a given NDIlib_find_instance_t, do\r\n// not call NDIlib_find_get_current_sources asynchronously.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_source_t* NDIlib_find_get_current_sources(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources);\r\n\r\n// This will allow you to wait until the number of online sources have changed.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_find_wait_for_sources(NDIlib_find_instance_t p_instance, uint32_t timeout_in_ms);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.FrameSync.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// It is important when using video to realize that often you are using difference clocks for different parts\r\n// of the signal chain. Within NDI, the sender can send at the clock rate that it wants and the receiver will\r\n// receive it at that rate. The receiver however is very unlikely to share the exact same clock rate in many\r\n// cases. For instance, bear in mind that computer clocks rely on crystals which while all rated for the same\r\n// frequency are still not exact. If you sending computer has an audio clock that it \"thinks\" is 48000Hz, to\r\n// the receiver computer that has a different audio clock this might be 48001Hz or 47998Hz. While these\r\n// differences might appear small they accumulate over time and can cause audio to either slightly drift out\r\n// of sync (it is receiving more audio sample than it needs to play back) or might cause audio glitches\r\n// because it is not receiving enough audio samples. While we have described the situation for audio, the\r\n// same exact problem occurs for video sources; it is commonly thought that this can be solved by simply\r\n// having a \"frame buffer\" and that displaying the \"most recently received video frame\" will solve these\r\n// timing discrepancies. Unfortunately this is not the case and when it is done because of the variance in\r\n// clock timings, it is very common the video will appear the \"jitter\" when the sending and receiving clocks\r\n// are almost in alignment. The solution to these problems is to implement a \"time base corrector\" for the\r\n// video clock which is a device that uses hysteresis to know when the best time is to either drop or insert\r\n// a video frame such that the video is most likely to play back smoothly, and audio should be dynamically\r\n// audio sampled (with a high order resampling filter) to adaptively track any clocking differences.\r\n// Implementing these components is very difficult to get entirely correct under all scenarios and this\r\n// implementation is provided to facilitate this and help people who are building real time video\r\n// applications to receive audio and video without needing to undertake the full complexity of implementing\r\n// such clock devices.\r\n//\r\n// Another way to look at what this class does is that it transforms \"push\" sources (i.e. NDI sources in\r\n// which the data is pushed from the sender to the receiver) into \"pull\" sources in which a host application\r\n// is pulling the data down-stream. The frame-sync automatically tracks all clocks to achieve the best video\r\n// performance doing this operation.\r\n//\r\n// In addition to time-base correction operations, these implementations also will automatically detect and\r\n// correct timing jitter that might occur. This will internally correct for timing anomalies that might be\r\n// caused by network, sender or receiver side timing errors caused by CPU limitations, network bandwidth\r\n// fluctuations, etc...\r\n//\r\n// A very common use of a frame-synchronizer might be if you are displaying video on screen timed to the GPU\r\n// v-sync, you should use such a device to convert from the incoming time-base into the time-base of the GPU.\r\n//\r\n// The following are common times that you want to use a frame-synchronizer\r\n//     Video playback on screen : Yes, you want the clock to be synced with vertical refresh.\r\n//     Audio playback through sound card : Yes you want the clock to be synced with your sound card clock.\r\n//     Video mixing : Yes you want the input video clocks to all be synced to your output video clock.\r\n//     Audio mixing : Yes, you want all input audio clocks to be brought into sync with your output\r\n//                    audio clock.\r\n//     Recording a single channel : No, you want to record the signal in it's raw form without\r\n//                                  any re-clocking.\r\n//     Recording multiple channels : Maybe. If you want to sync some input channels to match a master clock\r\n//                                   so that they can be ISO edited, then you might want a frame-sync.\r\n\r\n// The type instance for a frame-synchronizer.\r\nstruct NDIlib_framesync_instance_type;\r\ntypedef struct NDIlib_framesync_instance_type* NDIlib_framesync_instance_t;\r\n\r\n// Create a frame synchronizer instance that can be used to get frames from a receiver. Once this receiver\r\n// has been bound to a frame-sync then you should use it in order to receive video frames. You can continue\r\n// to use the underlying receiver for other operations (tally, PTZ, etc...). Note that it remains your\r\n// responsibility to destroy the receiver even when a frame-sync is using it. You should always destroy the\r\n// receiver after the frame-sync has been destroyed.\r\n//\r\nPROCESSINGNDILIB_API\r\nNDIlib_framesync_instance_t NDIlib_framesync_create(NDIlib_recv_instance_t p_receiver);\r\n\r\n// Destroy a frame-sync implementation.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_destroy(NDIlib_framesync_instance_t p_instance);\r\n\r\n// This function will pull audio samples from the frame-sync queue. This function will always return data\r\n// immediately, inserting silence if no current audio data is present. You should call this at the rate that\r\n// you want audio and it will automatically adapt the incoming audio signal to match the rate at which you\r\n// are calling by using dynamic audio sampling. Note that you have no obligation that your requested sample\r\n// rate, no channels and no samples match the incoming signal and all combinations of conversions\r\n// are supported.\r\n//\r\n// If you wish to know what the current incoming audio format is, then you can make a call with the\r\n// parameters set to zero and it will then return the associated settings. For instance a call as follows:\r\n//\r\n//     NDIlib_framesync_capture_audio(p_instance, p_audio_data, 0, 0, 0);\r\n//\r\n// will return in p_audio_data the current received audio format if there is one or sample_rate and\r\n// no_channels equal to zero if there is not one. At any time you can specify sample_rate and no_channels as\r\n// zero and it will return the current received audio format.\r\n//\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_capture_audio(\r\n\tNDIlib_framesync_instance_t p_instance,\r\n\tNDIlib_audio_frame_v2_t* p_audio_data,\r\n\tint sample_rate, int no_channels, int no_samples\r\n);\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_capture_audio_v2(\r\n\tNDIlib_framesync_instance_t p_instance,\r\n\tNDIlib_audio_frame_v3_t* p_audio_data,\r\n\tint sample_rate, int no_channels, int no_samples\r\n);\r\n\r\n// Free audio returned by NDIlib_framesync_capture_audio.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_free_audio(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v2_t* p_audio_data);\r\n\r\n// Free audio returned by NDIlib_framesync_capture_audio_v2.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_free_audio_v2(NDIlib_framesync_instance_t p_instance, NDIlib_audio_frame_v3_t* p_audio_data);\r\n\r\n// This function will tell you the approximate current depth of the audio queue to give you an indication\r\n// of the number of audio samples you can request. Note that if you should treat the results of this function\r\n// with some care because in reality the frame-sync API is meant to dynamically resample audio to match the\r\n// rate that you are calling it. If you have an inaccurate clock then this function can be useful.\r\n// for instance :\r\n//\r\n//  while(true)\r\n//  {   int no_samples = NDIlib_framesync_audio_queue_depth(p_instance);\r\n//      NDIlib_framesync_capture_audio( ... );\r\n//      play_audio( ... )\r\n//      NDIlib_framesync_free_audio( ... )\r\n//      inaccurate_sleep( 33ms );\r\n//  }\r\n//\r\n// Obviously because audio is being received in real-time there is no guarantee after the call that the\r\n// number is correct since new samples might have been captured in that time. On synchronous use of this\r\n// function however this will be the minimum number of samples in the queue at any later time until\r\n// NDIlib_framesync_capture_audio is called.\r\n//\r\nPROCESSINGNDILIB_API\r\nint NDIlib_framesync_audio_queue_depth(NDIlib_framesync_instance_t p_instance);\r\n\r\n// This function will pull video samples from the frame-sync queue. This function will always immediately\r\n// return a video sample by using time-base correction. You can specify the desired field type which is then\r\n// used to return the best possible frame. Note that field based frame-synchronization means that the\r\n// frame-synchronizer attempts to match the fielded input phase with the frame requests so that you have the\r\n// most correct possible field ordering on output. Note that the same frame can be returned multiple times.\r\n//\r\n// If no video frame has ever been received, this will return NDIlib_video_frame_v2_t as an empty (all zero)\r\n// structure. The reason for this is that it allows you to determine that there has not yet been any video\r\n// and act accordingly. For instance you might want to display a constant frame output at a particular video\r\n// format, or black.\r\n//\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_capture_video(\r\n\tNDIlib_framesync_instance_t p_instance,\r\n\tNDIlib_video_frame_v2_t* p_video_data,\r\n\tNDIlib_frame_format_type_e field_type NDILIB_CPP_DEFAULT_VALUE(NDIlib_frame_format_type_progressive)\r\n);\r\n\r\n// Free audio returned by NDIlib_framesync_capture_video.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_framesync_free_video(NDIlib_framesync_instance_t p_instance, NDIlib_video_frame_v2_t* p_video_data);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Lib.cplusplus.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n\r\n// C++ implementations of default constructors are here to avoid them needing to be inline with all of the\r\n// rest of the code.\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic push\r\n#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\r\n#endif\r\n\r\n// All the structs used and reasonable defaults are here\r\ninline NDIlib_source_t::NDIlib_source_t(const char* p_ndi_name_, const char* p_url_address_)\r\n\t: p_ndi_name(p_ndi_name_), p_url_address(p_url_address_) {}\r\n\r\ninline NDIlib_video_frame_v2_t::NDIlib_video_frame_v2_t(int xres_, int yres_, NDIlib_FourCC_video_type_e FourCC_, int frame_rate_N_, int frame_rate_D_,\r\n                                                        float picture_aspect_ratio_, NDIlib_frame_format_type_e frame_format_type_,\r\n                                                        int64_t timecode_, uint8_t* p_data_, int line_stride_in_bytes_, const char* p_metadata_, int64_t timestamp_)\r\n\t: xres(xres_), yres(yres_), FourCC(FourCC_), frame_rate_N(frame_rate_N_), frame_rate_D(frame_rate_D_),\r\n\t  picture_aspect_ratio(picture_aspect_ratio_), frame_format_type(frame_format_type_),\r\n\t  timecode(timecode_), p_data(p_data_), line_stride_in_bytes(line_stride_in_bytes_), p_metadata(p_metadata_), timestamp(timestamp_) {}\r\n\r\ninline NDIlib_audio_frame_v2_t::NDIlib_audio_frame_v2_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, float* p_data_,\r\n                                                        int channel_stride_in_bytes_, const char* p_metadata_, int64_t timestamp_)\r\n\t: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),\r\n\t  p_data(p_data_), channel_stride_in_bytes(channel_stride_in_bytes_), p_metadata(p_metadata_), timestamp(timestamp_) {}\r\n\r\ninline NDIlib_audio_frame_v3_t::NDIlib_audio_frame_v3_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_,\r\n                                                        NDIlib_FourCC_audio_type_e FourCC_, uint8_t* p_data_, int channel_stride_in_bytes_,\r\n                                                        const char* p_metadata_, int64_t timestamp_)\r\n\t: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),\r\n\t  FourCC(FourCC_), p_data(p_data_), channel_stride_in_bytes(channel_stride_in_bytes_),\r\n\t  p_metadata(p_metadata_), timestamp(timestamp_) {}\r\n\r\ninline NDIlib_video_frame_t::NDIlib_video_frame_t(int xres_, int yres_, NDIlib_FourCC_video_type_e FourCC_, int frame_rate_N_, int frame_rate_D_,\r\n                                                  float picture_aspect_ratio_, NDIlib_frame_format_type_e frame_format_type_,\r\n                                                  int64_t timecode_, uint8_t* p_data_, int line_stride_in_bytes_)\r\n\t: xres(xres_), yres(yres_), FourCC(FourCC_), frame_rate_N(frame_rate_N_), frame_rate_D(frame_rate_D_),\r\n\t  picture_aspect_ratio(picture_aspect_ratio_), frame_format_type(frame_format_type_),\r\n\t  timecode(timecode_), p_data(p_data_), line_stride_in_bytes(line_stride_in_bytes_) {}\r\n\r\ninline NDIlib_audio_frame_t::NDIlib_audio_frame_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, float* p_data_,\r\n                                                  int channel_stride_in_bytes_)\r\n\t: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),\r\n\t  p_data(p_data_), channel_stride_in_bytes(channel_stride_in_bytes_) {}\r\n\r\ninline NDIlib_metadata_frame_t::NDIlib_metadata_frame_t(int length_, int64_t timecode_, char* p_data_)\r\n\t: length(length_), timecode(timecode_), p_data(p_data_) {}\r\n\r\ninline NDIlib_tally_t::NDIlib_tally_t(bool on_program_, bool on_preview_)\r\n\t: on_program(on_program_), on_preview(on_preview_) {}\r\n\r\ninline NDIlib_listener_event::NDIlib_listener_event(void)\r\n\t: p_uuid(NULL), p_name(NULL), p_value(NULL) {}\r\n\r\ninline NDIlib_routing_create_t::NDIlib_routing_create_t(const char* p_ndi_name_, const char* p_groups_)\r\n\t: p_ndi_name(p_ndi_name_), p_groups(p_groups_) {}\r\n\r\ninline NDIlib_recv_create_v3_t::NDIlib_recv_create_v3_t(const NDIlib_source_t source_to_connect_to_, NDIlib_recv_color_format_e color_format_,\r\n                                                        NDIlib_recv_bandwidth_e bandwidth_, bool allow_video_fields_, const char* p_ndi_name_)\r\n\t: source_to_connect_to(source_to_connect_to_), color_format(color_format_), bandwidth(bandwidth_), allow_video_fields(allow_video_fields_), p_ndi_recv_name(p_ndi_name_) {}\r\n\r\ninline NDIlib_recv_create_t::NDIlib_recv_create_t(const NDIlib_source_t source_to_connect_to_, NDIlib_recv_color_format_e color_format_,\r\n                                                  NDIlib_recv_bandwidth_e bandwidth_, bool allow_video_fields_)\r\n\t: source_to_connect_to(source_to_connect_to_), color_format(color_format_), bandwidth(bandwidth_), allow_video_fields(allow_video_fields_) {}\r\n\r\ninline NDIlib_recv_performance_t::NDIlib_recv_performance_t(void)\r\n\t: video_frames(0), audio_frames(0), metadata_frames(0) {}\r\n\r\ninline NDIlib_recv_queue_t::NDIlib_recv_queue_t(void)\r\n\t: video_frames(0), audio_frames(0), metadata_frames(0) {}\r\n\r\ninline NDIlib_recv_recording_time_t::NDIlib_recv_recording_time_t(void)\r\n\t: no_frames(0), start_time(0), last_time(0) {}\r\n\r\ninline NDIlib_send_create_t::NDIlib_send_create_t(const char* p_ndi_name_, const char* p_groups_, bool clock_video_, bool clock_audio_)\r\n\t: p_ndi_name(p_ndi_name_), p_groups(p_groups_), clock_video(clock_video_), clock_audio(clock_audio_) {}\r\n\r\ninline NDIlib_find_create_t::NDIlib_find_create_t(bool show_local_sources_, const char* p_groups_, const char* p_extra_ips_)\r\n\t: show_local_sources(show_local_sources_), p_groups(p_groups_), p_extra_ips(p_extra_ips_) {}\r\n\r\ninline NDIlib_audio_frame_interleaved_16s_t::NDIlib_audio_frame_interleaved_16s_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, int reference_level_, int16_t* p_data_)\r\n\t: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),\r\n\t  reference_level(reference_level_), p_data(p_data_) {}\r\n\r\ninline NDIlib_audio_frame_interleaved_32s_t::NDIlib_audio_frame_interleaved_32s_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, int reference_level_, int32_t* p_data_)\r\n\t: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_),\r\n\t  reference_level(reference_level_), p_data(p_data_) {}\r\n\r\ninline NDIlib_audio_frame_interleaved_32f_t::NDIlib_audio_frame_interleaved_32f_t(int sample_rate_, int no_channels_, int no_samples_, int64_t timecode_, float* p_data_)\r\n\t: sample_rate(sample_rate_), no_channels(no_channels_), no_samples(no_samples_), timecode(timecode_), p_data(p_data_) {}\r\n\r\ninline NDIlib_recv_advertiser_create_t::NDIlib_recv_advertiser_create_t(const char* p_url_address)\r\n\t: p_url_address(p_url_address) {}\r\n\r\ninline NDIlib_recv_listener_create_t::NDIlib_recv_listener_create_t(const char* p_url_address)\r\n\t: p_url_address(p_url_address) {}\r\n\r\ninline NDIlib_receiver_t::NDIlib_receiver_t(void)\r\n\t: p_uuid(NULL), p_name(NULL), p_input_uuid(NULL), p_input_name(NULL), p_address(NULL),\r\n\t  p_streams(NULL), num_streams(0), p_commands(NULL), num_commands(0), events_subscribed(false) {}\r\n\r\ninline NDIlib_send_advertiser_create_t::NDIlib_send_advertiser_create_t(const char* p_url_address)\r\n\t: p_url_address(p_url_address) {}\r\n\r\ninline NDIlib_send_listener_create_t::NDIlib_send_listener_create_t(const char* p_url_address)\r\n\t: p_url_address(p_url_address) {}\r\n\r\ninline NDIlib_sender_t::NDIlib_sender_t(void)\r\n\t: p_uuid(NULL), p_name(NULL), p_metadata(NULL), p_address(NULL), port(0), p_groups(NULL), num_groups(0), events_subscribed(false) {}\r\n\r\n#ifdef __clang__\r\n#pragma clang diagnostic pop\r\n#endif\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Lib.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n#ifdef PROCESSINGNDILIB_STATIC\r\n#\tifdef __cplusplus\r\n#\t\tdefine PROCESSINGNDILIB_API extern \"C\"\r\n#\telse // __cplusplus\r\n#\t\tdefine PROCESSINGNDILIB_API\r\n#\tendif // __cplusplus\r\n#else // PROCESSINGNDILIB_STATIC\r\n#\tifdef _WIN32\r\n#\t\tifdef PROCESSINGNDILIB_EXPORTS\r\n#\t\t\tifdef __cplusplus\r\n#\t\t\t\tdefine PROCESSINGNDILIB_API extern \"C\" __declspec(dllexport)\r\n#\t\t\telse // __cplusplus\r\n#\t\t\t\tdefine PROCESSINGNDILIB_API __declspec(dllexport)\r\n#\t\t\tendif // __cplusplus\r\n#\t\telse // PROCESSINGNDILIB_EXPORTS\r\n#\t\t\tifdef __cplusplus\r\n#\t\t\t\tdefine PROCESSINGNDILIB_API extern \"C\" __declspec(dllimport)\r\n#\t\t\telse // __cplusplus\r\n#\t\t\t\tdefine PROCESSINGNDILIB_API __declspec(dllimport)\r\n#\t\t\tendif // __cplusplus\r\n#\t\t\tifdef _WIN64\r\n#\t\t\t\tdefine NDILIB_LIBRARY_NAME  \"Processing.NDI.Lib.x64.dll\"\r\n#\t\t\t\tdefine NDILIB_REDIST_FOLDER \"NDI_RUNTIME_DIR_V6\"\r\n#\t\t\t\tdefine NDILIB_REDIST_URL    \"http://ndi.link/NDIRedistV6\"\r\n#\t\t\telse // _WIN64\r\n#\t\t\t\tdefine NDILIB_LIBRARY_NAME  \"Processing.NDI.Lib.x86.dll\"\r\n#\t\t\t\tdefine NDILIB_REDIST_FOLDER \"NDI_RUNTIME_DIR_V6\"\r\n#\t\t\t\tdefine NDILIB_REDIST_URL    \"http://ndi.link/NDIRedistV6\"\r\n#\t\t\tendif // _WIN64\r\n#\t\tendif // PROCESSINGNDILIB_EXPORTS\r\n#\telse // _WIN32\r\n#\t\tifdef __APPLE__\r\n#\t\t\tdefine NDILIB_LIBRARY_NAME  \"libndi.dylib\"\r\n#\t\t\tdefine NDILIB_REDIST_FOLDER \"NDI_RUNTIME_DIR_V6\"\r\n#\t\t\tdefine NDILIB_REDIST_URL    \"http://ndi.link/NDIRedistV6Apple\"\r\n#\t\telse // __APPLE__\r\n#\t\t\tdefine NDILIB_LIBRARY_NAME  \"libndi.so.6\"\r\n#\t\t\tdefine NDILIB_REDIST_FOLDER \"NDI_RUNTIME_DIR_V6\"\r\n#\t\t\tdefine NDILIB_REDIST_URL    \"\"\r\n#\t\tendif // __APPLE__\r\n#\t\tifdef __cplusplus\r\n#\t\t\tdefine PROCESSINGNDILIB_API extern \"C\" __attribute((visibility(\"default\")))\r\n#\t\telse // __cplusplus\r\n#\t\t\tdefine PROCESSINGNDILIB_API __attribute((visibility(\"default\")))\r\n#\t\tendif // __cplusplus\r\n#\tendif // _WIN32\r\n#endif\t// PROCESSINGNDILIB_STATIC\r\n\r\n#ifndef PROCESSINGNDILIB_DEPRECATED\r\n#\tifdef _WIN32\r\n#\t\tifdef _MSC_VER\r\n#\t\t\tdefine PROCESSINGNDILIB_DEPRECATED __declspec(deprecated)\r\n#\t\telse // _MSC_VER\r\n#\t\t\tdefine PROCESSINGNDILIB_DEPRECATED __attribute((deprecated))\r\n#\t\tendif // _MSC_VER\r\n#\telse // _WIN32\r\n#\t\tdefine PROCESSINGNDILIB_DEPRECATED\r\n#\tendif // _WIN32\r\n#endif // PROCESSINGNDILIB_DEPRECATED\r\n\r\n#ifndef NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n#\tifdef __cplusplus\r\n#\t\tdefine NDILIB_CPP_DEFAULT_CONSTRUCTORS 1\r\n#\telse // __cplusplus\r\n#\t\tdefine NDILIB_CPP_DEFAULT_CONSTRUCTORS 0\r\n#\tendif // __cplusplus\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\r\n#ifndef NDILIB_CPP_DEFAULT_VALUE\r\n#\tifdef __cplusplus\r\n#\t\tdefine NDILIB_CPP_DEFAULT_VALUE(a) =(a)\r\n#\telse // __cplusplus\r\n#\t\tdefine NDILIB_CPP_DEFAULT_VALUE(a)\r\n#\tendif // __cplusplus\r\n#endif // NDILIB_CPP_DEFAULT_VALUE\r\n\r\n// Data structures shared by multiple SDKs.\r\n#include \"Processing.NDI.compat.h\"\r\n#include \"Processing.NDI.structs.h\"\r\n\r\n// This is not actually required, but will start and end the libraries which might get you slightly better\r\n// performance in some cases. In general it is more \"correct\" to call these although it is not required.\r\n// There is no way to call these that would have an adverse impact on anything (even calling destroy before\r\n// you've deleted all your objects). This will return false if the CPU is not sufficiently capable to run\r\n// NDILib currently NDILib requires SSE4.2 instructions (see documentation). You can verify a specific CPU\r\n// against the library with a call to NDIlib_is_supported_CPU().\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_initialize(void);\r\n\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_destroy(void);\r\n\r\nPROCESSINGNDILIB_API\r\nconst char* NDIlib_version(void);\r\n\r\n// Recover whether the current CPU in the system is capable of running NDILib.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_is_supported_CPU(void);\r\n\r\n// The finding (discovery API).\r\n#include \"Processing.NDI.Find.h\"\r\n\r\n// The receiving video and audio API.\r\n#include \"Processing.NDI.Recv.h\"\r\n\r\n// Extensions to support PTZ control, etc...\r\n#include \"Processing.NDI.Recv.ex.h\"\r\n\r\n// The receiver advertiser API.\r\n#include \"Processing.NDI.RecvAdvertiser.h\"\r\n\r\n// The receiver listener API.\r\n#include \"Processing.NDI.RecvListener.h\"\r\n\r\n// The sending video API.\r\n#include \"Processing.NDI.Send.h\"\r\n\r\n// The sender advertiser API.\r\n#include \"Processing.NDI.SendAdvertiser.h\"\r\n\r\n// The sender listener API.\r\n#include \"Processing.NDI.SendListener.h\"\r\n\r\n// The routing of inputs API.\r\n#include \"Processing.NDI.Routing.h\"\r\n\r\n// Utility functions.\r\n#include \"Processing.NDI.utilities.h\"\r\n\r\n// Deprecated structures and functions.\r\n#include \"Processing.NDI.deprecated.h\"\r\n\r\n// The frame synchronizer.\r\n#include \"Processing.NDI.FrameSync.h\"\r\n\r\n// Dynamic loading used for OSS libraries.\r\n#include \"Processing.NDI.DynamicLoad.h\"\r\n\r\n// The C++ implementations.\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n#include \"Processing.NDI.Lib.cplusplus.h\"\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Recv.ex.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// Has this receiver got PTZ control. Note that it might take a second or two after the connection for this\r\n// value to be set. To avoid the need to poll this function, you can know when the value of this function\r\n// might have changed when the NDILib_recv_capture* call would return NDIlib_frame_type_status_change.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_is_supported(NDIlib_recv_instance_t p_instance);\r\n\r\n// Has this receiver got recording control. Note that it might take a second or two after the connection for\r\n// this value to be set. To avoid the need to poll this function, you can know when the value of this\r\n// function might have changed when the NDILib_recv_capture* call would return NDIlib_frame_type_status_change.\r\n//\r\n// Note on deprecation of this function:\r\n//   NDI version 4 includes the native ability to record all NDI streams using an external application that\r\n//   is provided with the SDK. This is better in many ways than the internal recording support which only\r\n//   ever supported remotely recording systems and NDI|HX. This functionality will be supported in the SDK\r\n//   for some time although we are recommending that you use the newer support which is more feature rich and\r\n//   supports the recording of all stream types, does not take CPU time to record NDI sources (it does not\r\n//   require any type of re-compression since it can just store the data in the file), it will synchronize\r\n//   all recorders on a system (and cross systems if NTP clock locking is used).\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nbool NDIlib_recv_recording_is_supported(NDIlib_recv_instance_t p_instance);\r\n\r\n// PTZ Controls.\r\n// Zoom to an absolute value.\r\n// zoom_value = 0.0 (zoomed in) ... 1.0 (zoomed out)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_zoom(NDIlib_recv_instance_t p_instance, const float zoom_value);\r\n\r\n// Zoom at a particular speed.\r\n// zoom_speed = -1.0 (zoom outwards) ... +1.0 (zoom inwards)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_zoom_speed(NDIlib_recv_instance_t p_instance, const float zoom_speed);\r\n\r\n// Set the pan and tilt to an absolute value.\r\n// pan_value  = -1.0 (left) ... 0.0 (centered) ... +1.0 (right)\r\n// tilt_value = -1.0 (bottom) ... 0.0 (centered) ... +1.0 (top)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_pan_tilt(NDIlib_recv_instance_t p_instance, const float pan_value, const float tilt_value);\r\n\r\n// Set the pan and tilt direction and speed.\r\n// pan_speed = -1.0 (moving right) ... 0.0 (stopped) ... +1.0 (moving left)\r\n// tilt_speed = -1.0 (down) ... 0.0 (stopped) ... +1.0 (moving up)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_pan_tilt_speed(NDIlib_recv_instance_t p_instance, const float pan_speed, const float tilt_speed);\r\n\r\n// Store the current position, focus, etc... as a preset.\r\n// preset_no = 0 ... 99\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_store_preset(NDIlib_recv_instance_t p_instance, const int preset_no);\r\n\r\n// Recall a preset, including position, focus, etc...\r\n// preset_no = 0 ... 99\r\n// speed = 0.0(as slow as possible) ... 1.0(as fast as possible) The speed at which to move to the new preset.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_recall_preset(NDIlib_recv_instance_t p_instance, const int preset_no, const float speed);\r\n\r\n// Put the camera in auto-focus.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_auto_focus(NDIlib_recv_instance_t p_instance);\r\n\r\n// Focus to an absolute value.\r\n// focus_value = 0.0 (focused to infinity) ... 1.0 (focused as close as possible)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_focus(NDIlib_recv_instance_t p_instance, const float focus_value);\r\n\r\n// Focus at a particular speed.\r\n// focus_speed = -1.0 (focus outwards) ... +1.0 (focus inwards)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_focus_speed(NDIlib_recv_instance_t p_instance, const float focus_speed);\r\n\r\n// Put the camera in auto white balance mode.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_white_balance_auto(NDIlib_recv_instance_t p_instance);\r\n\r\n// Put the camera in indoor white balance.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_white_balance_indoor(NDIlib_recv_instance_t p_instance);\r\n\r\n// Put the camera in indoor white balance.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_white_balance_outdoor(NDIlib_recv_instance_t p_instance);\r\n\r\n// Use the current brightness to automatically set the current white balance.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_white_balance_oneshot(NDIlib_recv_instance_t p_instance);\r\n\r\n// Set the manual camera white balance using the R, B values.\r\n// red = 0.0(not red) ... 1.0(very red)\r\n// blue = 0.0(not blue) ... 1.0(very blue)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_white_balance_manual(NDIlib_recv_instance_t p_instance, const float red, const float blue);\r\n\r\n// Put the camera in auto-exposure mode.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_exposure_auto(NDIlib_recv_instance_t p_instance);\r\n\r\n// Manually set the camera exposure iris.\r\n// exposure_level = 0.0(dark) ... 1.0(light)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_exposure_manual(NDIlib_recv_instance_t p_instance, const float exposure_level);\r\n\r\n// Manually set the camera exposure parameters.\r\n// iris = 0.0(dark) ... 1.0(light)\r\n// gain = 0.0(dark) ... 1.0(light)\r\n// shutter_speed = 0.0(slow) ... 1.0(fast)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_ptz_exposure_manual_v2(\r\n\tNDIlib_recv_instance_t p_instance,\r\n\tconst float iris, const float gain, const float shutter_speed\r\n);\r\n\r\n// Recording control.\r\n// This will start recording.If the recorder was already recording then the message is ignored.A filename is\r\n// passed in as a \"hint\".Since the recorder might already be recording(or might not allow complete\r\n// flexibility over its filename), the filename might or might not be used.If the filename is empty, or not\r\n// present, a name will be chosen automatically. If you do not with to provide a filename hint you can simply\r\n// pass NULL.\r\n//\r\n// See note above on depreciation and why this is, and how to replace this functionality.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nbool NDIlib_recv_recording_start(NDIlib_recv_instance_t p_instance, const char* p_filename_hint);\r\n\r\n// Stop recording.\r\n//\r\n// See note above on depreciation and why this is, and how to replace this functionality.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nbool NDIlib_recv_recording_stop(NDIlib_recv_instance_t p_instance);\r\n\r\n// This will control the audio level for the recording. dB is specified in decibels relative to the reference\r\n// level of the source. Not all recording sources support controlling audio levels.For instance, a digital\r\n// audio device would not be able to avoid clipping on sources already at the wrong level, thus might not\r\n// support this message.\r\n//\r\n// See note above on depreciation and why this is, and how to replace this functionality.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nbool NDIlib_recv_recording_set_audio_level(NDIlib_recv_instance_t p_instance, const float level_dB);\r\n\r\n// This will determine if the source is currently recording. It will return true while recording is in\r\n// progress and false when it is not. Because there is one recorded and multiple people might be connected to\r\n// it, there is a chance that it is recording which was initiated by someone else.\r\n//\r\n// See note above on depreciation and why this is, and how to replace this functionality.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nbool NDIlib_recv_recording_is_recording(NDIlib_recv_instance_t p_instance);\r\n\r\n// Get the current filename for recording. When this is set it will return a non-NULL value which is owned by\r\n// you and freed using NDIlib_recv_free_string. If a file was already being recorded by another client, the\r\n// massage will contain the name of that file. The filename contains a UNC path (when one is available) to\r\n// the recorded file, and can be used to access the file on your local machine for playback.  If a UNC path\r\n// is not available, then this will represent the local filename. This will remain valid even after the file\r\n// has stopped being recorded until the next file is started.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst char* NDIlib_recv_recording_get_filename(NDIlib_recv_instance_t p_instance);\r\n\r\n// This will tell you whether there was a recording error and what that string is. When this is set it will\r\n// return a non-NULL value which is owned by you and freed using NDIlib_recv_free_string. When there is no\r\n// error it will return NULL.\r\n//\r\n// See note above on depreciation and why this is, and how to replace this functionality.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst char* NDIlib_recv_recording_get_error(NDIlib_recv_instance_t p_instance);\r\n\r\n// In order to get the duration.\r\ntypedef struct NDIlib_recv_recording_time_t\r\n{\r\n\t// The number of actual video frames recorded.\r\n\tint64_t no_frames;\r\n\r\n\t// The starting time and current largest time of the record, in UTC time, at 100-nanosecond unit\r\n\t// intervals. This allows you to know the record time irrespective of frame rate. For instance,\r\n\t// last_time - start_time would give you the recording length in 100-nanosecond intervals.\r\n\tint64_t start_time, last_time;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_recording_time_t(void);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_recv_recording_time_t;\r\n\r\n// Get the current recording times.\r\n//\r\n// See note above on depreciation and why this is, and how to replace this functionality.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nbool NDIlib_recv_recording_get_times(NDIlib_recv_instance_t p_instance, NDIlib_recv_recording_time_t* p_times);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Recv.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// Structures and type definitions required by NDI finding.\r\n// The reference to an instance of the receiver.\r\nstruct NDIlib_recv_instance_type;\r\ntypedef struct NDIlib_recv_instance_type* NDIlib_recv_instance_t;\r\n\r\ntypedef enum NDIlib_recv_bandwidth_e {\r\n\tNDIlib_recv_bandwidth_metadata_only = -10, // Receive metadata.\r\n\tNDIlib_recv_bandwidth_audio_only = 10,     // Receive metadata, audio.\r\n\tNDIlib_recv_bandwidth_lowest = 0,          // Receive metadata, audio, video at a lower bandwidth and resolution.\r\n\tNDIlib_recv_bandwidth_highest = 100,       // Receive metadata, audio, video at full resolution.\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_recv_bandwidth_max = 0x7fffffff\r\n} NDIlib_recv_bandwidth_e;\r\n\r\ntypedef enum NDIlib_recv_color_format_e {\r\n\t// When there is no alpha channel, this mode delivers BGRX.\r\n\t// When there is an alpha channel, this mode delivers BGRA.\r\n\tNDIlib_recv_color_format_BGRX_BGRA = 0,\r\n\r\n\t// When there is no alpha channel, this mode delivers UYVY.\r\n\t// When there is an alpha channel, this mode delivers BGRA.\r\n\tNDIlib_recv_color_format_UYVY_BGRA = 1,\r\n\r\n\t// When there is no alpha channel, this mode delivers RGBX.\r\n\t// When there is an alpha channel, this mode delivers RGBA.\r\n\tNDIlib_recv_color_format_RGBX_RGBA = 2,\r\n\r\n\t// When there is no alpha channel, this mode delivers UYVY.\r\n\t// When there is an alpha channel, this mode delivers RGBA.\r\n\tNDIlib_recv_color_format_UYVY_RGBA = 3,\r\n\r\n\t// This format will try to decode the video using the fastest available color format for the incoming\r\n\t// video signal. This format follows the following guidelines, although different platforms might\r\n\t// vary slightly based on their capabilities and specific performance profiles. In general if you want\r\n\t// the best performance this mode should be used.\r\n\t//\r\n\t// When using this format, you should consider than allow_video_fields is true, and individual fields\r\n\t// will always be delivered.\r\n\t//\r\n\t// For most video sources on most platforms, this will follow the following conventions.\r\n\t//      No alpha channel : UYVY\r\n\t//      Alpha channel    : UYVA\r\n\tNDIlib_recv_color_format_fastest = 100,\r\n\r\n\t// This format will try to provide the video in the format that is the closest to native for the incoming\r\n\t// codec yielding the highest quality. Specifically, this allows for receiving on 16bpp color from many\r\n\t// sources.\r\n\t//\r\n\t// When using this format, you should consider than allow_video_fields is true, and individual fields\r\n\t// will always be delivered.\r\n\t//\r\n\t// For most video sources on most platforms, this will follow the following conventions\r\n\t//      No alpha channel : P216, or UYVY\r\n\t//      Alpha channel    : PA16 or UYVA\r\n\tNDIlib_recv_color_format_best = 101,\r\n\r\n\t// Legacy definitions for backwards compatibility.\r\n\tNDIlib_recv_color_format_e_BGRX_BGRA = NDIlib_recv_color_format_BGRX_BGRA,\r\n\tNDIlib_recv_color_format_e_UYVY_BGRA = NDIlib_recv_color_format_UYVY_BGRA,\r\n\tNDIlib_recv_color_format_e_RGBX_RGBA = NDIlib_recv_color_format_RGBX_RGBA,\r\n\tNDIlib_recv_color_format_e_UYVY_RGBA = NDIlib_recv_color_format_UYVY_RGBA,\r\n\r\n#ifdef _WIN32\r\n\t// For Windows we can support flipped images which is unfortunately something that Microsoft decided to\r\n\t// do back in the old days.\r\n\tNDIlib_recv_color_format_BGRX_BGRA_flipped = 1000 + NDIlib_recv_color_format_BGRX_BGRA,\r\n#endif\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_recv_color_format_max = 0x7fffffff\r\n} NDIlib_recv_color_format_e;\r\n\r\n// The creation structure that is used when you are creating a receiver.\r\ntypedef struct NDIlib_recv_create_v3_t {\r\n\t// The source that you wish to connect to.\r\n\tNDIlib_source_t source_to_connect_to;\r\n\r\n\t// Your preference of color space. See above.\r\n\tNDIlib_recv_color_format_e color_format;\r\n\r\n\t// The bandwidth setting that you wish to use for this video source. Bandwidth controlled by changing\r\n\t// both the compression level and the resolution of the source. A good use for low bandwidth is working\r\n\t// on WIFI connections.\r\n\tNDIlib_recv_bandwidth_e bandwidth;\r\n\r\n\t// When this flag is FALSE, all video that you receive will be progressive. For sources that provide\r\n\t// fields, this is de-interlaced on the receiving side (because we cannot change what the up-stream\r\n\t//  source was actually rendering. This is provided as a convenience to down-stream sources that do not\r\n\t// wish to understand fielded video. There is almost no  performance impact of using this function.\r\n\tbool allow_video_fields;\r\n\r\n\t// The name of the NDI receiver to create. This is a NULL terminated UTF8 string and should be the name\r\n\t// of receive channel that you have. This is in many ways symmetric with the name of senders, so this\r\n\t// might be \"Channel 1\" on your system. If this is NULL then it will use the filename of your application\r\n\t// indexed with the number of the instance number of this receiver.\r\n\tconst char* p_ndi_recv_name;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_create_v3_t(\r\n\t\tconst NDIlib_source_t source_to_connect_to_ = NDIlib_source_t(),\r\n\t\tNDIlib_recv_color_format_e color_format_ = NDIlib_recv_color_format_UYVY_BGRA,\r\n\t\tNDIlib_recv_bandwidth_e bandwidth_ = NDIlib_recv_bandwidth_highest,\r\n\t\tbool allow_video_fields_ = true,\r\n\t\tconst char* p_ndi_name_ = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\r\n} NDIlib_recv_create_v3_t;\r\n\r\n\r\n// This allows you determine the current performance levels of the receiving to be able to detect whether\r\n// frames have been dropped.\r\ntypedef struct NDIlib_recv_performance_t {\r\n\t// The number of video frames.\r\n\tint64_t video_frames;\r\n\r\n\t// The number of audio frames.\r\n\tint64_t audio_frames;\r\n\r\n\t// The number of metadata frames.\r\n\tint64_t metadata_frames;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_performance_t(void);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_recv_performance_t;\r\n\r\n// Get the current queue depths.\r\ntypedef struct NDIlib_recv_queue_t {\r\n\t// The number of video frames.\r\n\tint video_frames;\r\n\r\n\t// The number of audio frames.\r\n\tint audio_frames;\r\n\r\n\t// The number of metadata frames.\r\n\tint metadata_frames;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_queue_t(void);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_recv_queue_t;\r\n\r\n//**************************************************************************************************************************\r\n// Create a new receiver instance. This will return NULL if it fails. If you create this with the default\r\n// settings (NULL) then it will automatically determine a receiver name.\r\nPROCESSINGNDILIB_API\r\nNDIlib_recv_instance_t NDIlib_recv_create_v3(const NDIlib_recv_create_v3_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// This will destroy an existing receiver instance.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_destroy(NDIlib_recv_instance_t p_instance);\r\n\r\n// This function allows you to change the connection to another video source, you can also disconnect it by\r\n// specifying a NULL here. This allows you to preserve a receiver without needing to.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_connect(NDIlib_recv_instance_t p_instance, const NDIlib_source_t* p_src NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// This will allow you to receive video, audio and metadata frames. Any of the buffers can be NULL, in which\r\n// case data of that type will not be captured in this call. This call can be called simultaneously on\r\n// separate threads, so it is entirely possible to receive audio, video, metadata all on separate threads.\r\n// This function will return NDIlib_frame_type_none if no data is received within the specified timeout and\r\n// NDIlib_frame_type_error if the connection is lost. Buffers captured with this must be freed with the\r\n// appropriate free function below.\r\nPROCESSINGNDILIB_API\r\nNDIlib_frame_type_e NDIlib_recv_capture_v2(\r\n\tNDIlib_recv_instance_t p_instance,     // The library instance.\r\n\tNDIlib_video_frame_v2_t* p_video_data, // The video data received (can be NULL).\r\n\tNDIlib_audio_frame_v2_t* p_audio_data, // The audio data received (can be NULL).\r\n\tNDIlib_metadata_frame_t* p_metadata,   // The metadata received (can be NULL).\r\n\tuint32_t timeout_in_ms                 // The amount of time in milliseconds to wait for data.\r\n);\r\n\r\n// This will allow you to receive video, audio and metadata frames. Any of the buffers can be NULL, in which\r\n// case data of that type will not be captured in this call. This call can be called simultaneously on\r\n// separate threads, so it is entirely possible to receive audio, video, metadata all on separate threads.\r\n// This function will return NDIlib_frame_type_none if no data is received within the specified timeout and\r\n// NDIlib_frame_type_error if the connection is lost. Buffers captured with this must be freed with the\r\n// appropriate free function below.\r\nPROCESSINGNDILIB_API\r\nNDIlib_frame_type_e NDIlib_recv_capture_v3(\r\n\tNDIlib_recv_instance_t p_instance,     // The library instance.\r\n\tNDIlib_video_frame_v2_t* p_video_data, // The video data received (can be NULL).\r\n\tNDIlib_audio_frame_v3_t* p_audio_data, // The audio data received (can be NULL).\r\n\tNDIlib_metadata_frame_t* p_metadata,   // The metadata received (can be NULL).\r\n\tuint32_t timeout_in_ms                 // The amount of time in milliseconds to wait for data.\r\n);\r\n\r\n// Free the buffers returned by capture for video.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_free_video_v2(NDIlib_recv_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\r\n// Free the buffers returned by capture for audio.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_free_audio_v2(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_v2_t* p_audio_data);\r\n\r\n// Free the buffers returned by capture for audio.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_free_audio_v3(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_v3_t* p_audio_data);\r\n\r\n// Free the buffers returned by capture for metadata.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_free_metadata(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\r\n// This will free a string that was allocated and returned by NDIlib_recv (for instance the\r\n// NDIlib_recv_get_web_control) function.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_free_string(NDIlib_recv_instance_t p_instance, const char* p_string);\r\n\r\n// This function will send a meta message to the source that we are connected too. This returns FALSE if we\r\n// are not currently connected to anything.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_send_metadata(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\r\n// Set the up-stream tally notifications. This returns FALSE if we are not currently connected to anything.\r\n// That said, the moment that we do connect to something it will automatically be sent the tally state.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_set_tally(NDIlib_recv_instance_t p_instance, const NDIlib_tally_t* p_tally);\r\n\r\n// Get the current performance structures. This can be used to determine if you have been calling\r\n// NDIlib_recv_capture fast enough, or if your processing of data is not keeping up with real-time. The total\r\n// structure will give you the total frame counts received, the dropped structure will tell you how many\r\n// frames have been dropped. Either of these could be NULL.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_get_performance(\r\n\tNDIlib_recv_instance_t p_instance,\r\n\tNDIlib_recv_performance_t* p_total, NDIlib_recv_performance_t* p_dropped\r\n);\r\n\r\n// This will allow you to determine the current queue depth for all of the frame sources at any time.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_get_queue(NDIlib_recv_instance_t p_instance, NDIlib_recv_queue_t* p_total);\r\n\r\n// Connection based metadata is data that is sent automatically each time a new connection is received. You\r\n// queue all of these up and they are sent on each connection. To reset them you need to clear them all and\r\n// set them up again.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_clear_connection_metadata(NDIlib_recv_instance_t p_instance);\r\n\r\n// Add a connection metadata string to the list of what is sent on each new connection. If someone is already\r\n// connected then this string will be sent to them immediately.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_add_connection_metadata(NDIlib_recv_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\r\n// Is this receiver currently connected to a source on the other end, or has the source not yet been found or\r\n// is no longer online. This will normally return 0 or 1.\r\nPROCESSINGNDILIB_API\r\nint NDIlib_recv_get_no_connections(NDIlib_recv_instance_t p_instance);\r\n\r\n// Get the URL that might be used for configuration of this input. Note that it might take a second or two\r\n// after the connection for this value to be set. This function will return NULL if there is no web control\r\n// user interface. You should call NDIlib_recv_free_string to free the string that is returned by this\r\n// function. The returned value will be a fully formed URL, for instance \"http://10.28.1.192/configuration/\".\r\n// To avoid the need to poll this function, you can know when the value of this function might have changed\r\n// when the NDILib_recv_capture* call would return NDIlib_frame_type_status_change.\r\nPROCESSINGNDILIB_API\r\nconst char* NDIlib_recv_get_web_control(NDIlib_recv_instance_t p_instance);\r\n\r\n// Retrieve the name of the current NDI source that the NDI receiver is connected to. This will return false\r\n// if there has been no change in the source information since the last call. If p_source_name is NULL, then\r\n// the name of the current NDI source will not be returned. If p_source_name is not NULL, then the name of\r\n// the current source will be returned, however, the returned value can be NULL if the NDI receiver is\r\n// currently not connected to a source. If the returned pointer is not NULL, then you should call\r\n// NDIlib_recv_free_string to free the string that is returned by this function. A timeout value can be given\r\n// to wait until a change occurs. If waiting is not desired, then use a timeout of 0.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_get_source_name(NDIlib_recv_instance_t p_instance, const char** p_source_name, uint32_t timeout_in_ms NDILIB_CPP_DEFAULT_VALUE(0));\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.RecvAdvertiser.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2024 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// The type instance for a receiver advertiser.\r\nstruct NDIlib_recv_advertiser_instance_type;\r\ntypedef struct NDIlib_recv_advertiser_instance_type* NDIlib_recv_advertiser_instance_t;\r\n\r\ntypedef struct NDIlib_recv_advertiser_create_t {\r\n\t// The URL address of the NDI Discovery Server to connect to. If NULL, then the default NDI discovery\r\n\t// server will be used. If there is no discovery server available, then the receiver advertiser will not\r\n\t// be able to be instantiated and the create function will return NULL. The format of this field is\r\n\t// expected to be the hostname or IP address, optionally followed by a colon and a port number. If the\r\n\t// port number is not specified, then port 5959 will be used. For example,\r\n\t//     127.0.0.1:5959\r\n\t//       or\r\n\t//     127.0.0.1\r\n\t//       or\r\n\t//     hostname:5959\r\n\t// This field can also specify multiple addresses separated by commas for redundancy support.\r\n\tconst char* p_url_address;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_advertiser_create_t(\r\n\t\tconst char* p_url_address = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_recv_advertiser_create_t;\r\n\r\n// Create an instance of the receiver advertiser. This will return NULL if it fails to create the advertiser.\r\nPROCESSINGNDILIB_API\r\nNDIlib_recv_advertiser_instance_t NDIlib_recv_advertiser_create(const NDIlib_recv_advertiser_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// Destroy an instance of the receiver advertiser.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_advertiser_destroy(NDIlib_recv_advertiser_instance_t p_instance);\r\n\r\n// Add the receiver to the list of receivers that are being advertised. Returns false if the receiver has\r\n// been previously registered.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_advertiser_add_receiver(\r\n\tNDIlib_recv_advertiser_instance_t p_instance,\r\n\tNDIlib_recv_instance_t p_receiver,\r\n\tbool allow_controlling, bool allow_monitoring,\r\n\tconst char* p_input_group_name NDILIB_CPP_DEFAULT_VALUE(NULL)\r\n);\r\n\r\n// Remove the receiver from the list of receivers that are being advertised. Returns false if the receiver\r\n// was not previously registered.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_advertiser_del_receiver(\r\n\tNDIlib_recv_advertiser_instance_t p_instance,\r\n\tNDIlib_recv_instance_t p_receiver\r\n);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.RecvListener.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2024 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// The type instance for a receiver listener.\r\nstruct NDIlib_recv_listener_instance_type;\r\ntypedef struct NDIlib_recv_listener_instance_type* NDIlib_recv_listener_instance_t;\r\n\r\ntypedef struct NDIlib_recv_listener_create_t {\r\n\t// The URL address of the NDI Discovery Server to connect to. If NULL, then the default NDI discovery\r\n\t// server will be used. If there is no discovery server available, then the receiver listener will not\r\n\t// be able to be instantiated and the create function will return NULL. The format of this field is\r\n\t// expected to be the hostname or IP address, optionally followed by a colon and a port number. If the\r\n\t// port number is not specified, then port 5959 will be used. For example,\r\n\t//     127.0.0.1:5959\r\n\t//       or\r\n\t//     127.0.0.1\r\n\t//       or\r\n\t//     hostname:5959\r\n\t// If this field is a comma-separated list, then only the first address will be used.\r\n\tconst char* p_url_address;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_listener_create_t(\r\n\t\tconst char* p_url_address = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_recv_listener_create_t;\r\n\r\n// Create an instance of the receiver listener. This will return NULL if it fails to create the listener.\r\nPROCESSINGNDILIB_API\r\nNDIlib_recv_listener_instance_t NDIlib_recv_listener_create(const NDIlib_recv_listener_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// Destroy an instance of the receiver listener.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_listener_destroy(NDIlib_recv_listener_instance_t p_instance);\r\n\r\n// Returns true if the receiver listener is actively connected to the configured NDI Discovery Server.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_listener_is_connected(NDIlib_recv_listener_instance_t p_instance);\r\n\r\n// Retrieve the URL address of the NDI Discovery Server that the receiver listener is connected to. This can\r\n// return NULL if the instance pointer is invalid.\r\nPROCESSINGNDILIB_API\r\nconst char* NDIlib_recv_listener_get_server_url(NDIlib_recv_listener_instance_t p_instance);\r\n\r\n// The types of streams that a receiver can receive from the source it's connected to.\r\ntypedef enum NDIlib_receiver_type_e {\r\n\tNDIlib_receiver_type_none = 0,\r\n\tNDIlib_receiver_type_metadata = 1,\r\n\tNDIlib_receiver_type_video = 2,\r\n\tNDIlib_receiver_type_audio = 3,\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_receiver_type_max = 0x7fffffff\r\n} NDIlib_receiver_type_e;\r\n\r\n// The types of commands that a receiver can process.\r\ntypedef enum NDIlib_receiver_command_e {\r\n\tNDIlib_receiver_command_none = 0,\r\n\r\n\t// A receiver can be told to connect to a specific source.\r\n\tNDIlib_receiver_command_connect = 1,\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_receiver_command_max = 0x7fffffff\r\n} NDIlib_receiver_command_e;\r\n\r\n// Describes a receiver that has been discovered.\r\ntypedef struct NDIlib_receiver_t {\r\n\t// The unique identifier for the receiver on the network.\r\n\tconst char* p_uuid;\r\n\r\n\t// The human-readable name of the receiver.\r\n\tconst char* p_name;\r\n\r\n\t// The unique identifier for the input group that the receiver belongs to.\r\n\tconst char* p_input_uuid;\r\n\r\n\t// The human-readable name of the input group that the receiver belongs to.\r\n\tconst char* p_input_name;\r\n\r\n\t// The known IP address of the receiver.\r\n\tconst char* p_address;\r\n\r\n\t// An array of streams that the receiver is set to receive. The last entry in this list will be\r\n\t// NDIlib_receiver_type_none.\r\n\tNDIlib_receiver_type_e* p_streams;\r\n\r\n\t// How many elements are in the p_streams array, excluding the NDIlib_receiver_type_none entry.\r\n\tuint32_t num_streams;\r\n\r\n\t// An array of commands that the receiver can process. The last entry in this list will be\r\n\t// NDIlib_receiver_command_none.\r\n\tNDIlib_receiver_command_e* p_commands;\r\n\r\n\t// How many elements are in the p_commands array, excluding the NDIlib_receiver_command_none entry.\r\n\tuint32_t num_commands;\r\n\r\n\t// Are we currently subscribed for receiver events?\r\n\tbool events_subscribed;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_receiver_t(void);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_receiver_t;\r\n\r\n// Retrieves the current list of advertised receivers. The memory for the returned structure is only valid\r\n// until the next call or when destroy is called. For a given NDIlib_recv_listener_instance_t, do not call\r\n// NDIlib_recv_listener_get_receivers asynchronously.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_receiver_t* NDIlib_recv_listener_get_receivers(NDIlib_recv_listener_instance_t p_instance, uint32_t* p_num_receivers);\r\n\r\n// This will allow you to wait until the number of online receivers has changed.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_listener_wait_for_receivers(NDIlib_recv_listener_instance_t p_instance, uint32_t timeout_in_ms);\r\n\r\n// This will subscribe this listener instance to begin receiving events from the specified receiver.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_listener_subscribe_events(NDIlib_recv_listener_instance_t p_instance, const char* p_receiver_uuid);\r\n\r\n// This will unsubscribe this listener instance from receiving events from the specified receiver.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_listener_unsubscribe_events(NDIlib_recv_listener_instance_t p_instance, const char* p_receiver_uuid);\r\n\r\n// For backwards compatibility.\r\ntypedef NDIlib_listener_event NDIlib_recv_listener_event;\r\n\r\n// Returns a list of the currently pending events for the listener. The events are returned in the order that\r\n// they were received. The timeout value is the amount of time in milliseconds that the function will wait\r\n// for events to be received. If the timeout is 0, then the function will return immediately with any events\r\n// that are currently pending. If the timeout is -1, then the function will wait indefinitely for events to\r\n// be received. The function will return NULL if no events were received within the timeout period. The\r\n// returned events should be freed using NDIlib_recv_listener_free_events().\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_recv_listener_event* NDIlib_recv_listener_get_events(NDIlib_recv_listener_instance_t p_instance, uint32_t* p_num_events, uint32_t timeout_in_ms);\r\n\r\n// Frees the memory allocated for the events returned by NDIlib_recv_listener_get_events().\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_recv_listener_free_events(NDIlib_recv_listener_instance_t p_instance, const NDIlib_recv_listener_event* p_events);\r\n\r\n// Trigger the \"connect\" command to be sent from the listener to the receiver. This will return false if the\r\n// command could not be sent, receiver is unknown, or some other error occurred. If p_source_name is NULL,\r\n// then this would indicate that the receiver should disconnect from its current source. Note that this\r\n// should only be called for a receiver that has NDIlib_receiver_command_connect in its list of commands that\r\n// it can respond to.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_recv_listener_send_connect(NDIlib_recv_listener_instance_t p_instance, const char* p_receiver_uuid, const char* p_source_name);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Routing.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// Structures and type definitions required by NDI routing.\r\n// The reference to an instance of the router.\r\nstruct NDIlib_routing_instance_type;\r\ntypedef struct NDIlib_routing_instance_type* NDIlib_routing_instance_t;\r\n\r\n// The creation structure that is used when you are creating a sender.\r\ntypedef struct NDIlib_routing_create_t\r\n{\r\n\t// The name of the NDI source to create. This is a NULL terminated UTF8 string.\r\n\tconst char* p_ndi_name;\r\n\r\n\t// What groups should this source be part of.\r\n\tconst char* p_groups;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_routing_create_t(const char* p_ndi_name_ = NULL, const char* p_groups_ = NULL);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_routing_create_t;\r\n\r\n// Create an NDI routing source.\r\nPROCESSINGNDILIB_API\r\nNDIlib_routing_instance_t NDIlib_routing_create(const NDIlib_routing_create_t* p_create_settings);\r\n\r\n// Destroy and NDI routing source.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_routing_destroy(NDIlib_routing_instance_t p_instance);\r\n\r\n// Change the routing of this source to another destination.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_routing_change(NDIlib_routing_instance_t p_instance, const NDIlib_source_t* p_source);\r\n\r\n// Change the routing of this source to another destination.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_routing_clear(NDIlib_routing_instance_t p_instance);\r\n\r\n// Get the current number of receivers connected to this source. This can be used to avoid even rendering\r\n// when nothing is connected to the video source. which can significantly improve the efficiency if you want\r\n// to make a lot of sources available on the network. If you specify a timeout that is not 0 then it will\r\n// wait until there are connections for this amount of time.\r\nPROCESSINGNDILIB_API\r\nint NDIlib_routing_get_no_connections(NDIlib_routing_instance_t p_instance, uint32_t timeout_in_ms);\r\n\r\n// Retrieve the source information for the given router instance.  This pointer is valid until\r\n// NDIlib_routing_destroy is called.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_source_t* NDIlib_routing_get_source_name(NDIlib_routing_instance_t p_instance);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.Send.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// Structures and type definitions required by NDI sending.\r\n// The reference to an instance of the sender.\r\nstruct NDIlib_send_instance_type;\r\ntypedef struct NDIlib_send_instance_type* NDIlib_send_instance_t;\r\n\r\n// The creation structure that is used when you are creating a sender.\r\ntypedef struct NDIlib_send_create_t {\r\n\t// The name of the NDI source to create. This is a NULL terminated UTF8 string.\r\n\tconst char* p_ndi_name;\r\n\r\n\t// What groups should this source be part of. NULL means default.\r\n\tconst char* p_groups;\r\n\r\n\t// Do you want audio and video to \"clock\" themselves. When they are clocked then by adding video frames,\r\n\t// they will be rate limited to match the current frame rate that you are submitting at. The same is true\r\n\t// for audio. In general if you are submitting video and audio off a single thread then you should only\r\n\t// clock one of them (video is probably the better of the two to clock off). If you are submitting audio\r\n\t// and video of separate threads then having both clocked can be useful.\r\n\tbool clock_video, clock_audio;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_send_create_t(\r\n\t\tconst char* p_ndi_name_ = NULL,\r\n\t\tconst char* p_groups_ = NULL,\r\n\t\tbool clock_video_ = true, bool clock_audio_ = true\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_send_create_t;\r\n\r\n// Create a new sender instance. This will return NULL if it fails. If you specify leave p_create_settings\r\n// null then the sender will be created with default settings.\r\nPROCESSINGNDILIB_API\r\nNDIlib_send_instance_t NDIlib_send_create(const NDIlib_send_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// This will destroy an existing finder instance.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_destroy(NDIlib_send_instance_t p_instance);\r\n\r\n// This will add a video frame.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_send_video_v2(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\r\n// This will add a video frame and will return immediately, having scheduled the frame to be displayed. All\r\n// processing and sending of the video will occur asynchronously. The memory accessed by NDIlib_video_frame_t\r\n// cannot be freed or re-used by the caller until a synchronizing event has occurred. In general the API is\r\n// better able to take advantage of asynchronous processing than you might be able to by simple having a\r\n// separate thread to submit frames.\r\n//\r\n// This call is particularly beneficial when processing BGRA video since it allows any color conversion,\r\n// compression and network sending to all be done on separate threads from your main rendering thread.\r\n//\r\n// Synchronizing events are :\r\n// - a call to NDIlib_send_send_video\r\n// - a call to NDIlib_send_send_video_async with another frame to be sent\r\n// - a call to NDIlib_send_send_video with p_video_data=NULL\r\n// - a call to NDIlib_send_destroy\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_send_video_async_v2(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_v2_t* p_video_data);\r\n\r\n// This will add an audio frame.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_send_audio_v2(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_v2_t* p_audio_data);\r\n\r\n// This will add an audio frame.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_send_audio_v3(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_v3_t* p_audio_data);\r\n\r\n// This will add a metadata frame.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_send_metadata(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\r\n// This allows you to receive metadata from the other end of the connection.\r\nPROCESSINGNDILIB_API\r\nNDIlib_frame_type_e NDIlib_send_capture(\r\n\tNDIlib_send_instance_t p_instance,   // The instance data.\r\n\tNDIlib_metadata_frame_t* p_metadata, // The metadata received (can be NULL).\r\n\tuint32_t timeout_in_ms               // The amount of time in milliseconds to wait for data.\r\n);\r\n\r\n// Free the buffers returned by capture for metadata.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_free_metadata(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\r\n// Determine the current tally sate. If you specify a timeout then it will wait until it has changed,\r\n// otherwise it will simply poll it and return the current tally immediately. The return value is whether\r\n// anything has actually change (true) or whether it timed out (false)\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_send_get_tally(NDIlib_send_instance_t p_instance, NDIlib_tally_t* p_tally, uint32_t timeout_in_ms);\r\n\r\n// Get the current number of receivers connected to this source. This can be used to avoid even rendering\r\n// when nothing is connected to the video source. which can significantly improve the efficiency if you want\r\n// to make a lot of sources available on the network. If you specify a timeout that is not 0 then it will\r\n// wait until there are connections for this amount of time.\r\nPROCESSINGNDILIB_API\r\nint NDIlib_send_get_no_connections(NDIlib_send_instance_t p_instance, uint32_t timeout_in_ms);\r\n\r\n// Connection based metadata is data that is sent automatically each time a new connection is received. You\r\n// queue all of these up and they are sent on each connection. To reset them you need to clear them all and\r\n// set them up again.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_clear_connection_metadata(NDIlib_send_instance_t p_instance);\r\n\r\n// Add a connection metadata string to the list of what is sent on each new connection. If someone is already\r\n// connected then this string will be sent to them immediately.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_add_connection_metadata(NDIlib_send_instance_t p_instance, const NDIlib_metadata_frame_t* p_metadata);\r\n\r\n// This will assign a new fail-over source for this video source. What this means is that if this video\r\n// source was to fail any receivers would automatically switch over to use this source, unless this source\r\n// then came back online. You can specify NULL to clear the source.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_set_failover(NDIlib_send_instance_t p_instance, const NDIlib_source_t* p_failover_source);\r\n\r\n// Retrieve the source information for the given sender instance.  This pointer is valid until NDIlib_send_destroy is called.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_source_t* NDIlib_send_get_source_name(NDIlib_send_instance_t p_instance);\r\n\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.SendAdvertiser.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2024 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n// \r\n// NOTE: It is very important to note the distinction between the automatic advertising done by the NDI\r\n// sender versus the advertising done with this NDI sender advertiser. The NDI sender will always advertise\r\n// via mDNS or the NDI Discovery Server, depending on how it has been configured. The advertising done within\r\n// this NDI sender advertiser API is strictly through the NDI Discovery Server for monitoring purposes. The\r\n// NDI finder or NDI receiver will not use the advertising from the NDI sender advertiser to locate NDI\r\n// sources in order to know their network endpoints or other information.\r\n// \r\n//***********************************************************************************************************\r\n\r\n// The type instance for a sender advertiser.\r\nstruct NDIlib_send_advertiser_instance_type;\r\ntypedef struct NDIlib_send_advertiser_instance_type* NDIlib_send_advertiser_instance_t;\r\n\r\ntypedef struct NDIlib_send_advertiser_create_t {\r\n\t// The URL address of the NDI Discovery Server to connect to. If NULL, then the default NDI discovery\r\n\t// server will be used. If there is no discovery server available, then the sender advertiser will not\r\n\t// be able to be instantiated and the create function will return NULL. The format of this field is\r\n\t// expected to be the hostname or IP address, optionally followed by a colon and a port number. If the\r\n\t// port number is not specified, then port 5959 will be used. For example,\r\n\t//     127.0.0.1:5959\r\n\t//       or\r\n\t//     127.0.0.1\r\n\t//       or\r\n\t//     hostname:5959\r\n\t// This field can also specify multiple addresses separated by commas for redundancy support.\r\n\tconst char* p_url_address;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_send_advertiser_create_t(\r\n\t\tconst char* p_url_address NDILIB_CPP_DEFAULT_VALUE(NULL)\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_send_advertiser_create_t;\r\n\r\n// Create an instance of the sender advertiser. This will return NULL if it fails to create the advertiser.\r\nPROCESSINGNDILIB_API\r\nNDIlib_send_advertiser_instance_t NDIlib_send_advertiser_create(const NDIlib_send_advertiser_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// Destroy an instance of the sender advertiser.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_advertiser_destroy(NDIlib_send_advertiser_instance_t p_instance);\r\n\r\n// Add the sender to the list of senders that are being advertised. Returns false if the receiver has been\r\n// previously registered.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_send_advertiser_add_sender(\r\n\tNDIlib_send_advertiser_instance_t p_instance,\r\n\tNDIlib_send_instance_t p_sender,\r\n\tbool allow_monitoring\r\n);\r\n\r\n// Remove the sender from the list of senders that are being advertised. Returns false if the sender was not\r\n// previously registered.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_send_advertiser_del_sender(\r\n\tNDIlib_send_advertiser_instance_t p_instance,\r\n\tNDIlib_send_instance_t p_sender\r\n);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.SendListener.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2024 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// The type instance for a sender listener.\r\nstruct NDIlib_send_listener_instance_type;\r\ntypedef struct NDIlib_send_listener_instance_type* NDIlib_send_listener_instance_t;\r\n\r\ntypedef struct NDIlib_send_listener_create_t {\r\n\t// The URL address of the NDI Discovery Server to connect to. If NULL, then the default NDI discovery\r\n\t// server will be used. If there is no discovery server available, then the sender listener will not\r\n\t// be able to be instantiated and the create function will return NULL. The format of this field is\r\n\t// expected to be the hostname or IP address, optionally followed by a colon and a port number. If the\r\n\t// port number is not specified, then port 5959 will be used. For example,\r\n\t//     127.0.0.1:5959\r\n\t//       or\r\n\t//     127.0.0.1\r\n\t//       or\r\n\t//     hostname:5959\r\n\t// If this field is a comma-separated list, then only the first address will be used.\r\n\tconst char* p_url_address;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_send_listener_create_t(\r\n\t\tconst char* p_url_address = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_send_listener_create_t;\r\n\r\n// Create an instance of the sender listener. This will return NULL if it fails to create the listener.\r\nPROCESSINGNDILIB_API\r\nNDIlib_send_listener_instance_t NDIlib_send_listener_create(const NDIlib_send_listener_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// Destroy an instance of the sender listener.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_listener_destroy(NDIlib_send_listener_instance_t p_instance);\r\n\r\n// Returns true if the sender listener is actively connected to the configured NDI Discovery Server.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_send_listener_is_connected(NDIlib_send_listener_instance_t p_instance);\r\n\r\n// Retrieve the URL address of the NDI Discovery Server that the sender listener is connected to. This can\r\n// return NULL if the instance pointer is invalid.\r\nPROCESSINGNDILIB_API\r\nconst char* NDIlib_send_listener_get_server_url(NDIlib_send_listener_instance_t p_instance);\r\n\r\n// Describes a sender that has been discovered.\r\ntypedef struct NDIlib_sender_t {\r\n\t// The unique identifier for the sender on the network.\r\n\tconst char* p_uuid;\r\n\r\n\t// The human-readable name of the sender.\r\n\tconst char* p_name;\r\n\r\n\t// Source metadata for the sender.\r\n\tconst char* p_metadata;\r\n\r\n\t// The known IP address of the sender.\r\n\tconst char* p_address;\r\n\r\n\t// The port number of the sender.\r\n\tint port;\r\n\r\n\t// An array of strings, one for each group that the sender belongs to. The last entry in this list will\r\n\t// be NULL.\r\n\tconst char** p_groups;\r\n\r\n\t// How many elements are in the p_groups array, excluding the NULL terminating entry.\r\n\tuint32_t num_groups;\r\n\r\n\t// Are we currently subscribed for sender events?\r\n\tbool events_subscribed;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_sender_t(void);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_sender_t;\r\n\r\n// Retrieves the current list of advertised senders. The memory for the returned structure is only valid\r\n// until the next call or when destroy is called. For a given NDIlib_send_listener_instance_t, do not call\r\n// NDIlib_send_listener_get_senders asynchronously.\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_sender_t* NDIlib_send_listener_get_senders(NDIlib_send_listener_instance_t p_instance, uint32_t* p_num_senders);\r\n\r\n// This will allow you to wait until the number of online sender has changed.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_send_listener_wait_for_senders(NDIlib_send_listener_instance_t p_instance, uint32_t timeout_in_ms);\r\n\r\n// For backwards compatibility.\r\ntypedef NDIlib_listener_event NDIlib_send_listener_event;\r\n\r\n// This will subscribe this listener instance to begin receiving events from the specified sender.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_listener_subscribe_events(NDIlib_send_listener_instance_t p_instance, const char* p_sender_uuid);\r\n\r\n// This will unsubscribe this listener instance from receiving events from the specified sender.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_listener_unsubscribe_events(NDIlib_send_listener_instance_t p_instance, const char* p_sender_uuid);\r\n\r\n// Returns a list of the currently pending events for the listener. The events are returned in the order that\r\n// they were received. The timeout value is the amount of time in milliseconds that the function will wait\r\n// for events to be received. If the timeout is 0, then the function will return immediately with any events\r\n// that are currently pending. If the timeout is -1, then the function will wait indefinitely for events to\r\n// be received. The function will return NULL if no events were received within the timeout period. The\r\n// returned events should be freed using NDIlib_send_listener_free_events().\r\nPROCESSINGNDILIB_API\r\nconst NDIlib_send_listener_event* NDIlib_send_listener_get_events(NDIlib_send_listener_instance_t p_instance, uint32_t* p_num_events, uint32_t timeout_in_ms);\r\n\r\n// Frees the memory allocated for the events returned by NDIlib_send_listener_get_events().\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_send_listener_free_events(NDIlib_send_listener_instance_t p_instance, const NDIlib_send_listener_event* p_events);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.compat.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n#ifndef __cplusplus\r\n#include <stdbool.h>\r\n#endif\r\n\r\n#include <stdint.h>\r\n\r\n#ifndef INFINITE\r\n//#define INFINITE INFINITE\r\nstatic const uint32_t INFINITE = 0xFFFFFFFF;\r\n#endif\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.deprecated.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// \r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// This describes a video frame\r\nPROCESSINGNDILIB_DEPRECATED\r\ntypedef struct NDIlib_video_frame_t {\r\n\t// The resolution of this frame.\r\n\tint xres, yres;\r\n\r\n\t// What FourCC this is with. This can be two values.\r\n\tNDIlib_FourCC_video_type_e FourCC;\r\n\r\n\t// What is the frame rate of this frame.\r\n\t// For instance NTSC is 30000,1001 = 30000/1001 = 29.97 fps\r\n\tint frame_rate_N, frame_rate_D;\r\n\r\n\t// What is the picture aspect ratio of this frame.\r\n\t// For instance 16.0/9.0 = 1.778 is 16:9 video. If this is zero, then square pixels are assumed (xres/yres).\r\n\tfloat picture_aspect_ratio;\r\n\r\n\t// Is this a fielded frame, or is it progressive.\r\n\tNDIlib_frame_format_type_e frame_format_type;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The video data itself.\r\n\tuint8_t* p_data;\r\n\r\n\t// The inter-line stride of the video data, in bytes.\r\n\tint line_stride_in_bytes;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_video_frame_t(\r\n\t\tint xres_ = 0, int yres_ = 0,\r\n\t\tNDIlib_FourCC_video_type_e FourCC_ = NDIlib_FourCC_type_UYVY,\r\n\t\tint frame_rate_N_ = 30000, int frame_rate_D_ = 1001,\r\n\t\tfloat picture_aspect_ratio_ = 0.0f,\r\n\t\tNDIlib_frame_format_type_e frame_format_type_ = NDIlib_frame_format_type_progressive,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tuint8_t* p_data_ = NULL, int line_stride_in_bytes_ = 0\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_video_frame_t;\r\n\r\n// This describes an audio frame\r\nPROCESSINGNDILIB_DEPRECATED\r\ntypedef struct NDIlib_audio_frame_t {\r\n\t// The sample-rate of this buffer.\r\n\tint sample_rate;\r\n\r\n\t// The number of audio channels.\r\n\tint no_channels;\r\n\r\n\t// The number of audio samples per channel.\r\n\tint no_samples;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The audio data.\r\n\tfloat* p_data;\r\n\r\n\t// The inter channel stride of the audio channels, in bytes.\r\n\tint channel_stride_in_bytes;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_audio_frame_t(\r\n\t\tint sample_rate_ = 48000, int no_channels_ = 2, int no_samples_ = 0,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tfloat* p_data_ = NULL, int channel_stride_in_bytes_ = 0\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_audio_frame_t;\r\n\r\n// For legacy reasons I called this the wrong thing. For backwards compatibility.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nNDIlib_find_instance_t NDIlib_find_create2(const NDIlib_find_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nNDIlib_find_instance_t NDIlib_find_create(const NDIlib_find_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// DEPRECATED. This function is basically exactly the following and was confusing to use.\r\n//    if ((!timeout_in_ms) || (NDIlib_find_wait_for_sources(timeout_in_ms)))\r\n//        return NDIlib_find_get_current_sources(p_instance, p_no_sources);\r\n//    return NULL;\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nconst NDIlib_source_t* NDIlib_find_get_sources(NDIlib_find_instance_t p_instance, uint32_t* p_no_sources, uint32_t timeout_in_ms);\r\n\r\n// The creation structure that is used when you are creating a receiver.\r\nPROCESSINGNDILIB_DEPRECATED\r\ntypedef struct NDIlib_recv_create_t {\r\n\t// The source that you wish to connect to.\r\n\tNDIlib_source_t source_to_connect_to;\r\n\r\n\t// Your preference of color space. See above.\r\n\tNDIlib_recv_color_format_e color_format;\r\n\r\n\t// The bandwidth setting that you wish to use for this video source. Bandwidth\r\n\t// controlled by changing both the compression level and the resolution of the source.\r\n\t// A good use for low bandwidth is working on WIFI connections.\r\n\tNDIlib_recv_bandwidth_e bandwidth;\r\n\r\n\t// When this flag is FALSE, all video that you receive will be progressive. For sources that provide\r\n\t// fields, this is de-interlaced on the receiving side (because we cannot change what the up-stream\r\n\t// source was actually rendering. This is provided as a convenience to down-stream sources that do not\r\n\t// wish to understand fielded video. There is almost no performance impact of using this function.\r\n\tbool allow_video_fields;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_recv_create_t(\r\n\t\tconst NDIlib_source_t source_to_connect_to_ = NDIlib_source_t(),\r\n\t\tNDIlib_recv_color_format_e color_format_ = NDIlib_recv_color_format_UYVY_BGRA,\r\n\t\tNDIlib_recv_bandwidth_e bandwidth_ = NDIlib_recv_bandwidth_highest,\r\n\t\tbool allow_video_fields_ = true\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_recv_create_t;\r\n\r\n// This function is deprecated, please use NDIlib_recv_create_v3 if you can. Using this function will\r\n// continue to work, and be supported for backwards compatibility. If the input parameter is NULL it will be\r\n// created with default settings and an automatically determined receiver name.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nNDIlib_recv_instance_t NDIlib_recv_create_v2(const NDIlib_recv_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// For legacy reasons I called this the wrong thing. For backwards compatibility. If the input parameter is\r\n// NULL it will be created with default settings and an automatically determined receiver name.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nNDIlib_recv_instance_t NDIlib_recv_create2(const NDIlib_recv_create_t* p_create_settings NDILIB_CPP_DEFAULT_VALUE(NULL));\r\n\r\n// This function is deprecated, please use NDIlib_recv_create_v3 if you can. Using this function will\r\n// continue to work, and be supported for backwards compatibility. This version sets bandwidth to highest and\r\n// allow fields to true. If the input parameter is NULL it will be created with default settings and an\r\n// automatically determined receiver name.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nNDIlib_recv_instance_t NDIlib_recv_create(const NDIlib_recv_create_t* p_create_settings);\r\n\r\n// This will allow you to receive video, audio and metadata frames. Any of the buffers can be NULL, in which\r\n// case data of that type will not be captured in this call. This call can be called simultaneously on\r\n// separate threads, so it is entirely possible to receive audio, video, metadata all on separate threads.\r\n// This function will return NDIlib_frame_type_none if no data is received within the specified timeout and\r\n// NDIlib_frame_type_error if the connection is lost. Buffers captured with this must be freed with the\r\n// appropriate free function below.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nNDIlib_frame_type_e NDIlib_recv_capture(\r\n\tNDIlib_recv_instance_t p_instance,   // The library instance.\r\n\tNDIlib_video_frame_t* p_video_data,  // The video data received (can be NULL).\r\n\tNDIlib_audio_frame_t* p_audio_data,  // The audio data received (can be NULL).\r\n\tNDIlib_metadata_frame_t* p_metadata, // The metadata received (can be NULL).\r\n\tuint32_t timeout_in_ms               // The amount of time in milliseconds to wait for data.\r\n);\r\n\r\n// Free the buffers returned by capture for video.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_recv_free_video(NDIlib_recv_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\r\n// Free the buffers returned by capture for audio.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_recv_free_audio(NDIlib_recv_instance_t p_instance, const NDIlib_audio_frame_t* p_audio_data);\r\n\r\n// This will add a video frame.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_send_send_video(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\r\n// This will add a video frame and will return immediately, having scheduled the frame to be displayed. All\r\n// processing and sending of the video will occur asynchronously. The memory accessed by NDIlib_video_frame_t\r\n// cannot be freed or re-used by the caller until a synchronizing event has occurred. In general the API is\r\n// better able to take advantage of asynchronous processing than you might be able to by simple having a\r\n// separate thread to submit frames.\r\n//\r\n// This call is particularly beneficial when processing BGRA video since it allows any color conversion,\r\n// compression and network sending to all be done on separate threads from your main rendering thread.\r\n//\r\n// Synchronizing events are :\r\n// - a call to NDIlib_send_send_video\r\n// - a call to NDIlib_send_send_video_async with another frame to be sent\r\n// - a call to NDIlib_send_send_video with p_video_data=NULL\r\n// - a call to NDIlib_send_destroy\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_send_send_video_async(NDIlib_send_instance_t p_instance, const NDIlib_video_frame_t* p_video_data);\r\n\r\n// This will add an audio frame\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_send_send_audio(NDIlib_send_instance_t p_instance, const NDIlib_audio_frame_t* p_audio_data);\r\n\r\n// Convert an planar floating point audio buffer into a interleaved short audio buffer.\r\n// IMPORTANT : You must allocate the space for the samples in the destination to allow for your own memory management.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_util_audio_to_interleaved_16s(const NDIlib_audio_frame_t* p_src, NDIlib_audio_frame_interleaved_16s_t* p_dst);\r\n\r\n// Convert an interleaved short audio buffer audio buffer into a planar floating point one.\r\n// IMPORTANT : You must allocate the space for the samples in the destination to allow for your own memory management.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_util_audio_from_interleaved_16s(const NDIlib_audio_frame_interleaved_16s_t* p_src, NDIlib_audio_frame_t* p_dst);\r\n\r\n// Convert an planar floating point audio buffer into a interleaved floating point audio buffer.\r\n// IMPORTANT : You must allocate the space for the samples in the destination to allow for your own memory management.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_util_audio_to_interleaved_32f(const NDIlib_audio_frame_t* p_src, NDIlib_audio_frame_interleaved_32f_t* p_dst);\r\n\r\n// Convert an interleaved floating point audio buffer into a planar floating point one.\r\n// IMPORTANT : You must allocate the space for the samples in the destination to allow for your own memory management.\r\nPROCESSINGNDILIB_API PROCESSINGNDILIB_DEPRECATED\r\nvoid NDIlib_util_audio_from_interleaved_32f(const NDIlib_audio_frame_interleaved_32f_t* p_src, NDIlib_audio_frame_t* p_dst);\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.structs.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n#ifndef NDI_LIB_FOURCC\r\n#define NDI_LIB_FOURCC(ch0, ch1, ch2, ch3) \\\r\n\t((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) | ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24))\r\n#endif\r\n\r\n// An enumeration to specify the type of a packet returned by the functions.\r\ntypedef enum NDIlib_frame_type_e {\r\n\t// What frame type is this?\r\n\tNDIlib_frame_type_none = 0,\r\n\tNDIlib_frame_type_video = 1,\r\n\tNDIlib_frame_type_audio = 2,\r\n\tNDIlib_frame_type_metadata = 3,\r\n\tNDIlib_frame_type_error = 4,\r\n\r\n\t// This indicates that the settings on this input have changed. This value will be returned from one of\r\n\t// the NDIlib_recv_capture functions when the device is known to have new settings, for instance the web\r\n\t// URL has changed or the device is now known to be a PTZ camera.\r\n\tNDIlib_frame_type_status_change = 100,\r\n\r\n\t// This indicates that the source has changed. This value will be returned from one of the\r\n\t// NDIlib_recv_capture functions when the source that the receiver is connected to has changed.\r\n\tNDIlib_frame_type_source_change = 101,\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_frame_type_max = 0x7fffffff\r\n} NDIlib_frame_type_e;\r\n\r\n// FourCC values for video frames.\r\ntypedef enum NDIlib_FourCC_video_type_e {\r\n\t// YCbCr color space using 4:2:2.\r\n\tNDIlib_FourCC_video_type_UYVY = NDI_LIB_FOURCC('U', 'Y', 'V', 'Y'),\r\n\tNDIlib_FourCC_type_UYVY = NDIlib_FourCC_video_type_UYVY,\r\n\r\n\t// YCbCr + Alpha color space, using 4:2:2:4.\r\n\t// In memory there are two separate planes. The first is a regular\r\n\t// UYVY 4:2:2 buffer. Immediately following this in memory is a\r\n\t// alpha channel buffer.\r\n\tNDIlib_FourCC_video_type_UYVA = NDI_LIB_FOURCC('U', 'Y', 'V', 'A'),\r\n\tNDIlib_FourCC_type_UYVA = NDIlib_FourCC_video_type_UYVA,\r\n\r\n\t// YCbCr color space using 4:2:2 in 16bpp.\r\n\t// In memory this is a semi-planar format. This is identical to a 16bpp version of the NV16 format.\r\n\t// The first buffer is a 16bpp luminance buffer.\r\n\t// Immediately after this is an interleaved buffer of 16bpp Cb, Cr pairs.\r\n\tNDIlib_FourCC_video_type_P216 = NDI_LIB_FOURCC('P', '2', '1', '6'),\r\n\tNDIlib_FourCC_type_P216 = NDIlib_FourCC_video_type_P216,\r\n\r\n\t// YCbCr color space with an alpha channel, using 4:2:2:4.\r\n\t// In memory this is a semi-planar format.\r\n\t// The first buffer is a 16bpp luminance buffer.\r\n\t// Immediately after this is an interleaved buffer of 16bpp Cb, Cr pairs.\r\n\t// Immediately after is a single buffer of 16bpp alpha channel.\r\n\tNDIlib_FourCC_video_type_PA16 = NDI_LIB_FOURCC('P', 'A', '1', '6'),\r\n\tNDIlib_FourCC_type_PA16 = NDIlib_FourCC_video_type_PA16,\r\n\r\n\t// Planar 8bit 4:2:0 video format.\r\n\t// The first buffer is an 8bpp luminance buffer.\r\n\t// Immediately following this is a 8bpp Cr buffer.\r\n\t// Immediately following this is a 8bpp Cb buffer.\r\n\tNDIlib_FourCC_video_type_YV12 = NDI_LIB_FOURCC('Y', 'V', '1', '2'),\r\n\tNDIlib_FourCC_type_YV12 = NDIlib_FourCC_video_type_YV12,\r\n\r\n\t// The first buffer is an 8bpp luminance buffer.\r\n\t// Immediately following this is a 8bpp Cb buffer.\r\n\t// Immediately following this is a 8bpp Cr buffer.\r\n\tNDIlib_FourCC_video_type_I420 = NDI_LIB_FOURCC('I', '4', '2', '0'),\r\n\tNDIlib_FourCC_type_I420 = NDIlib_FourCC_video_type_I420,\r\n\r\n\t// Planar 8bit 4:2:0 video format.\r\n\t// The first buffer is an 8bpp luminance buffer.\r\n\t// Immediately following this is in interleaved buffer of 8bpp Cb, Cr pairs\r\n\tNDIlib_FourCC_video_type_NV12 = NDI_LIB_FOURCC('N', 'V', '1', '2'),\r\n\tNDIlib_FourCC_type_NV12 = NDIlib_FourCC_video_type_NV12,\r\n\r\n\t// Planar 8bit, 4:4:4:4 video format.\r\n\t// Color ordering in memory is blue, green, red, alpha\r\n\tNDIlib_FourCC_video_type_BGRA = NDI_LIB_FOURCC('B', 'G', 'R', 'A'),\r\n\tNDIlib_FourCC_type_BGRA = NDIlib_FourCC_video_type_BGRA,\r\n\r\n\t// Planar 8bit, 4:4:4 video format, packed into 32bit pixels.\r\n\t// Color ordering in memory is blue, green, red, 255\r\n\tNDIlib_FourCC_video_type_BGRX = NDI_LIB_FOURCC('B', 'G', 'R', 'X'),\r\n\tNDIlib_FourCC_type_BGRX = NDIlib_FourCC_video_type_BGRX,\r\n\r\n\t// Planar 8bit, 4:4:4:4 video format.\r\n\t// Color ordering in memory is red, green, blue, alpha\r\n\tNDIlib_FourCC_video_type_RGBA = NDI_LIB_FOURCC('R', 'G', 'B', 'A'),\r\n\tNDIlib_FourCC_type_RGBA = NDIlib_FourCC_video_type_RGBA,\r\n\r\n\t// Planar 8bit, 4:4:4 video format, packed into 32bit pixels.\r\n\t// Color ordering in memory is red, green, blue, 255.\r\n\tNDIlib_FourCC_video_type_RGBX = NDI_LIB_FOURCC('R', 'G', 'B', 'X'),\r\n\tNDIlib_FourCC_type_RGBX = NDIlib_FourCC_video_type_RGBX,\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_FourCC_video_type_max = 0x7fffffff\r\n} NDIlib_FourCC_video_type_e;\r\n\r\n// Really for backwards compatibility.\r\nPROCESSINGNDILIB_DEPRECATED\r\ntypedef NDIlib_FourCC_video_type_e NDIlib_FourCC_type_e;\r\n\r\n// FourCC values for audio frames.\r\ntypedef enum NDIlib_FourCC_audio_type_e {\r\n\t// Planar 32-bit floating point. Be sure to specify the channel stride.\r\n\tNDIlib_FourCC_audio_type_FLTP = NDI_LIB_FOURCC('F', 'L', 'T', 'p'),\r\n\tNDIlib_FourCC_type_FLTP = NDIlib_FourCC_audio_type_FLTP,\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_FourCC_audio_type_max = 0x7fffffff\r\n} NDIlib_FourCC_audio_type_e;\r\n\r\ntypedef enum NDIlib_frame_format_type_e {\r\n\t// A progressive frame.\r\n\tNDIlib_frame_format_type_progressive = 1,\r\n\r\n\t// A fielded frame with the field 0 being on the even lines and field 1 being\r\n\t// on the odd lines.\r\n\tNDIlib_frame_format_type_interleaved = 0,\r\n\r\n\t// Individual fields.\r\n\tNDIlib_frame_format_type_field_0 = 2,\r\n\tNDIlib_frame_format_type_field_1 = 3,\r\n\r\n\t// Make sure this is a 32-bit enumeration.\r\n\tNDIlib_frame_format_type_max = 0x7fffffff\r\n} NDIlib_frame_format_type_e;\r\n\r\n// When you specify this as a timecode, the timecode will be synthesized for you. This may be used when\r\n// sending video, audio or metadata. If you never specify a timecode at all, asking for each to be\r\n// synthesized, then this will use the current system time as the starting timecode and then generate\r\n// synthetic ones, keeping your streams exactly in sync as long as the frames you are sending do not deviate\r\n// from the system time in any meaningful way. In practice this means that if you never specify timecodes\r\n// that they will always be generated for you correctly. Timecodes coming from different senders on the same\r\n// machine will always be in sync with each other when working in this way. If you have NTP installed on your\r\n// local network, then streams can be synchronized between multiple machines with very high precision.\r\n//\r\n// If you specify a timecode at a particular frame (audio or video), then ask for all subsequent ones to be\r\n// synthesized. The subsequent ones will be generated to continue this sequence maintaining the correct\r\n// relationship both the between streams and samples generated, avoiding them deviating in time from the\r\n// timecode that you specified in any meaningful way.\r\n//\r\n// If you specify timecodes on one stream (e.g. video) and ask for the other stream (audio) to be\r\n// synthesized, the correct timecodes will be generated for the other stream and will be synthesize exactly\r\n// to match (they are not quantized inter-streams) the correct sample positions.\r\n//\r\n// When you send metadata messages and ask for the timecode to be synthesized, then it is chosen to match the\r\n// closest audio or video frame timecode so that it looks close to something you might want ... unless there\r\n// is no sample that looks close in which a timecode is synthesized from the last ones known and the time\r\n// since it was sent.\r\nstatic const int64_t NDIlib_send_timecode_synthesize = INT64_MAX;\r\n\r\n// If the time-stamp is not available (i.e. a version of a sender before v2.5).\r\nstatic const int64_t NDIlib_recv_timestamp_undefined = INT64_MAX;\r\n\r\n// This is a descriptor of a NDI source available on the network.\r\ntypedef struct NDIlib_source_t {\r\n\t// A UTF8 string that provides a user readable name for this source. This can be used for serialization,\r\n\t// etc... and comprises the machine name and the source name on that machine. In the form,\r\n\t//     MACHINE_NAME (NDI_SOURCE_NAME)\r\n\t// If you specify this parameter either as NULL, or an EMPTY string then the specific IP address and port\r\n\t// number from below is used.\r\n\tconst char* p_ndi_name;\r\n\r\n\t// A UTF8 string that provides the actual network address and any parameters. This is not meant to be\r\n\t// application readable and might well change in the future. This can be NULL if you do not know it and\r\n\t// the API internally will instantiate a finder that is used to discover it even if it is not yet\r\n\t// available on the network.\r\n\tunion {\t// The current way of addressing the value.\r\n\t\tconst char* p_url_address;\r\n\r\n\t\t// We used to use an IP address before we used the more general URL notification this is now\r\n\t\t// depreciated but maintained for compatibility.\r\n\t\tPROCESSINGNDILIB_DEPRECATED const char* p_ip_address;\r\n\t};\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_source_t(const char* p_ndi_name_ = NULL, const char* p_url_address_ = NULL);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_source_t;\r\n\r\n// This describes a video frame.\r\ntypedef struct NDIlib_video_frame_v2_t {\r\n\t// The resolution of this frame.\r\n\tint xres, yres;\r\n\r\n\t// What FourCC describing the type of data for this frame.\r\n\tNDIlib_FourCC_video_type_e FourCC;\r\n\r\n\t// What is the frame rate of this frame.\r\n\t// For instance NTSC is 30000,1001 = 30000/1001 = 29.97 fps.\r\n\tint frame_rate_N, frame_rate_D;\r\n\r\n\t// What is the picture aspect ratio of this frame.\r\n\t// For instance 16.0/9.0 = 1.778 is 16:9 video\r\n\t// 0 means square pixels.\r\n\tfloat picture_aspect_ratio;\r\n\r\n\t// Is this a fielded frame, or is it progressive.\r\n\tNDIlib_frame_format_type_e frame_format_type;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The video data itself.\r\n\tuint8_t* p_data;\r\n\r\n\tunion {\t// If the FourCC is not a compressed type, then this will be the inter-line stride of the video data\r\n\t\t// in bytes.  If the stride is 0, then it will default to sizeof(one pixel)*xres.\r\n\t\tint line_stride_in_bytes;\r\n\r\n\t\t// If the FourCC is a compressed type, then this will be the size of the p_data buffer in bytes.\r\n\t\tint data_size_in_bytes;\r\n\t};\r\n\r\n\t// Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be in XML format.\r\n\t// If you do not want any metadata then you may specify NULL here.\r\n\tconst char* p_metadata; // Present in >= v2.5\r\n\r\n\t// This is only valid when receiving a frame and is specified as a 100-nanosecond time that was the exact\r\n\t// moment that the frame was submitted by the sending side and is generated by the SDK. If this value is\r\n\t// NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.\r\n\tint64_t timestamp; // Present in >= v2.5\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_video_frame_v2_t(\r\n\t\tint xres_ = 0, int yres_ = 0,\r\n\t\tNDIlib_FourCC_video_type_e FourCC_ = NDIlib_FourCC_video_type_UYVY,\r\n\t\tint frame_rate_N_ = 30000, int frame_rate_D_ = 1001,\r\n\t\tfloat picture_aspect_ratio_ = 0.0f,\r\n\t\tNDIlib_frame_format_type_e frame_format_type_ = NDIlib_frame_format_type_progressive,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tuint8_t* p_data_ = NULL, int line_stride_in_bytes_ = 0,\r\n\t\tconst char* p_metadata_ = NULL,\r\n\t\tint64_t timestamp_ = 0\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_video_frame_v2_t;\r\n\r\n// This describes an audio frame.\r\ntypedef struct NDIlib_audio_frame_v2_t {\r\n\t// The sample-rate of this buffer.\r\n\tint sample_rate;\r\n\r\n\t// The number of audio channels.\r\n\tint no_channels;\r\n\r\n\t// The number of audio samples per channel.\r\n\tint no_samples;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The audio data.\r\n\tfloat* p_data;\r\n\r\n\t// The inter channel stride of the audio channels, in bytes.\r\n\tint channel_stride_in_bytes;\r\n\r\n\t// Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be in XML format.\r\n\t// If you do not want any metadata then you may specify NULL here.\r\n\tconst char* p_metadata; // Present in >= v2.5\r\n\r\n\t// This is only valid when receiving a frame and is specified as a 100-nanosecond time that was the exact\r\n\t// moment that the frame was submitted by the sending side and is generated by the SDK. If this value is\r\n\t// NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.\r\n\tint64_t timestamp; // Present in >= v2.5\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_audio_frame_v2_t(\r\n\t\tint sample_rate_ = 48000, int no_channels_ = 2, int no_samples_ = 0,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tfloat* p_data_ = NULL, int channel_stride_in_bytes_ = 0,\r\n\t\tconst char* p_metadata_ = NULL,\r\n\t\tint64_t timestamp_ = 0\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_audio_frame_v2_t;\r\n\r\n// This describes an audio frame.\r\ntypedef struct NDIlib_audio_frame_v3_t {\r\n\t// The sample-rate of this buffer.\r\n\tint sample_rate;\r\n\r\n\t// The number of audio channels.\r\n\tint no_channels;\r\n\r\n\t// The number of audio samples per channel.\r\n\tint no_samples;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// What FourCC describing the type of data for this frame.\r\n\tNDIlib_FourCC_audio_type_e FourCC;\r\n\r\n\t// The audio data.\r\n\tuint8_t* p_data;\r\n\r\n\tunion {\r\n\t\t// If the FourCC is not a compressed type and the audio format is planar, then this will be the\r\n\t\t// stride in bytes for a single channel.\r\n\t\tint channel_stride_in_bytes;\r\n\r\n\t\t// If the FourCC is a compressed type, then this will be the size of the p_data buffer in bytes.\r\n\t\tint data_size_in_bytes;\r\n\t};\r\n\r\n\t// Per frame metadata for this frame. This is a NULL terminated UTF8 string that should be in XML format.\r\n\t// If you do not want any metadata then you may specify NULL here.\r\n\tconst char* p_metadata;\r\n\r\n\t// This is only valid when receiving a frame and is specified as a 100-nanosecond time that was the exact\r\n\t// moment that the frame was submitted by the sending side and is generated by the SDK. If this value is\r\n\t// NDIlib_recv_timestamp_undefined then this value is not available and is NDIlib_recv_timestamp_undefined.\r\n\tint64_t timestamp;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_audio_frame_v3_t(\r\n\t\tint sample_rate_ = 48000, int no_channels_ = 2, int no_samples_ = 0,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tNDIlib_FourCC_audio_type_e FourCC_ = NDIlib_FourCC_audio_type_FLTP,\r\n\t\tuint8_t* p_data_ = NULL, int channel_stride_in_bytes_ = 0,\r\n\t\tconst char* p_metadata_ = NULL,\r\n\t\tint64_t timestamp_ = 0\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_audio_frame_v3_t;\r\n\r\n// The data description for metadata.\r\ntypedef struct NDIlib_metadata_frame_t {\r\n\t// The length of the string in UTF8 characters. This includes the NULL terminating character. If this is\r\n\t// 0, then the length is assume to be the length of a NULL terminated string.\r\n\tint length;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The metadata as a UTF8 XML string. This is a NULL terminated string.\r\n\tchar* p_data;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_metadata_frame_t(int length_ = 0, int64_t timecode_ = NDIlib_send_timecode_synthesize, char* p_data_ = NULL);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_metadata_frame_t;\r\n\r\n// Tally structures\r\ntypedef struct NDIlib_tally_t {\r\n\t// Is this currently on program output.\r\n\tbool on_program;\r\n\r\n\t// Is this currently on preview output.\r\n\tbool on_preview;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_tally_t(bool on_program_ = false, bool on_preview_ = false);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_tally_t;\r\n\r\n// This represents the base type of an event received from a sender or receiver listener.\r\ntypedef struct NDIlib_listener_event {\r\n\t// The unique identifier for the receiver/sender that triggered the event.\r\n\tconst char* p_uuid;\r\n\r\n\t// The name of the event that was triggered.\r\n\tconst char* p_name;\r\n\r\n\t// The value of the event that was triggered.\r\n\tconst char* p_value;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_listener_event(void);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_listener_event;\r\n"
  },
  {
    "path": "src/modules/newtek/interop/Processing.NDI.utilities.h",
    "content": "#pragma once\r\n\r\n// NOTE : The following MIT license applies to this file ONLY and not to the SDK as a whole. Please review\r\n// the SDK documentation for the description of the full license terms, which are also provided in the file\r\n// \"NDI License Agreement.pdf\" within the SDK or online at http://ndi.link/ndisdk_license. Your use of any\r\n// part of this SDK is acknowledgment that you agree to the SDK license terms. The full NDI SDK may be\r\n// downloaded at http://ndi.video/\r\n//\r\n//***********************************************************************************************************\r\n//\r\n// Copyright (C) 2023-2026 Vizrt NDI AB. All rights reserved.\r\n//\r\n// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and\r\n// associated documentation files(the \"Software\"), to deal in the Software without restriction, including\r\n// without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell\r\n// copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the\r\n// following conditions :\r\n//\r\n// The above copyright notice and this permission notice shall be included in all copies or substantial\r\n// portions of the Software.\r\n//\r\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\r\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\r\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r\n// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR\r\n// THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n//\r\n//***********************************************************************************************************\r\n\r\n// Because many applications like submitting 16-bit interleaved audio, these functions will convert in and\r\n// out of that format. It is important to note that the NDI SDK does define fully audio levels, something\r\n// that most applications that you use do not. Specifically, the floating-point range, -1.0 to +1.0, is\r\n// defined as a professional audio reference level of +4 dBU. If we take 16-bit audio and scale it into this\r\n// range it is almost always correct for sending and will cause no problems. For receiving however it is not\r\n// at all uncommon that the user has audio that exceeds reference level and in this case it is likely that\r\n// audio exceeds the reference level and so if you are not careful you will end up having audio clipping when\r\n// you use the 16-bit range.\r\n\r\n// This describes an audio frame.\r\ntypedef struct NDIlib_audio_frame_interleaved_16s_t {\r\n\t// The sample-rate of this buffer.\r\n\tint sample_rate;\r\n\r\n\t// The number of audio channels.\r\n\tint no_channels;\r\n\r\n\t// The number of audio samples per channel.\r\n\tint no_samples;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The audio reference level in dB. This specifies how many dB above the reference level (+4 dBU) is the\r\n\t// full range of 16-bit audio. If you do not understand this and want to just use numbers:\r\n\t// - If you are sending audio, specify +0 dB. Most common applications produce audio at reference level.\r\n\t// - If receiving audio, specify +20 dB. This means that the full 16-bit range corresponds to\r\n\t//   professional level audio with 20 dB of headroom. Note that if you are writing it into a file it\r\n\t//   might sound soft because you have 20 dB of headroom before clipping.\r\n\tint reference_level;\r\n\r\n\t// The audio data, interleaved 16-bit samples.\r\n\tint16_t* p_data;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_audio_frame_interleaved_16s_t(\r\n\t\tint sample_rate_ = 48000, int no_channels_ = 2, int no_samples_ = 0,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tint reference_level_ = 0,\r\n\t\tint16_t* p_data_ = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_audio_frame_interleaved_16s_t;\r\n\r\n// This describes an audio frame.\r\ntypedef struct NDIlib_audio_frame_interleaved_32s_t {\r\n\t// The sample-rate of this buffer.\r\n\tint sample_rate;\r\n\r\n\t// The number of audio channels.\r\n\tint no_channels;\r\n\r\n\t// The number of audio samples per channel.\r\n\tint no_samples;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The audio reference level in dB. This specifies how many dB above the reference level (+4 dBU) is the\r\n\t// full range of 32-bit audio. If you do not understand this and want to just use numbers:\r\n\t// - If you are sending audio, specify +0 dB. Most common applications produce audio at reference level.\r\n\t// - If receiving audio, specify +20 dB. This means that the full 32-bit range corresponds to\r\n\t//   professional level audio with 20 dB of headroom. Note that if you are writing it into a file it\r\n\t//   might sound soft because you have 20 dB of headroom before clipping.\r\n\tint reference_level;\r\n\r\n\t// The audio data, interleaved 32-bit samples.\r\n\tint32_t* p_data;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_audio_frame_interleaved_32s_t(\r\n\t\tint sample_rate_ = 48000, int no_channels_ = 2, int no_samples_ = 0,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tint reference_level_ = 0,\r\n\t\tint32_t* p_data_ = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_audio_frame_interleaved_32s_t;\r\n\r\n// This describes an audio frame.\r\ntypedef struct NDIlib_audio_frame_interleaved_32f_t {\r\n\t// The sample-rate of this buffer.\r\n\tint sample_rate;\r\n\r\n\t// The number of audio channels.\r\n\tint no_channels;\r\n\r\n\t// The number of audio samples per channel.\r\n\tint no_samples;\r\n\r\n\t// The timecode of this frame in 100-nanosecond intervals.\r\n\tint64_t timecode;\r\n\r\n\t// The audio data, interleaved 32-bit floating-point samples.\r\n\tfloat* p_data;\r\n\r\n#if NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n\tNDIlib_audio_frame_interleaved_32f_t(\r\n\t\tint sample_rate_ = 48000, int no_channels_ = 2, int no_samples_ = 0,\r\n\t\tint64_t timecode_ = NDIlib_send_timecode_synthesize,\r\n\t\tfloat* p_data_ = NULL\r\n\t);\r\n#endif // NDILIB_CPP_DEFAULT_CONSTRUCTORS\r\n} NDIlib_audio_frame_interleaved_32f_t;\r\n\r\n// This will add an audio frame in interleaved 16-bit.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_send_send_audio_interleaved_16s(\r\n\tNDIlib_send_instance_t p_instance,\r\n\tconst NDIlib_audio_frame_interleaved_16s_t* p_audio_data\r\n);\r\n\r\n// This will add an audio frame in interleaved 32-bit.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_send_send_audio_interleaved_32s(\r\n\tNDIlib_send_instance_t p_instance,\r\n\tconst NDIlib_audio_frame_interleaved_32s_t* p_audio_data\r\n);\r\n\r\n// This will add an audio frame in interleaved floating point.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_send_send_audio_interleaved_32f(\r\n\tNDIlib_send_instance_t p_instance,\r\n\tconst NDIlib_audio_frame_interleaved_32f_t* p_audio_data\r\n);\r\n\r\n// Convert to interleaved 16-bit.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_audio_to_interleaved_16s_v2(\r\n\tconst NDIlib_audio_frame_v2_t* p_src,\r\n\tNDIlib_audio_frame_interleaved_16s_t* p_dst\r\n);\r\n\r\n// Convert to interleaved 16-bit. The FourCC of the source audio frame must be NDIlib_FourCC_audio_type_FLTP.\r\n// Returns true if the conversion was successful.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_util_audio_to_interleaved_16s_v3(\r\n\tconst NDIlib_audio_frame_v3_t* p_src,\r\n\tNDIlib_audio_frame_interleaved_16s_t* p_dst\r\n);\r\n\r\n// Convert from interleaved 16-bit.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_audio_from_interleaved_16s_v2(\r\n\tconst NDIlib_audio_frame_interleaved_16s_t* p_src,\r\n\tNDIlib_audio_frame_v2_t* p_dst\r\n);\r\n\r\n// Convert from interleaved 16-bit. The FourCC of the destination audio frame must be\r\n// NDIlib_FourCC_audio_type_FLTP and its p_data allocated accordingly.\r\n// Returns true if the conversion was successful.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_util_audio_from_interleaved_16s_v3(\r\n\tconst NDIlib_audio_frame_interleaved_16s_t* p_src,\r\n\tNDIlib_audio_frame_v3_t* p_dst\r\n);\r\n\r\n// Convert to interleaved 32-bit.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_audio_to_interleaved_32s_v2(\r\n\tconst NDIlib_audio_frame_v2_t* p_src,\r\n\tNDIlib_audio_frame_interleaved_32s_t* p_dst\r\n);\r\n\r\n// Convert to interleaved 32-bit. The FourCC of the source audio frame must be NDIlib_FourCC_audio_type_FLTP.\r\n// Returns true if the conversion was successful.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_util_audio_to_interleaved_32s_v3(\r\n\tconst NDIlib_audio_frame_v3_t* p_src,\r\n\tNDIlib_audio_frame_interleaved_32s_t* p_dst\r\n);\r\n\r\n// Convert from interleaved 32-bit.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_audio_from_interleaved_32s_v2(\r\n\tconst NDIlib_audio_frame_interleaved_32s_t* p_src,\r\n\tNDIlib_audio_frame_v2_t* p_dst\r\n);\r\n\r\n// Convert from interleaved 32-bit. The FourCC of the destination audio frame must be\r\n// NDIlib_FourCC_audio_type_FLTP and its p_data allocated accordingly.\r\n// Returns true if the conversion was successful.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_util_audio_from_interleaved_32s_v3(\r\n\tconst NDIlib_audio_frame_interleaved_32s_t* p_src,\r\n\tNDIlib_audio_frame_v3_t* p_dst\r\n);\r\n\r\n// Convert to interleaved floating point.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_audio_to_interleaved_32f_v2(\r\n\tconst NDIlib_audio_frame_v2_t* p_src,\r\n\tNDIlib_audio_frame_interleaved_32f_t* p_dst\r\n);\r\n\r\n// Convert to interleaved floating point. The FourCC of the source audio frame must be\r\n// NDIlib_FourCC_audio_type_FLTP. Returns true if the conversion was successful.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_util_audio_to_interleaved_32f_v3(\r\n\tconst NDIlib_audio_frame_v3_t* p_src,\r\n\tNDIlib_audio_frame_interleaved_32f_t* p_dst\r\n);\r\n\r\n// Convert from interleaved floating point.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_audio_from_interleaved_32f_v2(\r\n\tconst NDIlib_audio_frame_interleaved_32f_t* p_src,\r\n\tNDIlib_audio_frame_v2_t* p_dst\r\n);\r\n\r\n// Convert from interleaved floating point. The FourCC of the destination audio frame must be\r\n// NDIlib_FourCC_audio_type_FLTP and its p_data allocated accordingly.\r\n// Returns true if the conversion was successful.\r\nPROCESSINGNDILIB_API\r\nbool NDIlib_util_audio_from_interleaved_32f_v3(\r\n\tconst NDIlib_audio_frame_interleaved_32f_t* p_src,\r\n\tNDIlib_audio_frame_v3_t* p_dst\r\n);\r\n\r\n// This is a helper function that you may use to convert from 10-bit packed UYVY into 16-bit semi-planar. The\r\n// FourCC on the source is ignored in this function since we do not define a V210 format in NDI. You must\r\n// make sure that there is memory and a stride allocated in p_dst.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_V210_to_P216(const NDIlib_video_frame_v2_t* p_src_v210, NDIlib_video_frame_v2_t* p_dst_p216);\r\n\r\n// This converts from 16-bit semi-planar to 10-bit. You must make sure that there is memory and a stride\r\n// allocated in p_dst.\r\nPROCESSINGNDILIB_API\r\nvoid NDIlib_util_P216_to_V210(const NDIlib_video_frame_v2_t* p_src_p216, NDIlib_video_frame_v2_t* p_dst_v210);\r\n"
  },
  {
    "path": "src/modules/newtek/newtek.cpp",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"newtek.h\"\n\n#include \"consumer/newtek_ndi_consumer.h\"\n#include \"producer/newtek_ndi_producer.h\"\n\n#include \"util/ndi.h\"\n\n#include <core/consumer/frame_consumer.h>\n#include <protocol/amcp/amcp_command_repository_wrapper.h>\n\n#include <boost/property_tree/ptree.hpp>\n#include <common/env.h>\n\nnamespace caspar { namespace newtek {\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    try {\n        dependencies.consumer_registry->register_consumer_factory(L\"NDI Consumer\", create_ndi_consumer);\n        dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"ndi\",\n                                                                                create_preconfigured_ndi_consumer);\n\n        dependencies.producer_registry->register_producer_factory(L\"NDI Producer\", create_ndi_producer);\n\n        dependencies.command_repository->register_command(L\"Query Commands\", L\"NDI LIST\", ndi::list_command, 0);\n\n        bool autoload = caspar::env::properties().get(L\"configuration.ndi.auto-load\", false);\n        if (autoload)\n            ndi::load_library();\n\n    } catch (...) {\n    }\n}\n\n}} // namespace caspar::newtek\n"
  },
  {
    "path": "src/modules/newtek/newtek.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace newtek {\n\nvoid init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::newtek"
  },
  {
    "path": "src/modules/newtek/producer/newtek_ndi_producer.cpp",
    "content": "/*\n * Copyright 2018\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Krzysztof Zegzula, zegzulakrzysztof@gmail.com\n * based on work of Robert Nagy, ronag89@gmail.com and Jerzy Jaśkiewicz, jurek@tvp.pl\n */\n\n#include \"../StdAfx.h\"\n\n#include \"newtek_ndi_producer.h\"\n\n#include <core/frame/draw_frame.h>\n#include <core/frame/frame.h>\n#include <core/frame/frame_factory.h>\n#include <core/frame/geometry.h>\n#include <core/frame/pixel_format.h>\n#include <core/monitor/monitor.h>\n#include <core/producer/frame_producer.h>\n\n#include <common/assert.h>\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/executor.h>\n#include <common/future.h>\n#include <common/param.h>\n#include <common/scope_exit.h>\n#include <common/timer.h>\n#include <common/utf.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/format.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/regex.hpp>\n#include <boost/thread.hpp>\n\n#include <tbb/parallel_for.h>\n\n#include <ffmpeg/util/av_util.h>\n\nextern \"C\" {\n#include <libavformat/avformat.h>\n}\n\n#include \"../util/ndi.h\"\n\nnamespace caspar { namespace newtek {\n\nstruct newtek_ndi_producer : public core::frame_producer\n{\n    static std::atomic<int> instances_;\n    const int               instance_no_;\n    const std::wstring      name_;\n    const bool              low_bandwidth_;\n\n    spl::shared_ptr<core::frame_factory> frame_factory_;\n    core::video_format_desc              format_desc_;\n    NDIlib_v6*                           ndi_lib_;\n    NDIlib_framesync_instance_t          ndi_framesync_;\n    NDIlib_recv_instance_t               ndi_recv_instance_;\n    spl::shared_ptr<diagnostics::graph>  graph_;\n    timer                                tick_timer_;\n    timer                                frame_timer_;\n\n    std::queue<core::draw_frame> frames_;\n    mutable std::mutex           frames_mutex_;\n    core::draw_frame             last_frame_;\n    executor                     executor_;\n\n    int cadence_counter_;\n    int cadence_length_;\n\n  public:\n    explicit newtek_ndi_producer(spl::shared_ptr<core::frame_factory> frame_factory,\n                                 core::video_format_desc              format_desc,\n                                 std::wstring                         name,\n                                 bool                                 low_bandwidth)\n        : format_desc_(format_desc)\n        , frame_factory_(frame_factory)\n        , name_(name)\n        , low_bandwidth_(low_bandwidth)\n        , instance_no_(instances_++)\n        , executor_(print())\n        , cadence_counter_(0)\n    {\n        ndi_lib_ = ndi::load_library();\n        graph_->set_text(print());\n        graph_->set_color(\"frame-time\", diagnostics::color(0.5f, 1.0f, 0.2f));\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        diagnostics::register_graph(graph_);\n        executor_.set_capacity(2);\n        cadence_length_ = static_cast<int>(format_desc_.audio_cadence.size());\n        initialize();\n    }\n\n    ~newtek_ndi_producer()\n    {\n        executor_.stop();\n        ndi_lib_->framesync_destroy(ndi_framesync_);\n        ndi_lib_->recv_destroy(ndi_recv_instance_);\n    }\n\n    std::wstring print() const override\n    {\n        return L\"ndi[\" + boost::lexical_cast<std::wstring>(instance_no_) + L\"|\" + name_ + L\"]\";\n    }\n\n    std::wstring name() const override { return L\"ndi\"; }\n\n    core::draw_frame receive_impl(const core::video_field field, int nb_samples) override\n    {\n        // TODO - fields\n        graph_->set_value(\"tick-time\", tick_timer_.elapsed() * format_desc_.fps * 0.5);\n        tick_timer_.restart();\n        if (executor_.size() < 2) {\n            executor_.begin_invoke([this]() { prepare_next_frame(); });\n        }\n        {\n            std::lock_guard<std::mutex> lock(frames_mutex_);\n            if (!frames_.empty()) {\n                last_frame_ = frames_.front();\n                frames_.pop();\n            }\n            return last_frame_;\n        }\n    }\n\n    bool is_ready() override\n    {\n        std::lock_guard<std::mutex> lock(frames_mutex_);\n        return !frames_.empty() || last_frame_;\n    }\n\n    bool prepare_next_frame()\n    {\n        try {\n            frame_timer_.restart();\n            NDIlib_video_frame_v2_t video_frame;\n            NDIlib_audio_frame_v2_t audio_frame;\n            ndi_lib_->framesync_capture_video(ndi_framesync_, &video_frame, NDIlib_frame_format_type_progressive);\n            ndi_lib_->framesync_capture_audio(ndi_framesync_,\n                                              &audio_frame,\n                                              format_desc_.audio_sample_rate,\n                                              format_desc_.audio_channels,\n                                              format_desc_.audio_cadence[++cadence_counter_ %= cadence_length_]);\n\n            CASPAR_SCOPE_EXIT\n            {\n                if (video_frame.p_data != nullptr)\n                    ndi_lib_->framesync_free_video(ndi_framesync_, &video_frame);\n                if (audio_frame.p_data != nullptr)\n                    ndi_lib_->framesync_free_audio(ndi_framesync_, &audio_frame);\n            };\n\n            if (video_frame.p_data != nullptr) {\n                std::shared_ptr<AVFrame> av_frame(av_frame_alloc(), [](AVFrame* frame) { av_frame_free(&frame); });\n                std::shared_ptr<AVFrame> a_frame(av_frame_alloc(), [](AVFrame* frame) { av_frame_free(&frame); });\n                av_frame->data[0]     = video_frame.p_data;\n                av_frame->linesize[0] = video_frame.line_stride_in_bytes;\n                switch (video_frame.FourCC) {\n                    case NDIlib_FourCC_type_BGRA:\n                        av_frame->format = AV_PIX_FMT_BGRA;\n                        break;\n                    case NDIlib_FourCC_type_BGRX:\n                        av_frame->format = AV_PIX_FMT_BGRA;\n                        break;\n                    case NDIlib_FourCC_type_RGBA:\n                        av_frame->format = AV_PIX_FMT_RGBA;\n                        break;\n                    case NDIlib_FourCC_type_RGBX:\n                        av_frame->format = AV_PIX_FMT_RGBA;\n                        break;\n                    case NDIlib_FourCC_type_UYVY:\n                        av_frame->format = AV_PIX_FMT_UYVY422;\n                        break;\n                    default: // should never happen because library handles the conversion for us\n                        av_frame->format = AV_PIX_FMT_BGRA;\n                        break;\n                }\n                av_frame->width  = video_frame.xres;\n                av_frame->height = video_frame.yres;\n                NDIlib_audio_frame_interleaved_32s_t audio_frame_32s;\n                audio_frame_32s.p_data = new int32_t[audio_frame.no_samples * audio_frame.no_channels];\n                if (audio_frame.p_data != nullptr) {\n                    audio_frame_32s.reference_level = 0;\n                    ndi_lib_->util_audio_to_interleaved_32s_v2(&audio_frame, &audio_frame_32s);\n                    av_channel_layout_default(&a_frame->ch_layout, audio_frame_32s.no_channels);\n                    a_frame->sample_rate = audio_frame_32s.sample_rate;\n                    a_frame->nb_samples  = audio_frame_32s.no_samples;\n                    a_frame->data[0]     = reinterpret_cast<uint8_t*>(audio_frame_32s.p_data);\n                }\n                auto mframe =\n                    ffmpeg::make_frame(this, *(frame_factory_.get()), std::move(av_frame), std::move(a_frame));\n                delete[] audio_frame_32s.p_data;\n                auto dframe = core::draw_frame(std::move(mframe));\n                {\n                    std::lock_guard<std::mutex> lock(frames_mutex_);\n                    frames_.push(dframe);\n                    while (frames_.size() > 2) { // should never happen because frame sync takes care of it\n                        frames_.pop();\n                        graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n                    }\n                }\n            }\n\n            graph_->set_value(\"frame-time\", frame_timer_.elapsed() * format_desc_.fps * 0.5);\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n            return false;\n        }\n        return true;\n    }\n\n    // frame_producer\n\n    void initialize()\n    {\n        auto sources = ndi::get_current_sources();\n\n        NDIlib_recv_create_v3_t NDI_recv_create_desc;\n        NDI_recv_create_desc.allow_video_fields = false;\n        NDI_recv_create_desc.bandwidth = low_bandwidth_ ? NDIlib_recv_bandwidth_lowest : NDIlib_recv_bandwidth_highest;\n        NDI_recv_create_desc.color_format = NDIlib_recv_color_format_UYVY_BGRA;\n        std::string src_name              = u8(name_);\n\n        auto found_source = sources.find(src_name);\n        if (found_source != sources.end()) {\n            NDI_recv_create_desc.source_to_connect_to = found_source->second;\n        } else {\n            CASPAR_LOG(info) << print() << \" Source currently not available.\";\n            NDI_recv_create_desc.source_to_connect_to.p_ndi_name = src_name.c_str();\n        }\n        std::string receiver_name = \"CasparCG \" + u8(env::version()) + \" NDI Producer \" + std::to_string(instance_no_);\n        NDI_recv_create_desc.p_ndi_recv_name = receiver_name.c_str();\n        ndi_recv_instance_                   = ndi_lib_->recv_create_v3(&NDI_recv_create_desc);\n        ndi_framesync_                       = ndi_lib_->framesync_create(ndi_recv_instance_);\n        CASPAR_VERIFY(ndi_recv_instance_);\n    }\n\n    core::draw_frame last_frame(const core::video_field field) override\n    {\n        if (!last_frame_) {\n            last_frame_ = receive_impl(field, 0);\n        }\n        return core::draw_frame::still(last_frame_);\n    }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"ndi/name\"]          = u8(name_);\n        state[\"ndi/low_bandwidth\"] = low_bandwidth_;\n        return state;\n    }\n\n}; // namespace newtek\n\nstd::atomic<int> newtek_ndi_producer::instances_(0);\n\nspl::shared_ptr<core::frame_producer> create_ndi_producer(const core::frame_producer_dependencies& dependencies,\n                                                          const std::vector<std::wstring>&         params)\n{\n    const bool ndi_prefix  = boost::iequals(params.at(0), \"[NDI]\");\n    auto       name_or_url = ndi_prefix ? params.at(1) : params.at(0);\n    const bool ndi_url     = boost::algorithm::istarts_with(name_or_url, L\"ndi:\");\n    if (!ndi_prefix && !ndi_url)\n        return core::frame_producer::empty();\n\n    if (ndi_url) {\n        boost::replace_all(name_or_url, L\"+\", L\" \");\n        boost::wregex expression(L\"^ndi://([^/]+)/([^/]+)\");\n\n        boost::match_results<std::wstring::const_iterator> match;\n        if (regex_search(name_or_url, match, expression)) {\n            std::wstring device(match[1].first, match[1].second);\n            std::wstring source(match[2].first, match[2].second);\n            name_or_url = device + L\" (\" + source + L\")\";\n        } else {\n            return core::frame_producer::empty();\n        }\n    }\n    const bool low_bandwidth = contains_param(L\"LOW_BANDWIDTH\", params);\n\n    return spl::make_shared<newtek_ndi_producer>(\n        dependencies.frame_factory, dependencies.format_desc, name_or_url, low_bandwidth);\n}\n}} // namespace caspar::newtek\n"
  },
  {
    "path": "src/modules/newtek/producer/newtek_ndi_producer.h",
    "content": "/*\n * Copyright 2018\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Krzysztof Zegzula, zegzulakrzysztof@gmail.com\n * based on work of Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\n#include <string>\n\nnamespace caspar { namespace newtek {\n\nspl::shared_ptr<core::frame_producer> create_ndi_producer(const core::frame_producer_dependencies& dependencies,\n                                                          const std::vector<std::wstring>&         params);\n\n}} // namespace caspar::newtek\n"
  },
  {
    "path": "src/modules/newtek/util/ndi.cpp",
    "content": "/*\n * Copyright 2018\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Krzysztof Zegzula, zegzulakrzysztof@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"ndi.h\"\n\n#include <memory>\n#include <mutex>\n\n#ifdef _WIN32\n#include <windows.h>\n#else\n#include <dlfcn.h>\n#include <stdlib.h>\n#endif\n\n#include <common/env.h>\n#include <common/except.h>\n\n#include <boost/filesystem.hpp>\n\nnamespace caspar { namespace newtek { namespace ndi {\n\nconst std::wstring& dll_name()\n{\n    static std::wstring name = u16(NDILIB_LIBRARY_NAME);\n\n    return name;\n}\n\nstatic std::mutex                              find_instance_mutex;\nstatic std::shared_ptr<NDIlib_find_instance_t> find_instance;\n\nNDIlib_v6* load_library()\n{\n    static NDIlib_v6* ndi_lib = nullptr;\n\n    if (ndi_lib)\n        return ndi_lib;\n\n    auto        dll_path    = boost::filesystem::path(env::initial_folder()) / NDILIB_LIBRARY_NAME;\n    const char* runtime_dir = getenv(NDILIB_REDIST_FOLDER);\n\n#ifdef _WIN32\n    HMODULE module = LoadLibrary(dll_path.c_str());\n\n    if (!module && runtime_dir) {\n        dll_path = boost::filesystem::path(runtime_dir) / NDILIB_LIBRARY_NAME;\n        module   = LoadLibrary(dll_path.c_str());\n    }\n\n    FARPROC NDIlib_v6_load = NULL;\n    if (module) {\n        CASPAR_LOG(info) << L\"Loaded \" << dll_path;\n        static std::shared_ptr<void> lib(module, FreeLibrary);\n        NDIlib_v6_load = GetProcAddress(module, \"NDIlib_v6_load\");\n    }\n\n    if (!NDIlib_v6_load) {\n        not_installed();\n    }\n\n    ndi_lib = (NDIlib_v6*)(((const NDIlib_v6* (*)(void))NDIlib_v6_load)());\n\n    if (!ndi_lib->NDIlib_initialize()) {\n        not_initialized();\n    }\n\n#else\n    // Try to load the library\n    void* hNDILib = dlopen(NDILIB_LIBRARY_NAME, RTLD_LOCAL | RTLD_LAZY);\n\n    if (!hNDILib && runtime_dir) {\n        dll_path = boost::filesystem::path(runtime_dir) / NDILIB_LIBRARY_NAME;\n        hNDILib  = dlopen(dll_path.c_str(), RTLD_LOCAL | RTLD_LAZY);\n    }\n\n    // The main NDI entry point for dynamic loading if we got the library\n    const NDIlib_v6* (*NDIlib_v6_load)(void) = NULL;\n    if (hNDILib) {\n        CASPAR_LOG(info) << L\"Loaded \" << dll_path;\n        static std::shared_ptr<void> lib(hNDILib, dlclose);\n        *((void**)&NDIlib_v6_load) = dlsym(hNDILib, \"NDIlib_v6_load\");\n    }\n\n    if (!NDIlib_v6_load) {\n        not_installed();\n    }\n\n    ndi_lib = (NDIlib_v6*)(NDIlib_v6_load());\n\n    if (!ndi_lib->NDIlib_initialize()) {\n        not_initialized();\n    }\n#endif\n\n    NDIlib_find_create_t find_instance_options = {};\n    find_instance_options.show_local_sources   = true;\n\n    find_instance.reset(new NDIlib_find_instance_t(ndi_lib->NDIlib_find_create_v2(&find_instance_options)),\n                        [](NDIlib_find_instance_t* p) { ndi_lib->NDIlib_find_destroy(*p); });\n    return ndi_lib;\n}\n\nstd::map<std::string, NDIlib_source_t> get_current_sources()\n{\n    auto                        sources_map = std::map<std::string, NDIlib_source_t>();\n    uint32_t                    no_sources;\n    std::lock_guard<std::mutex> guard(find_instance_mutex);\n    const NDIlib_source_t*      sources =\n        load_library()->NDIlib_find_get_current_sources(*(find_instance.get()), &no_sources);\n    for (uint32_t i = 0; i < no_sources; i++) {\n        sources_map.emplace(std::string(sources[i].p_ndi_name), sources[i]);\n    }\n    return sources_map;\n}\n\nvoid not_installed()\n{\n    CASPAR_THROW_EXCEPTION(not_supported()\n                           << msg_info(dll_name() + L\" not available. Install NDI Redist version 6.0 or higher from \" +\n                                       u16(NDILIB_REDIST_URL)));\n}\n\nvoid not_initialized()\n{\n    CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\"Unable to initialize NDI on this system.\"));\n}\n\nstd::string apply_default_discovery_port(std::string url)\n{\n    if (!url.empty() && url.find(':') == std::string::npos) {\n        url += \":5959\";\n    }\n    return url;\n}\n\nstd::wstring list_command(protocol::amcp::command_context& ctx)\n{\n    auto ndi_lib = load_library();\n    if (!ndi_lib) {\n        return L\"501 NDI LIST FAILED\\r\\n\";\n    }\n    std::wstringstream replyString;\n    replyString << L\"200 NDI LIST OK\\r\\n\";\n    uint32_t               no_sources;\n    const NDIlib_source_t* sources = ndi_lib->NDIlib_find_get_current_sources(*(find_instance.get()), &no_sources);\n    for (uint32_t i = 0; i < no_sources; i++) {\n        replyString << i + 1 << L\" \\\"\" << sources[i].p_ndi_name << L\"\\\" \" << sources[i].p_url_address << L\"\\r\\n\";\n    }\n    replyString << L\"\\r\\n\";\n    return replyString.str();\n}\n\n}}} // namespace caspar::newtek::ndi\n"
  },
  {
    "path": "src/modules/newtek/util/ndi.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Krzysztof Zegzula, zegzulakrzysztof@gmail.com\n */\n#pragma once\n\n#include \"../interop/Processing.NDI.Lib.h\"\n#include \"protocol/amcp/amcp_command_context.h\"\n#include <string>\n\nnamespace caspar { namespace newtek { namespace ndi {\n\nconst std::wstring&                    dll_name();\nNDIlib_v6*                             load_library();\nstd::map<std::string, NDIlib_source_t> get_current_sources();\nvoid                                   not_initialized();\nvoid                                   not_installed();\nstd::string                            apply_default_discovery_port(std::string url);\n\nstd::wstring list_command(protocol::amcp::command_context& ctx);\n\n}}} // namespace caspar::newtek::ndi\n"
  },
  {
    "path": "src/modules/oal/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (oal)\n\nset(SOURCES\n\t\tconsumer/oal_consumer.cpp\n\t\tconsumer/oal_consumer.h\n\n\t\toal.cpp\n\t\toal.h\n)\n\ncasparcg_add_module_project(oal\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"oal::init\"\n)\ntarget_include_directories(oal PRIVATE\n    ${FFMPEG_INCLUDE_PATH}\n)\ntarget_link_libraries(oal PRIVATE OpenAL::OpenAL)\n\nset_target_properties(oal PROPERTIES FOLDER modules)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources ./*)\n"
  },
  {
    "path": "src/modules/oal/consumer/oal_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"oal_consumer.h\"\n\n#include <common/diagnostics/graph.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/executor.h>\n#include <common/future.h>\n#include <common/log.h>\n#include <common/param.h>\n#include <common/timer.h>\n#include <common/utf.h>\n\n#include <core/consumer/channel_info.h>\n#include <core/consumer/frame_consumer.h>\n#include <core/frame/frame.h>\n#include <core/video_format.h>\n\n#include <boost/algorithm/string/erase.hpp>\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <tbb/concurrent_queue.h>\n\nextern \"C\" {\n#define __STDC_CONSTANT_MACROS\n#define __STDC_LIMIT_MACROS\n#include <libavutil/channel_layout.h>\n#include <libavutil/samplefmt.h>\n#include <libswresample/swresample.h>\n}\n\n#include <memory>\n#include <vector>\n\n#include <AL/al.h>\n#include <AL/alc.h>\n\nnamespace caspar { namespace oal {\n\nclass device\n{\n    ALCdevice*         device_  = nullptr;\n    ALCcontext*        context_ = nullptr;\n    const std::wstring device_name_;\n\n  public:\n    explicit device(std::wstring device_name)\n        : device_name_(std::move(device_name))\n    {\n        ALCchar* deviceName = nullptr;\n\n        if (!device_name_.empty()) {\n            ALboolean enumeration = alcIsExtensionPresent(nullptr, \"ALC_ENUMERATION_EXT\");\n\n            if (enumeration == AL_FALSE) {\n                // enumeration not supported\n                CASPAR_LOG(info) << L\"Unable to enumerate OpenAL devices. Using system default device\";\n            } else {\n                char* s;\n\n                if (alcIsExtensionPresent(nullptr, \"ALC_enumerate_all_EXT\") == AL_FALSE)\n                    s = (char*)alcGetString(nullptr, ALC_DEVICE_SPECIFIER);\n                else\n                    s = (char*)alcGetString(nullptr, ALC_ALL_DEVICES_SPECIFIER);\n\n                deviceName = iterate_and_find_device(s, device_name_);\n\n                if (deviceName == nullptr) {\n                    CASPAR_LOG(warning)\n                        << L\"Failed to find specified OpenAL output device. Using system default device\";\n                } else {\n                    CASPAR_LOG(debug) << L\"Found specified OpenAL output device\";\n                }\n            }\n        }\n\n        device_ = alcOpenDevice(deviceName);\n\n        if (device_ == nullptr)\n            CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(\"Failed to initialize audio device.\"));\n\n        context_ = alcCreateContext(device_, nullptr);\n\n        if (context_ == nullptr)\n            CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(\"Failed to create audio context.\"));\n\n        if (alcMakeContextCurrent(context_) == ALC_FALSE)\n            CASPAR_THROW_EXCEPTION(invalid_operation() << msg_info(\"Failed to activate audio context.\"));\n    }\n\n    ~device()\n    {\n        alcMakeContextCurrent(nullptr);\n\n        if (context_ != nullptr)\n            alcDestroyContext(context_);\n\n        if (device_ != nullptr)\n            alcCloseDevice(device_);\n    }\n\n    ALCdevice* get() { return device_; }\n\n  private:\n    static ALCchar* iterate_and_find_device(const char* list, const std::wstring& device_name)\n    {\n        ALCchar* result = nullptr;\n\n        // generate ascii string for comparison purposes vs what openAL provides\n        std::string short_device_name = u8(device_name);\n        boost::algorithm::erase_all(short_device_name, \" \");\n\n        CASPAR_LOG(info) << L\"------- OpenAL Device List -----\";\n\n        if (!list) {\n            CASPAR_LOG(info) << L\"No device names found\";\n        } else {\n            // iterate through all device names\n            // -> buffer contains multiple null-terminated device name strings\n            ALCchar* ptr = (ALCchar*)list;\n\n            while (strlen(ptr) > 0) {\n                // log each device name, so we can see what options are available\n                CASPAR_LOG(info) << ptr;\n\n                // store matching device name address if found\n                // -> device name will be empty string if not provided\n                std::string tmpStr = ptr;\n                boost::algorithm::erase_all(tmpStr, \" \");\n\n                if (boost::iequals(short_device_name, tmpStr)) {\n                    result = ptr;\n                }\n\n                // point to next device name start (or null if no more device names)\n                ptr += strlen(ptr) + 1;\n            }\n        }\n\n        CASPAR_LOG(info) << L\"------ OpenAL Devices List done -----\";\n\n        return result;\n    }\n};\n\nvoid init_device()\n{\n    static std::unique_ptr<device> instance;\n    static std::once_flag          f;\n\n    std::call_once(f, [&] {\n        std::wstring device_name =\n            env::properties().get(L\"configuration.system-audio.producer.default-device-name\", L\"\");\n        instance = std::make_unique<device>(device_name);\n    });\n}\n\nstruct oal_consumer : public core::frame_consumer\n{\n    spl::shared_ptr<diagnostics::graph> graph_;\n    caspar::timer                       perf_timer_;\n    int                                 channel_index_ = -1;\n\n    core::video_format_desc format_desc_;\n\n    ALuint              source_ = 0;\n    std::vector<ALuint> buffers_;\n    bool                started_  = false;\n    int                 duration_ = 1920;\n\n    std::shared_ptr<SwrContext> swr_;\n\n    executor executor_{L\"oal_consumer\"};\n\n  public:\n    explicit oal_consumer()\n    {\n        init_device();\n\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_color(\"late-frame\", diagnostics::color(0.6f, 0.3f, 0.3f));\n        diagnostics::register_graph(graph_);\n    }\n\n    ~oal_consumer() override\n    {\n        executor_.invoke([this] {\n            if (source_ != 0u) {\n                alSourceStop(source_);\n                alDeleteSources(1, &source_);\n            }\n\n            for (auto& buffer : buffers_) {\n                if (buffer != 0u)\n                    alDeleteBuffers(1, &buffer);\n            }\n        });\n    }\n\n    // frame consumer\n\n    void initialize(const core::video_format_desc& format_desc,\n                    const core::channel_info&      channel_info,\n                    int                            port_index) override\n    {\n        format_desc_   = format_desc;\n        channel_index_ = channel_info.index;\n        graph_->set_text(print());\n\n        executor_.begin_invoke([this] {\n            duration_ = *std::min_element(format_desc_.audio_cadence.begin(), format_desc_.audio_cadence.end());\n            buffers_.resize(8);\n            alGenBuffers(static_cast<ALsizei>(buffers_.size()), buffers_.data());\n            alGenSources(1, &source_);\n\n            alSourcei(source_, AL_LOOPING, AL_FALSE);\n        });\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        executor_.begin_invoke([=, this] {\n            auto dst         = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });\n            dst->format      = AV_SAMPLE_FMT_S16;\n            dst->sample_rate = format_desc_.audio_sample_rate;\n            av_channel_layout_default(&dst->ch_layout, 2);\n            dst->nb_samples = duration_;\n            if (av_frame_get_buffer(dst.get(), 32) < 0) {\n                // TODO FF error\n                CASPAR_THROW_EXCEPTION(invalid_argument());\n            }\n            std::memset(dst->extended_data[0], 0, dst->linesize[0]);\n\n            if (!started_) {\n                for (ALuint& buffer : buffers_) {\n                    alBufferData(buffer,\n                                 AL_FORMAT_STEREO16,\n                                 dst->extended_data[0],\n                                 static_cast<ALsizei>(dst->linesize[0]),\n                                 dst->sample_rate);\n                    alSourceQueueBuffers(source_, 1, &buffer);\n                }\n\n                alSourcePlay(source_);\n                started_ = true;\n\n                return;\n            }\n\n            auto src         = std::shared_ptr<AVFrame>(av_frame_alloc(), [](AVFrame* ptr) { av_frame_free(&ptr); });\n            src->format      = AV_SAMPLE_FMT_S32;\n            src->sample_rate = format_desc_.audio_sample_rate;\n            av_channel_layout_default(&src->ch_layout, format_desc_.audio_channels);\n            src->nb_samples       = static_cast<int>(frame.audio_data().size() / format_desc_.audio_channels);\n            src->extended_data[0] = const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(frame.audio_data().data()));\n            src->linesize[0]      = static_cast<int>(frame.audio_data().size() * sizeof(int32_t));\n\n            if (!swr_) {\n                swr_.reset(swr_alloc(), [](SwrContext* ptr) { swr_free(&ptr); });\n                if (!swr_) {\n                    CASPAR_THROW_EXCEPTION(bad_alloc());\n                }\n                if (swr_config_frame(swr_.get(), dst.get(), src.get()) < 0) {\n                    // TODO FF error\n                    CASPAR_THROW_EXCEPTION(invalid_argument());\n                }\n                if (swr_init(swr_.get()) < 0) {\n                    // TODO FF error\n                    CASPAR_THROW_EXCEPTION(invalid_argument());\n                }\n            }\n\n            if (swr_convert_frame(swr_.get(), nullptr, src.get()) < 0) {\n                // TODO FF error\n                CASPAR_THROW_EXCEPTION(invalid_argument());\n            }\n\n            ALint processed = 0;\n            alGetSourceiv(source_, AL_BUFFERS_PROCESSED, &processed);\n\n            auto in_duration  = swr_get_delay(swr_.get(), 48000);\n            auto out_duration = static_cast<int64_t>(processed) * duration_;\n            auto delta        = static_cast<int>(out_duration - in_duration);\n\n            ALenum state;\n            alGetSourcei(source_, AL_SOURCE_STATE, &state);\n            if (state != AL_PLAYING) {\n                while (delta > duration_) {\n                    ALuint buffer = 0;\n                    alSourceUnqueueBuffers(source_, 1, &buffer);\n                    if (buffer == 0u) {\n                        break;\n                    }\n                    alBufferData(buffer,\n                                 AL_FORMAT_STEREO16,\n                                 dst->extended_data[0],\n                                 static_cast<ALsizei>(dst->linesize[0]),\n                                 dst->sample_rate);\n                    alSourceQueueBuffers(source_, 1, &buffer);\n                    delta -= duration_;\n                }\n\n                alSourcePlay(source_);\n            }\n\n            // TODO (fix)\n            // if (std::abs(delta) > duration_ && swr_set_compensation(swr_.get(), delta, 2000) < 0) {\n            //    // TODO FF error\n            //    CASPAR_THROW_EXCEPTION(invalid_argument());\n            //}\n\n            for (auto n = 0; n < processed; ++n) {\n                if (swr_get_delay(swr_.get(), 48000) < dst->nb_samples) {\n                    break;\n                }\n\n                ALuint buffer = 0;\n                alSourceUnqueueBuffers(source_, 1, &buffer);\n                if (buffer == 0u) {\n                    // TODO error\n                    break;\n                }\n\n                if (swr_convert_frame(swr_.get(), dst.get(), nullptr) != 0) {\n                    // TODO FF error\n                    CASPAR_THROW_EXCEPTION(invalid_argument());\n                }\n\n                alBufferData(buffer,\n                             AL_FORMAT_STEREO16,\n                             dst->extended_data[0],\n                             static_cast<ALsizei>(dst->linesize[0]),\n                             dst->sample_rate);\n                alSourceQueueBuffers(source_, 1, &buffer);\n            }\n\n            graph_->set_value(\"tick-time\", perf_timer_.elapsed() * format_desc_.fps * 0.5);\n            perf_timer_.restart();\n        });\n\n        return make_ready_future(true);\n    }\n\n    std::wstring print() const override\n    {\n        return L\"oal[\" + std::to_wstring(channel_index_) + L\"|\" + format_desc_.name + L\"]\";\n    }\n\n    std::wstring name() const override { return L\"system-audio\"; }\n\n    bool has_synchronization_clock() const override { return false; }\n\n    int index() const override { return 500; }\n\n    core::monitor::state state() const override\n    {\n        static const core::monitor::state empty;\n        return empty;\n    }\n};\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info)\n{\n    if (params.empty() || !boost::iequals(params.at(0), L\"AUDIO\"))\n        return core::frame_consumer::empty();\n\n    return spl::make_shared<oal_consumer>();\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info)\n{\n    return spl::make_shared<oal_consumer>();\n}\n\n}} // namespace caspar::oal\n"
  },
  {
    "path": "src/modules/oal/consumer/oal_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <vector>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n\nnamespace caspar { namespace oal {\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info);\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info);\n\n}} // namespace caspar::oal\n"
  },
  {
    "path": "src/modules/oal/oal.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"oal.h\"\n\n#include \"consumer/oal_consumer.h\"\n\n#include <core/consumer/frame_consumer.h>\n\nnamespace caspar { namespace oal {\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    dependencies.consumer_registry->register_consumer_factory(L\"System Audio Consumer\", create_consumer);\n    dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"system-audio\",\n                                                                            create_preconfigured_consumer);\n}\n\n}} // namespace caspar::oal\n"
  },
  {
    "path": "src/modules/oal/oal.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace oal {\n\nvoid init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::oal\n"
  },
  {
    "path": "src/modules/screen/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (screen)\n\nset(SOURCES\n\tconsumer/screen_consumer.cpp\n\tconsumer/screen_consumer.h\n\n\tconsumer_screen_vertex.h\n\tconsumer_screen_fragment.h\n\n\tscreen.cpp\n\tscreen.h\n)\n\nbin2c(\"consumer/screen.vert\" \"consumer_screen_vertex.h\" \"caspar::screen\" \"vertex_shader\")\nbin2c(\"consumer/screen.frag\" \"consumer_screen_fragment.h\" \"caspar::screen\" \"fragment_shader\")\n\nif (MSVC)\nelse ()\n\tlist(APPEND SOURCES\n\t\tutil/x11_util.cpp\n\t\tutil/x11_util.h\n\t)\nendif ()\n\ncasparcg_add_module_project(screen\n\tSOURCES ${SOURCES}\n\tINIT_FUNCTION \"screen::init\"\n)\ntarget_include_directories(screen PRIVATE\n    ${CMAKE_CURRENT_BINARY_DIR}\n    ${FFMPEG_INCLUDE_PATH}\n)\ntarget_link_libraries(screen PRIVATE accelerator ffmpeg GLEW::glew sfml-system sfml-window)\n\nset_target_properties(screen PROPERTIES FOLDER modules)\nsource_group(sources\\\\consumer consumer/*)\nsource_group(sources ./*)\n"
  },
  {
    "path": "src/modules/screen/consumer/screen.frag",
    "content": "#version 450\n\n#define COLOUR_SPACE_RGB                0\n#define COLOUR_SPACE_DATAVIDEO_FULL     1\n#define COLOUR_SPACE_DATAVIDEO_LIMITED  2\n\n#define RANGE_16        (16.0f / 256.0f)\n#define RANGE_235       (235.0f / 256.0f)\n#define RANGE_HALF      (0.5f / 256.0f)\n#define RANGE_LIMITED   ((235.0f - 16.0f) / 256.0f)\n\nuniform sampler2D background;\n\nin vec4 TexCoord;\nout vec4 fragColor;\n\nuniform bool key_only;\nuniform int colour_space;\nuniform int window_width;\n\n// rgb=0~255, y=16~235, uv=16~240\nmat3 rgb2yuv_709 = mat3(0.183f, -0.101f, 0.439f,  0.614f, -0.338f, -0.399f, 0.062f, 0.439f,-0.040f);\n\nvec4 dtv_color(vec4 color)\n{\n    color.stp = rgb2yuv_709 * clamp(color.rgb  / (color.a + 0.0000001f), 0.0f, 1.0f);\n    return color;\n}\n\nvoid main()\n{\n    vec4 color = texture(background, TexCoord.xy);\n    if (key_only)\n        color = vec4(color.aaa, 1);\n\n    else if (colour_space == COLOUR_SPACE_DATAVIDEO_FULL) {  // Full range 0-255\n        color = dtv_color(color);\n        float x_coord = TexCoord.x * window_width * 0.5f;\n        bool isEvenPixel = round(x_coord) - x_coord < 0.0f ;\n        vec4 color2 = dtv_color(texture(background, TexCoord.xy + (isEvenPixel ? vec2(1.0f / window_width, 0.0f) : vec2(-1.0f / window_width, 0.0f))));\n        color.s = clamp((color.s * RANGE_LIMITED) + RANGE_16 + RANGE_HALF, RANGE_16, RANGE_235);\n        color.t = clamp(((isEvenPixel ? color.t + color2.t : color.p + color2.p) * RANGE_LIMITED * 0.5f) + RANGE_HALF + 0.5f, RANGE_16, RANGE_235);\n        color.p = clamp((color.w * RANGE_LIMITED) + RANGE_16 + RANGE_HALF, RANGE_16, RANGE_235);\n\n    } else if (colour_space == COLOUR_SPACE_DATAVIDEO_LIMITED) {  // Limited range 16-235\n        color = dtv_color(color);\n        float x_coord = TexCoord.x * window_width * 0.5f;\n        bool isEvenPixel = round(x_coord) - x_coord < 0.0f ;\n        vec4 color2 = dtv_color(texture(background, TexCoord.xy + (isEvenPixel ? vec2(1.0f / window_width, 0.0f) : vec2(-1.0f / window_width, 0.0f))));\n        color.s = clamp(color.s + RANGE_HALF, 0.0f, 1.0f);\n        color.t = clamp(((isEvenPixel ? color.t + color2.t : color.p + color2.p) * 0.5f) + RANGE_HALF + 0.5f, 0.0f, 1.0f);\n        color.p = clamp(color.w + RANGE_HALF, 0.0f, 1.0f);\n    }\n    fragColor = color;\n}\n"
  },
  {
    "path": "src/modules/screen/consumer/screen.vert",
    "content": "#version 450\nin vec4 TexCoordIn;\nin vec2 Position;\n\nout vec4 TexCoord;\n\nvoid main()\n{\n    TexCoord = TexCoordIn;\n    gl_Position = vec4(Position, 0, 1);\n}\n"
  },
  {
    "path": "src/modules/screen/consumer/screen_consumer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"screen_consumer.h\"\n\n#include <GL/glew.h>\n#include <SFML/Window.hpp>\n\n#include <common/array.h>\n#include <common/diagnostics/graph.h>\n#include <common/future.h>\n#include <common/gl/gl_check.h>\n#include <common/log.h>\n#include <common/memory.h>\n#include <common/param.h>\n#include <common/timer.h>\n#include <common/utf.h>\n\n#include <core/consumer/channel_info.h>\n#include <core/consumer/frame_consumer.h>\n#include <core/frame/frame.h>\n#include <core/frame/geometry.h>\n#include <core/video_format.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/lexical_cast.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <tbb/concurrent_queue.h>\n\n#include <thread>\n#include <tuple> // std::ignore\n#include <utility>\n#include <vector>\n\n#if defined(_MSC_VER)\n#include <windows.h>\n#else\n#include \"../util/x11_util.h\"\n#endif\n\n#include \"consumer_screen_fragment.h\"\n#include \"consumer_screen_vertex.h\"\n#include <accelerator/ogl/util/shader.h>\n\nnamespace caspar { namespace screen {\n\nstd::unique_ptr<accelerator::ogl::shader> get_shader()\n{\n    return std::make_unique<accelerator::ogl::shader>(std::string(reinterpret_cast<const char*>(vertex_shader)),\n                                                      std::string(reinterpret_cast<const char*>(fragment_shader)));\n}\n\nenum class stretch\n{\n    none,\n    uniform,\n    fill,\n    uniform_to_fill\n};\n\nstruct configuration\n{\n    enum class aspect_ratio\n    {\n        aspect_4_3 = 0,\n        aspect_16_9,\n        aspect_invalid,\n    };\n\n    enum class colour_spaces\n    {\n        RGB               = 0,\n        datavideo_full    = 1,\n        datavideo_limited = 2\n    };\n\n    std::wstring    name          = L\"Screen consumer\";\n    int             screen_index  = 0;\n    int             screen_x      = 0;\n    int             screen_y      = 0;\n    int             screen_width  = 0;\n    int             screen_height = 0;\n    screen::stretch stretch       = screen::stretch::fill;\n    bool            windowed      = true;\n    bool            key_only      = false;\n    bool            sbs_key       = false;\n    aspect_ratio    aspect        = aspect_ratio::aspect_invalid;\n    bool            vsync         = false;\n    bool            interactive   = true;\n    bool            borderless    = false;\n    bool            always_on_top = false;\n    colour_spaces   colour_space  = colour_spaces::RGB;\n    bool            high_bitdepth = false;\n    bool            gpu_texture   = false;\n};\n\nstruct frame\n{\n    GLuint                         pbo = 0;\n    GLuint                         tex = 0;\n    char*                          ptr = nullptr;\n    std::shared_ptr<core::texture> texture;\n    GLsync                         fence = nullptr;\n};\n\nstruct screen_consumer;\n\nstruct display_strategy\n{\n    virtual ~display_strategy() {}\n    virtual frame init_frame(const configuration& config, const core::video_format_desc& format_desc) = 0;\n    virtual void  cleanup_frame(frame& frame)                                                         = 0;\n    virtual void  do_tick(screen_consumer* self)                                                      = 0;\n};\nstruct gpu_strategy;\nstruct host_strategy;\n\nstruct screen_consumer\n{\n    const configuration     config_;\n    core::video_format_desc format_desc_;\n    int                     channel_index_;\n\n    std::vector<frame> frames_;\n\n    int screen_width_  = format_desc_.width;\n    int screen_height_ = format_desc_.height;\n    int square_width_  = format_desc_.square_width;\n    int square_height_ = format_desc_.square_height;\n    int screen_x_      = 0;\n    int screen_y_      = 0;\n\n    std::vector<core::frame_geometry::coord> draw_coords_;\n\n    sf::Window window_;\n\n    spl::shared_ptr<diagnostics::graph> graph_;\n    caspar::timer                       tick_timer_;\n\n    tbb::concurrent_bounded_queue<core::const_frame> frame_buffer_;\n\n    std::unique_ptr<accelerator::ogl::shader> shader_;\n    GLuint                                    vao_;\n    GLuint                                    vbo_;\n\n    std::atomic<bool> is_running_{true};\n    std::thread       thread_;\n\n    spl::shared_ptr<display_strategy> strategy_;\n\n    screen_consumer(const screen_consumer&)            = delete;\n    screen_consumer& operator=(const screen_consumer&) = delete;\n\n  public:\n    screen_consumer(const configuration& config, const core::video_format_desc& format_desc, int channel_index)\n        : config_(config)\n        , format_desc_(format_desc)\n        , channel_index_(channel_index)\n        , strategy_(config.gpu_texture ? spl::make_shared<display_strategy, gpu_strategy>()\n                                       : spl::make_shared<display_strategy, host_strategy>())\n    {\n        if (config_.gpu_texture) {\n            CASPAR_LOG(info) << print() << \" Using GPU texture for rendering.\";\n        } else {\n            CASPAR_LOG(info) << print() << \" Using frame copied to host for rendering.\";\n        }\n\n        if (format_desc_.format == core::video_format::ntsc &&\n            config_.aspect == configuration::aspect_ratio::aspect_4_3) {\n            // Use default values which are 4:3.\n        } else {\n            if (config_.aspect == configuration::aspect_ratio::aspect_16_9) {\n                square_width_ = format_desc.height * 16 / 9;\n            } else if (config_.aspect == configuration::aspect_ratio::aspect_4_3) {\n                square_width_ = format_desc.height * 4 / 3;\n            }\n        }\n\n        frame_buffer_.set_capacity(1);\n\n        graph_->set_color(\"tick-time\", diagnostics::color(0.0f, 0.6f, 0.9f));\n        graph_->set_color(\"frame-time\", diagnostics::color(0.1f, 1.0f, 0.1f));\n        graph_->set_color(\"dropped-frame\", diagnostics::color(0.3f, 0.6f, 0.3f));\n        graph_->set_text(print());\n        diagnostics::register_graph(graph_);\n\n#if defined(_MSC_VER)\n        DISPLAY_DEVICE              d_device = {sizeof(d_device), 0};\n        std::vector<DISPLAY_DEVICE> displayDevices;\n        for (int n = 0; EnumDisplayDevices(nullptr, n, &d_device, NULL); ++n) {\n            displayDevices.push_back(d_device);\n        }\n\n        if (config_.screen_index >= displayDevices.size()) {\n            CASPAR_LOG(warning) << print() << L\" Invalid screen-index: \" << config_.screen_index;\n        }\n\n        DEVMODE devmode = {};\n        if (!EnumDisplaySettings(displayDevices[config_.screen_index].DeviceName, ENUM_CURRENT_SETTINGS, &devmode)) {\n            CASPAR_LOG(warning) << print() << L\" Could not find display settings for screen-index: \"\n                                << config_.screen_index;\n        }\n\n        screen_x_      = devmode.dmPosition.x;\n        screen_y_      = devmode.dmPosition.y;\n        screen_width_  = devmode.dmPelsWidth;\n        screen_height_ = devmode.dmPelsHeight;\n#else\n        if (config_.screen_index > 1) {\n            CASPAR_LOG(warning) << print() << L\" Screen-index is not supported on linux\";\n        }\n#endif\n\n        if (config.windowed) {\n            screen_x_ += config.screen_x;\n            screen_y_ += config.screen_y;\n\n            if (config.screen_width > 0 && config.screen_height > 0) {\n                screen_width_  = config.screen_width;\n                screen_height_ = config.screen_height;\n            } else if (config.screen_width > 0) {\n                screen_width_  = config.screen_width;\n                screen_height_ = square_height_ * config.screen_width / square_width_;\n            } else if (config.screen_height > 0) {\n                screen_height_ = config.screen_height;\n                screen_width_  = square_width_ * config.screen_height / square_height_;\n            } else {\n                screen_width_  = square_width_;\n                screen_height_ = square_height_;\n            }\n        }\n\n        thread_ = std::thread([this] {\n            try {\n#if SFML_VERSION_MAJOR >= 3\n                sf::VideoMode mode{sf::Vector2u(config_.sbs_key ? screen_width_ * 2 : screen_width_, screen_height_),\n                                   sf::VideoMode::getDesktopMode().bitsPerPixel};\n                sf::ContextSettings settings{.depthBits         = 0,\n                                             .stencilBits       = 0,\n                                             .antiAliasingLevel = 0,\n                                             .majorVersion      = 4,\n                                             .minorVersion      = 5,\n                                             .attributeFlags    = sf::ContextSettings::Attribute::Core};\n                auto state = config_.windowed || config_.borderless ? sf::State::Windowed : sf::State::Fullscreen;\n                auto style = config_.borderless ? sf::Style::None : sf::Style::Default;\n                window_.create(mode, u8(print()), style, state, settings);\n#else\n                const auto    window_style = config_.borderless ? sf::Style::None\n                                             : config_.windowed ? sf::Style::Resize | sf::Style::Close\n                                                                : sf::Style::Fullscreen;\n                sf::VideoMode desktop      = sf::VideoMode::getDesktopMode();\n                sf::VideoMode mode(\n                    config_.sbs_key ? screen_width_ * 2 : screen_width_, screen_height_, desktop.bitsPerPixel);\n                window_.create(mode,\n                               u8(print()),\n                               window_style,\n                               sf::ContextSettings(0, 0, 0, 4, 5, sf::ContextSettings::Attribute::Core));\n#endif\n                window_.setPosition(sf::Vector2i(screen_x_, screen_y_));\n                window_.setMouseCursorVisible(config_.interactive);\n                std::ignore = window_.setActive(true);\n\n                if (config_.always_on_top) {\n#ifdef _MSC_VER\n                    HWND hwnd = window_.getSystemHandle();\n                    SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);\n#else\n                    window_always_on_top(window_);\n#endif\n                }\n\n                if (glewInit() != GLEW_OK) {\n                    CASPAR_THROW_EXCEPTION(gl::ogl_exception() << msg_info(\"Failed to initialize GLEW.\"));\n                }\n\n                if (!GLEW_VERSION_4_5 && (glewIsSupported(\"GL_ARB_sync GL_ARB_shader_objects GL_ARB_multitexture \"\n                                                          \"GL_ARB_direct_state_access GL_ARB_texture_barrier\") == 0u)) {\n                    CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\n                                               \"Your graphics card does not meet the minimum hardware requirements \"\n                                               \"since it does not support OpenGL 4.5 or higher.\"));\n                }\n\n                GL(glGenVertexArrays(1, &vao_));\n                GL(glGenBuffers(1, &vbo_));\n                GL(glBindVertexArray(vao_));\n                GL(glBindBuffer(GL_ARRAY_BUFFER, vbo_));\n\n                shader_ = get_shader();\n                shader_->use();\n                shader_->set(\"background\", 0);\n                shader_->set(\"window_width\", screen_width_);\n\n                for (int n = 0; n < 2; ++n) {\n                    frames_.push_back(strategy_->init_frame(config_, format_desc_));\n                }\n\n                GL(glDisable(GL_DEPTH_TEST));\n                GL(glClearColor(0.0, 0.0, 0.0, 0.0));\n                GL(glViewport(\n                    0, 0, config_.sbs_key ? format_desc_.width * 2 : format_desc_.width, format_desc_.height));\n\n                calculate_aspect();\n\n                window_.setVerticalSyncEnabled(config_.vsync);\n                if (config_.vsync) {\n                    CASPAR_LOG(info) << print() << \" Enabled vsync.\";\n                }\n\n                shader_->set(\"colour_space\", config_.colour_space);\n                if (config_.colour_space == configuration::colour_spaces::datavideo_full ||\n                    config_.colour_space == configuration::colour_spaces::datavideo_limited) {\n                    CASPAR_LOG(info) << print() << \" Enabled colours conversion for DataVideo TC-100/TC-200 \"\n                                     << (config_.colour_space == configuration::colour_spaces::datavideo_full\n                                             ? \"(Full Range).\"\n                                             : \"(Limited Range).\");\n                }\n\n                glClear(GL_COLOR_BUFFER_BIT);\n                window_.display();\n\n                while (is_running_) {\n                    tick();\n                }\n            } catch (tbb::user_abort&) {\n                // Do nothing\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n                is_running_ = false;\n            }\n\n            for (auto frame : frames_) {\n                strategy_->cleanup_frame(frame);\n            }\n\n            shader_.reset();\n            GL(glDeleteVertexArrays(1, &vao_));\n            GL(glDeleteBuffers(1, &vbo_));\n\n            window_.close();\n        });\n    }\n\n    ~screen_consumer()\n    {\n        is_running_ = false;\n        frame_buffer_.abort();\n        thread_.join();\n    }\n\n    bool poll()\n    {\n        int count = 0;\n#if SFML_VERSION_MAJOR >= 3\n        while (const auto e = window_.pollEvent()) {\n            count++;\n            if (e->is<sf::Event::Resized>()) {\n                calculate_aspect();\n            } else if (e->is<sf::Event::Closed>()) {\n                is_running_ = false;\n            }\n        }\n#else\n        sf::Event e;\n        while (window_.pollEvent(e)) {\n            count++;\n            if (e.type == sf::Event::Resized) {\n                calculate_aspect();\n            } else if (e.type == sf::Event::Closed) {\n                is_running_ = false;\n            }\n        }\n#endif\n        return count > 0;\n    }\n\n    void tick()\n    {\n        strategy_->do_tick(this);\n\n        window_.display();\n\n        std::rotate(frames_.begin(), frames_.begin() + 1, frames_.end());\n\n        graph_->set_value(\"tick-time\", tick_timer_.elapsed() * format_desc_.fps * 0.5);\n        tick_timer_.restart();\n    }\n\n    void draw()\n    {\n        GL(glBufferData(GL_ARRAY_BUFFER,\n                        static_cast<GLsizeiptr>(sizeof(core::frame_geometry::coord)) * draw_coords_.size(),\n                        draw_coords_.data(),\n                        GL_STATIC_DRAW));\n\n        auto stride = static_cast<GLsizei>(sizeof(core::frame_geometry::coord));\n\n        auto vtx_loc = shader_->get_attrib_location(\"Position\");\n        auto tex_loc = shader_->get_attrib_location(\"TexCoordIn\");\n\n        GL(glEnableVertexAttribArray(vtx_loc));\n        GL(glEnableVertexAttribArray(tex_loc));\n\n        GL(glVertexAttribPointer(vtx_loc, 2, GL_DOUBLE, GL_FALSE, stride, nullptr));\n        GL(glVertexAttribPointer(tex_loc, 4, GL_DOUBLE, GL_FALSE, stride, (GLvoid*)(2 * sizeof(GLdouble))));\n\n        shader_->set(\"window_width\", screen_width_);\n\n        if (config_.sbs_key) {\n            auto coords_size = static_cast<GLsizei>(draw_coords_.size());\n\n            // First half fill\n            shader_->set(\"key_only\", false);\n            GL(glDrawArrays(GL_TRIANGLES, 0, coords_size / 2));\n\n            // Second half key\n            shader_->set(\"key_only\", true);\n            GL(glDrawArrays(GL_TRIANGLES, coords_size / 2, coords_size / 2));\n        } else {\n            shader_->set(\"key_only\", config_.key_only);\n            GL(glDrawArrays(GL_TRIANGLES, 0, static_cast<GLsizei>(draw_coords_.size())));\n        }\n\n        GL(glDisableVertexAttribArray(vtx_loc));\n        GL(glDisableVertexAttribArray(tex_loc));\n        GL(glBindTexture(GL_TEXTURE_2D, 0));\n    }\n\n    std::future<bool> send(core::video_field field, const core::const_frame& frame)\n    {\n        const int MAX_TRIES = 3;\n        int       count     = 0;\n        while (count++ < MAX_TRIES && is_running_) {\n            if (frame_buffer_.try_push(frame))\n                break;\n\n            std::this_thread::sleep_for(std::chrono::milliseconds(1));\n        }\n\n        if (count == MAX_TRIES) {\n            graph_->set_tag(diagnostics::tag_severity::WARNING, \"dropped-frame\");\n        }\n\n        return make_ready_future(is_running_.load());\n    }\n\n    std::wstring channel_and_format() const\n    {\n        return L\"[\" + std::to_wstring(channel_index_) + L\"|\" + format_desc_.name + L\"]\";\n    }\n\n    std::wstring print() const { return config_.name + L\" \" + channel_and_format(); }\n\n    void calculate_aspect()\n    {\n        if (config_.windowed) {\n            screen_height_ = window_.getSize().y;\n            screen_width_  = window_.getSize().x;\n        }\n\n        GL(glViewport(0, 0, screen_width_, screen_height_));\n\n        std::pair<float, float> target_ratio = none();\n        if (config_.stretch == screen::stretch::fill) {\n            target_ratio = Fill();\n        } else if (config_.stretch == screen::stretch::uniform) {\n            target_ratio = uniform();\n        } else if (config_.stretch == screen::stretch::uniform_to_fill) {\n            target_ratio = uniform_to_fill();\n        }\n\n        if (config_.sbs_key) {\n            draw_coords_ = {\n                // First half fill\n                {-target_ratio.first, target_ratio.second, 0.0, 0.0}, // upper left\n                {0, target_ratio.second, 1.0, 0.0},                   // upper right\n                {0, -target_ratio.second, 1.0, 1.0},                  // lower right\n\n                {-target_ratio.first, target_ratio.second, 0.0, 0.0},  // upper left\n                {0, -target_ratio.second, 1.0, 1.0},                   // lower right\n                {-target_ratio.first, -target_ratio.second, 0.0, 1.0}, // lower left\n\n                // Second half key\n                {0, target_ratio.second, 0.0, 0.0},                   // upper left\n                {target_ratio.first, target_ratio.second, 1.0, 0.0},  // upper right\n                {target_ratio.first, -target_ratio.second, 1.0, 1.0}, // lower right\n\n                {0, target_ratio.second, 0.0, 0.0},                   // upper left\n                {target_ratio.first, -target_ratio.second, 1.0, 1.0}, // lower right\n                {0, -target_ratio.second, 0.0, 1.0}                   // lower left\n            };\n        } else {\n            draw_coords_ = {\n                //    vertex    texture\n                {-target_ratio.first, target_ratio.second, 0.0, 0.0}, // upper left\n                {target_ratio.first, target_ratio.second, 1.0, 0.0},  // upper right\n                {target_ratio.first, -target_ratio.second, 1.0, 1.0}, // lower right\n\n                {-target_ratio.first, target_ratio.second, 0.0, 0.0}, // upper left\n                {target_ratio.first, -target_ratio.second, 1.0, 1.0}, // lower right\n                {-target_ratio.first, -target_ratio.second, 0.0, 1.0} // lower left\n            };\n        }\n    }\n\n    std::pair<float, float> none() const\n    {\n        float width =\n            static_cast<float>(config_.sbs_key ? square_width_ * 2 : square_width_) / static_cast<float>(screen_width_);\n        float height = static_cast<float>(square_height_) / static_cast<float>(screen_height_);\n\n        return std::make_pair(width, height);\n    }\n\n    std::pair<float, float> uniform() const\n    {\n        float aspect = static_cast<float>(config_.sbs_key ? square_width_ * 2 : square_width_) /\n                       static_cast<float>(square_height_);\n        float width  = std::min(1.0f, static_cast<float>(screen_height_) * aspect / static_cast<float>(screen_width_));\n        float height = static_cast<float>(screen_width_ * width) / static_cast<float>(screen_height_ * aspect);\n\n        return std::make_pair(width, height);\n    }\n\n    static std::pair<float, float> Fill() { return std::make_pair(1.0f, 1.0f); }\n\n    std::pair<float, float> uniform_to_fill() const\n    {\n        float wr =\n            static_cast<float>(config_.sbs_key ? square_width_ * 2 : square_width_) / static_cast<float>(screen_width_);\n        float hr    = static_cast<float>(square_height_) / static_cast<float>(screen_height_);\n        float r_inv = 1.0f / std::min(wr, hr);\n\n        float width  = wr * r_inv;\n        float height = hr * r_inv;\n\n        return std::make_pair(width, height);\n    }\n};\n\nstruct host_strategy : public display_strategy\n{\n    virtual ~host_strategy() {}\n\n    virtual frame init_frame(const configuration& config, const core::video_format_desc& format_desc) override\n    {\n        screen::frame frame;\n        auto          flags = GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT | GL_MAP_WRITE_BIT;\n        GL(glCreateBuffers(1, &frame.pbo));\n        auto size_multiplier = config.high_bitdepth ? 2 : 1;\n        GL(glNamedBufferStorage(frame.pbo, format_desc.size * size_multiplier, nullptr, flags));\n        frame.ptr = reinterpret_cast<char*>(\n            GL2(glMapNamedBufferRange(frame.pbo, 0, format_desc.size * size_multiplier, flags)));\n\n        GL(glCreateTextures(GL_TEXTURE_2D, 1, &frame.tex));\n        GL(glTextureParameteri(frame.tex,\n                               GL_TEXTURE_MIN_FILTER,\n                               (config.colour_space == configuration::colour_spaces::datavideo_full ||\n                                config.colour_space == configuration::colour_spaces::datavideo_limited)\n                                   ? GL_NEAREST\n                                   : GL_LINEAR));\n        GL(glTextureParameteri(frame.tex,\n                               GL_TEXTURE_MAG_FILTER,\n                               (config.colour_space == configuration::colour_spaces::datavideo_full ||\n                                config.colour_space == configuration::colour_spaces::datavideo_limited)\n                                   ? GL_NEAREST\n                                   : GL_LINEAR));\n        GL(glTextureParameteri(frame.tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));\n        GL(glTextureParameteri(frame.tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));\n        GL(glTextureStorage2D(\n            frame.tex, 1, config.high_bitdepth ? GL_RGBA16 : GL_RGBA8, format_desc.width, format_desc.height));\n        GL(glClearTexImage(\n            frame.tex, 0, GL_BGRA, config.high_bitdepth ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE, nullptr));\n\n        return frame;\n    }\n\n    virtual void cleanup_frame(frame& frame) override\n    {\n        GL(glUnmapNamedBuffer(frame.pbo));\n        glDeleteBuffers(1, &frame.pbo);\n        glDeleteTextures(1, &frame.tex);\n    }\n\n    virtual void do_tick(screen_consumer* self) override\n    {\n        core::const_frame in_frame;\n\n        while (!self->frame_buffer_.try_pop(in_frame) && self->is_running_) {\n            // TODO (fix)\n            if (!self->poll()) {\n                std::this_thread::sleep_for(std::chrono::milliseconds(2));\n            }\n        }\n\n        if (!in_frame) {\n            return;\n        }\n\n        // Upload\n        {\n            auto& frame = self->frames_.front();\n\n            while (frame.fence != nullptr) {\n                auto wait = glClientWaitSync(frame.fence, 0, 0);\n                if (wait == GL_ALREADY_SIGNALED || wait == GL_CONDITION_SATISFIED) {\n                    glDeleteSync(frame.fence);\n                    frame.fence = nullptr;\n                }\n                if (!self->poll()) {\n                    // TODO (fix)\n                    std::this_thread::sleep_for(std::chrono::milliseconds(2));\n                }\n            }\n\n            auto size_multiplier = self->config_.high_bitdepth ? 2 : 1;\n            std::memcpy(frame.ptr, in_frame.image_data(0).begin(), self->format_desc_.size * size_multiplier);\n\n            GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, frame.pbo));\n            GL(glTextureSubImage2D(frame.tex,\n                                   0,\n                                   0,\n                                   0,\n                                   self->format_desc_.width,\n                                   self->format_desc_.height,\n                                   GL_BGRA,\n                                   self->config_.high_bitdepth ? GL_UNSIGNED_SHORT : GL_UNSIGNED_BYTE,\n                                   nullptr));\n            GL(glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0));\n\n            frame.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\n        }\n\n        // Display\n        {\n            auto& frame = self->frames_.back();\n\n            GL(glClear(GL_COLOR_BUFFER_BIT));\n\n            GL(glActiveTexture(GL_TEXTURE0));\n            GL(glBindTexture(GL_TEXTURE_2D, frame.tex));\n\n            self->draw();\n        }\n    }\n};\n\nstruct gpu_strategy : public display_strategy\n{\n    virtual ~gpu_strategy() {}\n    virtual frame init_frame(const configuration& config, const core::video_format_desc& format_desc) override\n    {\n        return frame();\n    }\n    virtual void cleanup_frame(frame& frame) override\n    {\n        if (frame.fence) {\n            glDeleteSync(frame.fence);\n            frame.fence = nullptr;\n        }\n        frame.texture.reset();\n    }\n\n    virtual void do_tick(screen_consumer* self) override\n    {\n        core::const_frame in_frame;\n\n        self->poll();\n\n        while (!self->frame_buffer_.try_pop(in_frame) && self->is_running_) {\n            // TODO (fix)\n            if (!self->poll()) {\n                std::this_thread::sleep_for(std::chrono::milliseconds(2));\n            }\n        }\n\n        // Display\n        {\n            auto& frame = self->frames_.front();\n\n            while (frame.fence != nullptr && self->is_running_) {\n                auto wait = glClientWaitSync(frame.fence, 0, 0);\n                if (wait == GL_ALREADY_SIGNALED || wait == GL_CONDITION_SATISFIED) {\n                    glDeleteSync(frame.fence);\n                    frame.fence = nullptr;\n                    frame.texture.reset();\n                }\n\n                if (!self->poll()) {\n                    // TODO (fix)\n                    std::this_thread::sleep_for(std::chrono::milliseconds(2));\n                }\n            }\n\n            if (!in_frame || !self->is_running_) {\n                self->graph_->set_value(\"tick-time\", self->tick_timer_.elapsed() * self->format_desc_.fps * 0.5);\n                self->tick_timer_.restart();\n                return;\n            }\n\n            GL(glClear(GL_COLOR_BUFFER_BIT));\n\n            if (in_frame.texture()) {\n                in_frame.texture()->bind(0);\n\n                self->draw();\n\n                frame.fence   = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);\n                frame.texture = in_frame.texture();\n            }\n        }\n    }\n};\n\nstruct screen_consumer_proxy : public core::frame_consumer\n{\n    const configuration              config_;\n    std::unique_ptr<screen_consumer> consumer_;\n\n  public:\n    explicit screen_consumer_proxy(configuration config)\n        : config_(std::move(config))\n    {\n    }\n\n    // frame_consumer\n\n    void initialize(const core::video_format_desc& format_desc,\n                    const core::channel_info&      channel_info,\n                    int                            port_index) override\n    {\n        consumer_.reset();\n        consumer_ = std::make_unique<screen_consumer>(config_, format_desc, channel_info.index);\n    }\n\n    std::future<bool> send(core::video_field field, core::const_frame frame) override\n    {\n        return consumer_->send(field, frame);\n    }\n\n    std::wstring print() const override { return consumer_ ? consumer_->print() : L\"[screen_consumer]\"; }\n\n    std::wstring name() const override { return L\"screen\"; }\n\n    bool has_synchronization_clock() const override { return false; }\n\n    int index() const override { return 600 + (config_.key_only ? 10 : 0) + config_.screen_index; }\n\n    core::monitor::state state() const override\n    {\n        core::monitor::state state;\n        state[\"screen/name\"]          = config_.name;\n        state[\"screen/index\"]         = config_.screen_index;\n        state[\"screen/key_only\"]      = config_.key_only;\n        state[\"screen/always_on_top\"] = config_.always_on_top;\n        return state;\n    }\n};\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info)\n{\n    if (params.empty() || !boost::iequals(params.at(0), L\"SCREEN\")) {\n        return core::frame_consumer::empty();\n    }\n\n    configuration config;\n\n    config.high_bitdepth = (channel_info.depth != common::bit_depth::bit8);\n\n    if (params.size() > 1) {\n        try {\n            config.screen_index = std::stoi(params.at(1));\n        } catch (...) {\n        }\n    }\n\n    config.windowed    = !contains_param(L\"FULLSCREEN\", params);\n    config.gpu_texture = contains_param(L\"GPU\", params);\n    config.key_only    = contains_param(L\"KEY_ONLY\", params);\n    config.sbs_key     = contains_param(L\"SBS_KEY\", params);\n    config.interactive = !contains_param(L\"NON_INTERACTIVE\", params);\n    config.borderless  = contains_param(L\"BORDERLESS\", params);\n\n    if (contains_param(L\"NAME\", params)) {\n        config.name = get_param(L\"NAME\", params);\n    }\n\n    if (contains_param(L\"X\", params)) {\n        config.screen_x = get_param(L\"X\", params, 0);\n    }\n    if (contains_param(L\"Y\", params)) {\n        config.screen_y = get_param(L\"Y\", params, 0);\n    }\n    if (contains_param(L\"WIDTH\", params)) {\n        config.screen_width = get_param(L\"WIDTH\", params, 0);\n    }\n    if (contains_param(L\"HEIGHT\", params)) {\n        config.screen_height = get_param(L\"HEIGHT\", params, 0);\n    }\n\n    if (config.sbs_key && config.key_only) {\n        CASPAR_LOG(warning) << L\" Key-only not supported with configuration of side-by-side fill and key. Ignored.\";\n        config.key_only = false;\n    }\n\n    return spl::make_shared<screen_consumer_proxy>(config);\n}\n\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info)\n{\n    configuration config;\n\n    config.high_bitdepth = (channel_info.depth != common::bit_depth::bit8);\n\n    config.name          = ptree.get(L\"name\", config.name);\n    config.screen_index  = ptree.get(L\"device\", config.screen_index + 1) - 1;\n    config.screen_x      = ptree.get(L\"x\", config.screen_x);\n    config.screen_y      = ptree.get(L\"y\", config.screen_y);\n    config.screen_width  = ptree.get(L\"width\", config.screen_width);\n    config.screen_height = ptree.get(L\"height\", config.screen_height);\n    config.windowed      = ptree.get(L\"windowed\", config.windowed);\n    config.key_only      = ptree.get(L\"key-only\", config.key_only);\n    config.sbs_key       = ptree.get(L\"sbs-key\", config.sbs_key);\n    config.vsync         = ptree.get(L\"vsync\", config.vsync);\n    config.interactive   = ptree.get(L\"interactive\", config.interactive);\n    config.borderless    = ptree.get(L\"borderless\", config.borderless);\n    config.always_on_top = ptree.get(L\"always-on-top\", config.always_on_top);\n    config.gpu_texture   = ptree.get(L\"gpu-texture\", config.gpu_texture);\n\n    auto colour_space_value = ptree.get(L\"colour-space\", L\"RGB\");\n    config.colour_space     = configuration::colour_spaces::RGB;\n    if (colour_space_value == L\"datavideo-full\")\n        config.colour_space = configuration::colour_spaces::datavideo_full;\n    else if (colour_space_value == L\"datavideo-limited\")\n        config.colour_space = configuration::colour_spaces::datavideo_limited;\n\n    if (config.sbs_key && config.key_only) {\n        CASPAR_LOG(warning) << L\" Key-only not supported with configuration of side-by-side fill and key. Ignored.\";\n        config.key_only = false;\n    }\n\n    if ((config.colour_space == configuration::colour_spaces::datavideo_full ||\n         config.colour_space == configuration::colour_spaces::datavideo_limited) &&\n        config.sbs_key) {\n        CASPAR_LOG(warning) << L\" Side-by-side fill and key not supported for DataVideo TC100/TC200. Ignored.\";\n        config.sbs_key = false;\n    }\n\n    if ((config.colour_space == configuration::colour_spaces::datavideo_full ||\n         config.colour_space == configuration::colour_spaces::datavideo_limited) &&\n        config.key_only) {\n        CASPAR_LOG(warning) << L\" Key only not supported for DataVideo TC100/TC200. Ignored.\";\n        config.key_only = false;\n    }\n\n    auto stretch_str = ptree.get(L\"stretch\", L\"fill\");\n    if (stretch_str == L\"none\") {\n        config.stretch = screen::stretch::none;\n    } else if (stretch_str == L\"uniform\") {\n        config.stretch = screen::stretch::uniform;\n    } else if (stretch_str == L\"uniform_to_fill\") {\n        config.stretch = screen::stretch::uniform_to_fill;\n    }\n\n    auto aspect_str = ptree.get(L\"aspect-ratio\", L\"default\");\n    if (aspect_str == L\"16:9\") {\n        config.aspect = configuration::aspect_ratio::aspect_16_9;\n    } else if (aspect_str == L\"4:3\") {\n        config.aspect = configuration::aspect_ratio::aspect_4_3;\n    }\n\n    return spl::make_shared<screen_consumer_proxy>(config);\n}\n\n}} // namespace caspar::screen\n"
  },
  {
    "path": "src/modules/screen/consumer/screen_consumer.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <common/bit_depth.h>\n#include <common/memory.h>\n\n#include <core/fwd.h>\n\n#include <boost/property_tree/ptree_fwd.hpp>\n#include <vector>\n\nnamespace caspar { namespace screen {\n\nspl::shared_ptr<core::frame_consumer> create_consumer(const std::vector<std::wstring>&     params,\n                                                      const core::video_format_repository& format_repository,\n                                                      const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                                                      const core::channel_info& channel_info);\nspl::shared_ptr<core::frame_consumer>\ncreate_preconfigured_consumer(const boost::property_tree::wptree&                      ptree,\n                              const core::video_format_repository&                     format_repository,\n                              const std::vector<spl::shared_ptr<core::video_channel>>& channels,\n                              const core::channel_info&                                channel_info);\n\n}} // namespace caspar::screen\n"
  },
  {
    "path": "src/modules/screen/screen.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"screen.h\"\n\n#include \"consumer/screen_consumer.h\"\n\n#include <core/consumer/frame_consumer.h>\n\nnamespace caspar { namespace screen {\n\nvoid init(const core::module_dependencies& dependencies)\n{\n    dependencies.consumer_registry->register_consumer_factory(L\"Screen Consumer\", create_consumer);\n    dependencies.consumer_registry->register_preconfigured_consumer_factory(L\"screen\", create_preconfigured_consumer);\n}\n\n}} // namespace caspar::screen\n"
  },
  {
    "path": "src/modules/screen/screen.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <core/module_dependencies.h>\n\nnamespace caspar { namespace screen {\n\nvoid init(const core::module_dependencies& dependencies);\n\n}} // namespace caspar::screen\n"
  },
  {
    "path": "src/modules/screen/util/x11_util.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, git@julusian.co.uk\n */\n\n#include \"x11_util.h\"\n\n#include <X11/X.h>\n#include <X11/Xlib.h>\n\nbool window_always_on_top(const sf::Window& window)\n{\n    Display* disp = XOpenDisplay(nullptr);\n    if (!disp)\n        return false;\n\n#if SFML_VERSION_MAJOR >= 3\n    Window win = window.getNativeHandle();\n#else\n    Window win = window.getSystemHandle();\n#endif\n\n    Atom   wm_state, wm_state_above;\n    XEvent event;\n\n    if ((wm_state = XInternAtom(disp, \"_NET_WM_STATE\", False)) != None) {\n        if ((wm_state_above = XInternAtom(disp, \"_NET_WM_STATE_ABOVE\", False)) != None) {\n            event.xclient.type         = ClientMessage;\n            event.xclient.serial       = 0;\n            event.xclient.send_event   = True;\n            event.xclient.display      = disp;\n            event.xclient.window       = win;\n            event.xclient.message_type = wm_state;\n            event.xclient.format       = 32;\n            event.xclient.data.l[0]    = 1;\n            event.xclient.data.l[1]    = wm_state_above;\n            event.xclient.data.l[2]    = 0;\n            event.xclient.data.l[3]    = 0;\n            event.xclient.data.l[4]    = 0;\n\n            XSendEvent(disp, DefaultRootWindow(disp), False, SubstructureRedirectMask | SubstructureNotifyMask, &event);\n        }\n    }\n\n    XCloseDisplay(disp);\n    return true;\n}\n"
  },
  {
    "path": "src/modules/screen/util/x11_util.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, git@julusian.co.uk\n */\n\n#pragma once\n\n#include <SFML/Window.hpp>\n\nbool window_always_on_top(const sf::Window& window);\n"
  },
  {
    "path": "src/protocol/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (protocol)\n\nset(SOURCES\n\t\tamcp/AMCPCommand.cpp\n\t\tamcp/AMCPCommandQueue.cpp\n\t\tamcp/AMCPCommandsImpl.cpp\n\t\tamcp/AMCPProtocolStrategy.cpp\n\t\tamcp/amcp_command_repository.cpp\n\t\tamcp/amcp_args.cpp\n\t\tamcp/amcp_command_repository_wrapper.cpp\n\n\t\tosc/oscpack/OscOutboundPacketStream.cpp\n\t\tosc/oscpack/OscPrintReceivedElements.cpp\n\t\tosc/oscpack/OscReceivedElements.cpp\n\t\tosc/oscpack/OscTypes.cpp\n\n\t\tosc/client.cpp\n\n\t\tutil/AsyncEventServer.cpp\n\t\tutil/lock_container.cpp\n\t\tutil/strategy_adapters.cpp\n\t\tutil/http_request.cpp\n\t\tutil/tokenize.cpp\n)\n\nset(HEADERS\n\t\tamcp/AMCPCommand.h\n\t\tamcp/AMCPCommandQueue.h\n\t\tamcp/AMCPCommandsImpl.h\n\t\tamcp/AMCPProtocolStrategy.h\n\t\tamcp/amcp_command_repository.h\n\t\tamcp/amcp_command_repository_wrapper.h\n\t\tamcp/amcp_shared.h\n\t\tamcp/amcp_args.h\n\t\tamcp/amcp_command_context.h\n\n\t\tosc/oscpack/MessageMappingOscPacketListener.h\n\t\tosc/oscpack/OscException.h\n\t\tosc/oscpack/OscHostEndianness.h\n\t\tosc/oscpack/OscOutboundPacketStream.h\n\t\tosc/oscpack/OscPacketListener.h\n\t\tosc/oscpack/OscPrintReceivedElements.h\n\t\tosc/oscpack/OscReceivedElements.h\n\t\tosc/oscpack/OscTypes.h\n\n\t\tosc/client.h\n\n\t\tutil/AsyncEventServer.h\n\t\tutil/ClientInfo.h\n\t\tutil/lock_container.h\n\t\tutil/ProtocolStrategy.h\n\t\tutil/protocol_strategy.h\n\t\tutil/strategy_adapters.h\n\t\tutil/http_request.h\n\t\tutil/tokenize.h\n\n\t\tStdAfx.h\n)\n\ncasparcg_add_library(protocol SOURCES ${SOURCES} ${HEADERS})\ntarget_include_directories(protocol  PRIVATE\n    ..\n    )\ntarget_precompile_headers(protocol PRIVATE \"StdAfx.h\")\n\nsource_group(sources\\\\amcp amcp/*)\nsource_group(sources\\\\cii cii/*)\nsource_group(sources\\\\clk clk/*)\nsource_group(sources\\\\log log/*)\nsource_group(sources\\\\osc\\\\oscpack osc/oscpack/*)\nsource_group(sources\\\\osc osc/*)\nsource_group(sources\\\\util util/*)\nsource_group(sources ./*)\n\ntarget_link_libraries(protocol PRIVATE common core)\n"
  },
  {
    "path": "src/protocol/StdAfx.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#define NOMINMAX\n#define WIN32_LEAN_AND_MEAN\n\n#if defined(_MSC_VER)\n#ifndef _SCL_SECURE_NO_WARNINGS\n#define _SCL_SECURE_NO_WARNINGS\n#endif\n#ifndef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n#endif\n#endif\n\n#if defined _DEBUG && defined _MSC_VER\n#include <crtdbg.h>\n#endif\n\n#include <algorithm>\n#include <cmath>\n#include <cstdint>\n#include <deque>\n#include <functional>\n#include <memory>\n#include <queue>\n#include <set>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include <boost/asio.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/range/algorithm.hpp>\n\n#include <common/memory.h>\n#include <common/utf.h>\n\n#include <common/except.h>\n#include <common/log.h>\n\n#include <cassert>\n"
  },
  {
    "path": "src/protocol/amcp/AMCPCommand.cpp",
    "content": "/*\n * Copyright (c) 2018 Norsk rikskringkasting AS\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"../StdAfx.h\"\n\n#include \"AMCPCommand.h\"\n#include <core/producer/stage.h>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nstd::future<std::wstring> AMCPCommand::Execute(const spl::shared_ptr<std::vector<channel_context>>& channels)\n{\n    return command_(ctx_, channels);\n}\n\nvoid send_reply(IO::ClientInfoPtrStd client, const std::wstring& str, const std::wstring& request_id)\n{\n    if (str.empty())\n        return;\n\n    std::wstring reply = str;\n    if (!request_id.empty())\n        reply = L\"RES \" + request_id + L\" \" + str;\n\n    client->send(std::move(reply));\n}\n\nvoid AMCPCommand::SendReply(const std::wstring& str, bool reply_without_req_id) const\n{\n    if (reply_without_req_id || !request_id_.empty()) {\n        send_reply(ctx_.client, str, request_id_);\n    }\n}\n\nvoid AMCPGroupCommand::SendReply(const std::wstring& str) const\n{\n    if (client_) {\n        send_reply(client_, str, request_id_);\n        return;\n    }\n\n    if (commands_.size() == 1) {\n        commands_.at(0)->SendReply(str, true);\n    }\n}\n\nstd::wstring AMCPGroupCommand::name() const\n{\n    if (commands_.size() == 1) {\n        return commands_.at(0)->name();\n    }\n\n    return L\"BATCH\";\n}\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPCommand.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#pragma once\n\n#include \"../util/ClientInfo.h\"\n#include \"amcp_shared.h\"\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nclass AMCPCommand\n{\n  private:\n    const command_context_simple ctx_;\n    const amcp_command_func      command_;\n    const std::wstring           name_;\n    const std::wstring           request_id_;\n\n  public:\n    AMCPCommand(const command_context_simple& ctx,\n                const amcp_command_func&      command,\n                const std::wstring&           name,\n                const std::wstring&           request_id)\n\n        : ctx_(ctx)\n        , command_(command)\n        , name_(name)\n        , request_id_(request_id)\n    {\n    }\n\n    using ptr_type = std::shared_ptr<AMCPCommand>;\n\n    std::future<std::wstring> Execute(const spl::shared_ptr<std::vector<channel_context>>& channels);\n\n    void SendReply(const std::wstring& str, bool reply_without_req_id) const;\n\n    const std::vector<std::wstring>& parameters() const { return ctx_.parameters; }\n\n    int channel_index() const { return ctx_.channel_index; }\n\n    IO::ClientInfoPtr client() const { return ctx_.client; }\n\n    const std::wstring& name() const { return name_; }\n};\n\nclass AMCPGroupCommand\n{\n    const std::vector<std::shared_ptr<AMCPCommand>> commands_;\n    const IO::ClientInfoPtrStd                      client_;\n    const std::wstring                              request_id_;\n    const bool                                      is_batch_;\n\n  public:\n    AMCPGroupCommand(const std::vector<std::shared_ptr<AMCPCommand>> commands,\n                     IO::ClientInfoPtrStd                            client,\n                     const std::wstring&                             request_id)\n        : commands_(commands)\n        , client_(client)\n        , request_id_(request_id)\n        , is_batch_(true)\n    {\n    }\n\n    AMCPGroupCommand(const std::vector<std::shared_ptr<AMCPCommand>> commands)\n        : commands_(commands)\n        , client_(nullptr)\n        , request_id_(L\"\")\n        , is_batch_(true)\n    {\n    }\n\n    AMCPGroupCommand(const std::shared_ptr<AMCPCommand> command)\n        : commands_({command})\n        , client_(nullptr)\n        , request_id_(L\"\")\n        , is_batch_(false)\n    {\n    }\n\n    bool HasClient() const { return !!client_; }\n\n    void SendReply(const std::wstring& str) const;\n\n    std::wstring name() const;\n\n    std::vector<std::shared_ptr<AMCPCommand>> Commands() const { return commands_; }\n};\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPCommandQueue.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#include \"../StdAfx.h\"\n\n#include \"AMCPCommandQueue.h\"\n\n#include <boost/lexical_cast.hpp>\n#include <common/except.h>\n#include <common/future.h>\n#include <common/timer.h>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nAMCPCommandQueue::AMCPCommandQueue(const std::wstring&                                  name,\n                                   const spl::shared_ptr<std::vector<channel_context>>& channels)\n    : executor_(L\"AMCPCommandQueue \" + name)\n    , channels_(channels)\n{\n}\n\nAMCPCommandQueue::~AMCPCommandQueue() {}\n\nstd::future<bool> exec_cmd(std::shared_ptr<AMCPCommand>                         cmd,\n                           const spl::shared_ptr<std::vector<channel_context>>& channels,\n                           bool                                                 reply_without_req_id)\n{\n    try {\n        try {\n            caspar::timer timer;\n\n            auto name = cmd->name();\n            CASPAR_LOG(debug) << \"Executing command: \" << name;\n\n            auto res = cmd->Execute(channels).share();\n            return std::async(std::launch::async, [cmd, res, reply_without_req_id, timer, name]() -> bool {\n                cmd->SendReply(res.get(), reply_without_req_id);\n\n                CASPAR_LOG(debug) << \"Executed command (\" << timer.elapsed() << \"s): \" << name;\n                return true;\n            });\n\n        } catch (file_not_found&) {\n            CASPAR_LOG(error) << \" File not found.\";\n            cmd->SendReply(L\"404 \" + cmd->name() + L\" FAILED\\r\\n\", reply_without_req_id);\n        } catch (expected_user_error&) {\n            cmd->SendReply(L\"403 \" + cmd->name() + L\" FAILED\\r\\n\", reply_without_req_id);\n        } catch (user_error&) {\n            CASPAR_LOG(error) << \" Check syntax.\";\n            cmd->SendReply(L\"403 \" + cmd->name() + L\" FAILED\\r\\n\", reply_without_req_id);\n        } catch (std::out_of_range&) {\n            CASPAR_LOG(error) << L\"Missing parameter. Check syntax.\";\n            cmd->SendReply(L\"402 \" + cmd->name() + L\" FAILED\\r\\n\", reply_without_req_id);\n        } catch (boost::bad_lexical_cast&) {\n            CASPAR_LOG(error) << L\"Invalid parameter. Check syntax.\";\n            cmd->SendReply(L\"403 \" + cmd->name() + L\" FAILED\\r\\n\", reply_without_req_id);\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n            CASPAR_LOG(error) << \"Failed to execute command: \" << cmd->name();\n            cmd->SendReply(L\"501 \" + cmd->name() + L\" FAILED\\r\\n\", reply_without_req_id);\n        }\n\n    } catch (...) {\n        CASPAR_LOG_CURRENT_EXCEPTION();\n    }\n\n    return make_ready_future(false);\n}\n\nvoid AMCPCommandQueue::AddCommand(std::shared_ptr<AMCPGroupCommand> pCurrentCommand)\n{\n    if (!pCurrentCommand)\n        return;\n\n    if (executor_.size() > 128) {\n        try {\n            CASPAR_LOG(error) << \"AMCP Command Queue Overflow.\";\n            CASPAR_LOG(error) << \"Failed to execute command:\" << pCurrentCommand->name();\n            pCurrentCommand->SendReply(L\"504 QUEUE OVERFLOW\\r\\n\");\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n        return;\n    }\n\n    executor_.begin_invoke([=, this] {\n        try {\n            Execute(pCurrentCommand);\n\n            CASPAR_LOG(trace) << \"Ready for a new command\";\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n    });\n}\n\nvoid AMCPCommandQueue::Execute(std::shared_ptr<AMCPGroupCommand> cmd) const\n{\n    if (cmd->Commands().empty())\n        return;\n\n    // Shortcut for commands which are either not a batch, or don't need to be\n    if (cmd->Commands().size() == 1) {\n        exec_cmd(cmd->Commands().at(0), channels_, true);\n        return;\n    }\n\n    caspar::timer timer;\n    CASPAR_LOG(warning) << \"Executing batch: \" << cmd->name() << L\"(\" << cmd->Commands().size() << L\" commands)\";\n\n    spl::shared_ptr<std::vector<channel_context>>     delayed_channels;\n    std::vector<std::shared_ptr<core::stage_delayed>> delayed_stages;\n    std::vector<std::future<bool>>                    results;\n    std::vector<std::unique_lock<std::mutex>>         channel_locks;\n\n    try {\n        for (auto& ch : *channels_) {\n            auto st = std::make_shared<core::stage_delayed>(ch.raw_channel->stage(), ch.raw_channel->index());\n            delayed_stages.push_back(st);\n            delayed_channels->emplace_back(ch.raw_channel, st, ch.lifecycle_key_);\n        }\n\n        // 'execute' aka queue all commands\n        for (auto& cmd2 : cmd->Commands()) {\n            results.push_back(exec_cmd(cmd2, delayed_channels, cmd->HasClient()));\n        }\n\n        // lock all the channels needed\n        for (auto& st : delayed_stages) {\n            if (st->count_queued() == 0) {\n                continue;\n            }\n\n            channel_locks.push_back(st->get_lock());\n        }\n\n        // execute the commands\n        for (auto& st : delayed_stages) {\n            st->release();\n        }\n    } catch (...) {\n        // Ensure the created executors don't get leaked\n        for (auto& st : delayed_stages) {\n            st->abort();\n        }\n\n        throw;\n    }\n\n    // wait for the commands to finish\n    for (auto& st : delayed_stages) {\n        st->wait();\n    }\n    channel_locks.clear();\n\n    int failed = 0;\n    for (auto& f : results) {\n        if (!f.get())\n            failed++;\n    }\n\n    if (failed > 0)\n        cmd->SendReply(L\"202 COMMIT PARTIAL\\r\\n\");\n    else\n        cmd->SendReply(L\"202 COMMIT OK\\r\\n\");\n\n    CASPAR_LOG(debug) << \"Executed batch (\" << timer.elapsed() << \"s): \" << cmd->name();\n}\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPCommandQueue.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#pragma once\n\n#include \"AMCPCommand.h\"\n\n#include <common/executor.h>\n#include <common/memory.h>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nclass AMCPCommandQueue\n{\n  public:\n    using ptr_type = spl::shared_ptr<AMCPCommandQueue>;\n\n    AMCPCommandQueue(const std::wstring& name, const spl::shared_ptr<std::vector<channel_context>>& channels);\n    ~AMCPCommandQueue();\n\n    void AddCommand(std::shared_ptr<AMCPGroupCommand> command);\n    void Execute(std::shared_ptr<AMCPGroupCommand> cmd) const;\n\n  private:\n    executor                                            executor_;\n    const spl::shared_ptr<std::vector<channel_context>> channels_;\n};\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPCommandsImpl.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#include \"../StdAfx.h\"\n\n#include \"AMCPCommandsImpl.h\"\n\n#include \"../util/http_request.h\"\n#include \"AMCPCommandQueue.h\"\n#include \"amcp_args.h\"\n\n#include <common/env.h>\n\n#include <common/base64.h>\n#include <common/filesystem.h>\n#include <common/future.h>\n#include <common/log.h>\n#include <common/os/filesystem.h>\n#include <common/param.h>\n\n#include <core/consumer/frame_consumer.h>\n#include <core/consumer/frame_consumer_registry.h>\n#include <core/consumer/output.h>\n#include <core/diagnostics/call_context.h>\n#include <core/diagnostics/osd_graph.h>\n#include <core/frame/frame_transform.h>\n#include <core/mixer/mixer.h>\n#include <core/producer/cg_proxy.h>\n#include <core/producer/color/color_producer.h>\n#include <core/producer/frame_producer.h>\n#include <core/producer/frame_producer_registry.h>\n#include <core/producer/stage.h>\n#include <core/producer/transition/sting_producer.h>\n#include <core/producer/transition/transition_producer.h>\n#include <core/video_format.h>\n\n#include <protocol/osc/client.h>\n\n#include <algorithm>\n#include <fstream>\n#include <future>\n#include <memory>\n\n#if defined(__GNUC__) && __GNUC__ == 14\n#pragma GCC diagnostic push\n#pragma GCC diagnostic ignored \"-Wstringop-overflow\"\n#endif\n#include <boost/algorithm/string.hpp>\n#include <boost/algorithm/string/regex.hpp>\n#include <boost/archive/iterators/base64_from_binary.hpp>\n#include <boost/archive/iterators/insert_linebreaks.hpp>\n#include <boost/date_time/posix_time/posix_time.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/filesystem/fstream.hpp>\n#include <boost/lexical_cast.hpp>\n#include <boost/locale.hpp>\n#include <boost/property_tree/ptree.hpp>\n#include <boost/property_tree/xml_parser.hpp>\n#include <boost/range/adaptor/transformed.hpp>\n#include <boost/range/algorithm/copy.hpp>\n#include <boost/regex.hpp>\n#if defined(__GNUC__) && __GNUC__ == 14\n#pragma GCC diagnostic pop\n#endif\n\n#include <tbb/concurrent_unordered_map.h>\n\n/* Return codes\n\n102 [action]\t\t\tInformation that [action] has happened\n101 [action]\t\t\tInformation that [action] has happened plus one row of data\n\n202 [command] OK\t\t[command] has been executed\n201 [command] OK\t\t[command] has been executed, plus one row of data\n200 [command] OK\t\t[command] has been executed, plus multiple lines of data. ends with an empty line\n\n400 ERROR\t\t\t\tthe command could not be understood\n401 [command] ERROR\t\tinvalid/missing channel\n402 [command] ERROR\t\tparameter missing\n403 [command] ERROR\t\tinvalid parameter\n404 [command] ERROR\t\tfile not found\n\n500 FAILED\t\t\t\t\t\tinternal error\n501 [command] FAILED\t\t\tinternal error\n502 [command] FAILED\t\t\tcould not read file\n503 [command] FAILED\t\t\taccess denied\n504 [command] QUEUE OVERFLOW\tcommand queue overflow\n\n600 [command] FAILED\t[command] not implemented\n*/\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nusing namespace core;\nnamespace pt = boost::property_tree;\n\nstd::wstring read_utf8_file(const boost::filesystem::path& file)\n{\n    std::wstringstream           result;\n    boost::filesystem::wifstream filestream(file);\n\n    if (filestream) {\n        // Consume BOM first\n        filestream.get();\n        // read all data\n        result << filestream.rdbuf();\n    }\n\n    return result.str();\n}\n\nstd::wstring read_latin1_file(const boost::filesystem::path& file)\n{\n    boost::locale::generator gen;\n    gen.locale_cache_enabled(true);\n    gen.categories(boost::locale::category_t::codepage);\n\n    std::stringstream           result_stream;\n    boost::filesystem::ifstream filestream(file);\n    filestream.imbue(gen(\"en_US.ISO8859-1\"));\n\n    if (filestream) {\n        // read all data\n        result_stream << filestream.rdbuf();\n    }\n\n    std::string  result = result_stream.str();\n    std::wstring widened_result;\n\n    // The first 255 codepoints in unicode is the same as in latin1\n    boost::copy(result | boost::adaptors::transformed([](char c) { return static_cast<unsigned char>(c); }),\n                std::back_inserter(widened_result));\n\n    return widened_result;\n}\n\nstd::wstring read_file(const boost::filesystem::path& file)\n{\n    static const uint8_t BOM[] = {0xef, 0xbb, 0xbf};\n\n    if (!boost::filesystem::exists(file)) {\n        return L\"\";\n    }\n\n    if (boost::filesystem::file_size(file) >= 3) {\n        boost::filesystem::ifstream bom_stream(file);\n\n        char header[3];\n        bom_stream.read(header, 3);\n        bom_stream.close();\n\n        if (std::memcmp(BOM, header, 3) == 0)\n            return read_utf8_file(file);\n    }\n\n    return read_latin1_file(file);\n}\n\nstd::wstring get_sub_directory(const std::wstring& base_folder, const std::wstring& sub_directory)\n{\n    if (sub_directory.empty())\n        return base_folder;\n\n    auto found = find_case_insensitive(base_folder + L\"/\" + sub_directory);\n\n    if (!found)\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L\"Sub directory \" + sub_directory + L\" not found.\"));\n\n    return *found;\n}\n\nstd::vector<spl::shared_ptr<core::video_channel>> get_channels(const command_context& ctx)\n{\n    std::vector<spl::shared_ptr<core::video_channel>> result;\n    for (auto& cc : *ctx.channels) {\n        result.emplace_back(cc.raw_channel);\n    }\n    return result;\n}\n\ncore::frame_producer_dependencies get_producer_dependencies(const std::shared_ptr<core::video_channel>& channel,\n                                                            const command_context&                      ctx)\n{\n    return core::frame_producer_dependencies(channel->frame_factory(),\n                                             get_channels(ctx),\n                                             ctx.static_context->format_repository,\n                                             channel->stage()->video_format_desc(),\n                                             ctx.static_context->producer_registry,\n                                             ctx.static_context->cg_registry);\n}\n\nbool try_match_sting(const std::vector<std::wstring>& params, sting_info& stingInfo)\n{\n    auto match = std::find_if(params.begin(), params.end(), param_comparer(L\"STING\"));\n    if (match == params.end())\n        return false;\n\n    auto start_ind = static_cast<int>(match - params.begin());\n\n    if (params.size() <= start_ind + 1) {\n        // No mask filename\n        return false;\n    }\n\n    auto params_token = params.at(start_ind + 1);\n    if (is_args_token(params_token)) {\n        auto args = tokenize_args(params_token);\n\n        std::wstring val;\n        if (!get_arg_value(args, L\"MASK\", val)) {\n            // TODO - throw error?\n            // No mask filename\n            return false;\n        }\n        stingInfo.mask_filename = val;\n\n        if (get_arg_value(args, L\"trigger_point\", val)) {\n            int val2 = boost::lexical_cast<int>(val);\n            if (val2 > 0) {\n                stingInfo.trigger_point = val2;\n            }\n        }\n        if (get_arg_value(args, L\"overlay\", val)) {\n            stingInfo.overlay_filename = val;\n        }\n\n        if (get_arg_value(args, L\"audio_fade_start\", val)) {\n            int val2 = boost::lexical_cast<int>(val);\n            if (val2 > 0) {\n                stingInfo.audio_fade_start = val2;\n            }\n        }\n        if (get_arg_value(args, L\"audio_fade_duration\", val)) {\n            int val2 = boost::lexical_cast<int>(val);\n            if (val2 > 0) {\n                stingInfo.audio_fade_duration = val2;\n            }\n        }\n\n    } else {\n        stingInfo.mask_filename = params.at(start_ind + 1);\n\n        if (params.size() > start_ind + 2) {\n            stingInfo.trigger_point = boost::lexical_cast<int>(params.at(start_ind + 2));\n        }\n\n        if (params.size() > start_ind + 3) {\n            stingInfo.overlay_filename = params.at(start_ind + 3);\n        }\n    }\n\n    return true;\n}\n\n// Basic Commands\n\nstd::wstring loadbg_command(command_context& ctx)\n{\n    // Perform loading of the clip\n    core::diagnostics::scoped_call_context save;\n    core::diagnostics::call_context::for_thread().video_channel = ctx.channel_index + 1;\n    core::diagnostics::call_context::for_thread().layer         = ctx.layer_index();\n\n    auto channel   = ctx.channel.raw_channel;\n    bool auto_play = contains_param(L\"AUTO\", ctx.parameters);\n\n    try {\n        auto new_producer = ctx.static_context->producer_registry->create_producer(\n            get_producer_dependencies(channel, ctx), ctx.parameters);\n\n        if (new_producer == frame_producer::empty())\n            CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(!ctx.parameters.empty() ? ctx.parameters[0] : L\"\"));\n\n        spl::shared_ptr<frame_producer> transition_producer = frame_producer::empty();\n        transition_info                 transitionInfo;\n        sting_info                      stingInfo;\n\n        if (try_match_sting(ctx.parameters, stingInfo)) {\n            transition_producer =\n                create_sting_producer(get_producer_dependencies(channel, ctx), new_producer, stingInfo);\n        } else {\n            std::wstring message;\n            for (std::wstring& parameter : ctx.parameters) {\n                message += boost::to_upper_copy(parameter) + L\" \";\n            }\n\n            // Try other transitions\n            try_match_transition(message, transitionInfo);\n            transition_producer = create_transition_producer(new_producer, transitionInfo);\n        }\n\n        // TODO - we should pass the format into load(), so that we can catch it having changed since the producer was\n        // initialised\n        ctx.channel.stage->load(ctx.layer_index(), transition_producer, false, auto_play); // TODO: LOOP\n    } catch (file_not_found&) {\n        if (contains_param(L\"CLEAR_ON_404\", ctx.parameters)) {\n            ctx.channel.stage->load(\n                ctx.layer_index(), core::create_color_producer(channel->frame_factory(), 0), false, auto_play);\n        }\n        throw;\n    }\n\n    return L\"202 LOADBG OK\\r\\n\";\n}\n\nstd::wstring load_command(command_context& ctx)\n{\n    core::diagnostics::scoped_call_context save;\n    core::diagnostics::call_context::for_thread().video_channel = ctx.channel_index + 1;\n    core::diagnostics::call_context::for_thread().layer         = ctx.layer_index();\n\n    if (ctx.parameters.empty()) {\n        // Must be a promoting load\n        ctx.channel.stage->preview(ctx.layer_index());\n    } else {\n        try {\n            auto new_producer = ctx.static_context->producer_registry->create_producer(\n                get_producer_dependencies(ctx.channel.raw_channel, ctx), ctx.parameters);\n            auto transition_producer = create_transition_producer(new_producer, transition_info{});\n\n            ctx.channel.stage->load(ctx.layer_index(), transition_producer, true);\n        } catch (file_not_found&) {\n            if (contains_param(L\"CLEAR_ON_404\", ctx.parameters)) {\n                ctx.channel.stage->load(\n                    ctx.layer_index(), core::create_color_producer(ctx.channel.raw_channel->frame_factory(), 0), true);\n            }\n            throw;\n        }\n    }\n\n    return L\"202 LOAD OK\\r\\n\";\n}\n\nstd::wstring play_command(command_context& ctx)\n{\n    try {\n        if (!ctx.parameters.empty())\n            loadbg_command(ctx);\n    } catch (file_not_found&) {\n        if (contains_param(L\"CLEAR_ON_404\", ctx.parameters)) {\n            ctx.channel.stage->play(ctx.layer_index());\n        }\n        throw;\n    }\n\n    ctx.channel.stage->play(ctx.layer_index());\n\n    return L\"202 PLAY OK\\r\\n\";\n}\n\nstd::wstring pause_command(command_context& ctx)\n{\n    ctx.channel.stage->pause(ctx.layer_index());\n    return L\"202 PAUSE OK\\r\\n\";\n}\n\nstd::wstring resume_command(command_context& ctx)\n{\n    ctx.channel.stage->resume(ctx.layer_index());\n    return L\"202 RESUME OK\\r\\n\";\n}\n\nstd::wstring stop_command(command_context& ctx)\n{\n    ctx.channel.stage->stop(ctx.layer_index());\n    return L\"202 STOP OK\\r\\n\";\n}\n\nstd::wstring clear_command(command_context& ctx)\n{\n    int index = ctx.layer_index(std::numeric_limits<int>::min());\n    if (index != std::numeric_limits<int>::min())\n        ctx.channel.stage->clear(index);\n    else\n        ctx.channel.stage->clear();\n\n    return L\"202 CLEAR OK\\r\\n\";\n}\n\nstd::wstring clear_all_command(command_context& ctx)\n{\n    for (auto& ch : *ctx.channels) {\n        ch.stage->clear();\n    }\n\n    return L\"202 CLEAR ALL OK\\r\\n\";\n}\n\nstd::future<std::wstring> callbg_command(command_context& ctx)\n{\n    const auto result = ctx.channel.stage->callbg(ctx.layer_index(), ctx.parameters).share();\n\n    // TODO: because of std::async deferred timed waiting does not work\n\n    /*auto wait_res = result.wait_for(std::chrono::seconds(2));\n    if (wait_res == std::future_status::timeout)\n    CASPAR_THROW_EXCEPTION(timed_out());*/\n\n    return std::async(std::launch::deferred, [result]() -> std::wstring {\n        std::wstring res = result.get();\n\n        std::wstringstream replyString;\n        if (res.empty())\n            replyString << L\"202 CALLBG OK\\r\\n\";\n        else\n            replyString << L\"201 CALLBG OK\\r\\n\" << res << L\"\\r\\n\";\n\n        return replyString.str();\n    });\n}\n\nstd::future<std::wstring> call_command(command_context& ctx)\n{\n    const auto result = ctx.channel.stage->call(ctx.layer_index(), ctx.parameters).share();\n\n    // TODO: because of std::async deferred timed waiting does not work\n\n    /*auto wait_res = result.wait_for(std::chrono::seconds(2));\n    if (wait_res == std::future_status::timeout)\n    CASPAR_THROW_EXCEPTION(timed_out());*/\n\n    return std::async(std::launch::deferred, [result]() -> std::wstring {\n        std::wstring res = result.get();\n\n        std::wstringstream replyString;\n        if (res.empty())\n            replyString << L\"202 CALL OK\\r\\n\";\n        else\n            replyString << L\"201 CALL OK\\r\\n\" << res << L\"\\r\\n\";\n\n        return replyString.str();\n    });\n}\n\nstd::wstring swap_command(command_context& ctx)\n{\n    bool swap_transforms = ctx.parameters.size() > 1 && boost::iequals(ctx.parameters.at(1), L\"TRANSFORMS\");\n\n    if (ctx.layer_index(-1) != -1) {\n        std::vector<std::wstring> strs;\n        boost::split(strs, ctx.parameters[0], boost::is_any_of(L\"-\"));\n\n        auto ch2 = ctx.channels->at(std::stoi(strs.at(0)) - 1);\n\n        int l1 = ctx.layer_index();\n        int l2 = std::stoi(strs.at(1));\n\n        ctx.channel.stage->swap_layer(l1, l2, ch2.stage, swap_transforms);\n    } else {\n        auto ch2 = ctx.channels->at(std::stoi(ctx.parameters[0]) - 1);\n        ctx.channel.stage->swap_layers(ch2.stage, swap_transforms);\n    }\n\n    return L\"202 SWAP OK\\r\\n\";\n}\n\nstd::future<std::wstring> apply_command(command_context& ctx)\n{\n    const auto result = ctx.channel.raw_channel->output().call(ctx.layer_index(), ctx.parameters).share();\n\n    // TODO: because of std::async deferred timed waiting does not work\n\n    /*auto wait_res = result.wait_for(std::chrono::seconds(2));\n    if (wait_res == std::future_status::timeout)\n    CASPAR_THROW_EXCEPTION(timed_out());*/\n\n    return std::async(std::launch::deferred, [result]() -> std::wstring {\n        bool res = result.get();\n\n        std::wstringstream replyString;\n        if (res)\n            replyString << L\"202 APPLY OK\\r\\n\";\n        else\n            replyString << L\"403 APPLY FAILED\\r\\n\";\n\n        return replyString.str();\n    });\n}\n\nstd::wstring add_command(command_context& ctx)\n{\n    replace_placeholders(L\"<CLIENT_IP_ADDRESS>\", ctx.client->address(), ctx.parameters);\n\n    core::diagnostics::scoped_call_context save;\n    core::diagnostics::call_context::for_thread().video_channel = ctx.channel_index + 1;\n\n    auto consumer =\n        ctx.static_context->consumer_registry->create_consumer(ctx.parameters,\n                                                               ctx.static_context->format_repository,\n                                                               get_channels(ctx),\n                                                               ctx.channel.raw_channel->get_consumer_channel_info());\n    ctx.channel.raw_channel->output().add(ctx.layer_index(consumer->index()), consumer);\n\n    return L\"202 ADD OK\\r\\n\";\n}\n\nstd::wstring remove_command(command_context& ctx)\n{\n    auto index = ctx.layer_index(std::numeric_limits<int>::min());\n\n    if (index == std::numeric_limits<int>::min()) {\n        replace_placeholders(L\"<CLIENT_IP_ADDRESS>\", ctx.client->address(), ctx.parameters);\n\n        if (ctx.parameters.size() == 0) {\n            return L\"402 REMOVE FAILED\\r\\n\";\n        }\n\n        index = ctx.static_context->consumer_registry\n                    ->create_consumer(ctx.parameters,\n                                      ctx.static_context->format_repository,\n                                      get_channels(ctx),\n                                      ctx.channel.raw_channel->get_consumer_channel_info())\n                    ->index();\n    }\n\n    if (!ctx.channel.raw_channel->output().remove(index)) {\n        return L\"404 REMOVE FAILED\\r\\n\";\n    }\n\n    return L\"202 REMOVE OK\\r\\n\";\n}\n\nstd::wstring print_command(command_context& ctx)\n{\n    std::vector<std::wstring> params = {L\"IMAGE\"};\n    if (!ctx.parameters.empty()) {\n        params.resize(ctx.parameters.size() + 1);\n        std::copy(std::cbegin(ctx.parameters), std::cend(ctx.parameters), params.begin() + 1);\n    }\n\n    ctx.channel.raw_channel->output().add(\n        ctx.static_context->consumer_registry->create_consumer(params,\n                                                               ctx.static_context->format_repository,\n                                                               get_channels(ctx),\n                                                               ctx.channel.raw_channel->get_consumer_channel_info()));\n\n    return L\"202 PRINT OK\\r\\n\";\n}\n\nstd::wstring log_level_command(command_context& ctx)\n{\n    if (ctx.parameters.size() == 0) {\n        std::wstringstream replyString;\n        replyString << L\"201 LOG OK\\r\\n\" << boost::to_upper_copy(log::get_log_level()) << L\"\\r\\n\";\n\n        return replyString.str();\n    }\n\n    if (!log::set_log_level(ctx.parameters.at(0))) {\n        return L\"403 LOG FAILED\\r\\n\";\n    }\n\n    return L\"202 LOG OK\\r\\n\";\n}\n\nstd::wstring set_command(command_context& ctx)\n{\n    std::wstring name  = boost::to_upper_copy(ctx.parameters[0]);\n    std::wstring value = boost::to_upper_copy(ctx.parameters[1]);\n\n    if (name == L\"MODE\") {\n        auto format_desc = ctx.static_context->format_repository.find(value);\n        if (format_desc.format != core::video_format::invalid) {\n            ctx.channel.raw_channel->stage()->video_format_desc(format_desc);\n            return L\"202 SET MODE OK\\r\\n\";\n        }\n\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid video mode\"));\n    }\n\n    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid channel variable\"));\n}\n\nstd::wstring data_store_command(command_context& ctx)\n{\n    std::wstring filename = env::data_folder();\n    filename.append(ctx.parameters[0]);\n    filename.append(L\".ftd\");\n\n    auto data_path       = boost::filesystem::path(filename).parent_path().wstring();\n    auto found_data_path = find_case_insensitive(data_path);\n\n    if (found_data_path)\n        data_path = *found_data_path;\n\n    if (!boost::filesystem::exists(data_path))\n        boost::filesystem::create_directories(data_path);\n\n    auto found_filename = find_case_insensitive(filename);\n\n    if (found_filename)\n        filename = *found_filename; // Overwrite case insensitive.\n\n    boost::filesystem::wofstream datafile(filename);\n    if (!datafile)\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(L\"Could not open file \" + filename));\n\n    datafile << static_cast<wchar_t>(65279); // UTF-8 BOM character\n    datafile << ctx.parameters[1] << std::flush;\n    datafile.close();\n\n    return L\"202 DATA STORE OK\\r\\n\";\n}\n\nstd::wstring data_retrieve_command(command_context& ctx)\n{\n    std::wstring filename = env::data_folder();\n    filename.append(ctx.parameters[0]);\n    filename.append(L\".ftd\");\n\n    std::wstring file_contents;\n\n    auto found_file = find_case_insensitive(filename);\n\n    if (found_file)\n        file_contents = read_file(boost::filesystem::path(*found_file));\n\n    if (file_contents.empty())\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(filename + L\" not found\"));\n\n    std::wstringstream reply;\n    reply << L\"201 DATA RETRIEVE OK\\r\\n\";\n\n    std::wstringstream file_contents_stream(file_contents);\n    std::wstring       line;\n\n    bool firstLine = true;\n    while (std::getline(file_contents_stream, line)) {\n        if (firstLine)\n            firstLine = false;\n        else\n            reply << \"\\n\";\n\n        reply << line;\n    }\n\n    reply << \"\\r\\n\";\n    return reply.str();\n}\n\nstd::wstring data_list_command(command_context& ctx)\n{\n    std::wstring sub_directory;\n\n    if (!ctx.parameters.empty())\n        sub_directory = ctx.parameters.at(0);\n\n    std::wstringstream replyString;\n    replyString << L\"200 DATA LIST OK\\r\\n\";\n\n    for (boost::filesystem::recursive_directory_iterator itr(get_sub_directory(env::data_folder(), sub_directory)), end;\n         itr != end;\n         ++itr) {\n        if (boost::filesystem::is_regular_file(itr->path())) {\n            if (!boost::iequals(itr->path().extension().wstring(), L\".ftd\"))\n                continue;\n\n            auto relativePath = get_relative_without_extension(itr->path(), env::data_folder());\n            auto str          = relativePath.generic_wstring();\n\n            if (str[0] == L'\\\\' || str[0] == L'/')\n                str = std::wstring(str.begin() + 1, str.end());\n\n            replyString << str << L\"\\r\\n\";\n        }\n    }\n\n    replyString << L\"\\r\\n\";\n\n    return boost::to_upper_copy(replyString.str());\n}\n\nstd::wstring data_remove_command(command_context& ctx)\n{\n    std::wstring filename = env::data_folder();\n    filename.append(ctx.parameters[0]);\n    filename.append(L\".ftd\");\n\n    if (!boost::filesystem::exists(filename))\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(filename + L\" not found\"));\n\n    if (!boost::filesystem::remove(filename))\n        CASPAR_THROW_EXCEPTION(caspar_exception() << msg_info(filename + L\" could not be removed\"));\n\n    return L\"202 DATA REMOVE OK\\r\\n\";\n}\n\n// Template Graphics Commands\n\nstd::wstring cg_add_command(command_context& ctx)\n{\n    // CG 1 ADD 0 \"template_folder/templatename\" [STARTLABEL] 0/1 [DATA]\n\n    int          layer = std::stoi(ctx.parameters.at(0));\n    std::wstring label;             //_parameters[2]\n    bool         bDoStart  = false; //_parameters[2] alt. _parameters[3]\n    unsigned int dataIndex = 3;\n\n    if (ctx.parameters.at(2).length() > 1) { // read label\n        label = ctx.parameters.at(2);\n        ++dataIndex;\n\n        if (ctx.parameters.at(3).length() > 0) // read play-on-load-flag\n            bDoStart = ctx.parameters.at(3).at(0) == L'1' ? true : false;\n    } else { // read play-on-load-flag\n        bDoStart = ctx.parameters.at(2).at(0) == L'1' ? true : false;\n    }\n\n    const wchar_t* pDataString = nullptr;\n    std::wstring   dataFromFile;\n    if (ctx.parameters.size() > dataIndex) { // read data\n        const std::wstring& dataString = ctx.parameters.at(dataIndex);\n\n        if (dataString.at(0) == L'<' || dataString.at(0) == L'{') // the data is XML or Json\n            pDataString = dataString.c_str();\n        else {\n            // The data is not an XML-string, it must be a filename\n            std::wstring filename = env::data_folder();\n            filename.append(dataString);\n            filename.append(L\".ftd\");\n\n            auto found_file = find_case_insensitive(filename);\n\n            if (found_file) {\n                dataFromFile = read_file(boost::filesystem::path(*found_file));\n                pDataString  = dataFromFile.c_str();\n            }\n        }\n    }\n\n    auto filename = ctx.parameters.at(1);\n    auto proxy =\n        ctx.static_context->cg_registry->get_or_create_proxy(spl::make_shared_ptr(ctx.channel.raw_channel),\n                                                             get_producer_dependencies(ctx.channel.raw_channel, ctx),\n                                                             ctx.layer_index(core::cg_proxy::DEFAULT_LAYER),\n                                                             filename);\n\n    if (proxy == core::cg_proxy::empty())\n        CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L\"Could not find template \" + filename));\n    else\n        proxy->add(layer, filename, bDoStart, label, pDataString != nullptr ? pDataString : L\"\");\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nstd::wstring cg_play_command(command_context& ctx)\n{\n    int layer = std::stoi(ctx.parameters.at(0));\n    ctx.static_context->cg_registry\n        ->get_proxy(spl::make_shared_ptr(ctx.channel.raw_channel), ctx.layer_index(core::cg_proxy::DEFAULT_LAYER))\n        ->play(layer);\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nspl::shared_ptr<core::cg_proxy> get_expected_cg_proxy(command_context& ctx)\n{\n    auto proxy = ctx.static_context->cg_registry->get_proxy(spl::make_shared_ptr(ctx.channel.raw_channel),\n                                                            ctx.layer_index(core::cg_proxy::DEFAULT_LAYER));\n\n    if (proxy == cg_proxy::empty())\n        CASPAR_THROW_EXCEPTION(expected_user_error() << msg_info(L\"No CG proxy running on layer\"));\n\n    return proxy;\n}\n\nstd::wstring cg_stop_command(command_context& ctx)\n{\n    int layer = std::stoi(ctx.parameters.at(0));\n    get_expected_cg_proxy(ctx)->stop(layer);\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nstd::wstring cg_next_command(command_context& ctx)\n{\n    int layer = std::stoi(ctx.parameters.at(0));\n    get_expected_cg_proxy(ctx)->next(layer);\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nstd::wstring cg_remove_command(command_context& ctx)\n{\n    int layer = std::stoi(ctx.parameters.at(0));\n    get_expected_cg_proxy(ctx)->remove(layer);\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nstd::wstring cg_clear_command(command_context& ctx)\n{\n    ctx.channel.stage->clear(ctx.layer_index(core::cg_proxy::DEFAULT_LAYER));\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nstd::wstring cg_update_command(command_context& ctx)\n{\n    int layer = std::stoi(ctx.parameters.at(0));\n\n    std::wstring dataString = ctx.parameters.at(1);\n    if (dataString.at(0) != L'<' && dataString.at(0) != L'{') {\n        // The data is not XML or Json, it must be a filename\n        std::wstring filename = env::data_folder();\n        filename.append(dataString);\n        filename.append(L\".ftd\");\n\n        dataString = read_file(boost::filesystem::path(filename));\n    }\n\n    get_expected_cg_proxy(ctx)->update(layer, dataString);\n\n    return L\"202 CG OK\\r\\n\";\n}\n\nstd::wstring cg_invoke_command(command_context& ctx)\n{\n    std::wstringstream replyString;\n    replyString << L\"201 CG OK\\r\\n\";\n    int  layer  = std::stoi(ctx.parameters.at(0));\n    auto result = get_expected_cg_proxy(ctx)->invoke(layer, ctx.parameters.at(1));\n    replyString << result << L\"\\r\\n\";\n\n    return replyString.str();\n}\n\n// Mixer Commands\n\nstd::future<core::frame_transform> get_current_transform(command_context& ctx)\n{\n    return ctx.channel.stage->get_current_transform(ctx.layer_index());\n}\n\ntemplate <typename Func>\nstd::future<std::wstring> reply_value(command_context& ctx, const Func& extractor)\n{\n    auto transform = get_current_transform(ctx).share();\n\n    return std::async(std::launch::deferred, [transform, extractor]() -> std::wstring {\n        auto value = extractor(transform.get());\n        return L\"201 MIXER OK\\r\\n\" + boost::lexical_cast<std::wstring>(value) + L\"\\r\\n\";\n    });\n}\n\nclass transforms_applier\n{\n    static tbb::concurrent_unordered_map<int, std::vector<stage::transform_tuple_t>> deferred_transforms_;\n\n    std::vector<stage::transform_tuple_t> transforms_;\n    command_context&                      ctx_;\n    bool                                  defer_;\n\n  public:\n    explicit transforms_applier(command_context& ctx)\n        : ctx_(ctx)\n    {\n        defer_ = !ctx.parameters.empty() && boost::iequals(ctx.parameters.back(), L\"DEFER\");\n\n        if (defer_)\n            ctx.parameters.pop_back();\n    }\n\n    void add(stage::transform_tuple_t&& transform) { transforms_.push_back(std::move(transform)); }\n\n    std::future<void> commit_deferred()\n    {\n        const int  channel_index = ctx_.channel_index;\n        const auto f             = ctx_.channel.stage->apply_transforms(deferred_transforms_[channel_index]).share();\n\n        return std::async(std::launch::deferred, [=]() {\n            f.get();\n            deferred_transforms_[channel_index].clear();\n        });\n    }\n\n    void apply()\n    {\n        if (defer_) {\n            auto& defer_tranforms = deferred_transforms_[ctx_.channel_index];\n            defer_tranforms.insert(defer_tranforms.end(), transforms_.begin(), transforms_.end());\n        } else\n            ctx_.channel.stage->apply_transforms(transforms_);\n    }\n};\ntbb::concurrent_unordered_map<int, std::vector<stage::transform_tuple_t>> transforms_applier::deferred_transforms_;\n\nstd::future<std::wstring> mixer_keyer_command(command_context& ctx)\n{\n    if (ctx.parameters.empty())\n        return reply_value(ctx, [](const frame_transform& t) { return t.image_transform.is_key ? 1 : 0; });\n\n    transforms_applier transforms(ctx);\n    bool               value = std::stoi(ctx.parameters.at(0));\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.is_key = value;\n            return transform;\n        },\n        0,\n        tweener(L\"linear\")));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_invert_command(command_context& ctx)\n{\n    if (ctx.parameters.empty())\n        return reply_value(ctx, [](const frame_transform& t) { return t.image_transform.invert ? 1 : 0; });\n\n    transforms_applier transforms(ctx);\n    bool               value = std::stoi(ctx.parameters.at(0));\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.invert = value;\n            return transform;\n        },\n        0,\n        tweener(L\"linear\")));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_chroma_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto chroma2 = get_current_transform(ctx).share();\n\n        return std::async(std::launch::deferred, [chroma2]() -> std::wstring {\n            auto chroma = chroma2.get().image_transform.chroma;\n            return L\"201 MIXER OK\\r\\n\" + std::wstring(chroma.enable ? L\"1 \" : L\"0 \") +\n                   std::to_wstring(chroma.target_hue) + L\" \" + std::to_wstring(chroma.hue_width) + L\" \" +\n                   std::to_wstring(chroma.min_saturation) + L\" \" + std::to_wstring(chroma.min_brightness) + L\" \" +\n                   std::to_wstring(chroma.softness) + L\" \" + std::to_wstring(chroma.spill_suppress) + L\" \" +\n                   std::to_wstring(chroma.spill_suppress_saturation) + L\" \" +\n                   std::wstring(chroma.show_mask ? L\"1\" : L\"0\") + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    core::chroma       chroma;\n\n    int          duration;\n    std::wstring tween;\n\n    auto legacy_mode = core::get_chroma_mode(ctx.parameters.at(0));\n\n    if (legacy_mode) {\n        duration = ctx.parameters.size() > 4 ? std::stoi(ctx.parameters.at(4)) : 0;\n        tween    = ctx.parameters.size() > 5 ? ctx.parameters.at(5) : L\"linear\";\n\n        if (*legacy_mode == chroma::legacy_type::none) {\n            chroma.enable = false;\n        } else {\n            chroma.enable                    = true;\n            chroma.hue_width                 = 0.5 - std::stod(ctx.parameters.at(1)) * 0.5;\n            chroma.min_brightness            = std::stod(ctx.parameters.at(1));\n            chroma.min_saturation            = std::stod(ctx.parameters.at(1));\n            chroma.softness                  = std::stod(ctx.parameters.at(2)) - std::stod(ctx.parameters.at(1));\n            chroma.spill_suppress            = 180.0 - std::stod(ctx.parameters.at(3)) * 180.0;\n            chroma.spill_suppress_saturation = 1;\n\n            if (*legacy_mode == chroma::legacy_type::green)\n                chroma.target_hue = 120;\n            else if (*legacy_mode == chroma::legacy_type::blue)\n                chroma.target_hue = 240;\n        }\n    } else {\n        duration = ctx.parameters.size() > 9 ? std::stoi(ctx.parameters.at(9)) : 0;\n        tween    = ctx.parameters.size() > 10 ? ctx.parameters.at(10) : L\"linear\";\n\n        chroma.enable = ctx.parameters.at(0) == L\"1\";\n\n        if (chroma.enable) {\n            chroma.target_hue                = std::stod(ctx.parameters.at(1));\n            chroma.hue_width                 = std::stod(ctx.parameters.at(2));\n            chroma.min_saturation            = std::stod(ctx.parameters.at(3));\n            chroma.min_brightness            = std::stod(ctx.parameters.at(4));\n            chroma.softness                  = std::stod(ctx.parameters.at(5));\n            chroma.spill_suppress            = std::stod(ctx.parameters.at(6));\n            chroma.spill_suppress_saturation = std::stod(ctx.parameters.at(7));\n            chroma.show_mask                 = std::stod(ctx.parameters.at(8));\n        }\n    }\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.chroma = chroma;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_blend_command(command_context& ctx)\n{\n    if (ctx.parameters.empty())\n        return reply_value(ctx, [](const frame_transform& t) { return get_blend_mode(t.image_transform.blend_mode); });\n\n    transforms_applier transforms(ctx);\n    auto               value = get_blend_mode(ctx.parameters.at(0));\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.blend_mode = value;\n            return transform;\n        },\n        0,\n        tweener(L\"linear\")));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\ntemplate <typename Getter, typename Setter>\nstd::future<std::wstring>\nsingle_double_animatable_mixer_command(command_context& ctx, const Getter& getter, const Setter& setter)\n{\n    if (ctx.parameters.empty())\n        return reply_value(ctx, getter);\n\n    transforms_applier transforms(ctx);\n    double             value    = std::stod(ctx.parameters.at(0));\n    int                duration = ctx.parameters.size() > 1 ? std::stoi(ctx.parameters[1]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 2 ? ctx.parameters[2] : L\"linear\";\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            setter(transform, value);\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_opacity_command(command_context& ctx)\n{\n    return single_double_animatable_mixer_command(\n        ctx,\n        [](const frame_transform& t) { return t.image_transform.opacity; },\n        [](frame_transform& t, double value) { t.image_transform.opacity = value; });\n}\n\nstd::future<std::wstring> mixer_brightness_command(command_context& ctx)\n{\n    return single_double_animatable_mixer_command(\n        ctx,\n        [](const frame_transform& t) { return t.image_transform.brightness; },\n        [](frame_transform& t, double value) { t.image_transform.brightness = value; });\n}\n\nstd::future<std::wstring> mixer_saturation_command(command_context& ctx)\n{\n    return single_double_animatable_mixer_command(\n        ctx,\n        [](const frame_transform& t) { return t.image_transform.saturation; },\n        [](frame_transform& t, double value) { t.image_transform.saturation = value; });\n}\n\nstd::future<std::wstring> mixer_contrast_command(command_context& ctx)\n{\n    return single_double_animatable_mixer_command(\n        ctx,\n        [](const frame_transform& t) { return t.image_transform.contrast; },\n        [](frame_transform& t, double value) { t.image_transform.contrast = value; });\n}\n\nstd::future<std::wstring> mixer_levels_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto levels2 = get_current_transform(ctx).share();\n        return std::async(std::launch::deferred, [levels2]() -> std::wstring {\n            auto levels = levels2.get().image_transform.levels;\n            return L\"201 MIXER OK\\r\\n\" + std::to_wstring(levels.min_input) + L\" \" + std::to_wstring(levels.max_input) +\n                   L\" \" + std::to_wstring(levels.gamma) + L\" \" + std::to_wstring(levels.min_output) + L\" \" +\n                   std::to_wstring(levels.max_output) + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    levels             value;\n    value.min_input       = std::stod(ctx.parameters.at(0));\n    value.max_input       = std::stod(ctx.parameters.at(1));\n    value.gamma           = std::stod(ctx.parameters.at(2));\n    value.min_output      = std::stod(ctx.parameters.at(3));\n    value.max_output      = std::stod(ctx.parameters.at(4));\n    int          duration = ctx.parameters.size() > 5 ? std::stoi(ctx.parameters[5]) : 0;\n    std::wstring tween    = ctx.parameters.size() > 6 ? ctx.parameters[6] : L\"linear\";\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.levels = value;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_fill_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto transform2 = get_current_transform(ctx).share();\n        return std::async(std::launch::deferred, [transform2]() -> std::wstring {\n            auto transform   = transform2.get().image_transform;\n            auto translation = transform.fill_translation;\n            auto scale       = transform.fill_scale;\n            return L\"201 MIXER OK\\r\\n\" + std::to_wstring(translation[0]) + L\" \" + std::to_wstring(translation[1]) +\n                   L\" \" + std::to_wstring(scale[0]) + L\" \" + std::to_wstring(scale[1]) + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    int                duration = ctx.parameters.size() > 4 ? std::stoi(ctx.parameters[4]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 5 ? ctx.parameters[5] : L\"linear\";\n    double             x        = std::stod(ctx.parameters.at(0));\n    double             y        = std::stod(ctx.parameters.at(1));\n    double             x_s      = std::stod(ctx.parameters.at(2));\n    double             y_s      = std::stod(ctx.parameters.at(3));\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) mutable -> frame_transform {\n            transform.image_transform.fill_translation[0] = x;\n            transform.image_transform.fill_translation[1] = y;\n            transform.image_transform.fill_scale[0]       = x_s;\n            transform.image_transform.fill_scale[1]       = y_s;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_clip_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto transform2 = get_current_transform(ctx).share();\n        return std::async(std::launch::deferred, [transform2]() -> std::wstring {\n            auto transform   = transform2.get().image_transform;\n            auto translation = transform.clip_translation;\n            auto scale       = transform.clip_scale;\n\n            return L\"201 MIXER OK\\r\\n\" + std::to_wstring(translation[0]) + L\" \" + std::to_wstring(translation[1]) +\n                   L\" \" + std::to_wstring(scale[0]) + L\" \" + std::to_wstring(scale[1]) + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    int                duration = ctx.parameters.size() > 4 ? std::stoi(ctx.parameters[4]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 5 ? ctx.parameters[5] : L\"linear\";\n    double             x        = std::stod(ctx.parameters.at(0));\n    double             y        = std::stod(ctx.parameters.at(1));\n    double             x_s      = std::stod(ctx.parameters.at(2));\n    double             y_s      = std::stod(ctx.parameters.at(3));\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.clip_translation[0] = x;\n            transform.image_transform.clip_translation[1] = y;\n            transform.image_transform.clip_scale[0]       = x_s;\n            transform.image_transform.clip_scale[1]       = y_s;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_anchor_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto transform2 = get_current_transform(ctx).share();\n        return std::async(std::launch::deferred, [transform2]() -> std::wstring {\n            auto transform = transform2.get().image_transform;\n            auto anchor    = transform.anchor;\n            return L\"201 MIXER OK\\r\\n\" + std::to_wstring(anchor[0]) + L\" \" + std::to_wstring(anchor[1]) + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    int                duration = ctx.parameters.size() > 2 ? std::stoi(ctx.parameters[2]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 3 ? ctx.parameters[3] : L\"linear\";\n    double             x        = std::stod(ctx.parameters.at(0));\n    double             y        = std::stod(ctx.parameters.at(1));\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) mutable -> frame_transform {\n            transform.image_transform.anchor[0] = x;\n            transform.image_transform.anchor[1] = y;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_crop_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto transform2 = get_current_transform(ctx).share();\n        return std::async(std::launch::deferred, [transform2]() -> std::wstring {\n            auto crop = transform2.get().image_transform.crop;\n            return L\"201 MIXER OK\\r\\n\" + std::to_wstring(crop.ul[0]) + L\" \" + std::to_wstring(crop.ul[1]) + L\" \" +\n                   std::to_wstring(crop.lr[0]) + L\" \" + std::to_wstring(crop.lr[1]) + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    int                duration = ctx.parameters.size() > 4 ? std::stoi(ctx.parameters[4]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 5 ? ctx.parameters[5] : L\"linear\";\n    double             ul_x     = std::stod(ctx.parameters.at(0));\n    double             ul_y     = std::stod(ctx.parameters.at(1));\n    double             lr_x     = std::stod(ctx.parameters.at(2));\n    double             lr_y     = std::stod(ctx.parameters.at(3));\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.crop.ul[0] = ul_x;\n            transform.image_transform.crop.ul[1] = ul_y;\n            transform.image_transform.crop.lr[0] = lr_x;\n            transform.image_transform.crop.lr[1] = lr_y;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_rotation_command(command_context& ctx)\n{\n    static const double PI = 3.141592653589793;\n\n    return single_double_animatable_mixer_command(\n        ctx,\n        [](const frame_transform& t) { return t.image_transform.angle / PI * 180.0; },\n        [](frame_transform& t, double value) { t.image_transform.angle = value * PI / 180.0; });\n}\n\nstd::future<std::wstring> mixer_perspective_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto transform2 = get_current_transform(ctx).share();\n        return std::async(std::launch::deferred, [transform2]() -> std::wstring {\n            auto perspective = transform2.get().image_transform.perspective;\n            return L\"201 MIXER OK\\r\\n\" + std::to_wstring(perspective.ul[0]) + L\" \" +\n                   std::to_wstring(perspective.ul[1]) + L\" \" + std::to_wstring(perspective.ur[0]) + L\" \" +\n                   std::to_wstring(perspective.ur[1]) + L\" \" + std::to_wstring(perspective.lr[0]) + L\" \" +\n                   std::to_wstring(perspective.lr[1]) + L\" \" + std::to_wstring(perspective.ll[0]) + L\" \" +\n                   std::to_wstring(perspective.ll[1]) + L\"\\r\\n\";\n        });\n    }\n\n    transforms_applier transforms(ctx);\n    int                duration = ctx.parameters.size() > 8 ? std::stoi(ctx.parameters[8]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 9 ? ctx.parameters[9] : L\"linear\";\n    double             ul_x     = std::stod(ctx.parameters.at(0));\n    double             ul_y     = std::stod(ctx.parameters.at(1));\n    double             ur_x     = std::stod(ctx.parameters.at(2));\n    double             ur_y     = std::stod(ctx.parameters.at(3));\n    double             lr_x     = std::stod(ctx.parameters.at(4));\n    double             lr_y     = std::stod(ctx.parameters.at(5));\n    double             ll_x     = std::stod(ctx.parameters.at(6));\n    double             ll_y     = std::stod(ctx.parameters.at(7));\n\n    transforms.add(stage::transform_tuple_t(\n        ctx.layer_index(),\n        [=](frame_transform transform) -> frame_transform {\n            transform.image_transform.perspective.ul[0] = ul_x;\n            transform.image_transform.perspective.ul[1] = ul_y;\n            transform.image_transform.perspective.ur[0] = ur_x;\n            transform.image_transform.perspective.ur[1] = ur_y;\n            transform.image_transform.perspective.lr[0] = lr_x;\n            transform.image_transform.perspective.lr[1] = lr_y;\n            transform.image_transform.perspective.ll[0] = ll_x;\n            transform.image_transform.perspective.ll[1] = ll_y;\n            return transform;\n        },\n        duration,\n        tween));\n    transforms.apply();\n\n    return make_ready_future<std::wstring>(L\"202 MIXER OK\\r\\n\");\n}\n\nstd::future<std::wstring> mixer_volume_command(command_context& ctx)\n{\n    return single_double_animatable_mixer_command(\n        ctx,\n        [](const frame_transform& t) { return t.audio_transform.volume; },\n        [](frame_transform& t, double value) { t.audio_transform.volume = value; });\n}\n\nstd::wstring mixer_mastervolume_command(command_context& ctx)\n{\n    if (ctx.parameters.empty()) {\n        auto volume = ctx.channel.raw_channel->mixer().get_master_volume();\n        return L\"201 MIXER OK\\r\\n\" + std::to_wstring(volume) + L\"\\r\\n\";\n    }\n\n    float master_volume = boost::lexical_cast<float>(ctx.parameters.at(0));\n    ctx.channel.raw_channel->mixer().set_master_volume(master_volume);\n\n    return L\"202 MIXER OK\\r\\n\";\n}\n\nstd::wstring mixer_grid_command(command_context& ctx)\n{\n    transforms_applier transforms(ctx);\n    int                duration = ctx.parameters.size() > 1 ? std::stoi(ctx.parameters[1]) : 0;\n    std::wstring       tween    = ctx.parameters.size() > 2 ? ctx.parameters[2] : L\"linear\";\n    int                n        = std::stoi(ctx.parameters.at(0));\n    double             delta    = 1.0 / static_cast<double>(n);\n    for (int x = 0; x < n; ++x) {\n        for (int y = 0; y < n; ++y) {\n            int index = x + y * n + 1;\n            transforms.add(stage::transform_tuple_t(\n                index,\n                [=](frame_transform transform) -> frame_transform {\n                    transform.image_transform.fill_translation[0] = x * delta;\n                    transform.image_transform.fill_translation[1] = y * delta;\n                    transform.image_transform.fill_scale[0]       = delta;\n                    transform.image_transform.fill_scale[1]       = delta;\n                    transform.image_transform.clip_translation[0] = x * delta;\n                    transform.image_transform.clip_translation[1] = y * delta;\n                    transform.image_transform.clip_scale[0]       = delta;\n                    transform.image_transform.clip_scale[1]       = delta;\n                    return transform;\n                },\n                duration,\n                tween));\n        }\n    }\n    transforms.apply();\n\n    return L\"202 MIXER OK\\r\\n\";\n}\n\nstd::future<std::wstring> mixer_commit_command(command_context& ctx)\n{\n    transforms_applier transforms(ctx);\n    const auto         r = transforms.commit_deferred().share();\n    return std::async(std::launch::deferred, [r]() -> std::wstring {\n        r.get();\n        return L\"202 MIXER OK\\r\\n\";\n    });\n}\n\nstd::wstring mixer_clear_command(command_context& ctx)\n{\n    int layer = ctx.layer_id;\n\n    if (layer == -1)\n        ctx.channel.stage->clear_transforms();\n    else\n        ctx.channel.stage->clear_transforms(layer);\n\n    return L\"202 MIXER OK\\r\\n\";\n}\n\nstd::wstring channel_grid_command(command_context& ctx)\n{\n    int   index = 1;\n    auto& self  = ctx.channels->back();\n\n    core::diagnostics::scoped_call_context save;\n    core::diagnostics::call_context::for_thread().video_channel = static_cast<int>(ctx.channels->size());\n\n    std::vector<std::wstring> params;\n    params.emplace_back(L\"SCREEN\");\n    params.emplace_back(L\"0\");\n    params.emplace_back(L\"NAME\");\n    params.emplace_back(L\"Channel Grid Window\");\n    auto screen =\n        ctx.static_context->consumer_registry->create_consumer(params,\n                                                               ctx.static_context->format_repository,\n                                                               get_channels(ctx),\n                                                               ctx.channel.raw_channel->get_consumer_channel_info());\n\n    self.raw_channel->output().add(screen);\n\n    for (auto& ch : *ctx.channels) {\n        if (ch.raw_channel != self.raw_channel) {\n            core::diagnostics::call_context::for_thread().layer = index;\n            auto producer = ctx.static_context->producer_registry->create_producer(\n                get_producer_dependencies(self.raw_channel, ctx),\n                L\"route://\" + std::to_wstring(ch.raw_channel->index()));\n            self.stage->load(index, producer, false);\n            self.stage->play(index);\n            index++;\n        }\n    }\n\n    auto num_channels       = ctx.channels->size() - 1;\n    int  square_side_length = std::ceil(std::sqrt(num_channels));\n\n    auto ctx2 =\n        command_context(ctx.static_context, ctx.channels, ctx.client, self, self.raw_channel->index(), ctx.layer_id);\n    ctx2.parameters.push_back(std::to_wstring(square_side_length));\n    mixer_grid_command(ctx2);\n\n    return L\"202 CHANNEL_GRID OK\\r\\n\";\n}\n\n// Thumbnail Commands\n\nstd::wstring make_request(command_context& ctx, const std::string& path, const std::wstring& default_response)\n{\n    auto res = http::request(ctx.static_context->proxy_host, ctx.static_context->proxy_port, path);\n    if (res.status_code >= 500 || res.body.size() == 0) {\n        CASPAR_LOG(error) << \"Failed to connect to media-scanner. Is it running? \\nReason: \" << res.status_message;\n        return default_response;\n    }\n    return u16(res.body);\n}\n\nstd::wstring thumbnail_list_command(command_context& ctx)\n{\n    return make_request(ctx, \"/thumbnail\", L\"501 THUMBNAIL LIST FAILED\\r\\n\");\n}\n\nstd::wstring thumbnail_retrieve_command(command_context& ctx)\n{\n    return make_request(\n        ctx, \"/thumbnail/\" + http::url_encode(u8(ctx.parameters.at(0))), L\"501 THUMBNAIL RETRIEVE FAILED\\r\\n\");\n}\n\nstd::wstring thumbnail_generate_command(command_context& ctx)\n{\n    return make_request(\n        ctx, \"/thumbnail/generate/\" + http::url_encode(u8(ctx.parameters.at(0))), L\"501 THUMBNAIL GENERATE FAILED\\r\\n\");\n}\n\nstd::wstring thumbnail_generateall_command(command_context& ctx)\n{\n    return make_request(ctx, \"/thumbnail/generate\", L\"501 THUMBNAIL GENERATE_ALL FAILED\\r\\n\");\n}\n\n// Query Commands\n\nstd::wstring cinf_command(command_context& ctx)\n{\n    return make_request(ctx, \"/cinf/\" + http::url_encode(u8(ctx.parameters.at(0))), L\"501 CINF FAILED\\r\\n\");\n}\n\nstd::wstring cls_command(command_context& ctx) { return make_request(ctx, \"/cls\", L\"501 CLS FAILED\\r\\n\"); }\n\nstd::wstring fls_command(command_context& ctx) { return make_request(ctx, \"/fls\", L\"501 FLS FAILED\\r\\n\"); }\n\nstd::wstring tls_command(command_context& ctx) { return make_request(ctx, \"/tls\", L\"501 TLS FAILED\\r\\n\"); }\n\nstd::wstring version_command(command_context& ctx) { return L\"201 VERSION OK\\r\\n\" + env::version() + L\"\\r\\n\"; }\n\nstruct param_visitor : public boost::static_visitor<void>\n{\n    std::wstring path;\n    pt::wptree&  o;\n\n    template <typename T>\n    param_visitor(std::string path, T& o)\n        : path(u16(path))\n        , o(o)\n    {\n    }\n\n    void operator()(const bool value) { o.add(path, value); }\n\n    void operator()(const int32_t value) { o.add(path, value); }\n\n    void operator()(const uint32_t value) { o.add(path, value); }\n\n    void operator()(const int64_t value) { o.add(path, value); }\n\n    void operator()(const uint64_t value) { o.add(path, value); }\n\n    void operator()(const float value) { o.add(path, value); }\n\n    void operator()(const double value) { o.add(path, value); }\n\n    void operator()(const std::string& value) { o.add(path, u16(value)); }\n\n    void operator()(const std::wstring& value) { o.add(path, value); }\n};\n\nstd::wstring info_channel_command(command_context& ctx)\n{\n    pt::wptree info;\n    pt::wptree channel_info;\n\n    auto state = ctx.channel.raw_channel->state();\n    for (const auto& p : state) {\n        const auto replaced = boost::algorithm::replace_all_copy(p.first, \"/\", \".\");\n        // avoid digit-only nodes in XML\n        const auto path = boost::algorithm::replace_all_regex_copy(\n            replaced, boost::regex(\"\\\\.(.*?)\\\\.([0-9]*?)\\\\.\"), std::string(\".$1.$1_$2.\"));\n        param_visitor param_visitor(path, channel_info);\n        for (const auto& element : p.second) {\n            boost::apply_visitor(param_visitor, element);\n        }\n    }\n\n    info.add_child(L\"channel\", channel_info);\n\n    std::wstringstream replyString;\n    // This is needed for backwards compatibility with old clients\n    replyString << L\"201 INFO OK\\r\\n\";\n\n    pt::xml_writer_settings<std::wstring> w(' ', 3);\n    pt::xml_parser::write_xml(replyString, info, w);\n\n    replyString << L\"\\r\\n\";\n    return replyString.str();\n}\n\nstd::wstring info_command(command_context& ctx)\n{\n    std::wstringstream replyString;\n    // This is needed for backwards compatibility with old clients\n    replyString << L\"200 INFO OK\\r\\n\";\n\n    for (auto& ch : *ctx.channels) {\n        replyString << ch.raw_channel->index() << L\" \" << ch.raw_channel->stage()->video_format_desc().name\n                    << L\" PLAYING\\r\\n\";\n    }\n    replyString << L\"\\r\\n\";\n    return replyString.str();\n}\n\nstd::wstring info_config_command(command_context& ctx)\n{\n    std::wstringstream replyString;\n    // This is needed for backwards compatibility with old clients\n    replyString << L\"201 INFO CONFIG OK\\r\\n\";\n\n    pt::xml_writer_settings<std::wstring> w(' ', 3);\n    pt::xml_parser::write_xml(replyString, caspar::env::properties(), w);\n\n    replyString << L\"\\r\\n\";\n    return replyString.str();\n}\n\nstd::wstring info_paths_command(command_context& ctx)\n{\n    boost::property_tree::wptree info;\n\n    info.add(L\"paths.media-path\", caspar::env::media_folder());\n    info.add(L\"paths.log-path\", caspar::env::log_folder());\n    info.add(L\"paths.data-path\", caspar::env::data_folder());\n    info.add(L\"paths.template-path\", caspar::env::template_folder());\n    info.add(L\"paths.initial-path\", caspar::env::initial_folder() + L\"/\");\n\n    std::wstringstream replyString;\n    // This is needed for backwards compatibility with old clients\n    replyString << L\"201 INFO PATHS OK\\r\\n\";\n\n    pt::xml_writer_settings<std::wstring> w(' ', 3);\n    pt::xml_parser::write_xml(replyString, info, w);\n\n    replyString << L\"\\r\\n\";\n    return replyString.str();\n}\n\nstd::wstring diag_command(command_context& ctx)\n{\n    core::diagnostics::osd::show_graphs(true);\n\n    return L\"202 DIAG OK\\r\\n\";\n}\n\nstd::wstring bye_command(command_context& ctx)\n{\n    ctx.client->disconnect();\n    return L\"\";\n}\n\nstd::wstring kill_command(command_context& ctx)\n{\n    ctx.static_context->shutdown_server_now(false); // false for not attempting to restart\n    return L\"202 KILL OK\\r\\n\";\n}\n\nstd::wstring restart_command(command_context& ctx)\n{\n    ctx.static_context->shutdown_server_now(true); // true for attempting to restart\n    return L\"202 RESTART OK\\r\\n\";\n}\n\nstd::wstring lock_command(command_context& ctx)\n{\n    int  channel_index = std::stoi(ctx.parameters.at(0)) - 1;\n    auto lock          = ctx.channels->at(channel_index).lock;\n    auto command       = boost::to_upper_copy(ctx.parameters.at(1));\n\n    if (command == L\"ACQUIRE\") {\n        std::wstring lock_phrase = ctx.parameters.at(2);\n\n        // TODO: read options\n\n        // just lock one channel\n        if (!lock->try_lock(lock_phrase, ctx.client))\n            return L\"503 LOCK ACQUIRE FAILED\\r\\n\";\n\n        return L\"202 LOCK ACQUIRE OK\\r\\n\";\n    }\n    if (command == L\"RELEASE\") {\n        lock->release_lock(ctx.client);\n        return L\"202 LOCK RELEASE OK\\r\\n\";\n    }\n    if (command == L\"CLEAR\") {\n        std::wstring override_phrase = env::properties().get(L\"configuration.lock-clear-phrase\", L\"\");\n        std::wstring client_override_phrase;\n\n        if (!override_phrase.empty())\n            client_override_phrase = ctx.parameters.at(2);\n\n        // just clear one channel\n        if (client_override_phrase != override_phrase)\n            return L\"503 LOCK CLEAR FAILED\\r\\n\";\n\n        lock->clear_locks();\n\n        return L\"202 LOCK CLEAR OK\\r\\n\";\n    }\n\n    CASPAR_THROW_EXCEPTION(file_not_found() << msg_info(L\"Unknown LOCK command \" + command));\n}\n\nstd::wstring gl_info_command(command_context& ctx)\n{\n    auto device = ctx.static_context->ogl_device.lock();\n    if (!device)\n        CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\"GL command only supported with OpenGL accelerator.\"));\n\n    std::wstringstream result;\n    result << L\"201 GL INFO OK\\r\\n\";\n\n    pt::xml_writer_settings<std::wstring> w(' ', 3);\n    pt::xml_parser::write_xml(result, device->info(), w);\n    result << L\"\\r\\n\";\n\n    return result.str();\n}\n\nstd::wstring gl_gc_command(command_context& ctx)\n{\n    auto device = ctx.static_context->ogl_device.lock();\n    if (!device)\n        CASPAR_THROW_EXCEPTION(not_supported() << msg_info(\"GL command only supported with OpenGL accelerator.\"));\n\n    device->gc().wait();\n\n    return L\"202 GL GC OK\\r\\n\";\n}\n\nstd::wstring get_osc_subscription_token(unsigned short port)\n{\n    std::wstringstream token;\n    token << \"osc-sub-\" << port;\n    return token.str();\n}\n\nstd::wstring osc_subscribe_command(command_context& ctx)\n{\n    using namespace boost::asio::ip;\n\n    unsigned short port = 0;\n    try {\n        port = std::stoi(ctx.parameters.at(0));\n    } catch (...) {\n        return L\"403 OSC SUBSCRIBE BAD PORT\\r\\n\";\n    }\n\n    auto subscription = ctx.static_context->osc_client->get_subscription_token(\n        udp::endpoint(make_address_v4(u8(ctx.client->address())), port));\n\n    ctx.client->add_lifecycle_bound_object(get_osc_subscription_token(port), subscription);\n\n    return L\"202 OSC SUBSCRIBE OK\\r\\n\";\n}\n\nstd::wstring osc_unsubscribe_command(command_context& ctx)\n{\n    unsigned short port = 0;\n    try {\n        port = std::stoi(ctx.parameters.at(0));\n    } catch (...) {\n        return L\"403 OSC UNSUBSCRIBE BAD PORT\\r\\n\";\n    }\n\n    ctx.client->remove_lifecycle_bound_object(get_osc_subscription_token(port));\n\n    return L\"202 OSC UNSUBSCRIBE OK\\r\\n\";\n}\n\nvoid register_commands(std::shared_ptr<amcp_command_repository_wrapper>& repo)\n{\n    repo->register_channel_command(L\"Basic Commands\", L\"LOADBG\", loadbg_command, 1);\n    repo->register_channel_command(L\"Basic Commands\", L\"CALLBG\", callbg_command, 1);\n    repo->register_channel_command(L\"Basic Commands\", L\"LOAD\", load_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"PLAY\", play_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"PAUSE\", pause_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"RESUME\", resume_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"STOP\", stop_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"CLEAR\", clear_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"CALL\", call_command, 1);\n    repo->register_channel_command(L\"Basic Commands\", L\"SWAP\", swap_command, 1);\n    repo->register_channel_command(L\"Basic Commands\", L\"ADD\", add_command, 1);\n    repo->register_channel_command(L\"Basic Commands\", L\"REMOVE\", remove_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"APPLY\", apply_command, 1);\n    repo->register_channel_command(L\"Basic Commands\", L\"PRINT\", print_command, 0);\n    repo->register_command(L\"Basic Commands\", L\"CLEAR ALL\", clear_all_command, 0);\n    repo->register_command(L\"Basic Commands\", L\"LOG LEVEL\", log_level_command, 0);\n    repo->register_channel_command(L\"Basic Commands\", L\"SET\", set_command, 2);\n    repo->register_command(L\"Basic Commands\", L\"LOCK\", lock_command, 2);\n\n    repo->register_command(L\"Data Commands\", L\"DATA STORE\", data_store_command, 2);\n    repo->register_command(L\"Data Commands\", L\"DATA RETRIEVE\", data_retrieve_command, 1);\n    repo->register_command(L\"Data Commands\", L\"DATA LIST\", data_list_command, 0);\n    repo->register_command(L\"Data Commands\", L\"DATA REMOVE\", data_remove_command, 1);\n\n    repo->register_channel_command(L\"Template Commands\", L\"CG ADD\", cg_add_command, 3);\n    repo->register_channel_command(L\"Template Commands\", L\"CG PLAY\", cg_play_command, 1);\n    repo->register_channel_command(L\"Template Commands\", L\"CG STOP\", cg_stop_command, 1);\n    repo->register_channel_command(L\"Template Commands\", L\"CG NEXT\", cg_next_command, 1);\n    repo->register_channel_command(L\"Template Commands\", L\"CG REMOVE\", cg_remove_command, 1);\n    repo->register_channel_command(L\"Template Commands\", L\"CG CLEAR\", cg_clear_command, 0);\n    repo->register_channel_command(L\"Template Commands\", L\"CG UPDATE\", cg_update_command, 2);\n    repo->register_channel_command(L\"Template Commands\", L\"CG INVOKE\", cg_invoke_command, 2);\n\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER KEYER\", mixer_keyer_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER INVERT\", mixer_invert_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER CHROMA\", mixer_chroma_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER BLEND\", mixer_blend_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER OPACITY\", mixer_opacity_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER BRIGHTNESS\", mixer_brightness_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER SATURATION\", mixer_saturation_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER CONTRAST\", mixer_contrast_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER LEVELS\", mixer_levels_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER FILL\", mixer_fill_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER CLIP\", mixer_clip_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER ANCHOR\", mixer_anchor_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER CROP\", mixer_crop_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER ROTATION\", mixer_rotation_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER PERSPECTIVE\", mixer_perspective_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER VOLUME\", mixer_volume_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER MASTERVOLUME\", mixer_mastervolume_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER GRID\", mixer_grid_command, 1);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER COMMIT\", mixer_commit_command, 0);\n    repo->register_channel_command(L\"Mixer Commands\", L\"MIXER CLEAR\", mixer_clear_command, 0);\n    repo->register_command(L\"Mixer Commands\", L\"CHANNEL_GRID\", channel_grid_command, 0);\n\n    repo->register_command(L\"Thumbnail Commands\", L\"THUMBNAIL LIST\", thumbnail_list_command, 0);\n    repo->register_command(L\"Thumbnail Commands\", L\"THUMBNAIL RETRIEVE\", thumbnail_retrieve_command, 1);\n    repo->register_command(L\"Thumbnail Commands\", L\"THUMBNAIL GENERATE\", thumbnail_generate_command, 1);\n    repo->register_command(L\"Thumbnail Commands\", L\"THUMBNAIL GENERATE_ALL\", thumbnail_generateall_command, 0);\n\n    repo->register_command(L\"Query Commands\", L\"CINF\", cinf_command, 1);\n    repo->register_command(L\"Query Commands\", L\"CLS\", cls_command, 0);\n    repo->register_command(L\"Query Commands\", L\"FLS\", fls_command, 0);\n    repo->register_command(L\"Query Commands\", L\"TLS\", tls_command, 0);\n    repo->register_command(L\"Query Commands\", L\"VERSION\", version_command, 0);\n    repo->register_command(L\"Query Commands\", L\"DIAG\", diag_command, 0);\n    repo->register_command(L\"Query Commands\", L\"BYE\", bye_command, 0);\n    repo->register_command(L\"Query Commands\", L\"KILL\", kill_command, 0);\n    repo->register_command(L\"Query Commands\", L\"RESTART\", restart_command, 0);\n    repo->register_channel_command(L\"Query Commands\", L\"INFO\", info_channel_command, 0);\n    repo->register_command(L\"Query Commands\", L\"INFO\", info_command, 0);\n    repo->register_command(L\"Query Commands\", L\"INFO CONFIG\", info_config_command, 0);\n    repo->register_command(L\"Query Commands\", L\"INFO PATHS\", info_paths_command, 0);\n    repo->register_command(L\"Query Commands\", L\"GL INFO\", gl_info_command, 0);\n    repo->register_command(L\"Query Commands\", L\"GL GC\", gl_gc_command, 0);\n\n    repo->register_command(L\"Query Commands\", L\"OSC SUBSCRIBE\", osc_subscribe_command, 1);\n    repo->register_command(L\"Query Commands\", L\"OSC UNSUBSCRIBE\", osc_unsubscribe_command, 1);\n}\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPCommandsImpl.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#pragma once\n\n#include \"amcp_command_context.h\"\n#include \"amcp_command_repository_wrapper.h\"\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nvoid register_commands(std::shared_ptr<amcp_command_repository_wrapper>& repo);\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPProtocolStrategy.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#include \"../StdAfx.h\"\n\n#include \"AMCPCommand.h\"\n#include \"AMCPCommandQueue.h\"\n#include \"AMCPProtocolStrategy.h\"\n#include \"amcp_command_context.h\"\n#include \"amcp_command_repository.h\"\n#include \"amcp_shared.h\"\n#include \"protocol/util/strategy_adapters.h\"\n#include \"protocol/util/tokenize.h\"\n\n#include \"../util/tokenize.h\"\n\n#include <algorithm>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/log/keywords/delimiter.hpp>\n\n#include <common/diagnostics/graph.h>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nusing IO::ClientInfoPtr;\n\nclass AMCPClientBatchInfo\n{\n  public:\n    AMCPClientBatchInfo(const IO::client_connection<wchar_t>::ptr client)\n        : client_(client)\n        , commands_()\n        , in_progress_(false)\n    {\n    }\n    ~AMCPClientBatchInfo() { commands_.clear(); }\n\n    void add_command(const AMCPCommand::ptr_type cmd) { commands_.push_back(cmd); }\n\n    std::shared_ptr<AMCPGroupCommand> finish()\n    {\n        const auto res = std::make_shared<AMCPGroupCommand>(commands_, client_, request_id_);\n\n        in_progress_ = false;\n        commands_.clear();\n\n        return std::move(res);\n    }\n\n    void begin(const std::wstring& request_id)\n    {\n        request_id_  = request_id;\n        in_progress_ = true;\n        commands_.clear();\n    }\n\n    bool                in_progress() const { return in_progress_; }\n    const std::wstring& request_id() const { return request_id_; }\n\n  private:\n    const IO::client_connection<wchar_t>::ptr client_;\n    std::vector<AMCPCommand::ptr_type>        commands_;\n    bool                                      in_progress_;\n    std::wstring                              request_id_;\n};\n\nclass AMCPProtocolStrategy\n{\n  private:\n    std::vector<AMCPCommandQueue::ptr_type>  commandQueues_;\n    spl::shared_ptr<amcp_command_repository> repo_;\n\n  public:\n    AMCPProtocolStrategy(const std::wstring& name, const spl::shared_ptr<amcp_command_repository>& repo)\n        : repo_(repo)\n    {\n        commandQueues_.push_back(spl::make_shared<AMCPCommandQueue>(L\"General Queue for \" + name, repo_->channels()));\n\n        for (auto& ch : *repo_->channels()) {\n            auto queue = spl::make_shared<AMCPCommandQueue>(\n                L\"Channel \" + std::to_wstring(ch.raw_channel->index()) + L\" for \" + name, repo_->channels());\n            std::weak_ptr<AMCPCommandQueue> queue_weak = queue;\n            commandQueues_.push_back(queue);\n        }\n    }\n\n    ~AMCPProtocolStrategy() {}\n\n    enum class error_state\n    {\n        no_error = 0,\n        command_error,\n        channel_error,\n        parameters_error,\n        unknown_error,\n        access_error\n    };\n\n    // The parser method expects message to be complete messages with the delimiter stripped away.\n    // Thesefore the AMCPProtocolStrategy should be decorated with a delimiter_based_chunking_strategy\n    void\n    parse(const std::wstring& message, const ClientInfoPtr& client, const std::shared_ptr<AMCPClientBatchInfo>& batch)\n    {\n        std::list<std::wstring> tokens;\n        IO::tokenize(message, tokens);\n\n        if (!tokens.empty() && boost::iequals(tokens.front(), L\"PING\")) {\n            tokens.pop_front();\n            std::wstringstream answer;\n            answer << L\"PONG\";\n\n            for (auto t : tokens)\n                answer << L\" \" << t;\n\n            answer << \"\\r\\n\";\n            client->send(answer.str(), true);\n            return;\n        }\n\n        CASPAR_LOG(info) << L\"Received message from \" << client->address() << \": \"\n                         << log::replace_nonprintable_copy(message, L'?') << L\"\\\\r\\\\n\";\n\n        std::wstring request_id;\n        std::wstring command_name;\n        error_state  err = parse_command_string(client, batch, tokens, request_id, command_name);\n        if (err != error_state::no_error) {\n            std::wstringstream answer;\n\n            if (!request_id.empty())\n                answer << L\"RES \" << request_id << L\" \";\n\n            switch (err) {\n                case error_state::command_error:\n                    answer << L\"400 ERROR\\r\\n\" << message << \"\\r\\n\";\n                    break;\n                case error_state::channel_error:\n                    answer << L\"401 \" << command_name << \" ERROR\\r\\n\";\n                    break;\n                case error_state::parameters_error:\n                    answer << L\"402 \" << command_name << \" ERROR\\r\\n\";\n                    break;\n                case error_state::access_error:\n                    answer << L\"503 \" << command_name << \" FAILED\\r\\n\";\n                    break;\n                case error_state::unknown_error:\n                    answer << L\"500 FAILED\\r\\n\";\n                    break;\n                default:\n                    CASPAR_THROW_EXCEPTION(programming_error() << msg_info(L\"Unhandled error_state enum constant \" +\n                                                                           std::to_wstring(static_cast<int>(err))));\n            }\n            client->send(answer.str());\n        }\n    }\n\n  private:\n    error_state parse_command_string(const ClientInfoPtr&                        client,\n                                     const std::shared_ptr<AMCPClientBatchInfo>& batch,\n                                     std::list<std::wstring>                     tokens,\n                                     std::wstring&                               request_id,\n                                     std::wstring&                               command_name)\n    {\n        try {\n            // Discard GetSwitch\n            if (!tokens.empty() && tokens.front().at(0) == L'/')\n                tokens.pop_front();\n\n            error_state error = parse_request_token(tokens, request_id);\n            if (error != error_state::no_error) {\n                return error;\n            }\n\n            // Fail if no more tokens.\n            if (tokens.empty()) {\n                return error_state::command_error;\n            }\n\n            if (parse_batch_commands(batch, tokens, request_id, error)) {\n                return error;\n            }\n\n            command_name                               = boost::to_upper_copy(tokens.front());\n            const std::shared_ptr<AMCPCommand> command = repo_->parse_command(client, tokens, request_id);\n            if (!command) {\n                return error_state::command_error;\n            }\n\n            const int channel_index = command->channel_index();\n            if (!repo_->check_channel_lock(client, channel_index)) {\n                return error_state::access_error;\n            }\n\n            if (batch->in_progress()) {\n                batch->add_command(command);\n                return error_state::no_error;\n            }\n\n            auto wrapped = std::make_shared<AMCPGroupCommand>(command);\n            commandQueues_.at(channel_index + 1)->AddCommand(std::move(wrapped));\n            return error_state::no_error;\n\n        } catch (std::out_of_range&) {\n            CASPAR_LOG(error) << \"Invalid channel specified.\";\n            return error_state::channel_error;\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n            return error_state::unknown_error;\n        }\n    }\n\n    static error_state parse_request_token(std::list<std::wstring>& tokens, std::wstring& request_id)\n    {\n        if (tokens.empty() || !boost::iequals(tokens.front(), L\"REQ\")) {\n            return error_state::no_error;\n        }\n\n        tokens.pop_front();\n\n        if (tokens.empty()) {\n            return error_state::parameters_error;\n        }\n\n        request_id = std::move(tokens.front());\n        tokens.pop_front();\n\n        return error_state::no_error;\n    }\n\n    bool parse_batch_commands(const std::shared_ptr<AMCPClientBatchInfo>& batch,\n                              std::list<std::wstring>&                    tokens,\n                              std::wstring&                               request_id,\n                              error_state&                                error)\n    {\n        if (boost::iequals(tokens.front(), L\"COMMIT\")) {\n            if (!batch->in_progress()) {\n                error = error_state::command_error;\n                return true;\n            }\n\n            commandQueues_.at(0)->AddCommand(std::move(batch->finish()));\n            error = error_state::no_error;\n            return true;\n        }\n        if (boost::iequals(tokens.front(), L\"BEGIN\")) {\n            if (batch->in_progress()) {\n                error = error_state::command_error;\n                return true;\n            }\n\n            batch->begin(request_id);\n            error = error_state::no_error;\n            return true;\n        }\n        if (boost::iequals(tokens.front(), L\"DISCARD\")) {\n            if (!batch->in_progress()) {\n                error = error_state::command_error;\n                return true;\n            }\n\n            batch->finish();\n            error = error_state::no_error;\n            return true;\n        }\n\n        return false;\n    }\n};\n\nclass AMCPClientStrategy : public IO::protocol_strategy<wchar_t>\n{\n    const std::shared_ptr<AMCPProtocolStrategy> strategy_;\n    const std::shared_ptr<AMCPClientBatchInfo>  batch_;\n    ClientInfoPtr                               client_info_;\n\n  public:\n    AMCPClientStrategy(const std::shared_ptr<AMCPProtocolStrategy>& strategy,\n                       const IO::client_connection<wchar_t>::ptr&   client_connection)\n        : strategy_(strategy)\n        , batch_(std::make_shared<AMCPClientBatchInfo>(client_connection))\n        , client_info_(client_connection)\n    {\n    }\n\n    void parse(const std::basic_string<wchar_t>& data) override { strategy_->parse(data, client_info_, batch_); }\n};\n\nclass amcp_client_strategy_factory : public IO::protocol_strategy_factory<wchar_t>\n{\n  public:\n    explicit amcp_client_strategy_factory(const std::shared_ptr<AMCPProtocolStrategy>& strategy)\n        : strategy_(strategy)\n    {\n    }\n\n    IO::protocol_strategy<wchar_t>::ptr create(const IO::client_connection<wchar_t>::ptr& client_connection) override\n    {\n        return spl::make_shared<AMCPClientStrategy>(strategy_, client_connection);\n    }\n\n  private:\n    const std::shared_ptr<AMCPProtocolStrategy> strategy_;\n};\n\nIO::protocol_strategy_factory<char>::ptr\ncreate_char_amcp_strategy_factory(const std::wstring& name, const spl::shared_ptr<amcp_command_repository>& repo)\n{\n    auto amcp_strategy = spl::make_shared<AMCPProtocolStrategy>(name, repo);\n    auto amcp_client   = spl::make_shared<amcp_client_strategy_factory>(amcp_strategy);\n    auto to_unicode    = spl::make_shared<IO::to_unicode_adapter_factory>(\"UTF-8\", amcp_client);\n    return spl::make_shared<IO::delimiter_based_chunking_strategy_factory<char>>(\"\\r\\n\", to_unicode);\n}\n\nIO::protocol_strategy_factory<wchar_t>::ptr\ncreate_wchar_amcp_strategy_factory(const std::wstring& name, const spl::shared_ptr<amcp_command_repository>& repo)\n{\n    auto amcp_strategy = spl::make_shared<AMCPProtocolStrategy>(name, repo);\n    auto amcp_client   = spl::make_shared<amcp_client_strategy_factory>(amcp_strategy);\n    return spl::make_shared<IO::delimiter_based_chunking_strategy_factory<wchar_t>>(L\"\\r\\n\", amcp_client);\n}\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/AMCPProtocolStrategy.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#pragma once\n\n#include \"../util/ClientInfo.h\"\n\n#include <common/memory.h>\n\n#include \"amcp_command_repository.h\"\n\n#include <string>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nIO::protocol_strategy_factory<char>::ptr\ncreate_char_amcp_strategy_factory(const std::wstring& name, const spl::shared_ptr<amcp_command_repository>& repo);\n\nIO::protocol_strategy_factory<wchar_t>::ptr\ncreate_wchar_amcp_strategy_factory(const std::wstring& name, const spl::shared_ptr<amcp_command_repository>& repo);\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_args.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"amcp_args.h\"\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nstd::map<std::wstring, std::wstring> tokenize_args(const std::wstring& message)\n{\n    std::map<std::wstring, std::wstring> pTokenMap;\n\n    std::wstring currentName;\n    std::wstring currentValue;\n\n    bool inValue        = false;\n    bool inQuote        = false;\n    bool getSpecialCode = false;\n\n    for (unsigned int charIndex = 1; charIndex < message.size() - 1; ++charIndex) {\n        if (!inValue) {\n            if (message[charIndex] == L' ') {\n                pTokenMap[currentName] = L\"\";\n                currentName.clear();\n                currentValue.clear();\n            } else if (message[charIndex] == L'=') {\n                boost::to_upper(currentName);\n                inValue = true;\n            } else {\n                currentName += message[charIndex];\n            }\n            continue;\n        }\n\n        if (getSpecialCode) {\n            // insert code-handling here\n            switch (message[charIndex]) {\n                case L'\\\\':\n                    currentValue += L\"\\\\\";\n                    break;\n                case L'\\\"':\n                    currentValue += L\"\\\"\";\n                    break;\n                case L'n':\n                    currentValue += L\"\\n\";\n                    break;\n                default:\n                    break;\n            };\n            getSpecialCode = false;\n            continue;\n        }\n\n        if (message[charIndex] == L'\\\\') {\n            getSpecialCode = true;\n            continue;\n        }\n\n        if (message[charIndex] == L' ' && inQuote == false) {\n            if (!currentValue.empty()) {\n                pTokenMap[currentName] = currentValue;\n                currentName.clear();\n                currentValue.clear();\n                inValue = false;\n            }\n            continue;\n        }\n\n        if (message[charIndex] == L'\\\"') {\n            inQuote = !inQuote;\n\n            if (!currentValue.empty() || !inQuote) {\n                pTokenMap[currentName] = currentValue;\n                currentName.clear();\n                currentValue.clear();\n                inValue = false;\n            }\n            continue;\n        }\n\n        currentValue += message[charIndex];\n    }\n\n    if (!currentValue.empty()) {\n        pTokenMap[currentName] = currentValue;\n        currentName.clear();\n        currentValue.clear();\n    }\n\n    return pTokenMap;\n}\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_args.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include <boost/algorithm/string.hpp>\n#include <map>\n#include <vector>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\ninline bool is_args_token(const std::wstring& message)\n{\n    return (message[0] == L'(' && message[message.size() - 1] == L')');\n}\n\ninline bool\nget_arg_value(const std::map<std::wstring, std::wstring>& args, const std::wstring& key, std::wstring& value)\n{\n    auto it = args.find(boost::to_upper_copy(key));\n    if (it != args.end()) {\n        value = it->second;\n        return true;\n    }\n    return false;\n}\n\ninline bool get_bool_arg(const std::map<std::wstring, std::wstring>& args, const std::wstring& key)\n{\n    std::wstring value;\n    if (get_arg_value(args, key, value)) {\n        return (value != L\"0\" && boost::to_upper_copy(value) != L\"FALSE\");\n    }\n    return false;\n}\n\nstd::map<std::wstring, std::wstring> tokenize_args(const std::wstring& message);\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_command_context.h",
    "content": "/*\n * Copyright (c) 2018 Norsk rikskringkasting AS\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include \"../util/ClientInfo.h\"\n#include \"amcp_command_repository.h\"\n#include \"amcp_shared.h\"\n#include <accelerator/accelerator.h>\n#include <future>\n#include <utility>\n\nnamespace caspar::protocol::osc {\nclass client;\n}\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nstruct amcp_command_static_context\n{\n    const core::video_format_repository                        format_repository;\n    const spl::shared_ptr<core::cg_producer_registry>          cg_registry;\n    const spl::shared_ptr<const core::frame_producer_registry> producer_registry;\n    const spl::shared_ptr<const core::frame_consumer_registry> consumer_registry;\n    const std::shared_ptr<amcp_command_repository>             parser;\n    std::function<void(bool)>                                  shutdown_server_now;\n    const std::string                                          proxy_host;\n    const std::string                                          proxy_port;\n    std::weak_ptr<accelerator::accelerator_device>             ogl_device;\n    const spl::shared_ptr<osc::client>                         osc_client;\n\n    amcp_command_static_context(core::video_format_repository                               format_repository,\n                                const spl::shared_ptr<core::cg_producer_registry>&          cg_registry,\n                                const spl::shared_ptr<const core::frame_producer_registry>& producer_registry,\n                                const spl::shared_ptr<const core::frame_consumer_registry>& consumer_registry,\n                                std::shared_ptr<amcp_command_repository>                    parser,\n                                std::function<void(bool)>                                   shutdown_server_now,\n                                std::string                                                 proxy_host,\n                                std::string                                                 proxy_port,\n                                std::weak_ptr<accelerator::accelerator_device>              ogl_device,\n                                const spl::shared_ptr<osc::client>&                         osc_client)\n        : format_repository(std::move(format_repository))\n        , cg_registry(cg_registry)\n        , producer_registry(producer_registry)\n        , consumer_registry(consumer_registry)\n        , parser(std::move(parser))\n        , shutdown_server_now(std::move(shutdown_server_now))\n        , proxy_host(std::move(proxy_host))\n        , proxy_port(std::move(proxy_port))\n        , ogl_device(std::move(ogl_device))\n        , osc_client(osc_client)\n    {\n    }\n};\n\nstruct command_context\n{\n    std::shared_ptr<amcp_command_static_context>        static_context;\n    const spl::shared_ptr<std::vector<channel_context>> channels;\n    const IO::ClientInfoPtr                             client;\n    const channel_context                               channel;\n    const int                                           channel_index;\n    const int                                           layer_id;\n    std::vector<std::wstring>                           parameters;\n\n    int layer_index(int default_ = 0) const { return layer_id == -1 ? default_ : layer_id; }\n\n    command_context(std::shared_ptr<amcp_command_static_context>        static_context,\n                    const spl::shared_ptr<std::vector<channel_context>> channels,\n                    const IO::ClientInfoPtr&                            client,\n                    channel_context                                     channel,\n                    int                                                 channel_index,\n                    int                                                 layer_id)\n        : static_context(std::move(static_context))\n        , channels(std::move(channels))\n        , client(client)\n        , channel(std::move(channel))\n        , channel_index(channel_index)\n        , layer_id(layer_id)\n    {\n    }\n};\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_command_repository.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../StdAfx.h\"\n\n#include \"amcp_command_repository.h\"\n\n#include <common/env.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/lexical_cast.hpp>\n\n#include <map>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nAMCPCommand::ptr_type make_cmd(amcp_command_func        func,\n                               const std::wstring&      name,\n                               const std::wstring&      id,\n                               IO::ClientInfoPtr        client,\n                               unsigned int             channel_index,\n                               int                      layer_index,\n                               std::list<std::wstring>& tokens)\n{\n    const std::vector<std::wstring> parameters(tokens.begin(), tokens.end());\n    const command_context_simple    ctx(std::move(client), channel_index, layer_index, std::move(parameters));\n\n    return std::make_shared<AMCPCommand>(ctx, func, name, id);\n}\n\nAMCPCommand::ptr_type find_command(const std::map<std::wstring, std::pair<amcp_command_func, int>>& commands,\n                                   const std::wstring&                                              name,\n                                   const std::wstring&                                              request_id,\n                                   IO::ClientInfoPtr                                                client,\n                                   int                                                              channel_index,\n                                   int                                                              layer_index,\n                                   std::list<std::wstring>&                                         tokens)\n{\n    std::wstring subcommand;\n\n    if (!tokens.empty())\n        subcommand = boost::to_upper_copy(tokens.front());\n\n    // Start with subcommand syntax like MIXER CLEAR etc\n    if (!subcommand.empty()) {\n        const auto fullname = name + L\" \" + subcommand;\n        const auto subcmd   = commands.find(fullname);\n\n        if (subcmd != commands.end()) {\n            tokens.pop_front();\n\n            if (tokens.size() >= subcmd->second.second) {\n                return make_cmd(\n                    subcmd->second.first, fullname, request_id, std::move(client), channel_index, layer_index, tokens);\n            }\n        }\n    }\n\n    // Resort to ordinary command\n    const auto command = commands.find(name);\n\n    if (command != commands.end() && tokens.size() >= command->second.second) {\n        return make_cmd(command->second.first, name, request_id, std::move(client), channel_index, layer_index, tokens);\n    }\n\n    return nullptr;\n}\n\ntemplate <typename Out, typename In>\nbool try_lexical_cast(const In& input, Out& result)\n{\n    Out        saved   = result;\n    const bool success = boost::conversion::detail::try_lexical_convert(input, result);\n\n    if (!success)\n        result = saved; // Needed because of how try_lexical_convert is implemented.\n\n    return success;\n}\n\nstatic void\nparse_channel_id(std::list<std::wstring>& tokens, std::wstring& channel_spec, int& channel_index, int& layer_index)\n{\n    if (!tokens.empty()) {\n        channel_spec                            = tokens.front();\n        std::wstring              channelid_str = boost::trim_copy(channel_spec);\n        std::vector<std::wstring> split;\n        boost::split(split, channelid_str, boost::is_any_of(\"-\"));\n\n        // Use non_throwing lexical cast to not hit exception break point all the time.\n        if (try_lexical_cast(split[0], channel_index)) {\n            --channel_index;\n\n            if (split.size() > 1)\n                try_lexical_cast(split[1], layer_index);\n\n            // Consume channel-spec\n            tokens.pop_front();\n        }\n    }\n}\n\nstruct amcp_command_repository::impl\n{\n    const spl::shared_ptr<std::vector<channel_context>> channels_;\n\n    std::map<std::wstring, std::pair<amcp_command_func, int>> commands{};\n    std::map<std::wstring, std::pair<amcp_command_func, int>> channel_commands{};\n\n    impl(const spl::shared_ptr<std::vector<channel_context>>& channels)\n        : channels_(channels)\n    {\n    }\n\n    AMCPCommand::ptr_type create_command(const std::wstring&      name,\n                                         const std::wstring&      id,\n                                         IO::ClientInfoPtr        client,\n                                         std::list<std::wstring>& tokens) const\n    {\n        auto command = find_command(commands, name, id, std::move(client), -1, -1, tokens);\n\n        if (command)\n            return command;\n\n        return nullptr;\n    }\n\n    AMCPCommand::ptr_type create_channel_command(const std::wstring&      name,\n                                                 const std::wstring&      id,\n                                                 IO::ClientInfoPtr        client,\n                                                 unsigned int             channel_index,\n                                                 int                      layer_index,\n                                                 std::list<std::wstring>& tokens) const\n    {\n        if (channels_->size() <= channel_index)\n            return nullptr;\n\n        auto command = find_command(channel_commands, name, id, std::move(client), channel_index, layer_index, tokens);\n\n        if (command)\n            return command;\n\n        return nullptr;\n    }\n\n    std::shared_ptr<AMCPCommand>\n    parse_command(IO::ClientInfoPtr client, std::list<std::wstring> tokens, const std::wstring& request_id) const\n    {\n        // Consume command name\n        const std::basic_string<wchar_t> command_name = boost::to_upper_copy(tokens.front());\n        tokens.pop_front();\n\n        // Determine whether the next parameter is a channel spec or not\n        int          channel_index = -1;\n        int          layer_index   = -1;\n        std::wstring channel_spec;\n        parse_channel_id(tokens, channel_spec, channel_index, layer_index);\n\n        // Create command instance\n        std::shared_ptr<AMCPCommand> command;\n        if (channel_index >= 0) {\n            command = create_channel_command(command_name, request_id, client, channel_index, layer_index, tokens);\n\n            if (!command) // Might be a non channel command, although the first argument is numeric\n            {\n                // Restore backed up channel spec string.\n                tokens.push_front(channel_spec);\n            }\n        }\n\n        // Create global instance\n        if (!command) {\n            command = create_command(command_name, request_id, client, tokens);\n        }\n\n        return std::move(command);\n    }\n\n    bool check_channel_lock(IO::ClientInfoPtr client, int channel_index) const\n    {\n        if (channel_index < 0 || channel_index >= channels_->size())\n            return true;\n\n        auto lock = channels_->at(channel_index).lock;\n        return !(lock && !lock->check_access(client));\n    }\n};\n\namcp_command_repository::amcp_command_repository(const spl::shared_ptr<std::vector<channel_context>>& channels)\n    : impl_(new impl(channels))\n{\n}\n\nconst spl::shared_ptr<std::vector<channel_context>>& amcp_command_repository::channels() const\n{\n    return impl_->channels_;\n}\n\nstd::shared_ptr<AMCPCommand> amcp_command_repository::parse_command(IO::ClientInfoPtr       client,\n                                                                    std::list<std::wstring> tokens,\n                                                                    const std::wstring&     request_id) const\n{\n    return impl_->parse_command(client, tokens, request_id);\n}\n\nbool amcp_command_repository::check_channel_lock(IO::ClientInfoPtr client, int channel_index) const\n{\n    return impl_->check_channel_lock(client, channel_index);\n}\n\nvoid amcp_command_repository::register_command(std::wstring      category,\n                                               std::wstring      name,\n                                               amcp_command_func command,\n                                               int               min_num_params)\n{\n    impl_->commands.insert(std::make_pair(std::move(name), std::make_pair(std::move(command), min_num_params)));\n}\n\nvoid amcp_command_repository::register_channel_command(std::wstring      category,\n                                                       std::wstring      name,\n                                                       amcp_command_func command,\n                                                       int               min_num_params)\n{\n    impl_->channel_commands.insert(std::make_pair(std::move(name), std::make_pair(std::move(command), min_num_params)));\n}\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_command_repository.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include \"../util/ClientInfo.h\"\n#include \"AMCPCommand.h\"\n\n#include <common/memory.h>\n\n#include <functional>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nclass amcp_command_repository\n{\n  public:\n    amcp_command_repository(const spl::shared_ptr<std::vector<channel_context>>& channels);\n\n    std::shared_ptr<AMCPCommand>\n         parse_command(IO::ClientInfoPtr client, std::list<std::wstring> tokens, const std::wstring& request_id) const;\n    bool check_channel_lock(IO::ClientInfoPtr client, int channel_index) const;\n\n    const spl::shared_ptr<std::vector<channel_context>>& channels() const;\n\n    void register_command(std::wstring category, std::wstring name, amcp_command_func command, int min_num_params);\n\n    void\n    register_channel_command(std::wstring category, std::wstring name, amcp_command_func command, int min_num_params);\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n\n    amcp_command_repository(const amcp_command_repository&)            = delete;\n    amcp_command_repository& operator=(const amcp_command_repository&) = delete;\n};\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_command_repository_wrapper.cpp",
    "content": "/*\n * Copyright (c) 2018 Norsk rikskringkasting AS\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#include \"amcp_command_repository_wrapper.h\"\n\n#include <common/future.h>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nvoid amcp_command_repository_wrapper::register_command(std::wstring                  category,\n                                                       std::wstring                  name,\n                                                       amcp_command_impl_func_future command,\n                                                       int                           min_num_params)\n{\n    std::weak_ptr<command_context_factory> weak_context_factory = context_factory_;\n    auto                                   func = [weak_context_factory, command](const command_context_simple&                        ctx,\n                                                const spl::shared_ptr<std::vector<channel_context>>& channels) {\n        auto context_factory = weak_context_factory.lock();\n        if (!context_factory)\n            return make_ready_future<std::wstring>(L\"\");\n\n        auto context = context_factory->create(ctx, channels);\n        return command(context);\n    };\n\n    repo_->register_command(category, name, func, min_num_params);\n}\n\nvoid amcp_command_repository_wrapper::register_command(std::wstring           category,\n                                                       std::wstring           name,\n                                                       amcp_command_impl_func command,\n                                                       int                    min_num_params)\n{\n    std::weak_ptr<command_context_factory> weak_context_factory = context_factory_;\n    auto                                   func = [weak_context_factory, command](const command_context_simple&                        ctx,\n                                                const spl::shared_ptr<std::vector<channel_context>>& channels) {\n        auto context_factory = weak_context_factory.lock();\n        if (!context_factory)\n            return make_ready_future<std::wstring>(L\"\");\n\n        auto context = context_factory->create(ctx, channels);\n        return make_ready_future(command(context));\n    };\n\n    repo_->register_command(category, name, func, min_num_params);\n}\n\nvoid amcp_command_repository_wrapper::register_channel_command(std::wstring                  category,\n                                                               std::wstring                  name,\n                                                               amcp_command_impl_func_future command,\n                                                               int                           min_num_params)\n{\n    std::weak_ptr<command_context_factory> weak_context_factory = context_factory_;\n    auto                                   func = [weak_context_factory, command](const command_context_simple&                        ctx,\n                                                const spl::shared_ptr<std::vector<channel_context>>& channels) {\n        auto context_factory = weak_context_factory.lock();\n        if (!context_factory)\n            return make_ready_future<std::wstring>(L\"\");\n\n        auto context = context_factory->create(ctx, channels);\n        return command(context);\n    };\n\n    repo_->register_channel_command(category, name, func, min_num_params);\n}\n\nvoid amcp_command_repository_wrapper::register_channel_command(std::wstring           category,\n                                                               std::wstring           name,\n                                                               amcp_command_impl_func command,\n                                                               int                    min_num_params)\n{\n    std::weak_ptr<command_context_factory> weak_context_factory = context_factory_;\n    auto                                   func = [weak_context_factory, command](const command_context_simple&                        ctx,\n                                                const spl::shared_ptr<std::vector<channel_context>>& channels) {\n        auto context_factory = weak_context_factory.lock();\n        if (!context_factory)\n            return make_ready_future<std::wstring>(L\"\");\n\n        auto context = context_factory->create(ctx, channels);\n        return make_ready_future(command(context));\n    };\n\n    repo_->register_channel_command(category, name, func, min_num_params);\n}\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_command_repository_wrapper.h",
    "content": "/*\n * Copyright (c) 2018 Norsk rikskringkasting AS\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Julian Waller, julian@superfly.tv\n */\n\n#pragma once\n\n#include \"amcp_command_context.h\"\n\nnamespace caspar { namespace protocol { namespace amcp {\n\ntypedef std::function<std::future<std::wstring>(command_context& args)> amcp_command_impl_func_future;\ntypedef std::function<std::wstring(command_context& args)>              amcp_command_impl_func;\n\nclass command_context_factory\n{\n  public:\n    command_context_factory(std::shared_ptr<amcp_command_static_context> static_context)\n        : static_context_(std::move(static_context))\n    {\n    }\n\n    command_context create(const command_context_simple&                        simple_ctx,\n                           const spl::shared_ptr<std::vector<channel_context>>& channels) const\n    {\n        const channel_context channel =\n            simple_ctx.channel_index >= 0 ? channels->at(simple_ctx.channel_index) : channel_context();\n        auto ctx = command_context(\n            static_context_, channels, simple_ctx.client, channel, simple_ctx.channel_index, simple_ctx.layer_id);\n        ctx.parameters = std::move(simple_ctx.parameters);\n        return ctx;\n    }\n\n  private:\n    std::shared_ptr<amcp_command_static_context> static_context_;\n};\n\nclass amcp_command_repository_wrapper\n{\n  public:\n    amcp_command_repository_wrapper(std::shared_ptr<amcp_command_repository> repo,\n                                    std::shared_ptr<command_context_factory> context_factory)\n        : repo_(repo)\n        , context_factory_(context_factory)\n    {\n    }\n\n    void register_command(std::wstring                  category,\n                          std::wstring                  name,\n                          amcp_command_impl_func_future command,\n                          int                           min_num_params);\n\n    void register_command(std::wstring category, std::wstring name, amcp_command_impl_func command, int min_num_params);\n\n    void register_channel_command(std::wstring                  category,\n                                  std::wstring                  name,\n                                  amcp_command_impl_func_future command,\n                                  int                           min_num_params);\n\n    void register_channel_command(std::wstring           category,\n                                  std::wstring           name,\n                                  amcp_command_impl_func command,\n                                  int                    min_num_params);\n\n  private:\n    std::shared_ptr<amcp_command_repository> repo_;\n    std::weak_ptr<command_context_factory>   context_factory_;\n};\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/amcp/amcp_shared.h",
    "content": "#pragma once\n\n#include \"../util/ClientInfo.h\"\n#include \"../util/lock_container.h\"\n#include <core/producer/stage.h>\n#include <core/video_channel.h>\n#include <utility>\n\nnamespace caspar { namespace protocol { namespace amcp {\n\nclass channel_context\n{\n  public:\n    explicit channel_context() {}\n    explicit channel_context(std::shared_ptr<core::video_channel> c,\n                             std::shared_ptr<core::stage_base>    s,\n                             const std::wstring&                  lifecycle_key)\n        : raw_channel(std::move(c))\n        , stage(std::move(s))\n        , lock(std::make_shared<caspar::IO::lock_container>(lifecycle_key))\n        , lifecycle_key_(lifecycle_key)\n    {\n    }\n    const std::shared_ptr<core::video_channel>        raw_channel;\n    const std::shared_ptr<core::stage_base>           stage;\n    const std::shared_ptr<caspar::IO::lock_container> lock;\n    const std::wstring                                lifecycle_key_;\n};\n\nstruct command_context_simple\n{\n    const IO::ClientInfoPtr         client;\n    const int                       channel_index;\n    const int                       layer_id;\n    const std::vector<std::wstring> parameters;\n\n    int layer_index(int default_ = 0) const { return layer_id == -1 ? default_ : layer_id; }\n\n    command_context_simple(IO::ClientInfoPtr                client,\n                           int                              channel_index,\n                           int                              layer_id,\n                           const std::vector<std::wstring>& parameters)\n        : client(std::move(client))\n        , channel_index(channel_index)\n        , layer_id(layer_id)\n        , parameters(parameters)\n    {\n    }\n};\n\ntypedef std::function<std::future<std::wstring>(const command_context_simple&                        args,\n                                                const spl::shared_ptr<std::vector<channel_context>>& channels)>\n    amcp_command_func;\n\n}}} // namespace caspar::protocol::amcp\n"
  },
  {
    "path": "src/protocol/osc/client.cpp",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../StdAfx.h\"\n\n#include \"client.h\"\n\n#include \"oscpack/OscOutboundPacketStream.h\"\n\n#include <common/endian.h>\n#include <common/utf.h>\n\n#include <core/monitor/monitor.h>\n\n#include <boost/asio.hpp>\n\n#include <condition_variable>\n#include <mutex>\n#include <thread>\n#include <vector>\n\nusing namespace boost::asio::ip;\n\nnamespace caspar { namespace protocol { namespace osc {\n\ntemplate <typename T>\nstruct param_visitor : public boost::static_visitor<void>\n{\n    T& o;\n\n    param_visitor(T& o)\n        : o(o)\n    {\n    }\n\n    void operator()(const bool value) { o << value; }\n    void operator()(const int32_t value) { o << static_cast<int32_t>(value); }\n    void operator()(const uint32_t value) { o << static_cast<int64_t>(value); }\n    void operator()(const int64_t value) { o << static_cast<int64_t>(value); }\n    void operator()(const uint64_t value) { o << static_cast<int64_t>(value); }\n    void operator()(const float value) { o << value; }\n    void operator()(const double value) { o << static_cast<float>(value); }\n    void operator()(const std::string& value) { o << value.c_str(); }\n    void operator()(const std::wstring& value) { o << u8(value).c_str(); }\n};\n\nstruct client::impl : public spl::enable_shared_from_this<client::impl>\n{\n    std::shared_ptr<boost::asio::io_context> io_context_;\n    udp::socket                              socket_;\n    std::map<udp::endpoint, int>             reference_counts_by_endpoint_;\n    std::vector<char>                        buffer_;\n\n    std::mutex              mutex_;\n    std::condition_variable cond_;\n    core::monitor::state    bundle_;\n    uint64_t                bundle_time_ = 0;\n\n    uint64_t time_ = 0;\n\n    std::atomic<bool> abort_request_{false};\n    std::thread       thread_;\n\n  public:\n    impl(std::shared_ptr<boost::asio::io_context> io_context)\n        : io_context_(std::move(io_context))\n        , socket_(*io_context_, udp::v4())\n        , buffer_(1000000)\n    {\n        thread_ = std::thread([this] {\n            try {\n                while (!abort_request_) {\n                    core::monitor::state       bundle;\n                    uint64_t                   bundle_time;\n                    std::vector<udp::endpoint> endpoints;\n\n                    {\n                        std::unique_lock<std::mutex> lock(mutex_);\n                        cond_.wait(lock, [&] { return bundle_time_ > 0 || abort_request_; });\n\n                        if (abort_request_) {\n                            return;\n                        }\n\n                        bundle       = std::move(bundle_);\n                        bundle_time  = bundle_time_;\n                        bundle_time_ = 0;\n\n                        for (auto& p : reference_counts_by_endpoint_) {\n                            endpoints.push_back(p.first);\n                        }\n                    }\n\n                    if (endpoints.empty()) {\n                        continue;\n                    }\n\n                    auto it = std::begin(bundle);\n\n                    while (it != std::end(bundle)) {\n                        ::osc::OutboundPacketStream o(reinterpret_cast<char*>(buffer_.data()),\n                                                      static_cast<unsigned long>(buffer_.size()));\n\n                        o << ::osc::BeginBundle(bundle_time);\n\n                        // TODO (fix): < 2048 is a hack. Properly calculate if messages will fit.\n                        while (it != std::end(bundle) && o.Size() < 2048) {\n                            o << ::osc::BeginMessage(it->first.c_str());\n\n                            param_visitor<decltype(o)> param_visitor(o);\n                            for (const auto& element : it->second) {\n                                boost::apply_visitor(param_visitor, element);\n                            }\n\n                            o << ::osc::EndMessage;\n\n                            ++it;\n                        }\n\n                        o << ::osc::EndBundle;\n\n                        boost::system::error_code ec;\n                        for (const auto& endpoint : endpoints) {\n                            socket_.send_to(boost::asio::buffer(o.Data(), o.Size()), endpoint, 0, ec);\n                        }\n                    }\n                }\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        });\n    }\n\n    ~impl()\n    {\n        abort_request_ = true;\n        cond_.notify_all();\n        thread_.join();\n    }\n\n    // TODO (refactor) This is weird...\n    std::shared_ptr<void> get_subscription_token(const boost::asio::ip::udp::endpoint& endpoint)\n    {\n        std::lock_guard<std::mutex> lock(mutex_);\n\n        ++reference_counts_by_endpoint_[endpoint];\n\n        std::weak_ptr<impl> weak_self = shared_from_this();\n\n        return std::shared_ptr<void>(nullptr, [weak_self, endpoint](void*) {\n            auto strong = weak_self.lock();\n\n            if (!strong)\n                return;\n\n            auto& self = *strong;\n\n            std::lock_guard<std::mutex> lock(self.mutex_);\n\n            int reference_count_after = --self.reference_counts_by_endpoint_[endpoint];\n\n            if (reference_count_after == 0) {\n                self.reference_counts_by_endpoint_.erase(endpoint);\n            }\n        });\n    }\n\n    void send(const core::monitor::state& state)\n    {\n        {\n            std::lock_guard<std::mutex> lock(mutex_);\n\n            // TODO: time_++ is a hack. Use proper channel time.\n            bundle_time_ = time_++;\n            bundle_      = state;\n        }\n        cond_.notify_all();\n    }\n};\n\nclient::client(std::shared_ptr<boost::asio::io_context> io_context)\n    : impl_(new impl(std::move(io_context)))\n{\n}\n\nclient::client(client&& other)\n    : impl_(std::move(other.impl_))\n{\n}\n\nclient& client::operator=(client&& other)\n{\n    impl_ = std::move(other.impl_);\n    return *this;\n}\n\nclient::~client() {}\n\nstd::shared_ptr<void> client::get_subscription_token(const boost::asio::ip::udp::endpoint& endpoint)\n{\n    return impl_->get_subscription_token(endpoint);\n}\n\nvoid client::send(const core::monitor::state& state) { impl_->send(state); }\n\n}}} // namespace caspar::protocol::osc\n"
  },
  {
    "path": "src/protocol/osc/client.h",
    "content": "/*\n * Copyright 2013 Sveriges Television AB http://casparcg.com/\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <boost/asio/ip/udp.hpp>\n\n#include <common/memory.h>\n#include <core/monitor/monitor.h>\n\nnamespace caspar { namespace protocol { namespace osc {\n\nclass client\n{\n    client(const client&);\n    client& operator=(const client&);\n\n  public:\n    client(std::shared_ptr<boost::asio::io_context> context);\n\n    client(client&&);\n\n    /**\n     * Get a subscription token that ensures that OSC messages are sent to the\n     * given endpoint as long as the token is alive. It will stop sending when\n     * the token is dropped unless another token to the same endpoint has\n     * previously been checked out.\n     *\n     * @param endpoint The UDP endpoint to send OSC messages to.\n     *\n     * @return The token. It is ok for the token to outlive the client\n     */\n    std::shared_ptr<void> get_subscription_token(const boost::asio::ip::udp::endpoint& endpoint);\n\n    ~client();\n\n    client& operator=(client&&);\n\n    void send(const core::monitor::state& state);\n\n  private:\n    struct impl;\n    spl::shared_ptr<impl> impl_;\n};\n\n}}} // namespace caspar::protocol::osc\n"
  },
  {
    "path": "src/protocol/osc/oscpack/MessageMappingOscPacketListener.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H\n#define INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H\n\n#include <cstring>\n#include <map>\n\n#include \"OscPacketListener.h\"\n\nnamespace osc {\n\ntemplate <class T>\nclass MessageMappingOscPacketListener : public OscPacketListener\n{\n  public:\n    using function_type = void (T::*)(const osc::ReceivedMessage&, const IpEndpointName&);\n\n  protected:\n    void RegisterMessageFunction(const char* addressPattern, function_type f)\n    {\n        functions_.insert(std::make_pair(addressPattern, f));\n    }\n\n    void ProcessMessage(const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint) override\n    {\n        typename function_map_type::iterator i = functions_.find(m.AddressPattern());\n        if (i != functions_.end())\n            (dynamic_cast<T*>(this)->*(i->second))(m, remoteEndpoint);\n    }\n\n  private:\n    struct cstr_compare\n    {\n        bool operator()(const char* lhs, const char* rhs) const { return strcmp(lhs, rhs) < 0; }\n    };\n\n    using function_map_type = std::map<const char*, function_type, cstr_compare>;\n    function_map_type functions_;\n};\n\n} // namespace osc\n\n#endif /* INCLUDED_MESSAGEMAPPINGOSCPACKETLISTENER_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscException.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_OSC_EXCEPTION_H\n#define INCLUDED_OSC_EXCEPTION_H\n\n#include <exception>\n\nnamespace osc {\n\nclass Exception : public std::exception\n{\n    const char* what_;\n\n  public:\n    Exception() throw() {}\n    Exception(const Exception& src) throw()\n        : what_(src.what_)\n    {\n    }\n    Exception(const char* w) throw()\n        : what_(w)\n    {\n    }\n    Exception& operator=(const Exception& src) throw()\n    {\n        what_ = src.what_;\n        return *this;\n    }\n    virtual ~Exception() throw() {}\n    const char* what() const throw() override { return what_; }\n};\n\n} // namespace osc\n\n#endif /* INCLUDED_OSC_EXCEPTION_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscHostEndianness.h",
    "content": "/*\n        oscpack -- Open Sound Control packet manipulation library\n        http://www.audiomulch.com/~rossb/oscpack\n\n        Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n        Permission is hereby granted, free of charge, to any person obtaining\n        a copy of this software and associated documentation files\n        (the \"Software\"), to deal in the Software without restriction,\n        including without limitation the rights to use, copy, modify, merge,\n        publish, distribute, sublicense, and/or sell copies of the Software,\n        and to permit persons to whom the Software is furnished to do so,\n        subject to the following conditions:\n\n        The above copyright notice and this permission notice shall be\n        included in all copies or substantial portions of the Software.\n\n        Any person wishing to distribute modifications to the Software is\n        requested to send the modifications to the original developer so that\n        they can be incorporated into the canonical version.\n\n        THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n        EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n        MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n        IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n        ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n        CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n        WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef OSC_HOSTENDIANNESS_H\n#define OSC_HOSTENDIANNESS_H\n\n#define OSC_HOST_LITTLE_ENDIAN 1\n\n/*\n    Make sure either OSC_HOST_LITTLE_ENDIAN or OSC_HOST_BIG_ENDIAN is defined\n\n    If you know a way to enhance the detection below for Linux and/or MacOSX\n    please let me know! I've tried a few things which don't work.\n*/\n\n#if defined(OSC_HOST_LITTLE_ENDIAN) || defined(OSC_HOST_BIG_ENDIAN)\n\n// you can define one of the above symbols from the command line\n// then you don't have to edit this file.\n\n#elif defined(__WIN32__) || defined(WIN32) || defined(WINCE)\n\nassume that __WIN32__ is only defined on little endian systems\n\n#define OSC_HOST_LITTLE_ENDIAN 1\n#undef OSC_HOST_BIG_ENDIAN\n\n#elif defined(__APPLE__)\n\n#if defined(__LITTLE_ENDIAN__)\n\n#define OSC_HOST_LITTLE_ENDIAN 1\n#undef OSC_HOST_BIG_ENDIAN\n\n#elif defined(__BIG_ENDIAN__)\n\n#define OSC_HOST_BIG_ENDIAN 1\n#undef OSC_HOST_LITTLE_ENDIAN\n\n#endif\n\n#endif\n\n#if !defined(OSC_HOST_LITTLE_ENDIAN) && !defined(OSC_HOST_BIG_ENDIAN)\n\n#error please edit OSCHostEndianness.h to configure endianness\n\n#endif\n\n#endif /* OSC_HOSTENDIANNESS_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscOutboundPacketStream.cpp",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n\n#include \"OscOutboundPacketStream.h\"\n\n#include <cassert>\n#include <cstring>\n\n#include <common/endian.h>\n\n#if defined(__WIN32__) || defined(WIN32)\n#include <malloc.h> // for alloca\n#else\n#include <alloca.h>\n#endif\n\n#include \"OscHostEndianness.h\"\n\nnamespace osc {\n\nstatic void FromInt32(char* p, int32_t x)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    /*union{\n        osc::int32_t i;\n        char c[4];\n    } u;\n\n    u.i = x;\n\n    p[3] = u.c[0];\n    p[2] = u.c[1];\n    p[1] = u.c[2];\n    p[0] = u.c[3];*/\n    *reinterpret_cast<int32_t*>(p) = caspar::swap_byte_order(x);\n#else\n    *reinterpret_cast<int32_t*>(p) = x;\n#endif\n}\n\nstatic void FromUInt32(char* p, uint32_t x)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    /*union{\n        osc::uint32_t i;\n        char c[4];\n    } u;\n\n    u.i = x;\n\n    p[3] = u.c[0];\n    p[2] = u.c[1];\n    p[1] = u.c[2];\n    p[0] = u.c[3];*/\n    *reinterpret_cast<uint32_t*>(p) = caspar::swap_byte_order(x);\n#else\n    *reinterpret_cast<uint32_t*>(p) = x;\n#endif\n}\n\nstatic void FromInt64(char* p, int64_t x)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    /*union{\n        osc::int64_t i;\n        char c[8];\n    } u;\n\n    u.i = x;\n\n    p[7] = u.c[0];\n    p[6] = u.c[1];\n    p[5] = u.c[2];\n    p[4] = u.c[3];\n    p[3] = u.c[4];\n    p[2] = u.c[5];\n    p[1] = u.c[6];\n    p[0] = u.c[7];*/\n    *reinterpret_cast<int64_t*>(p) = caspar::swap_byte_order(x);\n#else\n    *reinterpret_cast<int64_t*>(p) = x;\n#endif\n}\n\nstatic void FromUInt64(char* p, uint64_t x)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    /*union{\n        osc::uint64_t i;\n        char c[8];\n    } u;\n\n    u.i = x;\n\n    p[7] = u.c[0];\n    p[6] = u.c[1];\n    p[5] = u.c[2];\n    p[4] = u.c[3];\n    p[3] = u.c[4];\n    p[2] = u.c[5];\n    p[1] = u.c[6];\n    p[0] = u.c[7];*/\n    *reinterpret_cast<uint64_t*>(p) = caspar::swap_byte_order(x);\n#else\n    *reinterpret_cast<uint64_t*>(p) = x;\n#endif\n}\n\nstatic inline long RoundUp4(long x) { return (x - 1 & ~0x03L) + 4; }\n\nOutboundPacketStream::OutboundPacketStream(char* buffer, unsigned long capacity)\n    : data_(buffer)\n    , end_(data_ + capacity)\n    , typeTagsCurrent_(end_)\n    , messageCursor_(data_)\n    , argumentCurrent_(data_)\n    , elementSizePtr_(nullptr)\n    , messageIsInProgress_(false)\n{\n}\n\nOutboundPacketStream::~OutboundPacketStream() {}\n\nchar* OutboundPacketStream::BeginElement(char* beginPtr)\n{\n    if (elementSizePtr_ == nullptr) {\n        elementSizePtr_ = reinterpret_cast<uint32_t*>(data_);\n\n        return beginPtr;\n    }\n    // store an offset to the old element size ptr in the element size slot\n    // we store an offset rather than the actual pointer to be 64 bit clean.\n    *reinterpret_cast<uint32_t*>(beginPtr) = (uint32_t)(reinterpret_cast<char*>(elementSizePtr_) - data_);\n\n    elementSizePtr_ = reinterpret_cast<uint32_t*>(beginPtr);\n\n    return beginPtr + 4;\n}\n\nvoid OutboundPacketStream::EndElement(char* endPtr)\n{\n    assert(elementSizePtr_ != nullptr);\n\n    if (elementSizePtr_ == reinterpret_cast<uint32_t*>(data_)) {\n        elementSizePtr_ = nullptr;\n\n    } else {\n        // while building an element, an offset to the containing element's\n        // size slot is stored in the elements size slot (or a ptr to data_\n        // if there is no containing element). We retrieve that here\n        uint32_t* previousElementSizePtr = (uint32_t*)(data_ + *reinterpret_cast<uint32_t*>(elementSizePtr_));\n\n        // then we store the element size in the slot, note that the element\n        // size does not include the size slot, hence the - 4 below.\n        uint32_t elementSize = static_cast<uint32_t>(endPtr - reinterpret_cast<char*>(elementSizePtr_)) - 4;\n        FromUInt32(reinterpret_cast<char*>(elementSizePtr_), elementSize);\n\n        // finally, we reset the element size ptr to the containing element\n        elementSizePtr_ = previousElementSizePtr;\n    }\n}\n\nbool OutboundPacketStream::ElementSizeSlotRequired() const { return elementSizePtr_ != nullptr; }\n\nvoid OutboundPacketStream::CheckForAvailableBundleSpace()\n{\n    unsigned long required = Size() + (ElementSizeSlotRequired() ? 4 : 0) + 16;\n\n    if (required > Capacity())\n        throw OutOfBufferMemoryException(required);\n}\n\nvoid OutboundPacketStream::CheckForAvailableMessageSpace(const char* addressPattern)\n{\n    // plus 4 for at least four bytes of type tag\n    unsigned long required = Size() + (ElementSizeSlotRequired() ? 4 : 0) +\n                             RoundUp4(static_cast<unsigned long>(strlen(addressPattern)) + 1) + 4;\n\n    if (required > Capacity())\n        throw OutOfBufferMemoryException(required);\n}\n\nvoid OutboundPacketStream::CheckForAvailableArgumentSpace(long argumentLength)\n{\n    // plus three for extra type tag, comma and null terminator\n    unsigned long required = static_cast<unsigned long>(argumentCurrent_ - data_) + argumentLength +\n                             RoundUp4(static_cast<unsigned long>(end_ - typeTagsCurrent_) + 3);\n\n    if (required > Capacity())\n        throw OutOfBufferMemoryException(required);\n}\n\nvoid OutboundPacketStream::Clear()\n{\n    typeTagsCurrent_     = end_;\n    messageCursor_       = data_;\n    argumentCurrent_     = data_;\n    elementSizePtr_      = nullptr;\n    messageIsInProgress_ = false;\n}\n\nunsigned int OutboundPacketStream::Capacity() const { return static_cast<int>(end_ - data_); }\n\nunsigned int OutboundPacketStream::Size() const\n{\n    unsigned int result = static_cast<unsigned long>(argumentCurrent_ - data_);\n    if (IsMessageInProgress()) {\n        // account for the length of the type tag string. the total type tag\n        // includes an initial comma, plus at least one terminating \\0\n        result += RoundUp4(static_cast<unsigned long>(end_ - typeTagsCurrent_) + 2);\n    }\n\n    return result;\n}\n\nconst char* OutboundPacketStream::Data() const { return data_; }\n\nbool OutboundPacketStream::IsReady() const { return !IsMessageInProgress() && !IsBundleInProgress(); }\n\nbool OutboundPacketStream::IsMessageInProgress() const { return messageIsInProgress_; }\n\nbool OutboundPacketStream::IsBundleInProgress() const { return elementSizePtr_ != nullptr; }\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const BundleInitiator& rhs)\n{\n    if (IsMessageInProgress())\n        throw MessageInProgressException();\n\n    CheckForAvailableBundleSpace();\n\n    messageCursor_ = BeginElement(messageCursor_);\n\n    memcpy(messageCursor_, \"#bundle\\0\", 8);\n    FromUInt64(messageCursor_ + 8, rhs.timeTag);\n\n    messageCursor_ += 16;\n    argumentCurrent_ = messageCursor_;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const BundleTerminator& rhs)\n{\n    (void)rhs;\n\n    if (!IsBundleInProgress())\n        throw BundleNotInProgressException();\n    if (IsMessageInProgress())\n        throw MessageInProgressException();\n\n    EndElement(messageCursor_);\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const BeginMessage& rhs)\n{\n    if (IsMessageInProgress())\n        throw MessageInProgressException();\n\n    CheckForAvailableMessageSpace(rhs.addressPattern);\n\n    messageCursor_ = BeginElement(messageCursor_);\n\n    strcpy(messageCursor_, rhs.addressPattern);\n    unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs.addressPattern));\n    messageCursor_ += rhsLength + 1;\n\n    // zero pad to 4-byte boundary\n    unsigned long i = rhsLength + 1;\n    while (i & 0x3) {\n        *messageCursor_++ = '\\0';\n        ++i;\n    }\n\n    argumentCurrent_ = messageCursor_;\n    typeTagsCurrent_ = end_;\n\n    messageIsInProgress_ = true;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const MessageTerminator& rhs)\n{\n    (void)rhs;\n\n    if (!IsMessageInProgress())\n        throw MessageNotInProgressException();\n\n    int typeTagsCount = static_cast<int>(end_ - typeTagsCurrent_);\n\n    if (typeTagsCount) {\n        char* tempTypeTags = (char*)alloca(typeTagsCount);\n        memcpy(tempTypeTags, typeTagsCurrent_, typeTagsCount);\n\n        // slot size includes comma and null terminator\n        int typeTagSlotSize = RoundUp4(typeTagsCount + 2);\n\n        uint32_t argumentsSize = static_cast<uint32_t>(argumentCurrent_ - messageCursor_);\n\n        memmove(messageCursor_ + typeTagSlotSize, messageCursor_, argumentsSize);\n\n        messageCursor_[0] = ',';\n        // copy type tags in reverse (really forward) order\n        for (int i = 0; i < typeTagsCount; ++i)\n            messageCursor_[i + 1] = tempTypeTags[typeTagsCount - 1 - i];\n\n        char* p = messageCursor_ + 1 + typeTagsCount;\n        for (int i = 0; i < typeTagSlotSize - (typeTagsCount + 1); ++i)\n            *p++ = '\\0';\n\n        typeTagsCurrent_ = end_;\n\n        // advance messageCursor_ for next message\n        messageCursor_ += typeTagSlotSize + argumentsSize;\n\n    } else {\n        // send an empty type tags string\n        memcpy(messageCursor_, \",\\0\\0\\0\", 4);\n\n        // advance messageCursor_ for next message\n        messageCursor_ += 4;\n    }\n\n    argumentCurrent_ = messageCursor_;\n\n    EndElement(messageCursor_);\n\n    messageIsInProgress_ = false;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(bool rhs)\n{\n    CheckForAvailableArgumentSpace(0);\n\n    *--typeTagsCurrent_ = (char)(rhs ? TRUE_TYPE_TAG : FALSE_TYPE_TAG);\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const NilType& rhs)\n{\n    (void)rhs;\n    CheckForAvailableArgumentSpace(0);\n\n    *--typeTagsCurrent_ = NIL_TYPE_TAG;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const InfinitumType& rhs)\n{\n    (void)rhs;\n    CheckForAvailableArgumentSpace(0);\n\n    *--typeTagsCurrent_ = INFINITUM_TYPE_TAG;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(int32_t rhs)\n{\n    CheckForAvailableArgumentSpace(4);\n\n    *--typeTagsCurrent_ = INT32_TYPE_TAG;\n    FromInt32(argumentCurrent_, rhs);\n    argumentCurrent_ += 4;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(float rhs)\n{\n    CheckForAvailableArgumentSpace(4);\n\n    *--typeTagsCurrent_ = FLOAT_TYPE_TAG;\n\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        float f;\n        char  c[4];\n    } u;\n\n    u.f = rhs;\n\n    argumentCurrent_[3] = u.c[0];\n    argumentCurrent_[2] = u.c[1];\n    argumentCurrent_[1] = u.c[2];\n    argumentCurrent_[0] = u.c[3];\n#else\n    *reinterpret_cast<float*>(argumentCurrent_) = rhs;\n#endif\n\n    argumentCurrent_ += 4;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(char rhs)\n{\n    CheckForAvailableArgumentSpace(4);\n\n    *--typeTagsCurrent_ = CHAR_TYPE_TAG;\n    FromInt32(argumentCurrent_, rhs);\n    argumentCurrent_ += 4;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const RgbaColor& rhs)\n{\n    CheckForAvailableArgumentSpace(4);\n\n    *--typeTagsCurrent_ = RGBA_COLOR_TYPE_TAG;\n    FromUInt32(argumentCurrent_, rhs);\n    argumentCurrent_ += 4;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const MidiMessage& rhs)\n{\n    CheckForAvailableArgumentSpace(4);\n\n    *--typeTagsCurrent_ = MIDI_MESSAGE_TYPE_TAG;\n    FromUInt32(argumentCurrent_, rhs);\n    argumentCurrent_ += 4;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(int64_t rhs)\n{\n    CheckForAvailableArgumentSpace(8);\n\n    *--typeTagsCurrent_ = INT64_TYPE_TAG;\n    FromInt64(argumentCurrent_, rhs);\n    argumentCurrent_ += 8;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const TimeTag& rhs)\n{\n    CheckForAvailableArgumentSpace(8);\n\n    *--typeTagsCurrent_ = TIME_TAG_TYPE_TAG;\n    FromUInt64(argumentCurrent_, rhs);\n    argumentCurrent_ += 8;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(double rhs)\n{\n    CheckForAvailableArgumentSpace(8);\n\n    *--typeTagsCurrent_ = DOUBLE_TYPE_TAG;\n\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        double f;\n        char   c[8];\n    } u;\n\n    u.f = rhs;\n\n    argumentCurrent_[7] = u.c[0];\n    argumentCurrent_[6] = u.c[1];\n    argumentCurrent_[5] = u.c[2];\n    argumentCurrent_[4] = u.c[3];\n    argumentCurrent_[3] = u.c[4];\n    argumentCurrent_[2] = u.c[5];\n    argumentCurrent_[1] = u.c[6];\n    argumentCurrent_[0] = u.c[7];\n#else\n    *reinterpret_cast<double*>(argumentCurrent_) = rhs;\n#endif\n\n    argumentCurrent_ += 8;\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const char* rhs)\n{\n    CheckForAvailableArgumentSpace(RoundUp4(static_cast<long>(strlen(rhs)) + 1));\n\n    *--typeTagsCurrent_ = STRING_TYPE_TAG;\n    strcpy(argumentCurrent_, rhs);\n    unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs));\n    argumentCurrent_ += rhsLength + 1;\n\n    // zero pad to 4-byte boundary\n    unsigned long i = rhsLength + 1;\n    while (i & 0x3) {\n        *argumentCurrent_++ = '\\0';\n        ++i;\n    }\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const Symbol& rhs)\n{\n    CheckForAvailableArgumentSpace(RoundUp4(static_cast<long>(strlen(rhs)) + 1));\n\n    *--typeTagsCurrent_ = SYMBOL_TYPE_TAG;\n    strcpy(argumentCurrent_, rhs);\n    unsigned long rhsLength = static_cast<unsigned long>(strlen(rhs));\n    argumentCurrent_ += rhsLength + 1;\n\n    // zero pad to 4-byte boundary\n    unsigned long i = rhsLength + 1;\n    while (i & 0x3) {\n        *argumentCurrent_++ = '\\0';\n        ++i;\n    }\n\n    return *this;\n}\n\nOutboundPacketStream& OutboundPacketStream::operator<<(const Blob& rhs)\n{\n    CheckForAvailableArgumentSpace(4 + RoundUp4(rhs.size));\n\n    *--typeTagsCurrent_ = BLOB_TYPE_TAG;\n    FromUInt32(argumentCurrent_, rhs.size);\n    argumentCurrent_ += 4;\n\n    memcpy(argumentCurrent_, rhs.data, rhs.size);\n    argumentCurrent_ += rhs.size;\n\n    // zero pad to 4-byte boundary\n    unsigned long i = rhs.size;\n    while (i & 0x3) {\n        *argumentCurrent_++ = '\\0';\n        ++i;\n    }\n\n    return *this;\n}\n\n} // namespace osc\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscOutboundPacketStream.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_OSCOUTBOUNDPACKET_H\n#define INCLUDED_OSCOUTBOUNDPACKET_H\n\n#include \"OscException.h\"\n#include \"OscTypes.h\"\n\nnamespace osc {\n\nclass OutOfBufferMemoryException : public Exception\n{\n  public:\n    OutOfBufferMemoryException(std::size_t required_, const char* w = \"out of buffer memory\")\n        : Exception(w)\n        , required(required_)\n    {\n    }\n\n    std::size_t required;\n};\n\nclass BundleNotInProgressException : public Exception\n{\n  public:\n    BundleNotInProgressException(const char* w = \"call to EndBundle when bundle is not in progress\")\n        : Exception(w)\n    {\n    }\n};\n\nclass MessageInProgressException : public Exception\n{\n  public:\n    MessageInProgressException(const char* w = \"opening or closing bundle or message while message is in progress\")\n        : Exception(w)\n    {\n    }\n};\n\nclass MessageNotInProgressException : public Exception\n{\n  public:\n    MessageNotInProgressException(const char* w = \"call to EndMessage when message is not in progress\")\n        : Exception(w)\n    {\n    }\n};\n\nclass OutboundPacketStream\n{\n  public:\n    OutboundPacketStream(char* buffer, unsigned long capacity);\n    ~OutboundPacketStream();\n\n    void Clear();\n\n    unsigned int Capacity() const;\n\n    // invariant: size() is valid even while building a message.\n    unsigned int Size() const;\n\n    const char* Data() const;\n\n    // indicates that all messages have been closed with a matching EndMessage\n    // and all bundles have been closed with a matching EndBundle\n    bool IsReady() const;\n\n    bool IsMessageInProgress() const;\n    bool IsBundleInProgress() const;\n\n    OutboundPacketStream& operator<<(const BundleInitiator& rhs);\n    OutboundPacketStream& operator<<(const BundleTerminator& rhs);\n\n    OutboundPacketStream& operator<<(const BeginMessage& rhs);\n    OutboundPacketStream& operator<<(const MessageTerminator& rhs);\n\n    OutboundPacketStream& operator<<(bool rhs);\n    OutboundPacketStream& operator<<(const NilType& rhs);\n    OutboundPacketStream& operator<<(const InfinitumType& rhs);\n    OutboundPacketStream& operator<<(int32_t rhs);\n\n    // #ifndef __x86_64__\n    //     OutboundPacketStream& operator<<( int rhs )\n    //             { *this << (int32_t)rhs; return *this; }\n    // #endif\n\n    OutboundPacketStream& operator<<(float rhs);\n    OutboundPacketStream& operator<<(char rhs);\n    OutboundPacketStream& operator<<(const RgbaColor& rhs);\n    OutboundPacketStream& operator<<(const MidiMessage& rhs);\n    OutboundPacketStream& operator<<(int64_t rhs);\n    OutboundPacketStream& operator<<(const TimeTag& rhs);\n    OutboundPacketStream& operator<<(double rhs);\n    OutboundPacketStream& operator<<(const char* rhs);\n    OutboundPacketStream& operator<<(const Symbol& rhs);\n    OutboundPacketStream& operator<<(const Blob& rhs);\n\n  private:\n    char* BeginElement(char* beginPtr);\n    void  EndElement(char* endPtr);\n\n    bool ElementSizeSlotRequired() const;\n    void CheckForAvailableBundleSpace();\n    void CheckForAvailableMessageSpace(const char* addressPattern);\n    void CheckForAvailableArgumentSpace(long argumentLength);\n\n    char* data_;\n    char* end_;\n\n    char* typeTagsCurrent_; // stored in reverse order\n    char* messageCursor_;\n    char* argumentCurrent_;\n\n    // elementSizePtr_ has two special values: 0 indicates that a bundle\n    // isn't open, and elementSizePtr_==data_ indicates that a bundle is\n    // open but that it doesn't have a size slot (ie the outermost bundle)\n    uint32_t* elementSizePtr_;\n\n    bool messageIsInProgress_;\n};\n\n} // namespace osc\n\n#endif /* INCLUDED_OSC_OUTBOUND_PACKET_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscPacketListener.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_OSCPACKETLISTENER_H\n#define INCLUDED_OSCPACKETLISTENER_H\n\n#include \"../ip/PacketListener.h\"\n#include \"OscReceivedElements.h\"\n\nnamespace osc {\n\nclass OscPacketListener : public PacketListener\n{\n  protected:\n    virtual void ProcessBundle(const osc::ReceivedBundle& b, const IpEndpointName& remoteEndpoint)\n    {\n        // ignore bundle time tag for now\n\n        for (ReceivedBundle::const_iterator i = b.ElementsBegin(); i != b.ElementsEnd(); ++i) {\n            if (i->IsBundle())\n                ProcessBundle(ReceivedBundle(*i), remoteEndpoint);\n            else\n                ProcessMessage(ReceivedMessage(*i), remoteEndpoint);\n        }\n    }\n\n    virtual void ProcessMessage(const osc::ReceivedMessage& m, const IpEndpointName& remoteEndpoint) = 0;\n\n  public:\n    virtual void ProcessPacket(const char* data, int size, const IpEndpointName& remoteEndpoint)\n    {\n        osc::ReceivedPacket p(data, size);\n        if (p.IsBundle())\n            ProcessBundle(ReceivedBundle(p), remoteEndpoint);\n        else\n            ProcessMessage(ReceivedMessage(p), remoteEndpoint);\n    }\n};\n\n} // namespace osc\n\n#endif /* INCLUDED_OSCPACKETLISTENER_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscPrintReceivedElements.cpp",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n\n#include \"OscPrintReceivedElements.h\"\n\n#include <cstring>\n#include <ctime>\n#include <iomanip>\n#include <iostream>\n\nnamespace osc {\n\nstd::ostream& operator<<(std::ostream& os, const ReceivedMessageArgument& arg)\n{\n    switch (arg.TypeTag()) {\n        case TRUE_TYPE_TAG:\n            os << \"bool:true\";\n            break;\n\n        case FALSE_TYPE_TAG:\n            os << \"bool:false\";\n            break;\n\n        case NIL_TYPE_TAG:\n            os << \"(Nil)\";\n            break;\n\n        case INFINITUM_TYPE_TAG:\n            os << \"(Infinitum)\";\n            break;\n\n        case INT32_TYPE_TAG:\n            os << \"int32:\" << arg.AsInt32Unchecked();\n            break;\n\n        case FLOAT_TYPE_TAG:\n            os << \"float32:\" << arg.AsFloatUnchecked();\n            break;\n\n        case CHAR_TYPE_TAG: {\n            char s[2] = {0};\n            s[0]      = arg.AsCharUnchecked();\n            os << \"char:'\" << s << \"'\";\n        } break;\n\n        case RGBA_COLOR_TYPE_TAG: {\n            uint32 color = arg.AsRgbaColorUnchecked();\n\n            os << \"RGBA:0x\" << std::hex << std::setfill('0') << std::setw(2) << (int)(color >> 24 & 0xFF)\n               << std::setw(2) << (int)(color >> 16 & 0xFF) << std::setw(2) << (int)(color >> 8 & 0xFF) << std::setw(2)\n               << (int)(color & 0xFF) << std::setfill(' ');\n            os.unsetf(std::ios::basefield);\n        } break;\n\n        case MIDI_MESSAGE_TYPE_TAG: {\n            uint32 m = arg.AsMidiMessageUnchecked();\n            os << \"midi (port, status, data1, data2):<<\" << std::hex << std::setfill('0') << \"0x\" << std::setw(2)\n               << (int)(m >> 24 & 0xFF) << \" 0x\" << std::setw(2) << (int)(m >> 16 & 0xFF) << \" 0x\" << std::setw(2)\n               << (int)(m >> 8 & 0xFF) << \" 0x\" << std::setw(2) << (int)(m & 0xFF) << std::setfill(' ') << \">>\";\n            os.unsetf(std::ios::basefield);\n        } break;\n\n        case INT64_TYPE_TAG:\n            os << \"int64:\" << arg.AsInt64Unchecked();\n            break;\n\n        case TIME_TAG_TYPE_TAG: {\n            os << \"OSC-timetag:\" << arg.AsTimeTagUnchecked();\n\n            std::time_t t = (unsigned long)(arg.AsTimeTagUnchecked() >> 32);\n\n            // strip trailing newline from string returned by ctime\n            const char* timeString = std::ctime(&t);\n            size_t      len        = strlen(timeString);\n            char*       s          = new char[len + 1];\n            strcpy(s, timeString);\n            if (len)\n                s[len - 1] = '\\0';\n\n            os << \" \" << s;\n            delete[] s;\n        } break;\n\n        case DOUBLE_TYPE_TAG:\n            os << \"double:\" << arg.AsDoubleUnchecked();\n            break;\n\n        case STRING_TYPE_TAG:\n            os << \"OSC-string:`\" << arg.AsStringUnchecked() << \"'\";\n            break;\n\n        case SYMBOL_TYPE_TAG:\n            os << \"OSC-string (symbol):`\" << arg.AsSymbolUnchecked() << \"'\";\n            break;\n\n        case BLOB_TYPE_TAG: {\n            unsigned long size;\n            const void*   data;\n            arg.AsBlobUnchecked(data, size);\n            os << \"OSC-blob:<<\" << std::hex << std::setfill('0');\n            unsigned char* p = (unsigned char*)data;\n            for (unsigned long i = 0; i < size; ++i) {\n                os << \"0x\" << std::setw(2) << int(p[i]);\n                if (i != size - 1)\n                    os << ' ';\n            }\n            os.unsetf(std::ios::basefield);\n            os << \">>\" << std::setfill(' ');\n        } break;\n\n        default:\n            os << \"unknown\";\n    }\n\n    return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, const ReceivedMessage& m)\n{\n    os << \"[\";\n    if (m.AddressPatternIsUInt32())\n        os << m.AddressPatternAsUInt32();\n    else\n        os << m.AddressPattern();\n\n    bool first = true;\n    for (ReceivedMessage::const_iterator i = m.ArgumentsBegin(); i != m.ArgumentsEnd(); ++i) {\n        if (first) {\n            os << \" \";\n            first = false;\n        } else {\n            os << \", \";\n        }\n\n        os << *i;\n    }\n\n    os << \"]\";\n\n    return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, const ReceivedBundle& b)\n{\n    static int indent = 0;\n\n    for (int j = 0; j < indent; ++j)\n        os << \"  \";\n    os << \"{ ( \";\n    if (b.TimeTag() == 1)\n        os << \"immediate\";\n    else\n        os << b.TimeTag();\n    os << \" )\\n\";\n\n    ++indent;\n\n    for (ReceivedBundle::const_iterator i = b.ElementsBegin(); i != b.ElementsEnd(); ++i) {\n        if (i->IsBundle()) {\n            ReceivedBundle b2(*i);\n            os << b2 << \"\\n\";\n        } else {\n            ReceivedMessage m(*i);\n            for (int j = 0; j < indent; ++j)\n                os << \"  \";\n            os << m << \"\\n\";\n        }\n    }\n\n    --indent;\n\n    for (int j = 0; j < indent; ++j)\n        os << \"  \";\n    os << \"}\";\n\n    return os;\n}\n\nstd::ostream& operator<<(std::ostream& os, const ReceivedPacket& p)\n{\n    if (p.IsBundle()) {\n        ReceivedBundle b(p);\n        os << b << \"\\n\";\n    } else {\n        ReceivedMessage m(p);\n        os << m << \"\\n\";\n    }\n\n    return os;\n}\n\n} // namespace osc\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscPrintReceivedElements.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_OSCPRINTRECEIVEDELEMENTS_H\n#define INCLUDED_OSCPRINTRECEIVEDELEMENTS_H\n\n#include <iosfwd>\n\n#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H\n#include \"OscReceivedElements.h\"\n#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */\n\nnamespace osc {\n\nstd::ostream& operator<<(std::ostream& os, const ReceivedPacket& p);\nstd::ostream& operator<<(std::ostream& os, const ReceivedMessageArgument& arg);\nstd::ostream& operator<<(std::ostream& os, const ReceivedMessage& m);\nstd::ostream& operator<<(std::ostream& os, const ReceivedBundle& b);\n\n} // namespace osc\n\n#endif /* INCLUDED_OSCPRINTRECEIVEDELEMENTS_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscReceivedElements.cpp",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#undef _CRT_SECURE_NO_WARNINGS\n#define _CRT_SECURE_NO_WARNINGS\n\n#include \"OscReceivedElements.h\"\n\n#include \"OscHostEndianness.h\"\n\nnamespace osc {\n\n// return the first 4 byte boundary after the end of a str4\n// be careful about calling this version if you don't know whether\n// the string is terminated correctly.\nstatic inline const char* FindStr4End(const char* p)\n{\n    if (p[0] == '\\0') // special case for SuperCollider integer address pattern\n        return p + 4;\n\n    p += 3;\n\n    while (*p != 0)\n        p += 4;\n\n    return p + 1;\n}\n\n// return the first 4 byte boundary after the end of a str4\n// returns 0 if p == end or if the string is unterminated\nstatic inline const char* FindStr4End(const char* p, const char* end)\n{\n    if (p >= end)\n        return nullptr;\n\n    if (p[0] == '\\0') // special case for SuperCollider integer address pattern\n        return p + 4;\n\n    p += 3;\n    end -= 1;\n\n    while (p < end && (*p != 0))\n        p += 4;\n\n    if (*p != 0)\n        return nullptr;\n    return p + 1;\n}\n\nstatic inline unsigned long RoundUp4(unsigned long x)\n{\n    unsigned long remainder = x & 0x3UL;\n    if (remainder != 0u)\n        return x + (4 - remainder);\n    return x;\n}\n\nstatic inline int32 ToInt32(const char* p)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        osc::int32 i;\n        char       c[4];\n    } u;\n\n    u.c[0] = p[3];\n    u.c[1] = p[2];\n    u.c[2] = p[1];\n    u.c[3] = p[0];\n\n    return u.i;\n#else\n    return *(int32*)p;\n#endif\n}\n\nstatic inline uint32 ToUInt32(const char* p)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        osc::uint32 i;\n        char        c[4];\n    } u;\n\n    u.c[0] = p[3];\n    u.c[1] = p[2];\n    u.c[2] = p[1];\n    u.c[3] = p[0];\n\n    return u.i;\n#else\n    return *(uint32*)p;\n#endif\n}\n\nint64 ToInt64(const char* p)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        osc::int64 i;\n        char       c[8];\n    } u;\n\n    u.c[0] = p[7];\n    u.c[1] = p[6];\n    u.c[2] = p[5];\n    u.c[3] = p[4];\n    u.c[4] = p[3];\n    u.c[5] = p[2];\n    u.c[6] = p[1];\n    u.c[7] = p[0];\n\n    return u.i;\n#else\n    return *(int64*)p;\n#endif\n}\n\nuint64 ToUInt64(const char* p)\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        osc::uint64 i;\n        char        c[8];\n    } u;\n\n    u.c[0] = p[7];\n    u.c[1] = p[6];\n    u.c[2] = p[5];\n    u.c[3] = p[4];\n    u.c[4] = p[3];\n    u.c[5] = p[2];\n    u.c[6] = p[1];\n    u.c[7] = p[0];\n\n    return u.i;\n#else\n    return *(uint64*)p;\n#endif\n}\n\n//------------------------------------------------------------------------------\n\nbool ReceivedPacket::IsBundle() const { return Size() > 0 && Contents()[0] == '#'; }\n\n//------------------------------------------------------------------------------\n\nbool ReceivedBundleElement::IsBundle() const { return Size() > 0 && Contents()[0] == '#'; }\n\nint32 ReceivedBundleElement::Size() const { return ToUInt32(size_); }\n\n//------------------------------------------------------------------------------\n\nbool ReceivedMessageArgument::AsBool() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == TRUE_TYPE_TAG)\n        return true;\n    if (*typeTag_ == FALSE_TYPE_TAG)\n        return false;\n    throw WrongArgumentTypeException();\n}\n\nbool ReceivedMessageArgument::AsBoolUnchecked() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == TRUE_TYPE_TAG)\n        return true;\n    return false;\n}\n\nint32 ReceivedMessageArgument::AsInt32() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == INT32_TYPE_TAG)\n        return AsInt32Unchecked();\n    throw WrongArgumentTypeException();\n}\n\nint32 ReceivedMessageArgument::AsInt32Unchecked() const\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        osc::int32 i;\n        char       c[4];\n    } u;\n\n    u.c[0] = argument_[3];\n    u.c[1] = argument_[2];\n    u.c[2] = argument_[1];\n    u.c[3] = argument_[0];\n\n    return u.i;\n#else\n    return *(int32*)argument_;\n#endif\n}\n\nfloat ReceivedMessageArgument::AsFloat() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == FLOAT_TYPE_TAG)\n        return AsFloatUnchecked();\n    throw WrongArgumentTypeException();\n}\n\nfloat ReceivedMessageArgument::AsFloatUnchecked() const\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        float f;\n        char  c[4];\n    } u;\n\n    u.c[0] = argument_[3];\n    u.c[1] = argument_[2];\n    u.c[2] = argument_[1];\n    u.c[3] = argument_[0];\n\n    return u.f;\n#else\n    return *(float*)argument_;\n#endif\n}\n\nchar ReceivedMessageArgument::AsChar() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == CHAR_TYPE_TAG)\n        return AsCharUnchecked();\n    throw WrongArgumentTypeException();\n}\n\nchar ReceivedMessageArgument::AsCharUnchecked() const { return (char)ToInt32(argument_); }\n\nuint32 ReceivedMessageArgument::AsRgbaColor() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == RGBA_COLOR_TYPE_TAG)\n        return AsRgbaColorUnchecked();\n    throw WrongArgumentTypeException();\n}\n\nuint32 ReceivedMessageArgument::AsRgbaColorUnchecked() const { return ToUInt32(argument_); }\n\nuint32 ReceivedMessageArgument::AsMidiMessage() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == MIDI_MESSAGE_TYPE_TAG)\n        return AsMidiMessageUnchecked();\n    throw WrongArgumentTypeException();\n}\n\nuint32 ReceivedMessageArgument::AsMidiMessageUnchecked() const { return ToUInt32(argument_); }\n\nint64 ReceivedMessageArgument::AsInt64() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == INT64_TYPE_TAG)\n        return AsInt64Unchecked();\n    throw WrongArgumentTypeException();\n}\n\nint64 ReceivedMessageArgument::AsInt64Unchecked() const { return ToInt64(argument_); }\n\nuint64 ReceivedMessageArgument::AsTimeTag() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == TIME_TAG_TYPE_TAG)\n        return AsTimeTagUnchecked();\n    throw WrongArgumentTypeException();\n}\n\nuint64 ReceivedMessageArgument::AsTimeTagUnchecked() const { return ToUInt64(argument_); }\n\ndouble ReceivedMessageArgument::AsDouble() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == DOUBLE_TYPE_TAG)\n        return AsDoubleUnchecked();\n    throw WrongArgumentTypeException();\n}\n\ndouble ReceivedMessageArgument::AsDoubleUnchecked() const\n{\n#ifdef OSC_HOST_LITTLE_ENDIAN\n    union\n    {\n        double d;\n        char   c[8];\n    } u;\n\n    u.c[0] = argument_[7];\n    u.c[1] = argument_[6];\n    u.c[2] = argument_[5];\n    u.c[3] = argument_[4];\n    u.c[4] = argument_[3];\n    u.c[5] = argument_[2];\n    u.c[6] = argument_[1];\n    u.c[7] = argument_[0];\n\n    return u.d;\n#else\n    return *(double*)argument_;\n#endif\n}\n\nconst char* ReceivedMessageArgument::AsString() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == STRING_TYPE_TAG)\n        return argument_;\n    throw WrongArgumentTypeException();\n}\n\nconst char* ReceivedMessageArgument::AsSymbol() const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == SYMBOL_TYPE_TAG)\n        return argument_;\n    throw WrongArgumentTypeException();\n}\n\nvoid ReceivedMessageArgument::AsBlob(const void*& data, unsigned long& size) const\n{\n    if (!typeTag_)\n        throw MissingArgumentException();\n    if (*typeTag_ == BLOB_TYPE_TAG)\n        AsBlobUnchecked(data, size);\n    else\n        throw WrongArgumentTypeException();\n}\n\nvoid ReceivedMessageArgument::AsBlobUnchecked(const void*& data, unsigned long& size) const\n{\n    size = ToUInt32(argument_);\n    data = (void*)(argument_ + 4);\n}\n\n//------------------------------------------------------------------------------\n\nvoid ReceivedMessageArgumentIterator::Advance()\n{\n    if (!value_.typeTag_)\n        return;\n\n    switch (*value_.typeTag_++) {\n        case '\\0':\n            // don't advance past end\n            --value_.typeTag_;\n            break;\n\n        case TRUE_TYPE_TAG:\n        case FALSE_TYPE_TAG:\n        case NIL_TYPE_TAG:\n        case INFINITUM_TYPE_TAG:\n\n            // zero length\n            break;\n\n        case INT32_TYPE_TAG:\n        case FLOAT_TYPE_TAG:\n        case CHAR_TYPE_TAG:\n        case RGBA_COLOR_TYPE_TAG:\n        case MIDI_MESSAGE_TYPE_TAG:\n\n            value_.argument_ += 4;\n            break;\n\n        case INT64_TYPE_TAG:\n        case TIME_TAG_TYPE_TAG:\n        case DOUBLE_TYPE_TAG:\n\n            value_.argument_ += 8;\n            break;\n\n        case STRING_TYPE_TAG:\n        case SYMBOL_TYPE_TAG:\n\n            // we use the unsafe function FindStr4End(char*) here because all of\n            // the arguments have already been validated in\n            // ReceivedMessage::Init() below.\n\n            value_.argument_ = FindStr4End(value_.argument_);\n            break;\n\n        case BLOB_TYPE_TAG: {\n            uint32 blobSize  = ToUInt32(value_.argument_);\n            value_.argument_ = value_.argument_ + 4 + RoundUp4((unsigned long)blobSize);\n        } break;\n\n        default: // unknown type tag\n            // don't advance\n            --value_.typeTag_;\n            break;\n\n            //    not handled:\n            //    [ Indicates the beginning of an array. The tags following are for\n            //        data in the Array until a close brace tag is reached.\n            //    ] Indicates the end of an array.\n    }\n}\n\n//------------------------------------------------------------------------------\n\nReceivedMessage::ReceivedMessage(const ReceivedPacket& packet)\n    : addressPattern_(packet.Contents())\n{\n    Init(packet.Contents(), packet.Size());\n}\n\nReceivedMessage::ReceivedMessage(const ReceivedBundleElement& bundleElement)\n    : addressPattern_(bundleElement.Contents())\n{\n    Init(bundleElement.Contents(), bundleElement.Size());\n}\n\nbool ReceivedMessage::AddressPatternIsUInt32() const { return addressPattern_[0] == '\\0'; }\n\nuint32 ReceivedMessage::AddressPatternAsUInt32() const { return ToUInt32(addressPattern_); }\n\nvoid ReceivedMessage::Init(const char* message, unsigned long size)\n{\n    if (size == 0)\n        throw MalformedMessageException(\"zero length messages not permitted\");\n\n    if ((size & 0x03L) != 0)\n        throw MalformedMessageException(\"message size must be multiple of four\");\n\n    const char* end = message + size;\n\n    typeTagsBegin_ = FindStr4End(addressPattern_, end);\n    if (typeTagsBegin_ == nullptr) {\n        // address pattern was not terminated before end\n        throw MalformedMessageException(\"unterminated address pattern\");\n    }\n\n    if (typeTagsBegin_ == end) {\n        // message consists of only the address pattern - no arguments or type tags.\n        typeTagsBegin_ = nullptr;\n        typeTagsEnd_   = nullptr;\n        arguments_     = nullptr;\n\n    } else {\n        if (*typeTagsBegin_ != ',')\n            throw MalformedMessageException(\"type tags not present\");\n\n        if (*(typeTagsBegin_ + 1) == '\\0') {\n            // zero length type tags\n            typeTagsBegin_ = nullptr;\n            typeTagsEnd_   = nullptr;\n            arguments_     = nullptr;\n\n        } else {\n            // check that all arguments are present and well formed\n\n            arguments_ = FindStr4End(typeTagsBegin_, end);\n            if (arguments_ == nullptr) {\n                throw MalformedMessageException(\"type tags were not terminated before end of message\");\n            }\n\n            ++typeTagsBegin_; // advance past initial ','\n\n            const char* typeTag  = typeTagsBegin_;\n            const char* argument = arguments_;\n\n            do {\n                switch (*typeTag) {\n                    case TRUE_TYPE_TAG:\n                    case FALSE_TYPE_TAG:\n                    case NIL_TYPE_TAG:\n                    case INFINITUM_TYPE_TAG:\n\n                        // zero length\n                        break;\n\n                    case INT32_TYPE_TAG:\n                    case FLOAT_TYPE_TAG:\n                    case CHAR_TYPE_TAG:\n                    case RGBA_COLOR_TYPE_TAG:\n                    case MIDI_MESSAGE_TYPE_TAG:\n\n                        if (argument == end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n                        argument += 4;\n                        if (argument > end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n                        break;\n\n                    case INT64_TYPE_TAG:\n                    case TIME_TAG_TYPE_TAG:\n                    case DOUBLE_TYPE_TAG:\n\n                        if (argument == end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n                        argument += 8;\n                        if (argument > end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n                        break;\n\n                    case STRING_TYPE_TAG:\n                    case SYMBOL_TYPE_TAG:\n\n                        if (argument == end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n                        argument = FindStr4End(argument, end);\n                        if (argument == nullptr)\n                            throw MalformedMessageException(\"unterminated string argument\");\n                        break;\n\n                    case BLOB_TYPE_TAG: {\n                        if (argument + 4 > end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n\n                        uint32 blobSize = ToUInt32(argument);\n                        argument        = argument + 4 + RoundUp4((unsigned long)blobSize);\n                        if (argument > end)\n                            throw MalformedMessageException(\"arguments exceed message size\");\n                    } break;\n\n                    default:\n                        throw MalformedMessageException(\"unknown type tag\");\n\n                        //    not handled:\n                        //    [ Indicates the beginning of an array. The tags following are for\n                        //        data in the Array until a close brace tag is reached.\n                        //    ] Indicates the end of an array.\n                }\n\n            } while (*++typeTag != '\\0');\n            typeTagsEnd_ = typeTag;\n        }\n    }\n}\n\n//------------------------------------------------------------------------------\n\nReceivedBundle::ReceivedBundle(const ReceivedPacket& packet)\n    : elementCount_(0)\n{\n    Init(packet.Contents(), packet.Size());\n}\n\nReceivedBundle::ReceivedBundle(const ReceivedBundleElement& bundleElement)\n    : elementCount_(0)\n{\n    Init(bundleElement.Contents(), bundleElement.Size());\n}\n\nvoid ReceivedBundle::Init(const char* bundle, unsigned long size)\n{\n    if (size < 16)\n        throw MalformedBundleException(\"packet too short for bundle\");\n\n    if ((size & 0x03L) != 0)\n        throw MalformedBundleException(\"bundle size must be multiple of four\");\n\n    if (bundle[0] != '#' || bundle[1] != 'b' || bundle[2] != 'u' || bundle[3] != 'n' || bundle[4] != 'd' ||\n        bundle[5] != 'l' || bundle[6] != 'e' || bundle[7] != '\\0')\n        throw MalformedBundleException(\"bad bundle address pattern\");\n\n    end_ = bundle + size;\n\n    timeTag_ = bundle + 8;\n\n    const char* p = timeTag_ + 8;\n\n    while (p < end_) {\n        if (p + 4 > end_)\n            throw MalformedBundleException(\"packet too short for elementSize\");\n\n        uint32 elementSize = ToUInt32(p);\n        if ((elementSize & 0x03L) != 0)\n            throw MalformedBundleException(\"bundle element size must be multiple of four\");\n\n        p += 4 + elementSize;\n        if (p > end_)\n            throw MalformedBundleException(\"packet too short for bundle element\");\n\n        ++elementCount_;\n    }\n\n    if (p != end_)\n        throw MalformedBundleException(\"bundle contents \");\n}\n\nuint64 ReceivedBundle::TimeTag() const { return ToUInt64(timeTag_); }\n\n} // namespace osc\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscReceivedElements.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_OSCRECEIVEDELEMENTS_H\n#define INCLUDED_OSCRECEIVEDELEMENTS_H\n\n#include \"OscException.h\"\n#include \"OscTypes.h\"\n\nnamespace osc {\n\nclass MalformedMessageException : public Exception\n{\n  public:\n    MalformedMessageException(const char* w = \"malformed message\")\n        : Exception(w)\n    {\n    }\n};\n\nclass MalformedBundleException : public Exception\n{\n  public:\n    MalformedBundleException(const char* w = \"malformed bundle\")\n        : Exception(w)\n    {\n    }\n};\n\nclass WrongArgumentTypeException : public Exception\n{\n  public:\n    WrongArgumentTypeException(const char* w = \"wrong argument type\")\n        : Exception(w)\n    {\n    }\n};\n\nclass MissingArgumentException : public Exception\n{\n  public:\n    MissingArgumentException(const char* w = \"missing argument\")\n        : Exception(w)\n    {\n    }\n};\n\nclass ExcessArgumentException : public Exception\n{\n  public:\n    ExcessArgumentException(const char* w = \"too many arguments\")\n        : Exception(w)\n    {\n    }\n};\n\nclass ReceivedPacket\n{\n  public:\n    ReceivedPacket(const char* contents, int32 size)\n        : contents_(contents)\n        , size_(size)\n    {\n    }\n\n    bool IsMessage() const { return !IsBundle(); }\n    bool IsBundle() const;\n\n    int32       Size() const { return size_; }\n    const char* Contents() const { return contents_; }\n\n  private:\n    const char* contents_;\n    int32       size_;\n};\n\nclass ReceivedBundleElement\n{\n  public:\n    ReceivedBundleElement(const char* size)\n        : size_(size)\n    {\n    }\n\n    friend class ReceivedBundleElementIterator;\n\n    bool IsMessage() const { return !IsBundle(); }\n    bool IsBundle() const;\n\n    int32       Size() const;\n    const char* Contents() const { return size_ + 4; }\n\n  private:\n    const char* size_;\n};\n\nclass ReceivedBundleElementIterator\n{\n  public:\n    ReceivedBundleElementIterator(const char* sizePtr)\n        : value_(sizePtr)\n    {\n    }\n\n    ReceivedBundleElementIterator operator++()\n    {\n        Advance();\n        return *this;\n    }\n\n    ReceivedBundleElementIterator operator++(int)\n    {\n        ReceivedBundleElementIterator old(*this);\n        Advance();\n        return old;\n    }\n\n    const ReceivedBundleElement& operator*() const { return value_; }\n\n    const ReceivedBundleElement* operator->() const { return &value_; }\n\n    friend bool operator==(const ReceivedBundleElementIterator& lhs, const ReceivedBundleElementIterator& rhs);\n\n  private:\n    ReceivedBundleElement value_;\n\n    void Advance() { value_.size_ = value_.Contents() + value_.Size(); }\n\n    bool IsEqualTo(const ReceivedBundleElementIterator& rhs) const { return value_.size_ == rhs.value_.size_; }\n};\n\ninline bool operator==(const ReceivedBundleElementIterator& lhs, const ReceivedBundleElementIterator& rhs)\n{\n    return lhs.IsEqualTo(rhs);\n}\n\ninline bool operator!=(const ReceivedBundleElementIterator& lhs, const ReceivedBundleElementIterator& rhs)\n{\n    return !(lhs == rhs);\n}\n\nclass ReceivedMessageArgument\n{\n  public:\n    ReceivedMessageArgument(const char* typeTag, const char* argument)\n        : typeTag_(typeTag)\n        , argument_(argument)\n    {\n    }\n\n    friend class ReceivedMessageArgumentIterator;\n\n    const char TypeTag() const { return *typeTag_; }\n\n    // the unchecked methods below don't check whether the argument actually\n    // is of the specified type. they should only be used if you've already\n    // checked the type tag or the associated IsType() method.\n\n    bool IsBool() const { return *typeTag_ == TRUE_TYPE_TAG || *typeTag_ == FALSE_TYPE_TAG; }\n    bool AsBool() const;\n    bool AsBoolUnchecked() const;\n\n    bool IsNil() const { return *typeTag_ == NIL_TYPE_TAG; }\n    bool IsInfinitum() const { return *typeTag_ == INFINITUM_TYPE_TAG; }\n\n    bool  IsInt32() const { return *typeTag_ == INT32_TYPE_TAG; }\n    int32 AsInt32() const;\n    int32 AsInt32Unchecked() const;\n\n    bool  IsFloat() const { return *typeTag_ == FLOAT_TYPE_TAG; }\n    float AsFloat() const;\n    float AsFloatUnchecked() const;\n\n    bool IsChar() const { return *typeTag_ == CHAR_TYPE_TAG; }\n    char AsChar() const;\n    char AsCharUnchecked() const;\n\n    bool   IsRgbaColor() const { return *typeTag_ == RGBA_COLOR_TYPE_TAG; }\n    uint32 AsRgbaColor() const;\n    uint32 AsRgbaColorUnchecked() const;\n\n    bool   IsMidiMessage() const { return *typeTag_ == MIDI_MESSAGE_TYPE_TAG; }\n    uint32 AsMidiMessage() const;\n    uint32 AsMidiMessageUnchecked() const;\n\n    bool  IsInt64() const { return *typeTag_ == INT64_TYPE_TAG; }\n    int64 AsInt64() const;\n    int64 AsInt64Unchecked() const;\n\n    bool   IsTimeTag() const { return *typeTag_ == TIME_TAG_TYPE_TAG; }\n    uint64 AsTimeTag() const;\n    uint64 AsTimeTagUnchecked() const;\n\n    bool   IsDouble() const { return *typeTag_ == DOUBLE_TYPE_TAG; }\n    double AsDouble() const;\n    double AsDoubleUnchecked() const;\n\n    bool        IsString() const { return *typeTag_ == STRING_TYPE_TAG; }\n    const char* AsString() const;\n    const char* AsStringUnchecked() const { return argument_; }\n\n    bool        IsSymbol() const { return *typeTag_ == SYMBOL_TYPE_TAG; }\n    const char* AsSymbol() const;\n    const char* AsSymbolUnchecked() const { return argument_; }\n\n    bool IsBlob() const { return *typeTag_ == BLOB_TYPE_TAG; }\n    void AsBlob(const void*& data, unsigned long& size) const;\n    void AsBlobUnchecked(const void*& data, unsigned long& size) const;\n\n  private:\n    const char* typeTag_;\n    const char* argument_;\n};\n\nclass ReceivedMessageArgumentIterator\n{\n  public:\n    ReceivedMessageArgumentIterator(const char* typeTags, const char* arguments)\n        : value_(typeTags, arguments)\n    {\n    }\n\n    ReceivedMessageArgumentIterator operator++()\n    {\n        Advance();\n        return *this;\n    }\n\n    ReceivedMessageArgumentIterator operator++(int)\n    {\n        ReceivedMessageArgumentIterator old(*this);\n        Advance();\n        return old;\n    }\n\n    const ReceivedMessageArgument& operator*() const { return value_; }\n\n    const ReceivedMessageArgument* operator->() const { return &value_; }\n\n    friend bool operator==(const ReceivedMessageArgumentIterator& lhs, const ReceivedMessageArgumentIterator& rhs);\n\n  private:\n    ReceivedMessageArgument value_;\n\n    void Advance();\n\n    bool IsEqualTo(const ReceivedMessageArgumentIterator& rhs) const { return value_.typeTag_ == rhs.value_.typeTag_; }\n};\n\ninline bool operator==(const ReceivedMessageArgumentIterator& lhs, const ReceivedMessageArgumentIterator& rhs)\n{\n    return lhs.IsEqualTo(rhs);\n}\n\ninline bool operator!=(const ReceivedMessageArgumentIterator& lhs, const ReceivedMessageArgumentIterator& rhs)\n{\n    return !(lhs == rhs);\n}\n\nclass ReceivedMessageArgumentStream\n{\n    friend class ReceivedMessage;\n    ReceivedMessageArgumentStream(const ReceivedMessageArgumentIterator& begin,\n                                  const ReceivedMessageArgumentIterator& end)\n        : p_(begin)\n        , end_(end)\n    {\n    }\n\n    ReceivedMessageArgumentIterator p_, end_;\n\n  public:\n    // end of stream\n    bool Eos() const { return p_ == end_; }\n\n    ReceivedMessageArgumentStream& operator>>(bool& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsBool();\n        return *this;\n    }\n\n    // not sure if it would be useful to stream Nil and Infinitum\n    // for now it's not possible\n\n    ReceivedMessageArgumentStream& operator>>(int32& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsInt32();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(float& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsFloat();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(char& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsChar();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(RgbaColor& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs.value = (*p_++).AsRgbaColor();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(MidiMessage& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs.value = (*p_++).AsMidiMessage();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(int64& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsInt64();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(TimeTag& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs.value = (*p_++).AsTimeTag();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(double& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsDouble();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(Blob& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        (*p_++).AsBlob(rhs.data, rhs.size);\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(const char*& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs = (*p_++).AsString();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(Symbol& rhs)\n    {\n        if (Eos())\n            throw MissingArgumentException();\n\n        rhs.value = (*p_++).AsSymbol();\n        return *this;\n    }\n\n    ReceivedMessageArgumentStream& operator>>(MessageTerminator& rhs)\n    {\n        if (!Eos())\n            throw ExcessArgumentException();\n\n        return *this;\n    }\n};\n\nclass ReceivedMessage\n{\n    void Init(const char* bundle, unsigned long size);\n\n  public:\n    explicit ReceivedMessage(const ReceivedPacket& packet);\n    explicit ReceivedMessage(const ReceivedBundleElement& bundleElement);\n\n    const char* AddressPattern() const { return addressPattern_; }\n\n    // Support for non-standard SuperCollider integer address patterns:\n    bool   AddressPatternIsUInt32() const;\n    uint32 AddressPatternAsUInt32() const;\n\n    unsigned long ArgumentCount() const { return static_cast<unsigned long>(typeTagsEnd_ - typeTagsBegin_); }\n\n    const char* TypeTags() const { return typeTagsBegin_; }\n\n    using const_iterator = ReceivedMessageArgumentIterator;\n\n    ReceivedMessageArgumentIterator ArgumentsBegin() const\n    {\n        return ReceivedMessageArgumentIterator(typeTagsBegin_, arguments_);\n    }\n\n    ReceivedMessageArgumentIterator ArgumentsEnd() const\n    {\n        return ReceivedMessageArgumentIterator(typeTagsEnd_, nullptr);\n    }\n\n    ReceivedMessageArgumentStream ArgumentStream() const\n    {\n        return ReceivedMessageArgumentStream(ArgumentsBegin(), ArgumentsEnd());\n    }\n\n  private:\n    const char* addressPattern_;\n    const char* typeTagsBegin_;\n    const char* typeTagsEnd_;\n    const char* arguments_;\n};\n\nclass ReceivedBundle\n{\n    void Init(const char* message, unsigned long size);\n\n  public:\n    explicit ReceivedBundle(const ReceivedPacket& packet);\n    explicit ReceivedBundle(const ReceivedBundleElement& bundleElement);\n\n    uint64 TimeTag() const;\n\n    unsigned long ElementCount() const { return elementCount_; }\n\n    using const_iterator = ReceivedBundleElementIterator;\n\n    ReceivedBundleElementIterator ElementsBegin() const { return ReceivedBundleElementIterator(timeTag_ + 8); }\n\n    ReceivedBundleElementIterator ElementsEnd() const { return ReceivedBundleElementIterator(end_); }\n\n  private:\n    const char*   timeTag_;\n    const char*   end_;\n    unsigned long elementCount_;\n};\n\n} // namespace osc\n\n#endif /* INCLUDED_OSCRECEIVEDELEMENTS_H */\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscTypes.cpp",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#include \"OscTypes.h\"\n\nnamespace osc {\n\nBundleInitiator   BeginBundleImmediate(1);\nBundleTerminator  EndBundle;\nMessageTerminator EndMessage;\nNilType           Nil;\nInfinitumType     Infinitum;\n\n} // namespace osc\n"
  },
  {
    "path": "src/protocol/osc/oscpack/OscTypes.h",
    "content": "/*\n    oscpack -- Open Sound Control packet manipulation library\n    http://www.audiomulch.com/~rossb/oscpack\n\n    Copyright (c) 2004-2005 Ross Bencina <rossb@audiomulch.com>\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files\n    (the \"Software\"), to deal in the Software without restriction,\n    including without limitation the rights to use, copy, modify, merge,\n    publish, distribute, sublicense, and/or sell copies of the Software,\n    and to permit persons to whom the Software is furnished to do so,\n    subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    Any person wishing to distribute modifications to the Software is\n    requested to send the modifications to the original developer so that\n    they can be incorporated into the canonical version.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\n    ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\n    CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n*/\n#ifndef INCLUDED_OSCTYPES_H\n#define INCLUDED_OSCTYPES_H\n\n#include <cstdint>\n\nnamespace osc {\n\n// basic types\nusing int64  = std::int64_t;\nusing uint64 = std::uint64_t;\nusing int32  = std::int32_t;\nusing uint32 = std::uint32_t;\n\nenum TypeTagValues\n{\n    TRUE_TYPE_TAG         = 'T',\n    FALSE_TYPE_TAG        = 'F',\n    NIL_TYPE_TAG          = 'N',\n    INFINITUM_TYPE_TAG    = 'I',\n    INT32_TYPE_TAG        = 'i',\n    FLOAT_TYPE_TAG        = 'f',\n    CHAR_TYPE_TAG         = 'c',\n    RGBA_COLOR_TYPE_TAG   = 'r',\n    MIDI_MESSAGE_TYPE_TAG = 'm',\n    INT64_TYPE_TAG        = 'h',\n    TIME_TAG_TYPE_TAG     = 't',\n    DOUBLE_TYPE_TAG       = 'd',\n    STRING_TYPE_TAG       = 's',\n    SYMBOL_TYPE_TAG       = 'S',\n    BLOB_TYPE_TAG         = 'b'\n};\n\n// i/o manipulators used for streaming interfaces\n\nstruct BundleInitiator\n{\n    explicit BundleInitiator(uint64 timeTag_)\n        : timeTag(timeTag_)\n    {\n    }\n    uint64 timeTag;\n};\n\nextern BundleInitiator BeginBundleImmediate;\n\ninline BundleInitiator BeginBundle(uint64 timeTag = 1) { return BundleInitiator(timeTag); }\n\nstruct BundleTerminator\n{\n};\n\nextern BundleTerminator EndBundle;\n\nstruct BeginMessage\n{\n    explicit BeginMessage(const char* addressPattern_)\n        : addressPattern(addressPattern_)\n    {\n    }\n    const char* addressPattern;\n};\n\nstruct MessageTerminator\n{\n};\n\nextern MessageTerminator EndMessage;\n\n// osc specific types. they are defined as structs so they can be used\n// as separately identifiable types with the streaming operators.\n\nstruct NilType\n{\n};\n\nextern NilType Nil;\n\nstruct InfinitumType\n{\n};\n\nextern InfinitumType Infinitum;\n\nstruct RgbaColor\n{\n    RgbaColor() {}\n    explicit RgbaColor(uint32 value_)\n        : value(value_)\n    {\n    }\n    uint32 value;\n\n    operator uint32() const { return value; }\n};\n\nstruct MidiMessage\n{\n    MidiMessage() {}\n    explicit MidiMessage(uint32 value_)\n        : value(value_)\n    {\n    }\n    uint32 value;\n\n    operator uint32() const { return value; }\n};\n\nstruct TimeTag\n{\n    TimeTag() {}\n    explicit TimeTag(uint64 value_)\n        : value(value_)\n    {\n    }\n    uint64 value;\n\n    operator uint64() const { return value; }\n};\n\nstruct Symbol\n{\n    Symbol() {}\n    explicit Symbol(const char* value_)\n        : value(value_)\n    {\n    }\n    const char* value;\n\n    operator const char*() const { return value; }\n};\n\nstruct Blob\n{\n    Blob() {}\n    explicit Blob(const void* data_, unsigned long size_)\n        : data(data_)\n        , size(size_)\n    {\n    }\n    const void*   data;\n    unsigned long size;\n};\n\n} // namespace osc\n\n#endif /* INCLUDED_OSCTYPES_H */\n"
  },
  {
    "path": "src/protocol/util/AsyncEventServer.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#include \"../StdAfx.h\"\n\n#include \"AsyncEventServer.h\"\n\n#include <algorithm>\n#include <array>\n#include <functional>\n#include <memory>\n#include <set>\n#include <string>\n\n#include <boost/asio.hpp>\n\n#include <tbb/concurrent_hash_map.h>\n#include <tbb/concurrent_queue.h>\n\nusing boost::asio::ip::tcp;\n\nnamespace caspar { namespace IO {\n\nclass connection;\n\nusing connection_set = std::set<spl::shared_ptr<connection>>;\n\nclass connection : public spl::enable_shared_from_this<connection>\n{\n    using lifecycle_map_type = tbb::concurrent_hash_map<std::wstring, std::shared_ptr<void>>;\n    using send_queue         = tbb::concurrent_queue<std::string>;\n\n    const spl::shared_ptr<tcp::socket>       socket_;\n    std::shared_ptr<boost::asio::io_context> io_context_;\n    const std::wstring                       listen_port_;\n    const spl::shared_ptr<connection_set>    connection_set_;\n    protocol_strategy_factory<char>::ptr     protocol_factory_;\n    std::shared_ptr<protocol_strategy<char>> protocol_;\n\n    std::array<char, 32768> data_;\n    lifecycle_map_type      lifecycle_bound_objects_;\n    send_queue              send_queue_;\n    bool                    is_writing_;\n\n    class connection_holder : public client_connection<char>\n    {\n        std::weak_ptr<connection> connection_;\n\n      public:\n        explicit connection_holder(std::weak_ptr<connection> conn)\n            : connection_(std::move(conn))\n        {\n        }\n\n        void send(std::basic_string<char>&& data, bool skip_log) override\n        {\n            auto conn = connection_.lock();\n\n            if (conn)\n                conn->send(std::move(data));\n        }\n\n        void disconnect() override\n        {\n            auto conn = connection_.lock();\n\n            if (conn)\n                conn->disconnect();\n        }\n\n        std::wstring address() const override\n        {\n            auto conn = connection_.lock();\n\n            if (conn)\n                return conn->ipv4_address();\n            return L\"[destroyed-connection]\";\n        }\n\n        void add_lifecycle_bound_object(const std::wstring& key, const std::shared_ptr<void>& lifecycle_bound) override\n        {\n            auto conn = connection_.lock();\n\n            if (conn)\n                return conn->add_lifecycle_bound_object(key, lifecycle_bound);\n        }\n\n        std::shared_ptr<void> remove_lifecycle_bound_object(const std::wstring& key) override\n        {\n            auto conn = connection_.lock();\n\n            if (conn)\n                return conn->remove_lifecycle_bound_object(key);\n            return std::shared_ptr<void>();\n        }\n    };\n\n  public:\n    static spl::shared_ptr<connection> create(std::shared_ptr<boost::asio::io_context>    io_context,\n                                              spl::shared_ptr<tcp::socket>                socket,\n                                              const protocol_strategy_factory<char>::ptr& protocol,\n                                              spl::shared_ptr<connection_set>             connection_set)\n    {\n        spl::shared_ptr<connection> con(\n            new connection(std::move(io_context), std::move(socket), std::move(protocol), std::move(connection_set)));\n        con->init();\n        con->read_some();\n        return con;\n    }\n\n    void init() { protocol_ = protocol_factory_->create(spl::make_shared<connection_holder>(shared_from_this())); }\n\n    ~connection() { CASPAR_LOG(debug) << print() << L\" connection destroyed.\"; }\n\n    std::wstring print() const { return L\"async_event_server[:\" + listen_port_ + L\"]\"; }\n\n    std::wstring address() const { return u16(socket_->local_endpoint().address().to_string()); }\n\n    std::wstring ipv4_address() const\n    {\n        return socket_->is_open() ? u16(socket_->remote_endpoint().address().to_string()) : L\"no-address\";\n    }\n\n    void send(std::string&& data)\n    {\n        send_queue_.push(std::move(data));\n        auto self = shared_from_this();\n        boost::asio::dispatch(*io_context_, [=] { self->do_write(); });\n    }\n\n    void disconnect()\n    {\n        std::weak_ptr<connection> self = shared_from_this();\n        boost::asio::dispatch(*io_context_, [=] {\n            auto strong = self.lock();\n\n            if (strong)\n                strong->stop();\n        });\n    }\n\n    void add_lifecycle_bound_object(const std::wstring& key, const std::shared_ptr<void>& lifecycle_bound)\n    {\n        // thread-safe tbb_concurrent_hash_map\n        lifecycle_bound_objects_.insert(std::pair<std::wstring, std::shared_ptr<void>>(key, lifecycle_bound));\n    }\n    std::shared_ptr<void> remove_lifecycle_bound_object(const std::wstring& key)\n    {\n        // thread-safe tbb_concurrent_hash_map\n        lifecycle_map_type::const_accessor acc;\n        if (lifecycle_bound_objects_.find(acc, key)) {\n            auto result = acc->second;\n            lifecycle_bound_objects_.erase(acc);\n            return result;\n        }\n        return std::shared_ptr<void>();\n    }\n\n  private:\n    void do_write() // always called from the asio-service-thread\n    {\n        if (!is_writing_) {\n            std::string data;\n            if (send_queue_.try_pop(data)) {\n                write_some(std::move(data));\n            }\n        }\n    }\n\n    void stop() // always called from the asio-service-thread\n    {\n        connection_set_->erase(shared_from_this());\n\n        CASPAR_LOG(info) << print() << L\" Client \" << ipv4_address() << L\" disconnected (\" << connection_set_->size()\n                         << L\" connections).\";\n\n        boost::system::error_code ec;\n        socket_->shutdown(boost::asio::socket_base::shutdown_type::shutdown_both, ec);\n        socket_->close(ec);\n    }\n\n    connection(const std::shared_ptr<boost::asio::io_context>& io_context,\n               const spl::shared_ptr<tcp::socket>&             socket,\n               const protocol_strategy_factory<char>::ptr&     protocol_factory,\n               const spl::shared_ptr<connection_set>&          connection_set)\n        : socket_(socket)\n        , io_context_(io_context)\n        , listen_port_(socket_->is_open() ? std::to_wstring(socket_->local_endpoint().port()) : L\"no-port\")\n        , connection_set_(connection_set)\n        , protocol_factory_(protocol_factory)\n        , is_writing_(false)\n    {\n        CASPAR_LOG(info) << print() << L\" Accepted connection from \" << ipv4_address() << L\" (\"\n                         << connection_set_->size() + 1 << L\" connections).\";\n    }\n\n    void handle_read(const boost::system::error_code& error,\n                     size_t                           bytes_transferred) // always called from the asio-service-thread\n    {\n        if (!error) {\n            try {\n                std::string data(data_.begin(), data_.begin() + bytes_transferred);\n\n                protocol_->parse(data);\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n\n            read_some();\n        } else if (error != boost::asio::error::operation_aborted)\n            stop();\n    }\n\n    void handle_write(const spl::shared_ptr<std::string>& str,\n                      const boost::system::error_code&    error,\n                      size_t bytes_transferred) // always called from the asio-service-thread\n    {\n        if (!error) {\n            if (bytes_transferred != str->size()) {\n                str->assign(str->substr(bytes_transferred));\n                socket_->async_write_some(boost::asio::buffer(str->data(), str->size()),\n                                          std::bind(&connection::handle_write,\n                                                    shared_from_this(),\n                                                    str,\n                                                    std::placeholders::_1,\n                                                    std::placeholders::_2));\n            } else {\n                is_writing_ = false;\n                do_write();\n            }\n        } else if (error != boost::asio::error::operation_aborted && socket_->is_open())\n            stop();\n    }\n\n    void read_some() // always called from the asio-service-thread\n    {\n        socket_->async_read_some(\n            boost::asio::buffer(data_.data(), data_.size()),\n            std::bind(&connection::handle_read, shared_from_this(), std::placeholders::_1, std::placeholders::_2));\n    }\n\n    void write_some(std::string&& data) // always called from the asio-service-thread\n    {\n        is_writing_ = true;\n        auto str    = spl::make_shared<std::string>(std::move(data));\n        socket_->async_write_some(\n            boost::asio::buffer(str->data(), str->size()),\n            std::bind(\n                &connection::handle_write, shared_from_this(), str, std::placeholders::_1, std::placeholders::_2));\n    }\n\n    friend struct AsyncEventServer::implementation;\n};\n\nstruct AsyncEventServer::implementation : public spl::enable_shared_from_this<implementation>\n{\n    std::shared_ptr<boost::asio::io_context> io_context_;\n    tcp::acceptor                            acceptor_;\n    protocol_strategy_factory<char>::ptr     protocol_factory_;\n    spl::shared_ptr<connection_set>          connection_set_;\n    std::vector<lifecycle_factory_t>         lifecycle_factories_;\n\n    implementation(std::shared_ptr<boost::asio::io_context>    io_context,\n                   const protocol_strategy_factory<char>::ptr& protocol,\n                   const std::string&                          host,\n                   unsigned short                              port)\n        : io_context_(std::move(io_context))\n        , acceptor_([&]() {\n            boost::asio::ip::tcp::endpoint endpoint;\n            if (host.empty()) {\n                endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port);\n            } else {\n                try {\n                    auto addr = boost::asio::ip::make_address(host);\n                    // Only allow IPv4 to avoid crashes\n                    if (addr.is_v6()) {\n                        CASPAR_LOG(fatal) << \"IPv6 addresses are not supported for host: \" << host;\n                        throw std::runtime_error(\"IPv6 not supported\");\n                    }\n                    endpoint = boost::asio::ip::tcp::endpoint(addr, port);\n                } catch (...) {\n                    CASPAR_THROW_EXCEPTION(std::invalid_argument(\"Invalid AMCP bind address: \" + host));\n                }\n            }\n\n            return tcp::acceptor(*io_context_, endpoint);\n        }())\n        , protocol_factory_(protocol)\n    {\n    }\n\n    void stop()\n    {\n        try {\n            acceptor_.cancel();\n            acceptor_.close();\n        } catch (...) {\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n    }\n\n    ~implementation()\n    {\n        auto conns_set = connection_set_;\n\n        boost::asio::post(*io_context_, [conns_set] {\n            auto connections = *conns_set;\n            for (auto& connection : connections)\n                connection->stop();\n        });\n    }\n\n    void start_accept()\n    {\n        spl::shared_ptr<tcp::socket> socket(new tcp::socket(*io_context_));\n        acceptor_.async_accept(\n            *socket, std::bind(&implementation::handle_accept, shared_from_this(), socket, std::placeholders::_1));\n    }\n\n    void handle_accept(const spl::shared_ptr<tcp::socket>& socket, const boost::system::error_code& error)\n    {\n        if (!acceptor_.is_open())\n            return;\n\n        if (!error) {\n            boost::system::error_code ec;\n            socket->set_option(boost::asio::socket_base::keep_alive(true), ec);\n\n            if (ec)\n                CASPAR_LOG(warning) << print() << L\" Failed to enable TCP keep-alive on socket\";\n\n            auto conn = connection::create(io_context_, socket, protocol_factory_, connection_set_);\n            connection_set_->insert(conn);\n\n            for (auto& lifecycle_factory : lifecycle_factories_) {\n                auto lifecycle_bound = lifecycle_factory(u8(conn->ipv4_address()));\n                conn->add_lifecycle_bound_object(lifecycle_bound.first, lifecycle_bound.second);\n            }\n        }\n        start_accept();\n    }\n\n    std::wstring print() const\n    {\n        return L\"async_event_server[:\" + std::to_wstring(acceptor_.local_endpoint().port()) + L\"]\";\n    }\n\n    void add_client_lifecycle_object_factory(const lifecycle_factory_t& factory)\n    {\n        auto self = shared_from_this();\n        boost::asio::post(*io_context_, [=] { self->lifecycle_factories_.push_back(factory); });\n    }\n};\n\nAsyncEventServer::AsyncEventServer(std::shared_ptr<boost::asio::io_context>    io_context,\n                                   const protocol_strategy_factory<char>::ptr& protocol,\n                                   const std::string&                          host,\n                                   unsigned short                              port)\n    : impl_(new implementation(std::move(io_context), protocol, host, port))\n{\n    impl_->start_accept();\n}\n\nAsyncEventServer::~AsyncEventServer() { impl_->stop(); }\n\nvoid AsyncEventServer::add_client_lifecycle_object_factory(const lifecycle_factory_t& factory)\n{\n    impl_->add_client_lifecycle_object_factory(factory);\n}\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/AsyncEventServer.h",
    "content": "/*\n* copyright (c) 2010 Sveriges Television AB <info@casparcg.com>\n*\n*  This file is part of CasparCG.\n*\n*    CasparCG 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*    CasparCG 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 CasparCG.  If not, see <http://www.gnu.org/licenses/>.\n*\n*/\n\n// AsyncEventServer.h: interface for the AsyncServer class.\n//////////////////////////////////////////////////////////////////////\n#pragma once\n\n#include \"protocol_strategy.h\"\n\n#include <common/memory.h>\n\n#include <boost/asio.hpp>\n\nnamespace caspar { namespace IO {\n\nusing lifecycle_factory_t =\n    std::function<std::pair<std::wstring, std::shared_ptr<void>>(const std::string& ipv4_address)>;\n\nclass AsyncEventServer\n{\n  public:\n    explicit AsyncEventServer(std::shared_ptr<boost::asio::io_context>    io_context,\n                              const protocol_strategy_factory<char>::ptr& protocol,\n                              const std::string&                          host,\n                              unsigned short                              port);\n\n    ~AsyncEventServer();\n\n    void add_client_lifecycle_object_factory(const lifecycle_factory_t& lifecycle_factory);\n\n    struct implementation;\n\n  private:\n    spl::shared_ptr<implementation> impl_;\n\n    AsyncEventServer(const AsyncEventServer&)            = delete;\n    AsyncEventServer& operator=(const AsyncEventServer&) = delete;\n};\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/ClientInfo.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#pragma once\n\n#include <iostream>\n#include <memory>\n#include <string>\n\n#include \"protocol_strategy.h\"\n#include <common/log.h>\n\nnamespace caspar { namespace IO {\n\ntypedef spl::shared_ptr<client_connection<wchar_t>> ClientInfoPtr;\ntypedef std::shared_ptr<client_connection<wchar_t>> ClientInfoPtrStd;\n\nstruct ConsoleClientInfo : public client_connection<wchar_t>\n{\n    void send(std::wstring&& data, bool skip_log) override\n    {\n        std::wcout << L\"#\" + caspar::log::replace_nonprintable_copy(data, L'?') << std::flush;\n    }\n    void         disconnect() override {}\n    std::wstring address() const override { return L\"Console\"; }\n    void add_lifecycle_bound_object(const std::wstring& key, const std::shared_ptr<void>& lifecycle_bound) override {}\n    std::shared_ptr<void> remove_lifecycle_bound_object(const std::wstring& key) override\n    {\n        return std::shared_ptr<void>();\n    }\n};\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/ProtocolStrategy.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Nicklas P Andersson\n */\n\n#pragma once\n\n#include \"ClientInfo.h\"\n#include <string>\n\nnamespace caspar { namespace IO {\n\nclass IProtocolStrategy\n{\n  public:\n    virtual ~IProtocolStrategy() {}\n\n    virtual void        Parse(const std::wstring& msg, ClientInfoPtr pClientInfo) = 0;\n    virtual std::string GetCodepage() const                                       = 0;\n};\nusing ProtocolStrategyPtr = std::shared_ptr<IProtocolStrategy>;\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/http_request.cpp",
    "content": "#include \"http_request.h\"\n\n#include <common/except.h>\n\n#include <boost/asio.hpp>\n#include <iomanip>\n#include <sstream>\n#include <string>\n\nnamespace caspar { namespace http {\n\nHTTPResponse request(const std::string& host, const std::string& port, const std::string& path)\n{\n    using boost::asio::ip::tcp;\n    using namespace boost;\n\n    HTTPResponse res;\n\n    asio::io_context io_context;\n\n    // Get a list of endpoints corresponding to the server name.\n    tcp::resolver               resolver(io_context);\n    tcp::resolver::results_type resolver_result =\n        resolver.resolve(host, port, boost::asio::ip::resolver_query_base::numeric_service);\n\n    // Try each endpoint until we successfully establish a connection.\n    tcp::socket               socket(io_context);\n    boost::system::error_code error;\n    asio::connect(socket, resolver_result, error);\n    if (error == asio::error::connection_refused) {\n        res.status_code    = 503;\n        res.status_message = \"Connection refused\";\n        return res;\n    }\n    if (error) {\n        CASPAR_THROW_EXCEPTION(io_error() << msg_info(error.message()));\n    }\n\n    // Form the request. We specify the \"Connection: close\" header so that the\n    // server will close the socket after transmitting the response. This will\n    // allow us to treat all data up until the EOF as the content.\n    asio::streambuf request;\n    std::ostream    request_stream(&request);\n    request_stream << \"GET \" << path << \" HTTP/1.0\\r\\n\";\n    request_stream << \"Host: \" << host << \":\" << port << \"\\r\\n\";\n    request_stream << \"Accept: */*\\r\\n\";\n    request_stream << \"Connection: close\\r\\n\\r\\n\";\n\n    // Send the request.\n    asio::write(socket, request);\n\n    // Read the response status line. The response streambuf will automatically\n    // grow to accommodate the entire line. The growth may be limited by passing\n    // a maximum size to the streambuf constructor.\n    asio::streambuf response;\n    asio::read_until(socket, response, \"\\r\\n\");\n\n    // Check that response is OK.\n    std::istream response_stream(&response);\n    std::string  http_version;\n    response_stream >> http_version;\n    response_stream >> res.status_code;\n    std::getline(response_stream, res.status_message);\n\n    if (!response_stream || http_version.substr(0, 5) != \"HTTP/\") {\n        // TODO\n        CASPAR_THROW_EXCEPTION(io_error() << msg_info(\"Invalid Response\"));\n    }\n\n    if (res.status_code < 200 || res.status_code >= 300) {\n        // TODO\n        CASPAR_THROW_EXCEPTION(io_error() << msg_info(\"Invalid Response\"));\n    }\n\n    // Read the response headers, which are terminated by a blank line.\n    asio::read_until(socket, response, \"\\r\\n\\r\\n\");\n\n    // Process the response headers.\n    std::string header;\n    while (std::getline(response_stream, header) && header != \"\\r\") {\n        // TODO\n    }\n\n    std::stringstream body;\n\n    // Write whatever content we already have to output.\n    if (response.size() > 0) {\n        body << &response;\n    }\n\n    // Read until EOF, writing data to output as we go.\n    while (asio::read(socket, response, asio::transfer_at_least(1), error)) {\n        body << &response;\n    }\n\n    if (error != asio::error::eof) {\n        CASPAR_THROW_EXCEPTION(io_error() << msg_info(error.message()));\n    }\n\n    res.body = body.str();\n\n    return res;\n}\n\nstd::string url_encode(const std::string& str)\n{\n    std::stringstream escaped;\n    escaped.fill('0');\n    escaped << std::hex;\n\n    for (auto c : str) {\n        if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {\n            escaped << c;\n        } else {\n            escaped << std::uppercase << '%' << std::setw(2) << int((unsigned char)c) << std::nouppercase;\n        }\n    }\n\n    return escaped.str();\n}\n\n}} // namespace caspar::http\n"
  },
  {
    "path": "src/protocol/util/http_request.h",
    "content": "#pragma once\n\n#include <map>\n#include <string>\n\nnamespace caspar { namespace http {\n\nstruct HTTPResponse\n{\n    unsigned int                       status_code;\n    std::string                        status_message;\n    std::map<std::string, std::string> headers;\n    std::string                        body;\n};\n\nHTTPResponse request(const std::string& host, const std::string& port, const std::string& path);\n\nstd::string url_encode(const std::string& str);\n\n}} // namespace caspar::http\n"
  },
  {
    "path": "src/protocol/util/lock_container.cpp",
    "content": "#include \"../StdAfx.h\"\n\n#include \"lock_container.h\"\n#include <tbb/spin_rw_mutex.h>\n\nnamespace caspar { namespace IO {\n\nstruct lock_container::impl\n{\n    std::wstring lifecycle_key_;\n\n  private:\n    std::set<std::weak_ptr<client_connection<wchar_t>>, std::owner_less<std::weak_ptr<client_connection<wchar_t>>>>\n                               locks_;\n    std::wstring               lock_phrase_;\n    mutable tbb::spin_rw_mutex mutex_;\n\n  public:\n    impl(const std::wstring& lifecycle_key)\n        : lifecycle_key_(lifecycle_key)\n    {\n    }\n\n    bool check_access(client_connection<wchar_t>::ptr conn)\n    {\n        tbb::spin_rw_mutex::scoped_lock           lock(mutex_, false);\n        std::weak_ptr<client_connection<wchar_t>> weak_ptr(conn);\n        return locks_.empty() ? true : locks_.find(weak_ptr) != locks_.end();\n    }\n\n    bool try_lock(const std::wstring& lock_phrase, client_connection<wchar_t>::ptr conn)\n    {\n        tbb::spin_rw_mutex::scoped_lock lock(mutex_, false);\n        if (lock_phrase_.empty() || lock_phrase == lock_phrase_) {\n            std::weak_ptr<client_connection<wchar_t>> weak_ptr(conn);\n            if (locks_.find(weak_ptr) == locks_.end()) {\n                {\n                    lock.upgrade_to_writer();\n                    lock_phrase_ = lock_phrase;\n                    locks_.insert(weak_ptr);\n                }\n\n                lock.release(); // risk of reentrancy-deadlock if we don't release prior to trying to attach\n                                // lifecycle-bound object to connection\n\n                CASPAR_LOG(info) << lifecycle_key_ << \" acquired\";\n\n                {\n                    std::shared_ptr<void> obj(nullptr, [this, weak_ptr](void*) { do_release_lock(weak_ptr); });\n                    conn->add_lifecycle_bound_object(lifecycle_key_, obj);\n                }\n            }\n\n            return true;\n        }\n        return false;\n    }\n\n    void\n    clear_locks() // TODO: add a function-object parameter to be called for each clients that has it's lock released\n    {\n        std::vector<std::weak_ptr<client_connection<wchar_t>>> clients;\n\n        { // copy the connections locally and then clear the set\n            tbb::spin_rw_mutex::scoped_lock lock(mutex_, true);\n            clients.resize(locks_.size());\n            std::copy(locks_.begin(), locks_.end(), clients.begin());\n\n            locks_.clear();\n            lock_phrase_.clear();\n        }\n\n        // now we can take our time to inform the clients that their locks have been released.\n        for (auto& conn : clients) {\n            auto ptr = conn.lock();\n            if (ptr) {\n                ptr->remove_lifecycle_bound_object(\n                    lifecycle_key_); // this calls do_release_lock, which takes a write-lock\n                // TODO: invoke callback\n            }\n        }\n    }\n\n    void release_lock(client_connection<wchar_t>::ptr conn)\n    {\n        conn->remove_lifecycle_bound_object(lifecycle_key_); // this calls do_release_lock, which takes a write-lock\n    }\n\n  private:\n    void do_release_lock(std::weak_ptr<client_connection<wchar_t>> conn)\n    {\n        {\n            tbb::spin_rw_mutex::scoped_lock lock(mutex_, true);\n            if (!locks_.empty()) {\n                locks_.erase(conn);\n                if (locks_.empty())\n                    lock_phrase_.clear();\n            }\n        }\n\n        CASPAR_LOG(info) << lifecycle_key_ << \" released\";\n    }\n};\n\nlock_container::lock_container(const std::wstring& lifecycle_key)\n    : impl_(spl::make_unique<impl>(lifecycle_key))\n{\n}\nlock_container::~lock_container() {}\n\nbool lock_container::check_access(client_connection<wchar_t>::ptr conn) { return impl_->check_access(conn); }\nbool lock_container::try_lock(const std::wstring& lock_phrase, client_connection<wchar_t>::ptr conn)\n{\n    return impl_->try_lock(lock_phrase, conn);\n}\nvoid lock_container::release_lock(client_connection<wchar_t>::ptr conn) { impl_->release_lock(conn); }\nvoid lock_container::clear_locks() { return impl_->clear_locks(); }\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/lock_container.h",
    "content": "#pragma once\n\n#include <common/memory.h>\n\n#include \"protocol_strategy.h\"\n\nnamespace caspar { namespace IO {\n\nclass lock_container\n{\n  public:\n    lock_container(const std::wstring& lifecycle_key);\n    ~lock_container();\n\n    bool check_access(client_connection<wchar_t>::ptr conn);\n    bool try_lock(const std::wstring& lock_phrase, client_connection<wchar_t>::ptr conn);\n    void release_lock(client_connection<wchar_t>::ptr conn);\n    void clear_locks();\n\n  private:\n    struct impl;\n    spl::unique_ptr<impl> impl_;\n\n    lock_container(const lock_container&)            = delete;\n    lock_container& operator=(const lock_container&) = delete;\n};\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/protocol_strategy.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <string>\n\n#include <common/memory.h>\n\nnamespace caspar { namespace IO {\n\n/**\n * A protocol strategy handles a single client connection. A client_connection\n * instance is needed in order to send data to the client.\n */\ntemplate <class CharT>\nclass protocol_strategy\n{\n  public:\n    using ptr = spl::shared_ptr<protocol_strategy<CharT>>;\n\n    virtual ~protocol_strategy() {}\n\n    /**\n     * Parse some data received. If used directly by the async event server,\n     * then the data will be what was received from the TCP/IP stack, but if\n     * a delimiter based protocol is used, delimiter_based_chunking_strategy\n     * can be used to ensure that the strategy implementation is only\n     * provided complete messages.\n     *\n     * @param data The data received.\n     */\n    virtual void parse(const std::basic_string<CharT>& data) = 0;\n};\n\n/**\n * A handle for a protocol_strategy to use when interacting with the client.\n */\ntemplate <class CharT>\nclass client_connection\n{\n  public:\n    using ptr = spl::shared_ptr<client_connection<CharT>>;\n\n    virtual ~client_connection() {}\n\n    virtual void         send(std::basic_string<CharT>&& data, bool skip_log = false) = 0;\n    virtual void         disconnect()                                                 = 0;\n    virtual std::wstring address() const                                              = 0;\n\n    virtual void add_lifecycle_bound_object(const std::wstring& key, const std::shared_ptr<void>& lifecycle_bound) = 0;\n    virtual std::shared_ptr<void> remove_lifecycle_bound_object(const std::wstring& key)                           = 0;\n};\n\n/**\n * Creates unique instances of protocol_strategy implementations.\n *\n * Each async event server will have one instance of this factory, but create\n * unique protocol_strategy<char> instances for each connected client.\n *\n * Any shared state between client interactions could be held in the factory.\n */\ntemplate <class CharT>\nclass protocol_strategy_factory\n{\n  public:\n    using ptr = spl::shared_ptr<protocol_strategy_factory<CharT>>;\n\n    virtual ~protocol_strategy_factory() {}\n    virtual typename protocol_strategy<CharT>::ptr\n    create(const typename client_connection<CharT>::ptr& client_connection) = 0;\n};\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/strategy_adapters.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"../StdAfx.h\"\n\n#include \"strategy_adapters.h\"\n\n#include <boost/algorithm/string/replace.hpp>\n#include <boost/locale.hpp>\n\nnamespace caspar { namespace IO {\n\nclass to_unicode_adapter : public protocol_strategy<char>\n{\n    std::string                     codepage_;\n    protocol_strategy<wchar_t>::ptr unicode_strategy_;\n\n  public:\n    to_unicode_adapter(const std::string& codepage, const protocol_strategy<wchar_t>::ptr& unicode_strategy)\n        : codepage_(codepage)\n        , unicode_strategy_(unicode_strategy)\n    {\n    }\n\n    void parse(const std::basic_string<char>& data) override\n    {\n        auto utf_data = boost::locale::conv::to_utf<wchar_t>(data, codepage_, boost::locale::conv::skip);\n\n        unicode_strategy_->parse(utf_data);\n    }\n};\n\nclass from_unicode_client_connection : public client_connection<wchar_t>\n{\n    client_connection<char>::ptr client_;\n    std::string                  codepage_;\n\n  public:\n    from_unicode_client_connection(const client_connection<char>::ptr& client, const std::string& codepage)\n        : client_(client)\n        , codepage_(codepage)\n    {\n    }\n    ~from_unicode_client_connection() {}\n\n    void send(std::basic_string<wchar_t>&& data, bool skip_log) override\n    {\n        auto str = boost::locale::conv::from_utf<wchar_t>(data, codepage_);\n\n        client_->send(std::move(str), skip_log);\n\n        if (skip_log)\n            return;\n\n        if (data.length() < 512) {\n            boost::replace_all(data, L\"\\n\", L\"\\\\n\");\n            boost::replace_all(data, L\"\\r\", L\"\\\\r\");\n            CASPAR_LOG(info) << L\"Sent message to \" << client_->address() << L\":\"\n                             << log::replace_nonprintable_copy(data, L'?');\n        } else\n            CASPAR_LOG(info) << L\"Sent more than 512 bytes to \" << client_->address();\n    }\n\n    void disconnect() override { client_->disconnect(); }\n\n    std::wstring address() const override { return client_->address(); }\n\n    void add_lifecycle_bound_object(const std::wstring& key, const std::shared_ptr<void>& lifecycle_bound) override\n    {\n        client_->add_lifecycle_bound_object(key, lifecycle_bound);\n    }\n    std::shared_ptr<void> remove_lifecycle_bound_object(const std::wstring& key) override\n    {\n        return client_->remove_lifecycle_bound_object(key);\n    }\n};\n\nto_unicode_adapter_factory::to_unicode_adapter_factory(\n    const std::string&                             codepage,\n    const protocol_strategy_factory<wchar_t>::ptr& unicode_strategy_factory)\n    : codepage_(codepage)\n    , unicode_strategy_factory_(unicode_strategy_factory)\n{\n}\n\nprotocol_strategy<char>::ptr to_unicode_adapter_factory::create(const client_connection<char>::ptr& client_connection)\n{\n    auto client = spl::make_shared<from_unicode_client_connection>(client_connection, codepage_);\n\n    return spl::make_shared<to_unicode_adapter>(codepage_, unicode_strategy_factory_->create(client));\n}\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/strategy_adapters.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <boost/algorithm/string/split.hpp>\n\n#include \"ProtocolStrategy.h\"\n#include \"protocol_strategy.h\"\n\nnamespace caspar { namespace IO {\n\n/**\n * A protocol strategy factory adapter for converting incoming data from a\n * specific codepage to utf-16. The client_connection will do the reversed\n * conversion.\n *\n * The adapter is not safe if the codepage contains multibyte-characters and\n * the data is chunked with potentially incomplete characters, therefore it\n * must be wrapped in an adapter providing complete chunks like\n * delimiter_based_chunking_strategy_factory.\n */\nclass to_unicode_adapter_factory : public protocol_strategy_factory<char>\n{\n    std::string                             codepage_;\n    protocol_strategy_factory<wchar_t>::ptr unicode_strategy_factory_;\n\n  public:\n    to_unicode_adapter_factory(const std::string&                             codepage,\n                               const protocol_strategy_factory<wchar_t>::ptr& unicode_strategy_factory);\n\n    protocol_strategy<char>::ptr create(const client_connection<char>::ptr& client_connection) override;\n};\n\n/**\n * Protocol strategy adapter for ensuring that only complete chunks or\n * \"packets\" are delivered to the wrapped strategy. The chunks are determined\n * by a given delimiter.\n */\ntemplate <class CharT>\nclass delimiter_based_chunking_strategy : public protocol_strategy<CharT>\n{\n    std::basic_string<CharT>               delimiter_;\n    std::basic_string<CharT>               input_;\n    typename protocol_strategy<CharT>::ptr strategy_;\n\n  public:\n    delimiter_based_chunking_strategy(const std::basic_string<CharT>&               delimiter,\n                                      const typename protocol_strategy<CharT>::ptr& strategy)\n        : delimiter_(delimiter)\n        , strategy_(strategy)\n    {\n    }\n\n    void parse(const std::basic_string<CharT>& data) override\n    {\n        input_ += data;\n\n        auto delim_pos = input_.find(delimiter_);\n        while (delim_pos != std::string::npos) {\n            strategy_->parse(input_.substr(0, delim_pos));\n\n            input_    = std::move(input_.substr(delim_pos + delimiter_.size()));\n            delim_pos = input_.find_first_of(delimiter_);\n        }\n    }\n};\n\ntemplate <class CharT>\nclass delimiter_based_chunking_strategy_factory : public protocol_strategy_factory<CharT>\n{\n    std::basic_string<CharT>                       delimiter_;\n    typename protocol_strategy_factory<CharT>::ptr strategy_factory_;\n\n  public:\n    delimiter_based_chunking_strategy_factory(const std::basic_string<CharT>&                       delimiter,\n                                              const typename protocol_strategy_factory<CharT>::ptr& strategy_factory)\n        : delimiter_(delimiter)\n        , strategy_factory_(strategy_factory)\n    {\n    }\n\n    typename protocol_strategy<CharT>::ptr\n    create(const typename client_connection<CharT>::ptr& client_connection) override\n    {\n        return spl::make_shared<delimiter_based_chunking_strategy<CharT>>(delimiter_,\n                                                                          strategy_factory_->create(client_connection));\n    }\n};\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/tokenize.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n */\n\n#include \"tokenize.h\"\n\nnamespace caspar { namespace IO {\n\nstd::size_t tokenize(const std::wstring& message, std::list<std::wstring>& pTokenVector)\n{\n    // split on whitespace but keep strings within quotationmarks\n    // treat \\ as the start of an escape-sequence: the following char will indicate what to actually put in the\n    // string\n\n    std::wstring currentToken;\n\n    bool inQuote        = false;\n    int  inParamList    = 0;\n    bool getSpecialCode = false;\n\n    for (unsigned int charIndex = 0; charIndex < message.size(); ++charIndex) {\n        if (getSpecialCode) {\n            // insert code-handling here\n            switch (message[charIndex]) {\n                case L'\\\\':\n                    currentToken += L\"\\\\\";\n                    break;\n                case L'\\\"':\n                    currentToken += L\"\\\"\";\n                    break;\n                case L'n':\n                    currentToken += L\"\\n\";\n                    break;\n                default:\n                    break;\n            };\n            getSpecialCode = false;\n            continue;\n        }\n\n        if (message[charIndex] == L'\\\\') {\n            getSpecialCode = true;\n            continue;\n        }\n\n        if (message[charIndex] == L' ' && inQuote == false && inParamList == 0) {\n            if (!currentToken.empty()) {\n                pTokenVector.push_back(currentToken);\n                currentToken.clear();\n            }\n            continue;\n        } else if (!inQuote && message[charIndex] == L'(') {\n            inParamList++;\n            // continue;\n        } else if (!inQuote && message[charIndex] == L')') {\n            inParamList--;\n            if (inParamList == 0) {\n                currentToken += message[charIndex];\n                pTokenVector.push_back(currentToken);\n                currentToken.clear();\n                continue;\n            }\n            // continue;\n        } else if (message[charIndex] == L'\\\"') {\n            inQuote = !inQuote;\n\n            if (inParamList == 0) {\n                if (!inQuote) {\n                    pTokenVector.push_back(currentToken);\n                    currentToken.clear();\n                }\n                continue;\n            }\n        }\n\n        currentToken += message[charIndex];\n    }\n\n    if (!currentToken.empty()) {\n        pTokenVector.push_back(currentToken);\n        currentToken.clear();\n    }\n\n    return pTokenVector.size();\n}\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/protocol/util/tokenize.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.*\n */\n\n#pragma once\n\n#include <list>\n#include <string>\n\nnamespace caspar { namespace IO {\n\nstd::size_t tokenize(const std::wstring& message, std::list<std::wstring>& pTokenVector);\n\n}} // namespace caspar::IO\n"
  },
  {
    "path": "src/shell/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\nproject (shell)\n\njoin_list(\"${CASPARCG_MODULE_INCLUDE_STATEMENTS}\" \"\\n\" CASPARCG_MODULE_INCLUDE_STATEMENTS)\njoin_list(\"${CASPARCG_MODULE_INIT_STATEMENTS}\" \"\\n\" CASPARCG_MODULE_INIT_STATEMENTS)\njoin_list(\"${CASPARCG_MODULE_UNINIT_STATEMENTS}\" \"\\n\" CASPARCG_MODULE_UNINIT_STATEMENTS)\njoin_list(\"${CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS}\" \"\\n\" CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS)\nCONFIGURE_FILE (\"${PROJECT_SOURCE_DIR}/included_modules.tmpl\" \"${CMAKE_BINARY_DIR}/generated/included_modules.h\")\n\nset(SOURCES\n\t\tcasparcg.config\n\t\tmain.cpp\n\t\tserver.cpp\n)\nset(HEADERS\n\t\tplatform_specific.h\n\t\tserver.h\n)\n\nif (MSVC)\n\tlist(APPEND SOURCES\n\t\t\tresource.h\n\t\t\tshell.rc\n\t\t\twindows_specific.cpp\n\t)\nelse ()\n\tlist(APPEND SOURCES\n\t\t\tlinux_specific.cpp\n\t)\nendif ()\n\n\nadd_executable(casparcg ${SOURCES} ${HEADERS})\nset_target_properties(casparcg PROPERTIES\n        OUTPUT_NAME \"${CASPARCG_BINARY_NAME}\"\n    )\ntarget_compile_features(casparcg PRIVATE cxx_std_20)\ntarget_include_directories(casparcg PRIVATE\n    ..\n    ${BOOST_INCLUDE_PATH}\n    )\ncasparcg_add_build_dependencies(casparcg)\n\nsource_group(sources ./*)\n\ntarget_link_libraries(casparcg\n\t\taccelerator\n\t\tcommon\n\t\tcore\n\t\tprotocol\n\n\t\t\"${CASPARCG_MODULE_TARGETS}\"\n\n\t\tTBB::tbb\n\t\tTBB::tbbmalloc\n\t\tGLEW::glew\n)\n\nif (MSVC)\n\ttarget_link_libraries(casparcg\n\t\tWinmm.lib\n\t\tWs2_32.lib\n\t\tOpenGL32.lib\n\t\tdebug zlibstaticd.lib\n\t\toptimized zlibstatic.lib\n\n\t\tOpenAL::OpenAL\n\t\toptimized TBB::tbbmalloc_proxy\n\n\t\tavformat.lib\n\t\tavcodec.lib\n\t\tavutil.lib\n\t\tavfilter.lib\n\t\tavdevice.lib\n\t\tswscale.lib\n\t\tswresample.lib\n\n\t\td3d9.lib\n\t\td3d11.lib\n\t\tdxgi.lib\n\t)\nelse ()\n\ttarget_link_libraries(casparcg\n\t\t${Boost_LIBRARIES}\n\t\tOpenGL::GL\n\t\tOpenGL::OpenGL\n\t\tOpenGL::EGL\n\t\t${X11_LIBRARIES}\n\t\t${FFMPEG_LIBRARIES}\n\t\tdl\n\t\ticui18n\n\t\ticuuc\n\t\tz\n\t\tpthread\n\t)\nendif ()\n\nadd_custom_target(casparcg_copy_dependencies ALL)\ncasparcg_add_build_dependencies(casparcg_copy_dependencies)\n\nset(OUTPUT_FOLDER \"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}\")\nadd_custom_command(TARGET casparcg_copy_dependencies POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory \\\"${OUTPUT_FOLDER}\\\")\n\nif (MSVC)\n    if (is_multi_config)\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND if $(ConfigurationName) == Debug (\n\t\t\t\t    echo \\\"Copy Debug ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/\\\"\n\t\t\t    )\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND if $(ConfigurationName) NEQ Debug (\n\t\t\t\t    echo \\\"Copy Release ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/\\\"\n\t\t\t    )\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG_DIRS})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND if $(ConfigurationName) == Debug (\n\t\t\t\t    echo \\\"Copy Debug ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/${FOLDER_NAME}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/${FOLDER_NAME}/\\\"\n\t\t\t    )\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE_DIRS})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND if $(ConfigurationName) NEQ Debug (\n\t\t\t\t    echo \\\"Copy Release ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/${FOLDER_NAME}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/${FOLDER_NAME}/\\\"\n\t\t\t    )\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n    elseif(${CMAKE_BUILD_TYPE} MATCHES \"Debug\")\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND echo \\\"Copy Debug ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/\\\"\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_DEBUG_DIRS})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND echo \\\"Copy Debug ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/${FOLDER_NAME}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/${FOLDER_NAME}/\\\"\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n    else ()\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND echo \\\"Copy Release ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/\\\"\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n\n\t    foreach(FILE_TO_COPY ${CASPARCG_RUNTIME_DEPENDENCIES_RELEASE_DIRS})\n\t\t    get_filename_component(FOLDER_NAME \"${FILE_TO_COPY}\" NAME)\n\t\t    add_custom_command(\n\t\t\t    TARGET casparcg_copy_dependencies\n\t\t\t    POST_BUILD\n\t\t\t    COMMAND echo \\\"Copy Release ${FILE_TO_COPY}\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${OUTPUT_FOLDER}/${FOLDER_NAME}/\\\" &&\n\t\t\t\t    ${CMAKE_COMMAND} -E copy_directory \\\"${FILE_TO_COPY}\\\" \\\"${CMAKE_CURRENT_BINARY_DIR}/${FOLDER_NAME}/\\\"\n\t\t    )\n\t    endforeach(FILE_TO_COPY)\n    endif ()\nelse ()\n\tinstall(TARGETS casparcg)\n\n    if (\"${CASPARCG_BINARY_NAME}\" STREQUAL \"casparcg\")\n        # Looks like a 'default' build, produce a portable folder\n\t    install(FILES casparcg.config run.sh DESTINATION \".\")\n    else ()\n        # Looks like a build for a system package manager\n        install(FILES casparcg.config DESTINATION \"share/${CASPARCG_BINARY_NAME}\")\n    endif ()\nendif ()\n"
  },
  {
    "path": "src/shell/casparcg.config",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<configuration>\n    <paths>\n        <media-path>media/</media-path>\n        <log-path disable=\"false\">log/</log-path>\n        <data-path>data/</data-path>\n        <template-path>template/</template-path>\n    </paths>\n    <lock-clear-phrase>secret</lock-clear-phrase>\n    <channels>\n        <channel>\n            <video-mode>720p5000</video-mode>\n            <consumers>\n                <screen />\n                <system-audio />\n            </consumers>\n        </channel>\n    </channels>\n    <controllers>\n        <tcp>\n            <port>5250</port>\n            <protocol>AMCP</protocol>\n        </tcp>\n    </controllers>\n    <amcp>\n        <media-server>\n            <host>localhost</host>\n            <port>8000</port>\n        </media-server>\n    </amcp>\n</configuration>\n\n<!--\n<log-level> info  [trace|debug|info|warning|error|fatal]</log-level>\n<log-align-columns>true [true|false]</log-align-columns>\n<template-hosts>\n    <template-host>\n        <video-mode />\n        <filename />\n        <width />\n        <height />\n    </template-host>\n</template-hosts>\n<accelerator>auto [auto|opengl|vulkan] (auto evaluates to opengl)</accelerator>\n<flash>\n    <enabled>false [true|false]</enabled>\n    <buffer-depth>auto [auto|1..]</buffer-depth>\n</flash>\n<ffmpeg>\n    <producer>\n        <auto-deinterlace>interlaced [none|interlaced|all]</auto-deinterlace>\n        <threads>4 [1..]</threads>\n    </producer>\n</ffmpeg>\n<html>\n    <remote-debugging-port>0 [0|1024-65535]</remote-debugging-port>\n    <enable-gpu>false [true|false]</enable-gpu>\n\t<angle-backend>gl [|gl|d3d11|d3d9]</angle-backend>\n    <cache-path>(CEF writes some caches next to the executable, which can fail depending on permissions. This changes it to use another path)</cache-path>\n</html>\n<system-audio>\n    <producer>\n        <default-device-name></default-device-name>\n    </producer>\n</system-audio>\n<ndi>\n    <auto-load>false [true|false]</auto-load>\n    <discovery-server>[hostname:port] (Global NDI Discovery Server URL applied to all consumers. Per-consumer discovery-server overrides this value.)</discovery-server>\n</ndi>\n<video-modes>\n    <video-mode>\n        <id>1024x768p60</id>\n        <width>1024</width>\n        <height>768</height>\n        <time-scale>60000</time-scale>\n        <duration>1000</duration>\n        <cadence>800</cadence>\n    </video-mode>\n</video-modes>\n<channels>\n    <channel>\n        <video-mode>PAL [PAL|NTSC|576p2500|720p2398|720p2400|720p2500|720p5000|720p2997|720p5994|720p3000|720p6000|1080p2398|1080p2400|1080i5000|1080i5994|1080i6000|1080p2500|1080p2997|1080p3000|1080p5000|1080p5994|1080p6000|1556p2398|1556p2400|1556p2500|dci1080p2398|dci1080p2400|dci1080p2500|2160p2398|2160p2400|2160p2500|2160p2997|2160p3000|2160p5000|2160p5994|2160p6000|dci2160p2398|dci2160p2400|dci2160p2500] </video-mode>\n        <color-depth>8 [8|16]</color-depth>\n        <color-space>bt709 [bt709|bt2020]</color-space>\n        <consumers>\n            <decklink>\n                <device>[1..]</device>\n                <key-device>device + 1 [1..] (This is only used with the external_separate_device mode)</key-device>\n                <embedded-audio>false [true|false]</embedded-audio>\n                <latency>normal [normal|low|default]</latency>\n                <keyer>external [external|external_separate_device|internal|default]</keyer>\n                <key-only>false [true|false]</key-only>\n                <buffer-depth>3 [1..]</buffer-depth>\n                <pixel-format>[yuv|rgba](default is rgba for 8bit channels, yuv for high bit-depth channels)</pixel-format>\n                <video-mode>(Run the decklink at a different video-mode. Note: the framerate must match that of the channel)</video-mode>\n                <subregion>\n                    <src-x>0 (x offset into the channel)</src-x>\n                    <src-y>0 (y offset into the channel)</src-y>\n                    <dest-x>0 (x offset of the video onto the output)</dest-x>\n                    <dest-y>0 (y offset of the video onto the output)</dest-y>\n                    <width>0 (width of the region to copy. 0 means no-limit)</width>\n                    <height>0 (height of the region to copy. 0 means no-limit)</height>\n                </subregion>\n                <color-space> [bt601|bt709|bt2020](default is to follow channel)</color-space>\n                <hdr-metadata>\n                    <max-cll>1000 [1..65535]</max-cll>\n                    <max-fall>1000 [50..65535]</max-fall>\n                    <min-dml>0.005 [0.0001-6.5535]</min-dml>\n                    <max-dml>1000 [1-65535]</max-dml>\n                </hdr-metadata>\n\n                <wait-for-reference>auto [auto|enable|disable]</wait-for-reference>\n                <wait-for-reference-duration>10 (seconds)</wait-for-reference-duration>\n\n                <ports>\n                    (Add secondary ports to be run in sync with the primary. This allows for splitting a wide channel across multiple decklinks, with sync across the outputs guaranteed by the driver on supported cards)\n                    <port>\n                        <device>[1..]</device>\n                        <key-only>false [true|false]</key-only>\n                        <video-mode>(Run the decklink at a different video-mode. Note: the framerate must match that of the channel)</video-mode>\n                        <subregion>\n                            <src-x>0 (x offset into the channel)</src-x>\n                            <src-y>0 (y offset into the channel)</src-y>\n                            <dest-x>0 (x offset of the video onto the output)</dest-x>\n                            <dest-y>0 (y offset of the video onto the output)</dest-y>\n                            <width>0 (width of the region to copy. 0 means no-limit)</width>\n                            <height>0 (height of the region to copy. 0 means no-limit)</height>\n                        </subregion>\n                    </port>\n                </ports>\n            </decklink>\n      \t    <bluefish>\n                <device>[1..]</device>\n\t\t            <sdi-stream>1[1..] </sdi-stream>\n                <embedded-audio>false [true|false]</embedded-audio>\n                <keyer>disabled [external|internal|disabled] (external only supported on channels 1 and 3, using 3 requires 4 out connectors) ( internal only available on devices with a hardware keyer) </keyer>\n                <internal-keyer-audio-source> videooutputchannel [videooutputchannel|sdivideoinput] ( only valid when using internal keyer option) </internal-keyer-audio-source>\n                <watchdog>2[0..] ( set to 0 to disable the HW watchdog functionality, otherwise this value indicates how many frames to wait after a crash, before enabling the bypass relay's on the card - only works on sdi-stream 1) </watchdog>\n                <uhd-mode>0 [0|1|2|3] (0 = Disable BVC-Multi_Link,  1  = Auto ( ie. BVC-ML gets SQ, Native buffers get 2SI), 2 = Force 2SI output, 3 = Force SQ ie. Square Division output ) this setting only applies in UHD modes. </uhd-mode>\n            </bluefish>\n            <system-audio>\n            </system-audio>\n            <screen>\n                <device>1 [1..]</device>\n                <aspect-ratio>default [default|4:3|16:9]</aspect-ratio>\n                <stretch>fill [none|fill|uniform|uniform_to_fill]</stretch>\n                <windowed>true [true|false]</windowed>\n                <key-only>false [true|false]</key-only>\n                <vsync>false [true|false]</vsync>\n                <borderless>false [true|false]</borderless>\n                <interactive>true [true|false]</interactive>\n                <always-on-top>false [true|false]</always-on-top>\n                <x>0</x>\n                <y>0</y>\n                <width>0 (0=not set)</width>\n                <height>0 (0=not set)</height>\n                <sbs-key>false [true|false]</sbs-key>\n                <colour-space>RGB [RGB|datavideo-full|datavideo-limited] (Enables colour space conversion for DataVideo TC-100 / TC-200)</colour-space>\n            </screen>\n            <ndi>\n                <name>[custom name]</name>\n                <allow-fields>false [true|false]</allow-fields>\n                <use-advertiser>false [true|false]</use-advertiser>\n                <allow-monitoring>true [true|false]</allow-monitoring>\n                <discovery-server>[hostname:port] (NDI Discovery Server URL, comma-separated for multiple servers. Requires use-advertiser=true)</discovery-server>\n            </ndi>\n            <ffmpeg>\n                <path>[file|url]</path>\n                <args>[most ffmpeg arguments related to filtering and output codecs]</args>\n            </ffmpeg>\n            <artnet>\n                <universe>0</universe>\n\n                <host>127.0.0.1</host>\n                <port>6454</port>\n\n                <refresh-rate>30</refresh-rate>\n\n                <fixtures>\n                    <fixture>\n                        <type>RGBW</type>\n                        <start-address>1</start-address>\n                        <fixture-count>10</fixture-count>\n                        <fixture-channels>6</fixture-channels>\n\n                        <x>960</x>\n                        <y>540</y>\n\n                        <width>500</width>\n                        <height>100</height>\n\n                        <rotation>0</rotation>\n                    </fixture>\n                </fixtures>\n            </artnet>\n        </consumers>\n        <producers>\n            <producer id=\"0\">AMB LOOP</producer>\n            <producer id=\"10\">DECKLINK DEVICE 2</producer>\n        </producers>\n    </channel>\n</channels>\n<osc>\n  <default-port>6250</default-port>\n  <disable-send-to-amcp-clients>false [true|false]</disable-send-to-amcp-clients>\n  <predefined-clients>\n    <predefined-client>\n      <address>127.0.0.1</address>\n      <port>5253</port>\n    </predefined-client>\n  </predefined-clients>\n</osc>\n-->\n"
  },
  {
    "path": "src/shell/casparcg_auto_restart.bat",
    "content": "@Echo off\n\nIF EXIST scanner.exe (\n    start scanner.exe\n)\n\n:Start\nSET ERRORLEVEL 0\n\ncasparcg.exe\n\nif ERRORLEVEL 5 goto :Start\n"
  },
  {
    "path": "src/shell/copy_deps.sh",
    "content": "#!/bin/bash\n\nfunction usage()\n{\n    cat << EOU\nUsage: bash $0 <path to the binary> <path to copy the dependencies>\nEOU\nexit 1\n}\n\n#Validate the inputs\n[[ $# < 2 ]] && usage\n\n#Check if the paths are valid\n[[ ! -e $1 ]] && echo \"Not a valid input $1\" && exit 1\n[[ -d $2 ]] || echo \"No such directory $2 creating...\"&& mkdir -p \"$2\"\n\n#Get the library dependencies\nexport LD_LIBRARY_PATH=/opt/boost/lib\necho \"Collecting the shared library dependencies for $1...\"\ndeps=$(ldd $1 | awk 'BEGIN{ORS=\" \"}$1\\\n~/^\\//{print $1}$3~/^\\//{print $3}'\\\n | sed 's/,$/\\n/')\necho \"Copying the dependencies to $2\"\n\n#Copy the deps\nfor dep in $deps\ndo\n    if [[ $dep = *\"ld-linux-x86-64.so\"* ]] || [[ $dep = *\"libc.so\"* ]] || [[ $dep = *\"libstdc++.so\"* ]]; then\n        echo \"Skipping $dep\"\n    else\n        echo \"Copying $dep to $2\"\n        cp \"$dep\" \"$2\"\n    fi\ndone\n\n# Dynamic deps\ncp \"/usr/lib/x86_64-linux-gnu/nss/libsoftokn3.so\" \"$2\"\ncp \"/usr/lib/x86_64-linux-gnu/nss/libnssckbi.so\" \"$2\"\n\necho \"Done!\"\n"
  },
  {
    "path": "src/shell/included_modules.tmpl",
    "content": "/*\n * Generated file.\n */\n\n#pragma once\n\n#include <common/log.h>\n\n#include <core/module_dependencies.h>\n${CASPARCG_MODULE_INCLUDE_STATEMENTS}\n\nnamespace caspar {\n\nstatic bool intercept_command_line_args(int argc, char** argv)\n{${CASPARCG_MODULE_COMMAND_LINE_ARG_INTERCEPTORS_STATEMENTS}\n\treturn false;\n}\n\nstatic void initialize_modules(const core::module_dependencies& dependencies)\n{${CASPARCG_MODULE_INIT_STATEMENTS}}\n\nstatic void uninitialize_modules()\n{\n${CASPARCG_MODULE_UNINIT_STATEMENTS}}\n\n}\n"
  },
  {
    "path": "src/shell/liberation-fonts/AUTHORS",
    "content": "AUTHORS\n\nCurrent Contributors (sorted alphabetically):\n  - Pravin Satpute  <psatpute at redhat dot com>\n      Project Owner (Current)\n      Red Hat, Inc.\n\nPrevious Contributors\n\n  - Steve Matteson\n      Original Designer\n      Ascender, Inc.\n"
  },
  {
    "path": "src/shell/liberation-fonts/ChangeLog",
    "content": "* Thu Oct 04 2012 Pravin Satpute <psatpute AT redhat DOT com>\n- Resolved \"Glyphs with multiple unicode encodings inhibit subsetting\" #851790\n- Resolved #851791, #854601 and #851825\n- Following GASP table version as per Liberation old version. (Anti-aliasing disabled)\n- Added support for Serbian glyphs for wikipedia #657849\n- In Monospace fonts, isFixedPitch bit set via script for getting it recognized as Monospace in putty.exe\n\n* Fri Jul 06 2012 Pravin Satpute <psatpute AT redhat DOT com>\n- Initial version of Liberation fonts based on croscore fonts version 1.21.0\n- Converted TTF files into SFD files to be open source.\n- Update Copyright and License file\n- set fsType bit to 0, Installable Embedding is allowed.\n- Absolute value in HHeadAscent/Descent values for maintaining Metric compatibility.\n\n"
  },
  {
    "path": "src/shell/liberation-fonts/LICENSE",
    "content": "Digitized data copyright (c) 2010 Google Corporation\n\twith Reserved Font Arimo, Tinos and Cousine.\nCopyright (c) 2012 Red Hat, Inc.\n\twith Reserved Font Name Liberation.\n\nThis Font Software is licensed under the SIL Open Font License,\nVersion 1.1.\n\nThis license is copied below, and is also available with a FAQ at:\nhttp://scripts.sil.org/OFL\n\nSIL OPEN FONT LICENSE Version 1.1 - 26 February 2007\n\nPREAMBLE The goals of the Open Font License (OFL) are to stimulate\nworldwide development of collaborative font projects, to support the font\ncreation efforts of academic and linguistic communities, and to provide\na free and open framework in which fonts may be shared and improved in\npartnership with others.\n\nThe OFL allows the licensed fonts to be used, studied, modified and\nredistributed freely as long as they are not sold by themselves.\nThe fonts, including any derivative works, can be bundled, embedded,\nredistributed and/or sold with any software provided that any reserved\nnames are not used by derivative works.  The fonts and derivatives,\nhowever, cannot be released under any other type of license.  The\nrequirement for fonts to remain under this license does not apply to\nany document created using the fonts or their derivatives.\n\n \n\nDEFINITIONS\n\"Font Software\" refers to the set of files released by the Copyright\nHolder(s) under this license and clearly marked as such.\nThis may include source files, build scripts and documentation.\n\n\"Reserved Font Name\" refers to any names specified as such after the\ncopyright statement(s).\n\n\"Original Version\" refers to the collection of Font Software components\nas distributed by the Copyright Holder(s).\n\n\"Modified Version\" refers to any derivative made by adding to, deleting,\nor substituting ? in part or in whole ?\nany of the components of the Original Version, by changing formats or\nby porting the Font Software to a new environment.\n\n\"Author\" refers to any designer, engineer, programmer, technical writer\nor other person who contributed to the Font Software.\n\n\nPERMISSION & CONDITIONS\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of the Font Software, to use, study, copy, merge, embed, modify,\nredistribute, and sell modified and unmodified copies of the Font\nSoftware, subject to the following conditions:\n\n1) Neither the Font Software nor any of its individual components,in\n   Original or Modified Versions, may be sold by itself.\n\n2) Original or Modified Versions of the Font Software may be bundled,\n   redistributed and/or sold with any software, provided that each copy\n   contains the above copyright notice and this license. These can be\n   included either as stand-alone text files, human-readable headers or\n   in the appropriate machine-readable metadata fields within text or\n   binary files as long as those fields can be easily viewed by the user.\n\n3) No Modified Version of the Font Software may use the Reserved Font\n   Name(s) unless explicit written permission is granted by the\n   corresponding Copyright Holder. This restriction only applies to the\n   primary font name as presented to the users.\n\n4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font\n   Software shall not be used to promote, endorse or advertise any\n   Modified Version, except to acknowledge the contribution(s) of the\n   Copyright Holder(s) and the Author(s) or with their explicit written\n   permission.\n\n5) The Font Software, modified or unmodified, in part or in whole, must\n   be distributed entirely under this license, and must not be distributed\n   under any other license. The requirement for fonts to remain under\n   this license does not apply to any document created using the Font\n   Software.\n\n\n \nTERMINATION\nThis license becomes null and void if any of the above conditions are not met.\n\n \n\nDISCLAIMER\nTHE FONT SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT\nOF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT.  IN NO EVENT SHALL THE\nCOPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nINCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL\nDAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER\nDEALINGS IN THE FONT SOFTWARE.\n\n"
  },
  {
    "path": "src/shell/liberation-fonts/README",
    "content": "   1. What's this?\n  =================\n\n  The Liberation Fonts is font collection which aims to provide document \n  layout compatibility as usage of Times New Roman, Arial, Courier New.\n\n\n   2. Requirements\n  =================\n\n  * fontforge is installed.\n    (http://fontforge.sourceforge.net)\n\n\n   3. Install\n  ============\n\n  3.1 Decompress tarball\n\n    You can extract the files by following command:\n\n      $ tar zxvf liberation-fonts-[VERSION].tar.gz\n\n  3.2 Build from the source\n\n    Change into directory liberation-fonts-[VERSION]/ and build from sources by \n    following commands:\n\n      $ cd liberation-fonts-[VERSION]\n      $ make\n\n    The built font files will be available in 'build' directory.\n\n  3.3 Install to system\n\n    For Fedora, you could manually install the fonts by copying the TTFs to \n    ~/.fonts for user wide usage, or to /usr/share/fonts/truetype/liberation \n    for system-wide availability. Then, run \"fc-cache\" to let that cached.\n\n    For other distributions, please check out corresponding documentation.\n\n\n   4. Usage\n  ==========\n\n  Simply select preferred liberation font in applications and start using.\n\n\n   5. License\n  ============\n\n  This Font Software is licensed under the SIL Open Font License,\n  Version 1.1.\n\n  Please read file \"LICENSE\" for details.\n\n\n   6. For Maintainers\n  ====================\n\n  Before packaging a new release based on a new source tarball, you have to\n  update the version suffix in the Makefile:\n\n    VER = [VERSION]\n\n  Make sure that the defined version corresponds to the font software metadata\n  which you can check with ftinfo/otfinfo or fontforge itself. It is highly \n  recommended that file 'ChangeLog' is updated to reflect changes.\n\n  Create a tarball with the following command:\n\n    $ make dist\n\n  The new versioned tarball will be available in the dist/ folder as\n  'liberation-fonts-[NEW_VERSION].tar.gz'.\n\n  7. Credits\n ============\n\n  Please read file \"AUTHORS\" for list of contributors.\n"
  },
  {
    "path": "src/shell/liberation-fonts/TODO",
    "content": "Here are todo for next release\n1) Serbian glyph for wikipedia https://bugzilla.redhat.com/show_bug.cgi?id=657849\n\t- Improving shape of S_BE https://bugzilla.redhat.com/show_bug.cgi?id=657849#c96\n2) Liberation Mono not recognizing as Mono in Windows application #861003\n\t- presently it is patch, we have to update zero width characters to fixed width\n"
  },
  {
    "path": "src/shell/linux_specific.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#include \"platform_specific.h\"\n\n#include <common/log.h>\n#include <exception>\n\n#include <iostream>\n\n#include <X11/Xlib.h>\n\nnamespace caspar {\n\nvoid setup_prerequisites()\n{\n    // Enable utf8 console input and output\n    std::wcout.sync_with_stdio(false);\n    std::wcout.imbue(std::locale(\"\"));\n    std::wcin.imbue(std::locale(\"\"));\n\n    XInitThreads();\n\n    std::set_terminate([] { CASPAR_LOG_CURRENT_EXCEPTION(); });\n}\n\nvoid setup_console_window()\n{\n    // TODO: implement.\n}\n\nvoid increase_process_priority()\n{\n    // TODO: implement.\n}\n\nvoid wait_for_keypress()\n{\n    // TODO: implement if desirable.\n}\n\nstd::shared_ptr<void> setup_debugging_environment()\n{\n    // TODO: implement if applicable.\n    return nullptr;\n}\n\nvoid wait_for_remote_debugging()\n{\n    // TODO: implement if applicable.\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/shell/main.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n// tbbmalloc_proxy:\n// Replace the standard memory allocation routines in Microsoft* C/C++ RTL\n// (malloc/free, global new/delete, etc.) with the TBB memory allocator\n// as the default allocator suffers from low performance.\n\n#if defined _DEBUG && defined _MSC_VER\n#define _CRTDBG_MAP_ALLOC\n#include <crtdbg.h>\n#include <stdlib.h>\n#elif defined _MSC_VER\n#include <tbb/tbbmalloc_proxy.h>\n#endif\n\n#include \"included_modules.h\"\n#include \"platform_specific.h\"\n#include \"server.h\"\n\n#include <protocol/amcp/AMCPProtocolStrategy.h>\n#include <protocol/util/strategy_adapters.h>\n\n#include <common/env.h>\n#include <common/except.h>\n#include <common/log.h>\n#include <common/ptree.h>\n\n#include <boost/algorithm/string/predicate.hpp>\n#include <boost/algorithm/string/split.hpp>\n#include <boost/asio.hpp>\n#include <boost/filesystem.hpp>\n#include <boost/locale.hpp>\n#include <boost/property_tree/detail/file_parser_error.hpp>\n#include <boost/property_tree/xml_parser.hpp>\n#include <boost/stacktrace.hpp>\n\n#include <atomic>\n#include <thread>\n\n#include <clocale>\n#include <csignal>\n\nnamespace caspar {\n\nvoid setup_global_locale()\n{\n    boost::locale::generator gen;\n    gen.categories(boost::locale::category_t::codepage);\n\n    std::locale::global(gen(\"\"));\n\n    // sscanf is used in for example FFmpeg where we want decimals to be parsed as .\n    std::setlocale(LC_ALL, \"C\");\n}\n\nvoid print_info()\n{\n    CASPAR_LOG(info) << L\"############################################################################\";\n    CASPAR_LOG(info) << L\"CasparCG Server is distributed by the Swedish Broadcasting Corporation (SVT)\";\n    CASPAR_LOG(info) << L\"under the GNU General Public License GPLv3 or higher.\";\n    CASPAR_LOG(info) << L\"Please see LICENSE.TXT for details.\";\n    CASPAR_LOG(info) << L\"http://www.casparcg.com/\";\n    CASPAR_LOG(info) << L\"############################################################################\";\n    CASPAR_LOG(info) << L\"Starting CasparCG Video and Graphics Playout Server \" << env::version();\n}\n\nauto run(const std::wstring& config_file_name, std::atomic<bool>& should_wait_for_keypress)\n{\n    boost::asio::io_context io;\n\n    auto restart  = false;\n    auto shutdown = [&](bool restart_) {\n        restart = restart_;\n        io.stop();\n    };\n\n    print_info();\n\n    // Create server object which initializes channels, protocols and controllers.\n    std::unique_ptr<server> caspar_server(new server(shutdown));\n\n    // For example CEF resets the global locale, so this is to reset it back to \"our\" preference.\n    setup_global_locale();\n\n    std::wstringstream                                      str;\n    boost::property_tree::xml_writer_settings<std::wstring> w(' ', 3);\n    boost::property_tree::write_xml(str, env::properties(), w);\n    CASPAR_LOG(info) << boost::filesystem::absolute(config_file_name).lexically_normal()\n                     << L\":\\n-----------------------------------------\\n\"\n                     << str.str() << L\"-----------------------------------------\";\n\n    caspar_server->start();\n\n    // Create a dummy client which prints amcp responses to console.\n    auto console_client = spl::make_shared<IO::ConsoleClientInfo>();\n\n    auto amcp =\n        protocol::amcp::create_wchar_amcp_strategy_factory(L\"Console\", caspar_server->get_amcp_command_repository())\n            ->create(console_client);\n\n    // Use separate thread for the blocking console input, will be terminated\n    // anyway when the main thread terminates.\n\n    std::thread([&]() mutable {\n        std::wstring wcmd;\n        while (true) {\n#ifdef WIN32\n            if (!std::getline(std::wcin, wcmd)) { // TODO: It's blocking...\n                std::wcin.clear();\n                continue;\n            }\n#else\n            // Linux gets stuck in an endless loop if wcin gets a multibyte utf8 char\n            std::string cmd1;\n            if (!std::getline(std::cin, cmd1)) { // TODO: It's blocking...\n                if (std::cin.eof()) {\n                    std::cin.clear();\n                    break;\n                }\n                std::cin.clear();\n                continue;\n            }\n            wcmd = u16(cmd1);\n#endif\n\n            // If the cmd is empty, no point trying to parse it\n            if (!wcmd.empty()) {\n                if (boost::iequals(wcmd, L\"EXIT\") || boost::iequals(wcmd, L\"Q\") || boost::iequals(wcmd, L\"QUIT\") ||\n                    boost::iequals(wcmd, L\"BYE\")) {\n                    CASPAR_LOG(info) << L\"Received message from Console: \" << wcmd << L\"\\\\r\\\\n\";\n                    should_wait_for_keypress = true;\n                    shutdown(false); // false to not restart\n                    break;\n                }\n\n                wcmd += L\"\\r\\n\";\n                amcp->parse(wcmd);\n            }\n        }\n    }).detach();\n\n    // Signal handlers needs to be installed after Cef has been initialized.\n    boost::asio::signal_set signals(io, SIGINT, SIGTERM);\n    signals.async_wait([&](auto, auto) { io.stop(); });\n\n    io.run();\n\n    caspar_server.reset();\n\n    return restart;\n}\n\nvoid signal_handler(int signum)\n{\n    ::signal(signum, SIG_DFL);\n    boost::stacktrace::safe_dump_to(\"./backtrace.dump\");\n    ::raise(SIGABRT);\n}\n\nvoid terminate_handler()\n{\n    try {\n        std::rethrow_exception(std::current_exception());\n    } catch (...) {\n        CASPAR_LOG_CURRENT_EXCEPTION();\n    }\n    std::abort();\n}\n\n} // namespace caspar\n\nint main(int argc, char** argv)\n{\n    using namespace caspar;\n\n    if (intercept_command_line_args(argc, argv))\n        return 0;\n\n    ::signal(SIGSEGV, signal_handler);\n    ::signal(SIGABRT, signal_handler);\n    std::set_terminate(caspar::terminate_handler);\n\n    static auto backtrace = \"./backtrace.dump\";\n    if (boost::filesystem::exists(backtrace)) {\n        std::ifstream     ifs(backtrace);\n        std::stringstream str;\n        str << boost::stacktrace::stacktrace::from_dump(ifs);\n        CASPAR_LOG(error) << u16(str.str());\n        ifs.close();\n        boost::filesystem::remove(backtrace);\n    }\n\n    int return_code = 0;\n    setup_prerequisites();\n\n    setup_global_locale();\n\n    std::wcout << L\"Type \\\"q\\\" to close application.\" << std::endl;\n\n    // Set debug mode.\n    auto debugging_environment = setup_debugging_environment();\n\n    // Increase process priority.\n    increase_process_priority();\n\n    std::wstring config_file_name(L\"casparcg.config\");\n\n    try {\n        // Configure environment properties from configuration.\n        if (argc >= 2)\n            config_file_name = caspar::u16(argv[1]);\n\n        log::add_cout_sink();\n        env::configure(config_file_name);\n\n        log::set_log_column_alignment(env::properties().get(L\"configuration.log-align-columns\", true));\n\n        {\n            std::wstring target_level = env::properties().get(L\"configuration.log-level\", L\"info\");\n            if (!log::set_log_level(target_level)) {\n                log::set_log_level(L\"info\");\n                std::wcout << L\"Failed to set log level [\" << target_level << L\"]\" << std::endl;\n            }\n        }\n\n        if (env::properties().get(L\"configuration.debugging.remote\", false))\n            wait_for_remote_debugging();\n\n        // Start logging to file.\n        if (env::log_to_file()) {\n            log::add_file_sink(env::log_folder() + L\"caspar\");\n            std::wcout << L\"Logging [\" << log::get_log_level() << L\"] or higher severity to \" << env::log_folder()\n                       << std::endl\n                       << std::endl;\n        } else {\n            std::wcout << L\"Logging [\" << log::get_log_level() << L\"] or higher severity to console\" << std::endl\n                       << std::endl;\n        }\n\n        // Once logging to file, log configuration warnings.\n        env::log_configuration_warnings();\n\n        // Setup console window.\n        setup_console_window();\n\n        std::atomic<bool> should_wait_for_keypress;\n        should_wait_for_keypress = false;\n        auto should_restart      = run(config_file_name, should_wait_for_keypress);\n        return_code              = should_restart ? 5 : 0;\n\n        CASPAR_LOG(info) << \"Successfully shutdown CasparCG Server.\";\n\n        if (should_wait_for_keypress)\n            wait_for_keypress();\n    } catch (caspar::ptree_exception& e) {\n        auto info = boost::get_error_info<caspar::msg_info_t>(e);\n        if (info) {\n            CASPAR_LOG(fatal) << *info << \". Please check the configuration file (\" << u8(config_file_name)\n                              << \") for errors.\";\n        } else {\n            CASPAR_LOG(fatal) << \"Please check the configuration file (\" << u8(config_file_name) << \") for errors.\";\n            CASPAR_LOG_CURRENT_EXCEPTION();\n        }\n        wait_for_keypress();\n    } catch (boost::property_tree::file_parser_error& e) {\n        CASPAR_LOG(fatal) << \"At \" << u8(config_file_name) << \":\" << e.line() << \": \" << e.message()\n                          << \". Please check the configuration file (\" << u8(config_file_name) << \") for errors.\";\n        wait_for_keypress();\n    } catch (expected_user_error&) {\n        CASPAR_LOG(fatal) << \" Please check the configuration file (\" << u8(config_file_name) << \") for errors.\";\n        wait_for_keypress();\n    } catch (user_error&) {\n        CASPAR_LOG_CURRENT_EXCEPTION();\n        CASPAR_LOG(fatal) << \" Please check the configuration file (\" << u8(config_file_name) << \") for errors.\";\n        wait_for_keypress();\n    } catch (...) {\n        CASPAR_LOG_CURRENT_EXCEPTION();\n        CASPAR_LOG(fatal) << L\"Unhandled exception in main thread. Please report this error on the GitHub project page \"\n                             L\"(www.github.com/casparcg/server/issues).\";\n        std::this_thread::sleep_for(std::chrono::milliseconds(1000));\n        std::wcout << L\"\\n\\nCasparCG will automatically shutdown. See the log file located at the configured log-file \"\n                      L\"folder for more information.\\n\\n\";\n        std::this_thread::sleep_for(std::chrono::milliseconds(4000));\n    }\n\n    boost::log::core::get()->flush();\n\n    return return_code;\n}\n"
  },
  {
    "path": "src/shell/platform_specific.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Helge Norberg, helge.norberg@svt.se\n */\n\n#pragma once\n\n#include <memory>\n\nnamespace caspar {\n\nvoid                  setup_prerequisites();\nvoid                  setup_console_window();\nvoid                  increase_process_priority();\nvoid                  wait_for_keypress();\nstd::shared_ptr<void> setup_debugging_environment();\nvoid                  wait_for_remote_debugging();\n\n} // namespace caspar\n"
  },
  {
    "path": "src/shell/run.sh",
    "content": "#!/bin/sh\n\nRET=5\n\nwhile [ $RET -eq 5 ]\ndo\n  LD_LIBRARY_PATH=lib bin/casparcg \"$@\"\n  RET=$?\ndone\n\n"
  },
  {
    "path": "src/shell/server.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"included_modules.h\"\n\n#include \"server.h\"\n\n#include <accelerator/accelerator.h>\n\n#include <common/bit_depth.h>\n#include <common/env.h>\n#include <common/except.h>\n#include <common/memory.h>\n#include <common/ptree.h>\n#include <common/utf.h>\n\n#include <core/consumer/output.h>\n#include <core/diagnostics/call_context.h>\n#include <core/diagnostics/osd_graph.h>\n#include <core/frame/pixel_format.h>\n#include <core/mixer/image/image_mixer.h>\n#include <core/producer/cg_proxy.h>\n#include <core/producer/color/color_producer.h>\n#include <core/producer/frame_producer.h>\n#include <core/video_channel.h>\n#include <core/video_format.h>\n\n#include <modules/image/consumer/image_consumer.h>\n\n#include <protocol/amcp/AMCPCommandsImpl.h>\n#include <protocol/amcp/AMCPProtocolStrategy.h>\n#include <protocol/amcp/amcp_command_repository.h>\n#include <protocol/amcp/amcp_shared.h>\n#include <protocol/osc/client.h>\n#include <protocol/util/AsyncEventServer.h>\n#include <protocol/util/strategy_adapters.h>\n#include <protocol/util/tokenize.h>\n\n#include <boost/algorithm/string.hpp>\n#include <boost/asio.hpp>\n#include <boost/format.hpp>\n#include <boost/property_tree/ptree.hpp>\n\n#include <thread>\n#include <utility>\n\nnamespace caspar {\nusing namespace core;\nusing namespace protocol;\n\nstd::shared_ptr<boost::asio::io_context> create_io_context_with_running_service()\n{\n    auto io_context = std::make_shared<boost::asio::io_context>();\n    // To keep the io_context::run() running although no pending async\n    // operations are posted.\n    auto work = std::make_shared<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(\n        boost::asio::make_work_guard(*io_context));\n    auto weak_work = std::weak_ptr<boost::asio::executor_work_guard<boost::asio::io_context::executor_type>>(work);\n    auto thread    = std::make_shared<std::thread>([io_context, weak_work] {\n        while (auto strong = weak_work.lock()) {\n            try {\n                io_context->run();\n            } catch (...) {\n                CASPAR_LOG_CURRENT_EXCEPTION();\n            }\n        }\n\n        CASPAR_LOG(info) << \"[asio] Global io_context uninitialized.\";\n    });\n\n    return std::shared_ptr<boost::asio::io_context>(io_context.get(), [io_context, work, thread](void*) mutable {\n        CASPAR_LOG(info) << \"[asio] Shutting down global io_context.\";\n        work.reset();\n        io_context->stop();\n        if (thread->get_id() != std::this_thread::get_id())\n            thread->join();\n        else\n            thread->detach();\n    });\n}\n\nstruct server::impl\n{\n    std::shared_ptr<boost::asio::io_context>               io_context_ = create_io_context_with_running_service();\n    video_format_repository                                video_format_repository_;\n    accelerator::accelerator                               accelerator_;\n    std::shared_ptr<amcp::amcp_command_repository>         amcp_command_repo_;\n    std::shared_ptr<amcp::amcp_command_repository_wrapper> amcp_command_repo_wrapper_;\n    std::shared_ptr<amcp::command_context_factory>         amcp_context_factory_;\n    std::vector<spl::shared_ptr<IO::AsyncEventServer>>     async_servers_;\n    std::shared_ptr<IO::AsyncEventServer>                  primary_amcp_server_;\n    std::shared_ptr<osc::client>                           osc_client_ = std::make_shared<osc::client>(io_context_);\n    std::vector<std::shared_ptr<void>>                     predefined_osc_subscriptions_;\n    spl::shared_ptr<std::vector<protocol::amcp::channel_context>> channels_;\n    spl::shared_ptr<core::cg_producer_registry>                   cg_registry_;\n    spl::shared_ptr<core::frame_producer_registry>                producer_registry_;\n    spl::shared_ptr<core::frame_consumer_registry>                consumer_registry_;\n    std::function<void(bool)>                                     shutdown_server_now_;\n\n    impl(const impl&)            = delete;\n    impl& operator=(const impl&) = delete;\n\n    explicit impl(std::function<void(bool)> shutdown_server_now)\n        : video_format_repository_()\n        , accelerator_(video_format_repository_)\n        , producer_registry_(spl::make_shared<core::frame_producer_registry>())\n        , consumer_registry_(spl::make_shared<core::frame_consumer_registry>())\n        , shutdown_server_now_(std::move(shutdown_server_now))\n    {\n        caspar::core::diagnostics::osd::register_sink();\n    }\n\n    void start()\n    {\n        setup_video_modes(env::properties());\n        CASPAR_LOG(info) << L\"Initialized video modes.\";\n\n        setup_accelerator(env::properties());\n        CASPAR_LOG(info) << L\"Initialized accelerator.\";\n\n        auto xml_channels = setup_channels(env::properties());\n        CASPAR_LOG(info) << L\"Initialized channels.\";\n\n        setup_amcp_command_repo();\n        CASPAR_LOG(info) << L\"Initialized command repository.\";\n\n        module_dependencies dependencies(\n            cg_registry_, producer_registry_, consumer_registry_, amcp_command_repo_wrapper_);\n        initialize_modules(dependencies);\n        CASPAR_LOG(info) << L\"Initialized modules.\";\n\n        setup_channel_producers_and_consumers(xml_channels);\n        CASPAR_LOG(info) << L\"Initialized startup producers.\";\n\n        setup_controllers(env::properties());\n        CASPAR_LOG(info) << L\"Initialized controllers.\";\n\n        setup_osc(env::properties());\n        CASPAR_LOG(info) << L\"Initialized osc.\";\n    }\n\n    ~impl()\n    {\n        std::weak_ptr<boost::asio::io_context> weak_io_context = io_context_;\n        io_context_.reset();\n        predefined_osc_subscriptions_.clear();\n        osc_client_.reset();\n\n        amcp_command_repo_wrapper_.reset();\n        amcp_command_repo_.reset();\n        amcp_context_factory_.reset();\n\n        primary_amcp_server_.reset();\n        async_servers_.clear();\n\n        destroy_producers_synchronously();\n        destroy_consumers_synchronously();\n        channels_->clear();\n\n        while (weak_io_context.lock())\n            std::this_thread::sleep_for(std::chrono::milliseconds(100));\n\n        uninitialize_modules();\n        core::diagnostics::osd::shutdown();\n    }\n\n    void setup_video_modes(const boost::property_tree::wptree& pt)\n    {\n        using boost::property_tree::wptree;\n\n        auto videomodes_config = pt.get_child_optional(L\"configuration.video-modes\");\n        if (videomodes_config) {\n            for (auto& xml_channel :\n                 pt | witerate_children(L\"configuration.video-modes\") | welement_context_iteration) {\n                ptree_verify_element_name(xml_channel, L\"video-mode\");\n\n                const std::wstring id = xml_channel.second.get(L\"id\", L\"\");\n                if (id == L\"\")\n                    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid video-mode id: \" + id));\n\n                const int width  = xml_channel.second.get<int>(L\"width\", 0);\n                const int height = xml_channel.second.get<int>(L\"height\", 0);\n                if (width == 0 || height == 0)\n                    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid dimensions: \" +\n                                                                    boost::lexical_cast<std::wstring>(width) + L\"x\" +\n                                                                    boost::lexical_cast<std::wstring>(height)));\n\n                const int field_count = xml_channel.second.get<int>(L\"field-count\", 1);\n                if (field_count != 1 && field_count != 2)\n                    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid field-count: \" +\n                                                                    boost::lexical_cast<std::wstring>(field_count)));\n\n                const int timescale = xml_channel.second.get<int>(L\"time-scale\", 60000);\n                const int duration  = xml_channel.second.get<int>(L\"duration\", 1000);\n                if (timescale == 0 || duration == 0)\n                    CASPAR_THROW_EXCEPTION(\n                        user_error() << msg_info(L\"Invalid framerate: \" + boost::lexical_cast<std::wstring>(timescale) +\n                                                 L\"/\" + boost::lexical_cast<std::wstring>(duration)));\n\n                std::vector<int> cadence;\n                int              cadence_sum = 0;\n\n                const std::wstring      cadence_str = xml_channel.second.get(L\"cadence\", L\"\");\n                std::list<std::wstring> cadence_parts;\n                boost::split(cadence_parts, cadence_str, boost::is_any_of(L\", \"));\n\n                for (auto& cad : cadence_parts) {\n                    if (cad.empty())\n                        continue;\n\n                    const int c = std::stoi(cad);\n                    cadence.push_back(c);\n                    cadence_sum += c;\n                }\n\n                if (cadence.empty()) {\n                    // Attempt to calculate in the cadence for integer formats\n                    const int c = static_cast<int>(48000 / (static_cast<double>(timescale) / duration) + 0.5);\n                    cadence.push_back(c);\n                    cadence_sum += c;\n                }\n\n                if (cadence_sum * timescale != 48000 * duration * cadence.size()) {\n                    auto samples_per_second =\n                        static_cast<double>(cadence_sum * timescale) / (duration * cadence.size());\n                    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Incorrect cadence in video-mode \" + id +\n                                                                    L\". Got \" + std::to_wstring(samples_per_second) +\n                                                                    L\" samples per second, expected 48000\"));\n                }\n\n                const auto new_format = video_format_desc(\n                    video_format::custom, field_count, width, height, width, height, timescale, duration, id, cadence);\n\n                const auto existing = video_format_repository_.find(id);\n                if (existing.format != video_format::invalid)\n                    CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Video-mode already exists: \" + id));\n\n                video_format_repository_.store(new_format);\n            }\n        }\n    }\n\n    void setup_accelerator(const boost::property_tree::wptree& pt)\n    {\n        using boost::property_tree::wptree;\n        using namespace boost::asio::ip;\n\n#ifdef ENABLE_VULKAN\n        caspar::accelerator::accelerator_backend backend = caspar::accelerator::accelerator_backend::invalid;\n        auto accelerator = boost::to_lower_copy(pt.get(L\"configuration.accelerator\", L\"auto\"));\n        if (accelerator == L\"auto\") {\n            backend = caspar::accelerator::accelerator_backend::opengl;\n        } else if (accelerator == L\"opengl\") {\n            backend = caspar::accelerator::accelerator_backend::opengl;\n        } else if (accelerator == L\"vulkan\") {\n            backend = caspar::accelerator::accelerator_backend::vulkan;\n        } else {\n            CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid accelerator: \" + accelerator));\n        }\n#else\n        caspar::accelerator::accelerator_backend backend = caspar::accelerator::accelerator_backend::opengl;\n#endif\n\n        accelerator_.set_backend(backend);\n    }\n\n    std::vector<boost::property_tree::wptree> setup_channels(const boost::property_tree::wptree& pt)\n    {\n        using boost::property_tree::wptree;\n\n        std::vector<wptree> xml_channels;\n\n        for (auto& xml_channel : pt | witerate_children(L\"configuration.channels\") | welement_context_iteration) {\n            xml_channels.push_back(xml_channel.second);\n            ptree_verify_element_name(xml_channel, L\"channel\");\n\n            auto format_desc_str = xml_channel.second.get(L\"video-mode\", L\"PAL\");\n            auto format_desc     = video_format_repository_.find(format_desc_str);\n            auto color_depth     = xml_channel.second.get<unsigned char>(L\"color-depth\", 8);\n            if (color_depth != 8 && color_depth != 16)\n                CASPAR_THROW_EXCEPTION(user_error()\n                                       << msg_info(L\"Invalid color-depth: \" + std::to_wstring(color_depth)));\n\n            auto color_space_str = boost::to_lower_copy(xml_channel.second.get(L\"color-space\", L\"bt709\"));\n            if (color_space_str != L\"bt709\" && color_space_str != L\"bt2020\")\n                CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid color-space, must be bt709 or bt2020\"));\n\n            if (format_desc.format == video_format::invalid)\n                CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid video-mode: \" + format_desc_str));\n\n            auto weak_client = std::weak_ptr<osc::client>(osc_client_);\n            auto channel_id  = static_cast<int>(channels_->size() + 1);\n            auto depth       = color_depth == 16 ? common::bit_depth::bit16 : common::bit_depth::bit8;\n            auto default_color_space =\n                color_space_str == L\"bt2020\" ? core::color_space::bt2020 : core::color_space::bt709;\n            auto channel =\n                spl::make_shared<video_channel>(channel_id,\n                                                format_desc,\n                                                default_color_space,\n                                                accelerator_.create_image_mixer(channel_id, depth),\n                                                [channel_id, weak_client](core::monitor::state channel_state) {\n                                                    monitor::state state;\n                                                    state[\"\"][\"channel\"][channel_id] = channel_state;\n                                                    auto client                      = weak_client.lock();\n                                                    if (client) {\n                                                        client->send(std::move(state));\n                                                    }\n                                                });\n\n            const std::wstring lifecycle_key = L\"lock\" + std::to_wstring(channel_id);\n            channels_->emplace_back(channel, channel->stage(), lifecycle_key);\n        }\n\n        return xml_channels;\n    }\n\n    void setup_osc(const boost::property_tree::wptree& pt)\n    {\n        using boost::property_tree::wptree;\n        using namespace boost::asio::ip;\n\n        auto default_port                 = pt.get<unsigned short>(L\"configuration.osc.default-port\", 6250);\n        auto disable_send_to_amcp_clients = pt.get(L\"configuration.osc.disable-send-to-amcp-clients\", false);\n        auto predefined_clients           = pt.get_child_optional(L\"configuration.osc.predefined-clients\");\n\n        if (predefined_clients) {\n            for (auto& predefined_client :\n                 pt | witerate_children(L\"configuration.osc.predefined-clients\") | welement_context_iteration) {\n                ptree_verify_element_name(predefined_client, L\"predefined-client\");\n\n                const auto address = ptree_get<std::wstring>(predefined_client.second, L\"address\");\n                const auto port    = ptree_get<unsigned short>(predefined_client.second, L\"port\");\n\n                boost::system::error_code ec;\n                auto                      ipaddr = make_address_v4(u8(address), ec);\n                if (!ec)\n                    predefined_osc_subscriptions_.push_back(\n                        osc_client_->get_subscription_token(udp::endpoint(ipaddr, port)));\n                else\n                    CASPAR_LOG(warning) << \"Invalid OSC client. Must be valid ipv4 address: \" << address;\n            }\n        }\n\n        if (!disable_send_to_amcp_clients && primary_amcp_server_)\n            primary_amcp_server_->add_client_lifecycle_object_factory(\n                [=, this](const std::string& ipv4_address) -> std::pair<std::wstring, std::shared_ptr<void>> {\n                    using namespace boost::asio::ip;\n\n                    return std::make_pair(std::wstring(L\"osc_subscribe\"),\n                                          osc_client_->get_subscription_token(\n                                              udp::endpoint(make_address_v4(ipv4_address), default_port)));\n                });\n    }\n\n    void setup_channel_producers_and_consumers(const std::vector<boost::property_tree::wptree>& xml_channels)\n    {\n        auto console_client = spl::make_shared<IO::ConsoleClientInfo>();\n\n        std::vector<spl::shared_ptr<core::video_channel>> channels_vec;\n        for (auto& cc : *channels_) {\n            channels_vec.emplace_back(cc.raw_channel);\n        }\n\n        for (auto& channel : *channels_) {\n            core::diagnostics::scoped_call_context save;\n            core::diagnostics::call_context::for_thread().video_channel = channel.raw_channel->index();\n\n            auto xml_channel = xml_channels.at(channel.raw_channel->index() - 1);\n\n            // Consumers\n            if (xml_channel.get_child_optional(L\"consumers\")) {\n                for (auto& xml_consumer : xml_channel | witerate_children(L\"consumers\") | welement_context_iteration) {\n                    auto name = xml_consumer.first;\n\n                    try {\n                        if (name != L\"<xmlcomment>\")\n                            channel.raw_channel->output().add(\n                                consumer_registry_->create_consumer(name,\n                                                                    xml_consumer.second,\n                                                                    video_format_repository_,\n                                                                    channels_vec,\n                                                                    channel.raw_channel->get_consumer_channel_info()));\n                    } catch (...) {\n                        CASPAR_LOG_CURRENT_EXCEPTION();\n                    }\n                }\n            }\n\n            // Producers\n            if (xml_channel.get_child_optional(L\"producers\")) {\n                for (auto& xml_producer : xml_channel | witerate_children(L\"producers\") | welement_context_iteration) {\n                    ptree_verify_element_name(xml_producer, L\"producer\");\n\n                    const std::wstring command = xml_producer.second.get_value(L\"\");\n                    const auto         attrs   = xml_producer.second.get_child(L\"<xmlattr>\");\n                    const int          id      = attrs.get(L\"id\", -1);\n\n                    try {\n                        std::list<std::wstring> tokens{\n                            L\"PLAY\", (boost::wformat(L\"%i-%i\") % channel.raw_channel->index() % id).str()};\n                        IO::tokenize(command, tokens);\n                        auto cmd = amcp_command_repo_->parse_command(console_client, tokens, L\"\");\n\n                        if (cmd) {\n                            std::wstring res = cmd->Execute(channels_).get();\n                            console_client->send(std::move(res), false);\n                        }\n                    } catch (const user_error&) {\n                        CASPAR_LOG(error) << \"Failed to parse command: \" << command;\n                    } catch (...) {\n                        CASPAR_LOG_CURRENT_EXCEPTION();\n                    }\n                }\n            }\n        }\n    }\n\n    void setup_amcp_command_repo()\n    {\n        amcp_command_repo_ = std::make_shared<amcp::amcp_command_repository>(channels_);\n\n        auto accelerator_device = accelerator_.get_device();\n        auto ctx                = std::make_shared<amcp::amcp_command_static_context>(\n            video_format_repository_,\n            cg_registry_,\n            producer_registry_,\n            consumer_registry_,\n            amcp_command_repo_,\n            shutdown_server_now_,\n            u8(caspar::env::properties().get(L\"configuration.amcp.media-server.host\", L\"127.0.0.1\")),\n            u8(caspar::env::properties().get(L\"configuration.amcp.media-server.port\", L\"8000\")),\n            accelerator_device,\n            spl::make_shared_ptr(osc_client_));\n\n        amcp_context_factory_ = std::make_shared<amcp::command_context_factory>(ctx);\n\n        amcp_command_repo_wrapper_ =\n            std::make_shared<amcp::amcp_command_repository_wrapper>(amcp_command_repo_, amcp_context_factory_);\n\n        amcp::register_commands(amcp_command_repo_wrapper_);\n    }\n\n    void setup_controllers(const boost::property_tree::wptree& pt)\n    {\n        using boost::property_tree::wptree;\n        for (auto& xml_controller : pt | witerate_children(L\"configuration.controllers\") | welement_context_iteration) {\n            auto name     = xml_controller.first;\n            auto protocol = ptree_get<std::wstring>(xml_controller.second, L\"protocol\");\n\n            if (name == L\"tcp\") {\n                auto port = ptree_get<unsigned int>(xml_controller.second, L\"port\");\n                std::wstring host_w = xml_controller.second.get(L\"host\", L\"\");\n                auto host_utf8 = u8(host_w);\n\n                try {\n                    auto asyncbootstrapper = spl::make_shared<IO::AsyncEventServer>(\n                        io_context_,\n                        create_protocol(protocol, L\"TCP Port \" + std::to_wstring(port)),\n                        host_utf8,\n                        static_cast<short>(port));\n                    async_servers_.push_back(asyncbootstrapper);\n\n                    if (!primary_amcp_server_ && boost::iequals(protocol, L\"AMCP\"))\n                        primary_amcp_server_ = asyncbootstrapper;\n                } catch (...) {\n                    CASPAR_LOG(fatal) << L\"Failed to setup \" << protocol << L\" controller on port \"\n                                      << boost::lexical_cast<std::wstring>(port) << L\". It is likely already in use\";\n                    throw;\n                    // CASPAR_LOG_CURRENT_EXCEPTION();\n                }\n            } else\n                CASPAR_LOG(warning) << \"Invalid controller: \" << name;\n        }\n    }\n\n    IO::protocol_strategy_factory<char>::ptr create_protocol(const std::wstring& name,\n                                                             const std::wstring& port_description) const\n    {\n        using namespace IO;\n\n        if (boost::iequals(name, L\"AMCP\"))\n            return amcp::create_char_amcp_strategy_factory(port_description, spl::make_shared_ptr(amcp_command_repo_));\n\n        CASPAR_THROW_EXCEPTION(user_error() << msg_info(L\"Invalid protocol: \" + name));\n    }\n};\n\nserver::server(std::function<void(bool)> shutdown_server_now)\n    : impl_(new impl(std::move(shutdown_server_now)))\n{\n}\nvoid                                                     server::start() { impl_->start(); }\nspl::shared_ptr<protocol::amcp::amcp_command_repository> server::get_amcp_command_repository() const\n{\n    return spl::make_shared_ptr(impl_->amcp_command_repo_);\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/shell/server.h",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n\n#pragma once\n\n#include <protocol/amcp/amcp_command_repository.h>\n\n#include <functional>\n#include <memory>\n\nnamespace caspar {\n\nclass server final\n{\n  public:\n    explicit server(std::function<void(bool)> shutdown_server_now);\n    void                                                     start();\n    spl::shared_ptr<protocol::amcp::amcp_command_repository> get_amcp_command_repository() const;\n\n  private:\n    struct impl;\n    std::shared_ptr<impl> impl_;\n\n    server(const server&)            = delete;\n    server& operator=(const server&) = delete;\n};\n\n} // namespace caspar\n"
  },
  {
    "path": "src/shell/shell.rc",
    "content": "// Microsoft Visual C++ generated resource script.\n//\n#include \"resource.h\"\n\n#include \"version.h\"\n\n#define APSTUDIO_READONLY_SYMBOLS\n///////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 2 resource.\n//\n#include \"windows.h\"\n\n///////////////////////////////////\n#undef APSTUDIO_READONLY_SYMBOLS\n\n\n#define QUOTE(str) #str\n#define EXPAND_AND_QUOTE(str) QUOTE(str)\n\n///////////////////////////////////\n// Version\n1 VERSIONINFO\nFILEVERSION CASPAR_GEN, CASPAR_MAJOR, CASPAR_MINOR\nPRODUCTVERSION CASPAR_GEN, CASPAR_MAJOR, CASPAR_MINOR\nFILEFLAGSMASK 0\nFILEOS 0x40000\nBEGIN\n    BLOCK \"StringFileInfo\"\n    BEGIN\n        BLOCK \"040904e4\"\n        BEGIN\n   VALUE \"CompanyName\", \"SVT\"\n   VALUE \"FileDescription\", \"CasparCG video and graphics play-out server.\"\n   VALUE \"FileVersion\", EXPAND_AND_QUOTE(CASPAR_GEN) \".\" EXPAND_AND_QUOTE(CASPAR_MAJOR) \".\" EXPAND_AND_QUOTE(CASPAR_MINOR) \" \" CASPAR_HASH\n   VALUE \"InternalName\", \"\"\n   VALUE \"LegalCopyright\", \"GPLv3\"\n   VALUE \"OriginalFilename\", \"casparcg.exe\"\n   VALUE \"ProductName\", \"CasparCG\"\n   VALUE \"ProductVersion\", EXPAND_AND_QUOTE(CASPAR_GEN) \".\" EXPAND_AND_QUOTE(CASPAR_MAJOR) \".\" EXPAND_AND_QUOTE(CASPAR_MINOR) \" \" CASPAR_HASH\n END\n    END\n    BLOCK \"VarFileInfo\"\n    BEGIN\n        VALUE \"Translation\", 0x409, 1252\n    END\nEND\n\n///////////////////////////////////\n// Swedish (Sweden) resources\n\n#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_SVE)\nLANGUAGE LANG_SWEDISH, SUBLANG_SWEDISH\n\n#ifdef APSTUDIO_INVOKED\n///////////////////////////////////\n//\n// TEXTINCLUDE\n//\n\n1 TEXTINCLUDE\nBEGIN\n    \"resource.h\\0\"\nEND\n\n2 TEXTINCLUDE\nBEGIN\n    \"#include \"\"afxres.h\"\"\\r\\n\"\n    \"\\0\"\nEND\n\n3 TEXTINCLUDE\nBEGIN\n    \"\\r\\n\"\n    \"\\0\"\nEND\n\n#endif    // APSTUDIO_INVOKED\n\n\n///////////////////////////////////\n//\n// Icon\n//\n\n// Icon with lowest ID value placed first to ensure application icon\n// remains consistent on all systems.\nMAINICON            ICON                    \"CasparCG.ico\"\n#endif    // Swedish (Sweden) resources\n///////////////////////////////////\n\n\n\n#ifndef APSTUDIO_INVOKED\n///////////////////////////////////\n//\n// Generated from the TEXTINCLUDE 3 resource.\n//\n\n\n///////////////////////////////////\n#endif    // not APSTUDIO_INVOKED\n"
  },
  {
    "path": "src/shell/windows_specific.cpp",
    "content": "/*\n * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>\n *\n * This file is part of CasparCG (www.casparcg.com).\n *\n * CasparCG 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 * CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n *\n * Author: Robert Nagy, ronag89@gmail.com\n */\n#include \"platform_specific.h\"\n\n#include <common/env.h>\n#include <common/log.h>\n#include <common/os/windows/windows.h>\n\n#include <atlbase.h>\n#include <mmsystem.h>\n#include <winnt.h>\n\n#include <cstdlib>\n#include <sstream>\n#include <thread>\n\n#include <fcntl.h>\n#include <io.h>\n\n// NOTE: This is needed in order to make CComObject work since this is not a real ATL project.\nCComModule                               _AtlModule;\nextern __declspec(selectany) CAtlModule* _pAtlModule = &_AtlModule;\n\nextern \"C\" {\n// Force discrete nVidia GPU\n// (http://developer.download.nvidia.com/devzone/devcenter/gamegraphics/files/OptimusRenderingPolicies.pdf)\n_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;\n// Force discrete AMD GPU (https://community.amd.com/thread/169965 /\n// https://gpuopen.com/amdpowerxpressrequesthighperformance/)\n_declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;\n}\n\nnamespace caspar {\n\nLONG WINAPI UserUnhandledExceptionFilter(EXCEPTION_POINTERS* info)\n{\n    try {\n        CASPAR_LOG(fatal) << L\"#######################\\n UNHANDLED EXCEPTION: \\n\"\n                          << L\"Address:\" << info->ExceptionRecord->ExceptionAddress << L\"\\n\"\n                          << L\"Code:\" << info->ExceptionRecord->ExceptionCode << L\"\\n\"\n                          << L\"Flag:\" << info->ExceptionRecord->ExceptionFlags << L\"\\n\"\n                          << L\"Info:\" << (unsigned __int64)info->ExceptionRecord->ExceptionInformation << L\"\\n\"\n                          << L\"Continuing execution. \\n#######################\";\n\n        CASPAR_LOG_CURRENT_CALL_STACK();\n    } catch (...) {\n    }\n\n    return EXCEPTION_EXECUTE_HANDLER;\n}\n\nvoid setup_prerequisites()\n{\n    // Enable utf8 console input and output\n    _setmode(_fileno(stdout), _O_U8TEXT);\n    _setmode(_fileno(stdin), _O_U16TEXT);\n\n    SetUnhandledExceptionFilter(UserUnhandledExceptionFilter);\n\n    // Increase time precision. This will increase accuracy of function like Sleep(1) from 10 ms to 1 ms.\n    static struct inc_prec\n    {\n        inc_prec() { timeBeginPeriod(1); }\n        ~inc_prec() { timeEndPeriod(1); }\n    } inc_prec;\n}\n\nvoid change_icon(const HICON hNewIcon)\n{\n    auto hMod              = ::LoadLibrary(L\"Kernel32.dll\");\n    using SCI              = DWORD(__stdcall*)(HICON);\n    auto pfnSetConsoleIcon = reinterpret_cast<SCI>(::GetProcAddress(hMod, \"SetConsoleIcon\"));\n    pfnSetConsoleIcon(hNewIcon);\n    ::FreeLibrary(hMod);\n}\n\nvoid setup_console_window()\n{\n    auto  hOut           = GetStdHandle(STD_OUTPUT_HANDLE);\n    auto  hIn            = GetStdHandle(STD_INPUT_HANDLE);\n    DWORD dwPreviousMode = 0;\n\n    if (hIn != INVALID_HANDLE_VALUE && GetConsoleMode(hIn, &dwPreviousMode)) {\n        dwPreviousMode &= ~ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS; // disable quick edit mode\n        dwPreviousMode &= ENABLE_PROCESSED_INPUT | ~ENABLE_MOUSE_INPUT;    // allow mouse wheel scrolling\n        SetConsoleMode(hIn, dwPreviousMode);\n    }\n\n    // Disable close button in console to avoid shutdown without cleanup.\n    EnableMenuItem(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_GRAYED);\n    DrawMenuBar(GetConsoleWindow());\n    SetConsoleCtrlHandler(nullptr, true);\n\n    if (hOut != INVALID_HANDLE_VALUE) {\n        // Configure console size and position.\n        auto coord = GetLargestConsoleWindowSize(hOut);\n        coord.X /= 2;\n        coord.Y *= 10;\n        SetConsoleScreenBufferSize(hOut, coord);\n\n        SMALL_RECT DisplayArea = {0, 0, 0, 0};\n        DisplayArea.Right      = coord.X - 1;\n        DisplayArea.Bottom     = (coord.Y / 10 - 1) / 2;\n        SetConsoleWindowInfo(hOut, TRUE, &DisplayArea);\n    }\n\n    change_icon(::LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(101)));\n\n    // Set console title.\n    std::wstringstream str;\n    str << \"CasparCG Server \" << env::version() << L\" x64 \";\n#ifdef COMPILE_RELEASE\n    str << \" Release\";\n#elif COMPILE_PROFILE\n    str << \" Profile\";\n#elif COMPILE_DEVELOP\n    str << \" Develop\";\n#elif COMPILE_DEBUG\n    str << \" Debug\";\n#endif\n    SetConsoleTitle(str.str().c_str());\n}\n\nvoid increase_process_priority() { SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); }\n\nvoid wait_for_keypress()\n{\n    std::this_thread::sleep_for(std::chrono::milliseconds(200));\n    std::system(\"pause\");\n}\n\nstd::shared_ptr<void> setup_debugging_environment()\n{\n#ifdef _DEBUG\n    HANDLE hLogFile = CreateFile(\n        L\"crt_log.txt\", GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);\n    std::shared_ptr<void> crt_log(nullptr, [](HANDLE h) { ::CloseHandle(h); });\n\n    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);\n    _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);\n    _CrtSetReportFile(_CRT_WARN, hLogFile);\n    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);\n    _CrtSetReportFile(_CRT_ERROR, hLogFile);\n    _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);\n    _CrtSetReportFile(_CRT_ASSERT, hLogFile);\n\n    return crt_log;\n#else\n    return nullptr;\n#endif\n}\n\nvoid wait_for_remote_debugging()\n{\n#ifdef _DEBUG\n    MessageBox(nullptr, L\"Now is the time to connect for remote debugging...\", L\"Debug\", MB_OK | MB_TOPMOST);\n#endif\n}\n\n} // namespace caspar\n"
  },
  {
    "path": "src/tools/CMakeLists.txt",
    "content": "cmake_minimum_required (VERSION 3.28)\n\nadd_executable(bin2c bin2c.cpp)\ntarget_compile_features(bin2c PRIVATE cxx_std_20)\n\ntarget_include_directories(bin2c PRIVATE ..)\n\nfunction(bin2c source_file dest_file namespace obj_name)\n    ADD_CUSTOM_COMMAND(\n        OUTPUT ${dest_file}\n        COMMAND bin2c ${namespace} ${obj_name} ${CMAKE_CURRENT_SOURCE_DIR}/${source_file} > ${CMAKE_CURRENT_BINARY_DIR}/${dest_file}\n        DEPENDS bin2c ${CMAKE_CURRENT_SOURCE_DIR}/${source_file}\n    )\nendfunction()\n"
  },
  {
    "path": "src/tools/bin2c.cpp",
    "content": "#include <assert.h>\n#include <cerrno>\n#include <stdio.h>\n#include <string.h>\n\nint main(int argc, char** argv)\n{\n    if (argc != 4) {\n        fprintf(stderr, \"Usage: %s \\\"namespace\\\" \\\"constant_name\\\" \\\"input_filename\\\"\\n\", argv[0]);\n        return -1;\n    }\n    char* fn = argv[3];\n    FILE* f  = fopen(fn, \"rb\");\n\n    if (f == nullptr) {\n        fprintf(stderr, \"Error opening file: %s\\n\", strerror(errno));\n        return -1;\n    }\n\n    int   count = 0;\n    char* pch   = strtok(argv[1], \"::\");\n    while (pch != nullptr) {\n        printf(\"namespace %s {\\n\", pch);\n        pch = strtok(nullptr, \"::\");\n        count++;\n    }\n\n    printf(\"const uint8_t %s[] = {\\n\", argv[2]);\n    unsigned long n = 0;\n    while (!feof(f)) {\n        unsigned char c;\n        if (fread(&c, 1, 1, f) == 0)\n            break;\n        printf(\"0x%.2X,\", (int)c);\n        ++n;\n        if (n % 10 == 0)\n            printf(\"\\n\");\n    }\n    fclose(f);\n    printf(\"0x00\\n};\\n\");\n\n    for (int i = 0; i < count; i++)\n        printf(\"}\\n\");\n\n    return 0;\n}\n"
  },
  {
    "path": "src/version.tmpl",
    "content": "#define CASPAR_GEN ${CONFIG_VERSION_MAJOR}\n#define CASPAR_MAJOR ${CONFIG_VERSION_MINOR}\n#define CASPAR_MINOR ${CONFIG_VERSION_BUG}\n#define CASPAR_TAG \"${CONFIG_VERSION_TAG}\"\n#define CASPAR_HASH \"${CONFIG_VERSION_GIT_HASH}\"\n"
  },
  {
    "path": "tools/linux/Dockerfile",
    "content": "FROM docker.io/buildpack-deps:noble AS build-casparcg\n\tADD tools/linux/install-dependencies /\n\n\tRUN apt-get update && /install-dependencies\n\n\tRUN mkdir /source && mkdir /build && mkdir /install\n\n\tWORKDIR /build\n\n\tRUN wget https://sdk.lunarg.com/sdk/download/1.4.328.1/linux/vulkansdk-linux-x86_64-1.4.328.1.tar.xz\n\tRUN tar -xf vulkansdk-linux-x86_64-1.4.328.1.tar.xz && \\\n\t\tmv 1.4.328.1 /tmp/vulkan-sdk\n\tENV VULKAN_SDK=/tmp/vulkan-sdk/x86_64\n\tENV PATH=$VULKAN_SDK/bin:$PATH\n\n\tCOPY ./src /source\n\n\tARG CC\n\tARG CXX\n\tARG GIT_HASH\n\n\tRUN cmake -GNinja /source -DUSE_STATIC_BOOST=ON -DUSE_SYSTEM_CEF=OFF -DENABLE_VULKAN=ON\n\n\tRUN cmake --build .\n\n\tRUN cmake --install . --prefix staging\n\n\t# Find a better way to copy deps\n\tRUN ln -s /build/staging /staging && \\\n\t\t/source/shell/copy_deps.sh /build/shell/casparcg /staging/lib\n\nFROM docker.io/ubuntu:noble\n\tCOPY --from=build-casparcg /staging /opt/casparcg\n\n\tRUN set -ex; \\\n\t\t\tapt-get update; \\\n\t\t\tDEBIAN_FRONTEND=\"noninteractive\" apt-get install -y --no-install-recommends \\\n\t\t\ttzdata \\\n\t\t\tlibc++1 \\\n\t\t\tlibnss3 \\\n\t\t\tfontconfig \\\n\t\t\tlibglvnd0 \\\n\t\t\tlibgl1 \\\n\t\t\tlibglx0 \\\n\t\t\tlibegl1 \\\n\t\t\tlibgles2 \\\n\t\t\t; \\\n\t\t\trm -rf /var/lib/apt/lists/*\n\n\tWORKDIR /opt/casparcg\n\tRUN chmod 755 run.sh\n\tADD tools/linux/run_docker.sh ./\n\tCMD [\"./run_docker.sh\"]\n"
  },
  {
    "path": "tools/linux/build-in-docker",
    "content": "#! /bin/bash\n\nGIT_HASH=$(git rev-parse --verify --short HEAD)\n\ndocker build -t casparcg/server \\\n  --build-arg CC \\\n  --build-arg CXX \\\n  --build-arg PROC_COUNT \\\n  --build-arg GIT_HASH \\\n  -f $PWD/tools/linux/Dockerfile $PWD\n\n"
  },
  {
    "path": "tools/linux/deb/INSTALLING",
    "content": "Installation from Graphical User Interface\n\n    Double click on the casparcg-cef package. Click the install\n    button and follow the prompts. This can then be repeated for\n    the casparcg-server and casparcg-scanner packages if desired.\n\nInstallation from Command Line\n\n    At the command prompt type:\n\n        # sudo dpkg -i casparcg-*.deb\n\n    Then fix up any missing dependencies with:\n\n        # sudo apt-get install -f\n\nRunning\n\n    You will need to run both:\n\n        # casparcg-scanner --caspar.config casparcg.config\n\n    and\n\n        # casparcg-server-beta casparcg.config\n\n    with the same config file and potentially working directory (if the config file uses relative paths).\n\n    The server needs to be run as a normal user inside a running x11 server. The scanner can be run as a system service.\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/.gitignore",
    "content": ".debhelper\ndebhelper-build-stamp\n/casparcg-server-*/\n*.log\n*.substvars\n/files\n/tmp/\n/changelog"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/casparcg-server-beta.docs",
    "content": "CHANGELOG.md\nLICENSE\nREADME.md\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/casparcg-server-beta.manpages",
    "content": "debian/casparcg-server-beta.1\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/casparcg.txt2man",
    "content": "NAME\n  casparcg-server-beta - layered real-time video compositor to multiple outputs\nSYNOPSIS\n  casparcg-server-beta [path-to-config]\nDESCRIPTION\n  Play out professional graphics, audio and video to multiple outputs as a\n  layerbased real-time compositor.\n\n  If no path-to-config is provided, the default path is 'casparcg.config'.\nOPTIONS\n  There are no options.\nAUTHOR\n  Petter Reinholdtsen <pere@hungry.com> wrote this manual page.\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/control",
    "content": "Source: casparcg-server-beta\nMaintainer: Julian Waller <git@julusian.co.uk>\nSection: video\nPriority: optional\nStandards-Version: 4.6.0.1\nBuild-Depends: cmake,\n               debhelper-compat (= 13),\n               dh-exec,\n               libavcodec-dev,\n               libavdevice-dev,\n               libavfilter-dev,\n               libavformat-dev,\n               libavutil-dev,\n               libboost-coroutine-dev,\n               libboost-date-time-dev,\n               libboost-dev,\n               libboost-filesystem-dev,\n               libboost-locale-dev,\n               libboost-log-dev,\n               libboost-regex-dev,\n               libboost-thread-dev,\n               libegl-dev,\n               libicu-dev,\n               libglew-dev,\n               libjpeg-dev,\n               libopenal-dev,\n               libsfml-dev,\n               libsimde-dev,\n               libswresample-dev,\n               libswscale-dev,\n               libtbb-dev,\n               libxrandr-dev,\n               pkg-config,\n               txt2man,\n               zlib1g-dev,\n               libasound2,\n               libatk-bridge2.0-0,\n               libatk1.0-0,\n               libatspi2.0-0,\n               libc6,\n               libcairo2,\n               libcups2,\n               libdbus-1-3,\n               libdrm2,\n               libexpat1,\n               libgbm1,\n               libgcc-s1,\n               libglib2.0-0,\n               libnspr4,\n               libnss3,\n               libpango-1.0-0,\n               libx11-6,\n               libxcb1,\n               libxcomposite1,\n               libxdamage1,\n               libxext6,\n               libxfixes3,\n               libxkbcommon0,\n               libxrandr2\nHomepage: https://github.com/CasparCG/server/\nVcs-Git: https://github.com/CasparCG/server.git\nVcs-Browser: https://github.com/CasparCG/server/\n\nPackage: casparcg-server-beta\nPre-Depends: ${misc:Pre-Depends}\nDepends: fonts-liberation, ${misc:Depends}, ${shlibs:Depends}\nArchitecture: amd64 arm64\nDescription: This build will be broken, as CEF will not be packaged correctly inside of it. This exists simply as a build check\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/copyright",
    "content": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: casparcg-server\nSource: https://github.com/CasparCG/server/\nFiles-Excluded: resources/windows/flash-template-host-files/*\nComment: fth files are flash binary files not used on Linux\n\nFiles:     *\nCopyright: 2010-2018 Sveriges Television AB\n           2013 NewTek\nLicense:   GPL-3.0+\n\nFiles:     debian/*\nCopyright: 2023 Julian Waller\nLicense:   GPL-3.0+\n\nFiles:     src/common/tweener.cpp\nCopyright: 2001 Robert Penner\n           2011 Sveriges Television AB <info@casparcg.com>\nLicense:   GPL-3.0+\n\nFiles:     src/modules/decklink/linux_interop/*\nCopyright: 2009-2014 Blackmagic Design\nLicense:   Boost\n\nFiles:     src/protocol/osc/oscpack/*\nCopyright: 2004-2005 Ross Bencina <rossb@audiomulch.com>\nLicense:   MIT\n\nFiles:     src/common/gl/*\nCopyright: 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\nLicense:   Zlib\n This software is provided 'as-is', without any express or implied\n warranty.  In no event will the authors be held liable for any\n damages arising from the use of this software.\n .\n Permission is granted to anyone to use this software for any purpose,\n including commercial applications, and to alter it and redistribute\n it freely, subject to the following restrictions:\n .\n 1. The origin of this software must not be misrepresented;\n you must not claim that you wrote the original software.\n If you use this software in a product, an acknowledgment\n in the product documentation would be appreciated but is not required.\n .\n 2. Altered source versions must be plainly marked as such,\n and must not be misrepresented as being the original software.\n .\n 3. This notice may not be removed or altered from any source distribution.\n\nFiles:     src/CMakeModules/FindFFmpeg.cmake\nCopyright: 2006 Matthias Kretz, <kretz@kde.org>\n           2007 Matt Williams\n           2008 Alexander Neundorf, <neundorf@kde.org>\n           2011 Michael Jansen, <kde@michael-jansen.biz>\nLicense:   BSD-3-clause\n\nFiles:     src/CMakeModules/FindTBB.cmake\nCopyright: ?, Robert Maynard\n           2010-2012 Kitware, Inc.\n           2012 Rolf Eike Beer <eike@sf-mail.de>\nLicense:   BSD-3-clause\n\nFiles:     src/modules/bluefish/interop/*\nCopyright: 2018, Bluefish Technologies\nLicense:   Boost\n\nLicense:   GPL-3.0+\n CasparCG 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 CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n .\n On Debian systems, the complete text of the GNU General Public License\n Version 3 can be found in `/usr/share/common-licenses/GPL-3'.\n\nLicense:   MIT\n Permission is hereby granted, free of charge, to any person\n obtaining a copy of this software and associated documentation files\n (the 'Software') deal in the Software without restriction,\n including without limitation the rights to use, copy, modify, merge,\n publish, distribute, sublicense, and/or sell copies of the Software,\n and to permit persons to whom the Software is furnished to do so,\n subject to the following conditions:\n .\n The above copyright notice and this permission notice shall be\n included in all copies or substantial portions of the Software.\n .\n THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n\nLicense:   BSD-3-Clause\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n .\n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n * The name of the author may be used to endorse or promote products\n derived from this software without specific prior written permission.\n .\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n 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\n THE POSSIBILITY OF SUCH DAMAGE.\n\nLicense:   Apache-2.0\n Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n with the following modification; you may not use this file except in\n compliance with the Apache License and the following modification to it:\n Section 6. Trademarks. is deleted and replaced with:\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 and its affiliates, except as required to comply with Section 4(c) of\n the License and to reproduce the content of the NOTICE file.\n .\n You may obtain a copy of the Apache 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 Apache License with the above modification is\n distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n KIND, either express or implied. See the Apache License for the specific\n language governing permissions and limitations under the Apache License.\n .\n On Debian systems, the complete text of the Apache 2.0 License can be\n found in `/usr/share/common-licenses/Apache-2.0'.\n\nLicense:   Boost\n Permission is hereby granted, free of charge, to any person or organization\n obtaining a copy of the software and accompanying documentation covered by\n this license (the \"Software\") to use, reproduce, display, distribute,\n execute, and transmit the Software, and to prepare derivative works of the\n Software, and to permit third-parties to whom the Software is furnished to\n do so, all subject to the following:\n .\n The copyright notices in the Software and this entire statement, including\n the above license grant, this restriction and the following disclaimer,\n must be included in all copies of the Software, in whole or in part, and\n all derivative works of the Software, unless such copies or derivative\n works are solely in the form of machine-executable object code generated by\n a source language processor.\n .\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/gbp.conf",
    "content": "[DEFAULT]\npristine-tar = True\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/patches/README",
    "content": "0xxx: Grabbed from upstream development.\n1xxx: Possibly relevant for upstream adoption.\n2xxx: Only relevant for packaging.\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/patches/series",
    "content": ""
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/rules",
    "content": "#!/usr/bin/make -f\n%:\n\tdh $@ --sourcedirectory=src --buildsystem=cmake\n\noverride_dh_auto_configure:\n\tdh_auto_configure -- -DDIAG_FONT_PATH=/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf -DCASPARCG_BINARY_NAME=casparcg-server-beta -DUSE_SYSTEM_CEF=OFF\n\n# Generate and install manual page\ndebian/casparcg-server-beta.1: debian/casparcg.txt2man\n\ttxt2man -t CASPARCG -d 2018-12-14 -s 1 debian/casparcg.txt2man > $@\n\noverride_dh_installman: debian/casparcg-server-beta.1\n\tdh_installman\n\t$(RM) debian/casparcg-server-beta.1\n\noverride_dh_gencontrol:\n\tCASPARCG_CEF_VER=$(dpkg-query -W -f='${Version}' casparcg-cef-142)\n\tsed -i \"s/@CASPARCG_CEF_VER@/${CASPARCG_CEF_VER}/\" debian/control\n\tdh_gencontrol\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/upstream/metadata",
    "content": "---\nBug-Database: https://github.com/CasparCG/server/issues\nBug-Submit: https://github.com/CasparCG/server/issues/new\nRepository-Browse: https://github.com/CasparCG/server\n"
  },
  {
    "path": "tools/linux/deb/debian-sid/debian/watch",
    "content": "version=4\nopts=\\\nsearchmode=plain,\\\nrepack,\\\nrepacksuffix=+dfsg,\\\ndversionmangle=s/\\+(debian|dfsg|ds|deb)(\\.\\d+)?$//,\\\nuversionmangle=s/(\\d)[_\\.\\-\\+]?((RC|rc|pre|dev|beta|alpha)\\d*)$/$1~$2/,\\\nfilenamemangle=s%.*/v?@ANY_VERSION@%@PACKAGE@-$1.tar.xz%\" \\\nhttps://api.github.com/repos/casparcg/server/releases?per_page=50 \\\nhttps://api.github.com/repos/[^/]+/[^/]+/tarball/v?@ANY_VERSION@\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/.gitignore",
    "content": ".debhelper\ndebhelper-build-stamp\n/casparcg-server-*/\n*.log\n*.substvars\n/files\n/tmp/\n/changelog"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/casparcg-server-beta.docs",
    "content": "CHANGELOG.md\nLICENSE\nREADME.md\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/casparcg-server-beta.manpages",
    "content": "debian/casparcg-server-beta.1\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/casparcg.txt2man",
    "content": "NAME\n  casparcg-server-beta - layered real-time video compositor to multiple outputs\nSYNOPSIS\n  casparcg-server-beta [path-to-config]\nDESCRIPTION\n  Play out professional graphics, audio and video to multiple outputs as a\n  layerbased real-time compositor.\n\n  If no path-to-config is provided, the default path is 'casparcg.config'.\nOPTIONS\n  There are no options.\nAUTHOR\n  Petter Reinholdtsen <pere@hungry.com> wrote this manual page.\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/control",
    "content": "Source: casparcg-server-beta\nMaintainer: Julian Waller <git@julusian.co.uk>\nSection: video\nPriority: optional\nStandards-Version: 4.6.0.1\nBuild-Depends: cmake,\n               debhelper-compat (= 13),\n               dh-exec,\n               libavcodec-dev,\n               libavdevice-dev,\n               libavfilter-dev,\n               libavformat-dev,\n               libavutil-dev,\n               libboost-coroutine-dev,\n               libboost-date-time-dev,\n               libboost-dev,\n               libboost-filesystem-dev,\n               libboost-locale-dev,\n               libboost-log-dev,\n               libboost-regex-dev,\n               libboost-system-dev,\n               libboost-thread-dev,\n               libegl-dev,\n               libicu-dev,\n               libglew-dev,\n               libjpeg-dev,\n               libopenal-dev,\n               libsfml-dev,\n               libsimde-dev,\n               libswresample-dev,\n               libswscale-dev,\n               libtbb-dev,\n               libxrandr-dev,\n               pkg-config,\n               txt2man,\n               zlib1g-dev,\n               libasound2,\n               libatk-bridge2.0-0,\n               libatk1.0-0,\n               libatspi2.0-0,\n               libc6,\n               libcairo2,\n               libcups2,\n               libdbus-1-3,\n               libdrm2,\n               libexpat1,\n               libgbm1,\n               libgcc-s1,\n               libglib2.0-0,\n               libnspr4,\n               libnss3,\n               libpango-1.0-0,\n               libx11-6,\n               libxcb1,\n               libxcomposite1,\n               libxdamage1,\n               libxext6,\n               libxfixes3,\n               libxkbcommon0,\n               libxrandr2\nHomepage: https://github.com/CasparCG/server/\nVcs-Git: https://github.com/CasparCG/server.git\nVcs-Browser: https://github.com/CasparCG/server/\n\nPackage: casparcg-server-beta\nPre-Depends: ${misc:Pre-Depends}\nDepends: fonts-liberation, ${misc:Depends}, ${shlibs:Depends}\nArchitecture: amd64 arm64\nDescription: This build will be broken, as CEF will not be packaged correctly inside of it. This exists simply as a build check\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/copyright",
    "content": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: casparcg-server\nSource: https://github.com/CasparCG/server/\nFiles-Excluded: resources/windows/flash-template-host-files/*\nComment: fth files are flash binary files not used on Linux\n\nFiles:     *\nCopyright: 2010-2018 Sveriges Television AB\n           2013 NewTek\nLicense:   GPL-3.0+\n\nFiles:     debian/*\nCopyright: 2023 Julian Waller\nLicense:   GPL-3.0+\n\nFiles:     src/common/tweener.cpp\nCopyright: 2001 Robert Penner\n           2011 Sveriges Television AB <info@casparcg.com>\nLicense:   GPL-3.0+\n\nFiles:     src/modules/decklink/linux_interop/*\nCopyright: 2009-2014 Blackmagic Design\nLicense:   Boost\n\nFiles:     src/protocol/osc/oscpack/*\nCopyright: 2004-2005 Ross Bencina <rossb@audiomulch.com>\nLicense:   MIT\n\nFiles:     src/common/gl/*\nCopyright: 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\nLicense:   Zlib\n This software is provided 'as-is', without any express or implied\n warranty.  In no event will the authors be held liable for any\n damages arising from the use of this software.\n .\n Permission is granted to anyone to use this software for any purpose,\n including commercial applications, and to alter it and redistribute\n it freely, subject to the following restrictions:\n .\n 1. The origin of this software must not be misrepresented;\n you must not claim that you wrote the original software.\n If you use this software in a product, an acknowledgment\n in the product documentation would be appreciated but is not required.\n .\n 2. Altered source versions must be plainly marked as such,\n and must not be misrepresented as being the original software.\n .\n 3. This notice may not be removed or altered from any source distribution.\n\nFiles:     src/CMakeModules/FindFFmpeg.cmake\nCopyright: 2006 Matthias Kretz, <kretz@kde.org>\n           2007 Matt Williams\n           2008 Alexander Neundorf, <neundorf@kde.org>\n           2011 Michael Jansen, <kde@michael-jansen.biz>\nLicense:   BSD-3-clause\n\nFiles:     src/CMakeModules/FindTBB.cmake\nCopyright: ?, Robert Maynard\n           2010-2012 Kitware, Inc.\n           2012 Rolf Eike Beer <eike@sf-mail.de>\nLicense:   BSD-3-clause\n\nFiles:     src/modules/bluefish/interop/*\nCopyright: 2018, Bluefish Technologies\nLicense:   Boost\n\nLicense:   GPL-3.0+\n CasparCG 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 CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n .\n On Debian systems, the complete text of the GNU General Public License\n Version 3 can be found in `/usr/share/common-licenses/GPL-3'.\n\nLicense:   MIT\n Permission is hereby granted, free of charge, to any person\n obtaining a copy of this software and associated documentation files\n (the 'Software') deal in the Software without restriction,\n including without limitation the rights to use, copy, modify, merge,\n publish, distribute, sublicense, and/or sell copies of the Software,\n and to permit persons to whom the Software is furnished to do so,\n subject to the following conditions:\n .\n The above copyright notice and this permission notice shall be\n included in all copies or substantial portions of the Software.\n .\n THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n\nLicense:   BSD-3-Clause\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n .\n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n * The name of the author may be used to endorse or promote products\n derived from this software without specific prior written permission.\n .\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n 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\n THE POSSIBILITY OF SUCH DAMAGE.\n\nLicense:   Apache-2.0\n Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n with the following modification; you may not use this file except in\n compliance with the Apache License and the following modification to it:\n Section 6. Trademarks. is deleted and replaced with:\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 and its affiliates, except as required to comply with Section 4(c) of\n the License and to reproduce the content of the NOTICE file.\n .\n You may obtain a copy of the Apache 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 Apache License with the above modification is\n distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n KIND, either express or implied. See the Apache License for the specific\n language governing permissions and limitations under the Apache License.\n .\n On Debian systems, the complete text of the Apache 2.0 License can be\n found in `/usr/share/common-licenses/Apache-2.0'.\n\nLicense:   Boost\n Permission is hereby granted, free of charge, to any person or organization\n obtaining a copy of the software and accompanying documentation covered by\n this license (the \"Software\") to use, reproduce, display, distribute,\n execute, and transmit the Software, and to prepare derivative works of the\n Software, and to permit third-parties to whom the Software is furnished to\n do so, all subject to the following:\n .\n The copyright notices in the Software and this entire statement, including\n the above license grant, this restriction and the following disclaimer,\n must be included in all copies of the Software, in whole or in part, and\n all derivative works of the Software, unless such copies or derivative\n works are solely in the form of machine-executable object code generated by\n a source language processor.\n .\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/gbp.conf",
    "content": "[DEFAULT]\npristine-tar = True\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/patches/README",
    "content": "0xxx: Grabbed from upstream development.\n1xxx: Possibly relevant for upstream adoption.\n2xxx: Only relevant for packaging.\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/patches/series",
    "content": ""
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/rules",
    "content": "#!/usr/bin/make -f\n%:\n\tdh $@ --sourcedirectory=src --buildsystem=cmake\n\noverride_dh_auto_configure:\n\tdh_auto_configure -- -DDIAG_FONT_PATH=/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf -DCASPARCG_BINARY_NAME=casparcg-server-beta -DUSE_SYSTEM_CEF=OFF\n\n# Generate and install manual page\ndebian/casparcg-server-beta.1: debian/casparcg.txt2man\n\ttxt2man -t CASPARCG -d 2018-12-14 -s 1 debian/casparcg.txt2man > $@\n\noverride_dh_installman: debian/casparcg-server-beta.1\n\tdh_installman\n\t$(RM) debian/casparcg-server-beta.1\n\noverride_dh_gencontrol:\n\tCASPARCG_CEF_VER=$(dpkg-query -W -f='${Version}' casparcg-cef-142)\n\tsed -i \"s/@CASPARCG_CEF_VER@/${CASPARCG_CEF_VER}/\" debian/control\n\tdh_gencontrol\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/upstream/metadata",
    "content": "---\nBug-Database: https://github.com/CasparCG/server/issues\nBug-Submit: https://github.com/CasparCG/server/issues/new\nRepository-Browse: https://github.com/CasparCG/server\n"
  },
  {
    "path": "tools/linux/deb/debian-trixie/debian/watch",
    "content": "version=4\nopts=\\\nsearchmode=plain,\\\nrepack,\\\nrepacksuffix=+dfsg,\\\ndversionmangle=s/\\+(debian|dfsg|ds|deb)(\\.\\d+)?$//,\\\nuversionmangle=s/(\\d)[_\\.\\-\\+]?((RC|rc|pre|dev|beta|alpha)\\d*)$/$1~$2/,\\\nfilenamemangle=s%.*/v?@ANY_VERSION@%@PACKAGE@-$1.tar.xz%\" \\\nhttps://api.github.com/repos/casparcg/server/releases?per_page=50 \\\nhttps://api.github.com/repos/[^/]+/[^/]+/tarball/v?@ANY_VERSION@\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/.gitignore",
    "content": ".debhelper\ndebhelper-build-stamp\n/casparcg-server-*/\n*.log\n*.substvars\n/files\n/tmp/\n/changelog"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/casparcg-server-beta.docs",
    "content": "CHANGELOG.md\nLICENSE\nREADME.md\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/casparcg-server-beta.manpages",
    "content": "debian/casparcg-server-beta.1\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/casparcg.txt2man",
    "content": "NAME\n  casparcg-server-beta - layered real-time video compositor to multiple outputs\nSYNOPSIS\n  casparcg-server-beta [path-to-config]\nDESCRIPTION\n  Play out professional graphics, audio and video to multiple outputs as a\n  layerbased real-time compositor.\n\n  If no path-to-config is provided, the default path is 'casparcg.config'.\nOPTIONS\n  There are no options.\nAUTHOR\n  Petter Reinholdtsen <pere@hungry.com> wrote this manual page.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/control",
    "content": "Source: casparcg-server-beta\nMaintainer: Julian Waller <git@julusian.co.uk>\nSection: video\nPriority: optional\nStandards-Version: 4.6.0.1\nBuild-Depends: cmake,\n               debhelper-compat (= 13),\n               dh-exec,\n               libavcodec-dev,\n               libavdevice-dev,\n               libavfilter-dev,\n               libavformat-dev,\n               libavutil-dev,\n               libboost-coroutine-dev,\n               libboost-date-time-dev,\n               libboost-dev,\n               libboost-filesystem-dev,\n               libboost-locale-dev,\n               libboost-log-dev,\n               libboost-regex-dev,\n               libboost-system-dev,\n               libboost-thread-dev,\n               libicu-dev,\n               libglew-dev,\n               libjpeg-dev,\n               libopenal-dev,\n               libsfml-dev,\n               libsimde-dev,\n               libswresample-dev,\n               libswscale-dev,\n               libtbb-dev,\n               libxrandr-dev,\n               pkg-config,\n               txt2man,\n               zlib1g-dev,\n               casparcg-cef-142-dev\nHomepage: https://github.com/CasparCG/server/\nVcs-Git: https://github.com/CasparCG/server.git\nVcs-Browser: https://github.com/CasparCG/server/\n\nPackage: casparcg-server-beta\nPre-Depends: ${misc:Pre-Depends}\nDepends: fonts-liberation, casparcg-cef-142 (= @CASPARCG_CEF_VER@), ${misc:Depends}, ${shlibs:Depends}\nArchitecture: amd64\nDescription: layered real-time video compositor to multiple outputs\n Play out professional graphics, audio and video to multiple outputs as a\n layerbased real-time compositor.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/copyright",
    "content": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: casparcg-server\nSource: https://github.com/CasparCG/server/\nFiles-Excluded: resources/windows/flash-template-host-files/*\nComment: fth files are flash binary files not used on Linux\n\nFiles:     *\nCopyright: 2010-2018 Sveriges Television AB\n           2013 NewTek\nLicense:   GPL-3.0+\n\nFiles:     debian/*\nCopyright: 2023 Julian Waller\nLicense:   GPL-3.0+\n\nFiles:     src/common/tweener.cpp\nCopyright: 2001 Robert Penner\n           2011 Sveriges Television AB <info@casparcg.com>\nLicense:   GPL-3.0+\n\nFiles:     src/modules/decklink/linux_interop/*\nCopyright: 2009-2014 Blackmagic Design\nLicense:   Boost\n\nFiles:     src/protocol/osc/oscpack/*\nCopyright: 2004-2005 Ross Bencina <rossb@audiomulch.com>\nLicense:   MIT\n\nFiles:     src/common/gl/*\nCopyright: 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\nLicense:   Zlib\n This software is provided 'as-is', without any express or implied\n warranty.  In no event will the authors be held liable for any\n damages arising from the use of this software.\n .\n Permission is granted to anyone to use this software for any purpose,\n including commercial applications, and to alter it and redistribute\n it freely, subject to the following restrictions:\n .\n 1. The origin of this software must not be misrepresented;\n you must not claim that you wrote the original software.\n If you use this software in a product, an acknowledgment\n in the product documentation would be appreciated but is not required.\n .\n 2. Altered source versions must be plainly marked as such,\n and must not be misrepresented as being the original software.\n .\n 3. This notice may not be removed or altered from any source distribution.\n\nFiles:     src/CMakeModules/FindFFmpeg.cmake\nCopyright: 2006 Matthias Kretz, <kretz@kde.org>\n           2007 Matt Williams\n           2008 Alexander Neundorf, <neundorf@kde.org>\n           2011 Michael Jansen, <kde@michael-jansen.biz>\nLicense:   BSD-3-clause\n\nFiles:     src/CMakeModules/FindTBB.cmake\nCopyright: ?, Robert Maynard\n           2010-2012 Kitware, Inc.\n           2012 Rolf Eike Beer <eike@sf-mail.de>\nLicense:   BSD-3-clause\n\nFiles:     src/modules/bluefish/interop/*\nCopyright: 2018, Bluefish Technologies\nLicense:   Boost\n\nLicense:   GPL-3.0+\n CasparCG 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 CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n .\n On Debian systems, the complete text of the GNU General Public License\n Version 3 can be found in `/usr/share/common-licenses/GPL-3'.\n\nLicense:   MIT\n Permission is hereby granted, free of charge, to any person\n obtaining a copy of this software and associated documentation files\n (the 'Software') deal in the Software without restriction,\n including without limitation the rights to use, copy, modify, merge,\n publish, distribute, sublicense, and/or sell copies of the Software,\n and to permit persons to whom the Software is furnished to do so,\n subject to the following conditions:\n .\n The above copyright notice and this permission notice shall be\n included in all copies or substantial portions of the Software.\n .\n THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n\nLicense:   BSD-3-Clause\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n .\n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n * The name of the author may be used to endorse or promote products\n derived from this software without specific prior written permission.\n .\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n 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\n THE POSSIBILITY OF SUCH DAMAGE.\n\nLicense:   Apache-2.0\n Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n with the following modification; you may not use this file except in\n compliance with the Apache License and the following modification to it:\n Section 6. Trademarks. is deleted and replaced with:\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 and its affiliates, except as required to comply with Section 4(c) of\n the License and to reproduce the content of the NOTICE file.\n .\n You may obtain a copy of the Apache 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 Apache License with the above modification is\n distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n KIND, either express or implied. See the Apache License for the specific\n language governing permissions and limitations under the Apache License.\n .\n On Debian systems, the complete text of the Apache 2.0 License can be\n found in `/usr/share/common-licenses/Apache-2.0'.\n\nLicense:   Boost\n Permission is hereby granted, free of charge, to any person or organization\n obtaining a copy of the software and accompanying documentation covered by\n this license (the \"Software\") to use, reproduce, display, distribute,\n execute, and transmit the Software, and to prepare derivative works of the\n Software, and to permit third-parties to whom the Software is furnished to\n do so, all subject to the following:\n .\n The copyright notices in the Software and this entire statement, including\n the above license grant, this restriction and the following disclaimer,\n must be included in all copies of the Software, in whole or in part, and\n all derivative works of the Software, unless such copies or derivative\n works are solely in the form of machine-executable object code generated by\n a source language processor.\n .\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/gbp.conf",
    "content": "[DEFAULT]\npristine-tar = True\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/patches/README",
    "content": "0xxx: Grabbed from upstream development.\n1xxx: Possibly relevant for upstream adoption.\n2xxx: Only relevant for packaging.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/patches/series",
    "content": ""
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/rules",
    "content": "#!/usr/bin/make -f\n%:\n\tdh $@ --sourcedirectory=src --buildsystem=cmake\n\noverride_dh_auto_configure:\n\tdh_auto_configure -- -DDIAG_FONT_PATH=/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf -DCASPARCG_BINARY_NAME=casparcg-server-beta\n\n# Generate and install manual page\ndebian/casparcg-server-beta.1: debian/casparcg.txt2man\n\ttxt2man -t CASPARCG -d 2018-12-14 -s 1 debian/casparcg.txt2man > $@\n\noverride_dh_installman: debian/casparcg-server-beta.1\n\tdh_installman\n\t$(RM) debian/casparcg-server-beta.1\n\noverride_dh_gencontrol:\n\tCASPARCG_CEF_VER=$(dpkg-query -W -f='${Version}' casparcg-cef-142)\n\tsed -i \"s/@CASPARCG_CEF_VER@/${CASPARCG_CEF_VER}/\" debian/control\n\tdh_gencontrol\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/upstream/metadata",
    "content": "---\nBug-Database: https://github.com/CasparCG/server/issues\nBug-Submit: https://github.com/CasparCG/server/issues/new\nRepository-Browse: https://github.com/CasparCG/server\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-noble/debian/watch",
    "content": "version=4\nopts=\\\nsearchmode=plain,\\\nrepack,\\\nrepacksuffix=+dfsg,\\\ndversionmangle=s/\\+(debian|dfsg|ds|deb)(\\.\\d+)?$//,\\\nuversionmangle=s/(\\d)[_\\.\\-\\+]?((RC|rc|pre|dev|beta|alpha)\\d*)$/$1~$2/,\\\nfilenamemangle=s%.*/v?@ANY_VERSION@%@PACKAGE@-$1.tar.xz%\" \\\nhttps://api.github.com/repos/casparcg/server/releases?per_page=50 \\\nhttps://api.github.com/repos/[^/]+/[^/]+/tarball/v?@ANY_VERSION@\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/.gitignore",
    "content": ".debhelper\ndebhelper-build-stamp\n/casparcg-server-*/\n*.log\n*.substvars\n/files\n/tmp/\n/changelog"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/casparcg-server-beta.docs",
    "content": "CHANGELOG.md\nLICENSE\nREADME.md\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/casparcg-server-beta.manpages",
    "content": "debian/casparcg-server-beta.1\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/casparcg.txt2man",
    "content": "NAME\n  casparcg-server-beta - layered real-time video compositor to multiple outputs\nSYNOPSIS\n  casparcg-server-beta [path-to-config]\nDESCRIPTION\n  Play out professional graphics, audio and video to multiple outputs as a\n  layerbased real-time compositor.\n\n  If no path-to-config is provided, the default path is 'casparcg.config'.\nOPTIONS\n  There are no options.\nAUTHOR\n  Petter Reinholdtsen <pere@hungry.com> wrote this manual page.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/control",
    "content": "Source: casparcg-server-beta\nMaintainer: Julian Waller <git@julusian.co.uk>\nSection: video\nPriority: optional\nStandards-Version: 4.6.0.1\nBuild-Depends: cmake,\n               debhelper-compat (= 13),\n               dh-exec,\n               libavcodec-dev,\n               libavdevice-dev,\n               libavfilter-dev,\n               libavformat-dev,\n               libavutil-dev,\n               libboost-coroutine-dev,\n               libboost-date-time-dev,\n               libboost-dev,\n               libboost-filesystem-dev,\n               libboost-locale-dev,\n               libboost-log-dev,\n               libboost-regex-dev,\n               libboost-system-dev,\n               libboost-thread-dev,\n               libegl-dev,\n               libicu-dev,\n               libglew-dev,\n               libjpeg-dev,\n               libopenal-dev,\n               libsfml-dev,\n               libsimde-dev,\n               libswresample-dev,\n               libswscale-dev,\n               libtbb-dev,\n               libxrandr-dev,\n               pkg-config,\n               txt2man,\n               zlib1g-dev,\n               casparcg-cef-142-dev\nHomepage: https://github.com/CasparCG/server/\nVcs-Git: https://github.com/CasparCG/server.git\nVcs-Browser: https://github.com/CasparCG/server/\n\nPackage: casparcg-server-beta\nPre-Depends: ${misc:Pre-Depends}\nDepends: fonts-liberation, casparcg-cef-142 (= @CASPARCG_CEF_VER@), ${misc:Depends}, ${shlibs:Depends}\nArchitecture: amd64 arm64\nDescription: layered real-time video compositor to multiple outputs\n Play out professional graphics, audio and video to multiple outputs as a\n layerbased real-time compositor.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/copyright",
    "content": "Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/\nUpstream-Name: casparcg-server\nSource: https://github.com/CasparCG/server/\nFiles-Excluded: resources/windows/flash-template-host-files/*\nComment: fth files are flash binary files not used on Linux\n\nFiles:     *\nCopyright: 2010-2018 Sveriges Television AB\n           2013 NewTek\nLicense:   GPL-3.0+\n\nFiles:     debian/*\nCopyright: 2023 Julian Waller\nLicense:   GPL-3.0+\n\nFiles:     src/common/tweener.cpp\nCopyright: 2001 Robert Penner\n           2011 Sveriges Television AB <info@casparcg.com>\nLicense:   GPL-3.0+\n\nFiles:     src/modules/decklink/linux_interop/*\nCopyright: 2009-2014 Blackmagic Design\nLicense:   Boost\n\nFiles:     src/protocol/osc/oscpack/*\nCopyright: 2004-2005 Ross Bencina <rossb@audiomulch.com>\nLicense:   MIT\n\nFiles:     src/common/gl/*\nCopyright: 2007-2009 Laurent Gomila (laurent.gom@gmail.com)\nLicense:   Zlib\n This software is provided 'as-is', without any express or implied\n warranty.  In no event will the authors be held liable for any\n damages arising from the use of this software.\n .\n Permission is granted to anyone to use this software for any purpose,\n including commercial applications, and to alter it and redistribute\n it freely, subject to the following restrictions:\n .\n 1. The origin of this software must not be misrepresented;\n you must not claim that you wrote the original software.\n If you use this software in a product, an acknowledgment\n in the product documentation would be appreciated but is not required.\n .\n 2. Altered source versions must be plainly marked as such,\n and must not be misrepresented as being the original software.\n .\n 3. This notice may not be removed or altered from any source distribution.\n\nFiles:     src/CMakeModules/FindFFmpeg.cmake\nCopyright: 2006 Matthias Kretz, <kretz@kde.org>\n           2007 Matt Williams\n           2008 Alexander Neundorf, <neundorf@kde.org>\n           2011 Michael Jansen, <kde@michael-jansen.biz>\nLicense:   BSD-3-clause\n\nFiles:     src/CMakeModules/FindTBB.cmake\nCopyright: ?, Robert Maynard\n           2010-2012 Kitware, Inc.\n           2012 Rolf Eike Beer <eike@sf-mail.de>\nLicense:   BSD-3-clause\n\nFiles:     src/modules/bluefish/interop/*\nCopyright: 2018, Bluefish Technologies\nLicense:   Boost\n\nLicense:   GPL-3.0+\n CasparCG 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 CasparCG 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 CasparCG. If not, see <http://www.gnu.org/licenses/>.\n .\n On Debian systems, the complete text of the GNU General Public License\n Version 3 can be found in `/usr/share/common-licenses/GPL-3'.\n\nLicense:   MIT\n Permission is hereby granted, free of charge, to any person\n obtaining a copy of this software and associated documentation files\n (the 'Software') deal in the Software without restriction,\n including without limitation the rights to use, copy, modify, merge,\n publish, distribute, sublicense, and/or sell copies of the Software,\n and to permit persons to whom the Software is furnished to do so,\n subject to the following conditions:\n .\n The above copyright notice and this permission notice shall be\n included in all copies or substantial portions of the Software.\n .\n THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\n EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n SOFTWARE.\n\nLicense:   BSD-3-Clause\n Redistribution and use in source and binary forms, with or without\n modification, are permitted provided that the following conditions are met:\n .\n * Redistributions of source code must retain the above copyright notice,\n this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above copyright notice,\n this list of conditions and the following disclaimer in the documentation\n and/or other materials provided with the distribution.\n * The name of the author may be used to endorse or promote products\n derived from this software without specific prior written permission.\n .\n THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n 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\n THE POSSIBILITY OF SUCH DAMAGE.\n\nLicense:   Apache-2.0\n Licensed under the Apache License, Version 2.0 (the \"Apache License\")\n with the following modification; you may not use this file except in\n compliance with the Apache License and the following modification to it:\n Section 6. Trademarks. is deleted and replaced with:\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 and its affiliates, except as required to comply with Section 4(c) of\n the License and to reproduce the content of the NOTICE file.\n .\n You may obtain a copy of the Apache 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 Apache License with the above modification is\n distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n KIND, either express or implied. See the Apache License for the specific\n language governing permissions and limitations under the Apache License.\n .\n On Debian systems, the complete text of the Apache 2.0 License can be\n found in `/usr/share/common-licenses/Apache-2.0'.\n\nLicense:   Boost\n Permission is hereby granted, free of charge, to any person or organization\n obtaining a copy of the software and accompanying documentation covered by\n this license (the \"Software\") to use, reproduce, display, distribute,\n execute, and transmit the Software, and to prepare derivative works of the\n Software, and to permit third-parties to whom the Software is furnished to\n do so, all subject to the following:\n .\n The copyright notices in the Software and this entire statement, including\n the above license grant, this restriction and the following disclaimer,\n must be included in all copies of the Software, in whole or in part, and\n all derivative works of the Software, unless such copies or derivative\n works are solely in the form of machine-executable object code generated by\n a source language processor.\n .\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT\n SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE\n FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,\n ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/gbp.conf",
    "content": "[DEFAULT]\npristine-tar = True\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/patches/README",
    "content": "0xxx: Grabbed from upstream development.\n1xxx: Possibly relevant for upstream adoption.\n2xxx: Only relevant for packaging.\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/patches/series",
    "content": ""
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/rules",
    "content": "#!/usr/bin/make -f\n%:\n\tdh $@ --sourcedirectory=src --buildsystem=cmake\n\noverride_dh_auto_configure:\n\tdh_auto_configure -- -DDIAG_FONT_PATH=/usr/share/fonts/truetype/liberation/LiberationMono-Regular.ttf -DCASPARCG_BINARY_NAME=casparcg-server-beta\n\n# Generate and install manual page\ndebian/casparcg-server-beta.1: debian/casparcg.txt2man\n\ttxt2man -t CASPARCG -d 2018-12-14 -s 1 debian/casparcg.txt2man > $@\n\noverride_dh_installman: debian/casparcg-server-beta.1\n\tdh_installman\n\t$(RM) debian/casparcg-server-beta.1\n\noverride_dh_gencontrol:\n\tCASPARCG_CEF_VER=$(dpkg-query -W -f='${Version}' casparcg-cef-142)\n\tsed -i \"s/@CASPARCG_CEF_VER@/${CASPARCG_CEF_VER}/\" debian/control\n\tdh_gencontrol\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/source/format",
    "content": "3.0 (quilt)\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/upstream/metadata",
    "content": "---\nBug-Database: https://github.com/CasparCG/server/issues\nBug-Submit: https://github.com/CasparCG/server/issues/new\nRepository-Browse: https://github.com/CasparCG/server\n"
  },
  {
    "path": "tools/linux/deb/ubuntu-resolute/debian/watch",
    "content": "version=4\nopts=\\\nsearchmode=plain,\\\nrepack,\\\nrepacksuffix=+dfsg,\\\ndversionmangle=s/\\+(debian|dfsg|ds|deb)(\\.\\d+)?$//,\\\nuversionmangle=s/(\\d)[_\\.\\-\\+]?((RC|rc|pre|dev|beta|alpha)\\d*)$/$1~$2/,\\\nfilenamemangle=s%.*/v?@ANY_VERSION@%@PACKAGE@-$1.tar.xz%\" \\\nhttps://api.github.com/repos/casparcg/server/releases?per_page=50 \\\nhttps://api.github.com/repos/[^/]+/[^/]+/tarball/v?@ANY_VERSION@\n"
  },
  {
    "path": "tools/linux/extract-from-docker",
    "content": "#! /bin/bash\ntempContainer=$(docker create casparcg/server)\ndocker cp $tempContainer:/opt/casparcg ./casparcg_server\ndocker rm -v $tempContainer\n"
  },
  {
    "path": "tools/linux/install-dependencies",
    "content": "#!/bin/bash\n\napt-get install -yq --no-install-recommends \\\n  autoconf \\\n  automake \\\n  cmake \\\n  ninja-build \\\n  curl \\\n  bzip2 \\\n  clang \\\n  g++ \\\n  gcc \\\n  git \\\n  gperf \\\n  libtool \\\n  make \\\n  perl \\\n  pkg-config \\\n  python3 \\\n  xz-utils \\\n  zlib1g-dev \\\n  libexpat1-dev \\\n  lsb-release \\\n  libglew-dev \\\n  libtbb-dev \\\n  libopenal-dev \\\n  libxcursor-dev \\\n  libxinerama-dev \\\n  libxi-dev \\\n  libsfml-dev \\\n  libxrandr-dev \\\n  libudev-dev \\\n  libglu1-mesa-dev \\\n  libgl1-mesa-dev \\\n  libegl1-mesa-dev \\\n  libboost-all-dev \\\n  libnss3-dev \\\n  libcups2-dev \\\n  libxdamage-dev \\\n  libxcomposite-dev \\\n  libatk1.0-dev \\\n  libatspi2.0-dev \\\n  libatk-bridge2.0-dev \\\n  libavcodec-dev \\\n  libavformat-dev \\\n  libavdevice-dev \\\n  libavutil-dev \\\n  libavfilter-dev \\\n  libswscale-dev \\\n  libswresample-dev \\\n  libsimde-dev\n"
  },
  {
    "path": "tools/linux/run_docker.sh",
    "content": "#!/bin/bash\n\nif [ -z \"$DISPLAY\" ]; then \n  echo \"WARNING: DISPLAY is not set\"\nfi\n\nif [ ! -d /tmp/.X11-unix ]; then\n  echo \"WARNING: X11 socket not found\"\nfi\n\nif [ ! -f /root/.Xauthority ]; then\n  echo \"WARNING: Xauthority not found\"\nfi\n\n./run.sh\n"
  },
  {
    "path": "tools/linux/start_docker.sh",
    "content": "#!/bin/bash\n\nCMD=\"docker run --rm -it\"\n\n# bind AMCP Ports\nCMD=\"$CMD -p 5250:5250\"\n\n# passthrough config\nCMD=\"$CMD -v $PWD/casparcg.config:/opt/casparcg/casparcg.config:ro\"\n\n# passthrough media folder\nCMD=\"$CMD -v $PWD/media:/opt/casparcg/media\"\n\n## DO NOT EDIT BELOW THIS LINE\n\nHAS_NVIDIA_RUNTIME=$(docker info | grep -i nvidia)\nif [ ! -z \"$HAS_NVIDIA_RUNTIME\" ]; then\n  CMD=\"$CMD --runtime=nvidia\"\nelse\n  # assume intel, so setup for that\n  CMD=\"$CMD --device /dev/dri\"\nfi\n\nDECKLINK_API_SO=\"/usr/lib/libDeckLinkAPI.so\"\nif [ -f \"$DECKLINK_API_SO\" ]; then\n  CMD=\"$CMD -v $DECKLINK_API_SO:$DECKLINK_API_SO:ro\"\n\n  for dev in /dev/blackmagic/*; do\n    if [ -f \"$dev\" ]; then\n      CMD=\"$CMD --device $dev\"\n    fi\n  done\nfi\n\nif [ ! -z \"$XAUTHORITY\" ]; then\n  CMD=\"$CMD -v $XAUTHORITY:/root/.Xauthority:ro\"\nelif [ -f \"$HOME/.Xauthority\" ]; then\n  CMD=\"$CMD -v $HOME/.Xauthority:/root/.Xauthority:ro\"\nelse\n  echo \"Failed to find Xauthority file\"\n  exit 9\nfi\n\nCMD=\"$CMD -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix:ro\"\n\nCMD=\"$CMD casparcg/server\"\n\necho \"Executing command: $CMD\"\n\n# Run it!\n$CMD\n"
  },
  {
    "path": "tools/update-format.sh",
    "content": "#!/bin/bash\n\n# args needed to format inline. can be overridden to use script for other purposes\nCLANG_ARGS=${CLANG_ARGS:--i}\n\nSOURCE_FILES=`find ./src/ \\( -name \\*.cpp -type f -or -name \\*.h -type f \\) -not -path \"./src/packages/*\" -not -path \"*interop*\" -not -path \"./src/cmake*\"`\nBAD_FILES=0\nfor SOURCE_FILE in $SOURCE_FILES\ndo\n  export FORMATTING_ISSUE_COUNT=`clang-format $CLANG_ARGS $SOURCE_FILE | grep offset | wc -l`\n  if [ \"$FORMATTING_ISSUE_COUNT\" -gt \"0\" ]; then\n    echo \"Source file $SOURCE_FILE contains formatting issues.\"\n    BAD_FILES=1\n  fi\ndone\n\nif [ $BAD_FILES ]; then \n  exit 1\nfi\n"
  },
  {
    "path": "tools/verify-format.sh",
    "content": "#!/bin/bash\n\n# override args to diff changes\nexport CLANG_ARGS=-output-replacements-xml\n\nSCRIPT_ROOT=$(dirname \"${0}\")/..\n\"${SCRIPT_ROOT}/tools/update-format.sh\"\n"
  },
  {
    "path": "tools/windows/build.bat",
    "content": "@echo off\n\nset BUILD_ARCHIVE_NAME=casparcg_server\nset BUILD_VCVARSALL=C:\\Program Files\\Microsoft Visual Studio\\2022\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat\nset BUILD_7ZIP=C:\\Program Files\\7-Zip\\7z.exe\n\n@REM Github Actions has Enterprise available\nif DEFINED CI set BUILD_VCVARSALL=C:\\Program Files\\Microsoft Visual Studio\\2022\\Enterprise\\VC\\Auxiliary\\Build\\vcvars64.bat\n\n:: Clean and enter shadow build folder\necho Cleaning...\nif exist dist rmdir dist /s /q || goto :error\nmkdir dist || goto :error\n\n:: Setup VC++ environment\necho Setting up VC++...\ncall \"%BUILD_VCVARSALL%\" amd64 || goto :error\n\n:: Run cmake\ncd dist || goto :error\ncmake -G \"Visual Studio 17 2022\" -A x64 ..\\src || goto :error\n\n:: Build with MSBuild\necho Building...\nmsbuild \"CasparCG Server.sln\" /t:Clean /p:Configuration=Release || goto :error\nmsbuild \"CasparCG Server.sln\" /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS% || goto :error\n\n:: Create server folder to later zip\nset SERVER_FOLDER=casparcg_server\ncall ..\\tools\\windows\\package.bat ..\n\n:: Create zip file\necho Creating zip...\nif exist \"%BUILD_ARCHIVE_NAME%.zip\" unlink \"%BUILD_ARCHIVE_NAME%.zip\" || goto :error\n\"%BUILD_7ZIP%\" a \"%BUILD_ARCHIVE_NAME%.zip\" \".\\%SERVER_FOLDER%\\*\" || goto :error\n\n:: Skip exiting with failure\ngoto :EOF\n\n:error\nexit /b %errorlevel%\n"
  },
  {
    "path": "tools/windows/package.bat",
    "content": "if exist \"%SERVER_FOLDER%\" rmdir \"%SERVER_FOLDER%\" /s /q\n\nxcopy shell\\Release \"%SERVER_FOLDER%\" /E /I /Y\nxcopy flashtemplatehost-prefix\\src\\flashtemplatehost \"%SERVER_FOLDER%\\\" /E /I /Y\n\ncopy %1\\src\\shell\\casparcg_auto_restart.bat \"%SERVER_FOLDER%\\\"\n\necho Copying documentation...\ncopy %1\\CHANGELOG.md \"%SERVER_FOLDER%\"\ncopy %1\\LICENSE \"%SERVER_FOLDER%\"\ncopy %1\\README.md \"%SERVER_FOLDER%\"\n\nif exist \"%MEDIA_SCANNER_FOLDER%\" xcopy \"%MEDIA_SCANNER_FOLDER%\" \"%SERVER_FOLDER%\" /E /I /Y"
  }
]