From d5c072584ee6f81305ed85de8759658ab7854606 Mon Sep 17 00:00:00 2001 From: "Marc A. Valle" Date: Fri, 25 Jun 2021 16:45:26 -0700 Subject: [PATCH] Release 2021.4.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New in This Release =================== * Updated dispatcher API to 2.4 * Advanced OpenVINO interop sample w/ remoteBlob support (Linux only) * C++ API and Samples (Preview) * Python API and Samples (Preview) * Added logging capability to Dispatcher * Added new tools: sample_multi_transcode and decvpp_tool * Added debug libraries to Windows package For more information on the preview C++/Python APIs and Samples, see https://software.intel.com/content/www/us/en/develop/articles/onevpl-preview-examples.html Issues and Limitations ====================== C++/Python previews ------------------- * This is a preview release made available to gather feedback for API improvements. Compatibility with future releases is not guaranteed. Dispatcher ---------- * MFXInit() and MFXInitEx() functions have been deprecated in the 2.0 oneVPL Specification. Use MFXLoad() instead. See the transition guide for more details. * If initialized with MFXInit() or MFXInitEx(), support is limited to the 1.x API and will load Intel(R) Media SDK hardware library rather than oneVPL hardware library. * If both Intel(R) Media SDK and oneVPL hardware libraries are installed, only oneVPL libraries will be loaded via MFXLoad(). See the oneVPL specification for more details. * The Media SDK runtimes enabling legacy GPU hardware only provide API features up to 1.35, even when initialized with MFXLoad. For more details, see [Upgrading from IntelĀ® Media SDK to IntelĀ® oneAPI Video Processing Library](https://software.intel.com/content/www/us/en/develop/articles/upgrading-from-msdk-to-onevpl.html). * The libmfx.dll and libmfx.so.2021.1.11 dispatchers are deprecated. They are provided for backwards compatibility only and will be removed from a future release. They do not include any changes since the 2021.1.1 release. * Dispatcher support has been extended to include hardware implementations, including those that implement API versions lower then 2.0. Applications patterned after the 2021.1.1 release samples, rather than the 2.0 specification may fail after re-build as the previous sample code made the assumption that 2.0 APIs would be available. To remedy this please follow the coding patterns in the [oneVPL spec](https://spec.oneapi.com/versions/latest/elements/oneVPL/source/API_ref/VPL_disp_api_func.html#_CPPv47MFXLoadv) Tools and samples ----------------- * Encode B-frame distance setting is inconsistent between CPU and GPU implementations. For the CPU implementation 0 means no B-frames, while for the GPU implementation 1 means no B-frames. * Colorspace flags are required when using sample_* tools, if colorspace is not set tools will fail. * Input size should be aligned to 16 bytes for sample_encode. * The sample_multi_transcode tool included in this release is only intended for GPU operation to remain more closely aligned with the version of this tool released with Intel(R) Media SDK. * The sample_multi_transcode tool has a synchronization issue in 1->N pipelines. When decode is faster than encoders, the issue can cause the free frames consumed faster than the framework released, eventually resulting in tool crash when there is no more memory available. * hello-transcode sample only supports the oneVPL CPU implementation in this release. * sample_decode may stop responding if the input is switched between multiple resolutions. * sample_encode occasionally hangs for (CPU) SVT-HEVC encodes when using VBR in Ubuntu 18.04. * sample_encode does not work if the input is scaled or color converted. * sample_encode, sample_decode, and sample_vpp are not in sync with Media SDK's version of these tools. This will be corrected in future releases. * Windows samples are installed to C:\Program Files (x86)\Intel\oneAPI\vpl\latest\examples by default. This should not be a writable location, so you will not be able to build samples here. To build examples, copy this folder to another location first. * When configuring systems to run the OpenVINO interop samples in Linux gmmlib version conflicts can occur. Debug shows undefined GmmLib symbols as the cause of a runtime error. This can be mitigated by using the media stack integrated with OpenVINO installation. Uninstall other versions of libva, iHD, and libgmm then select Media SDK when installing OpenVINO as described in the [OpenVINO install documentation](https://docs.openvinotoolkit.org/latest/openvino_docs_install_guides_installing_openvino_linux.html#install-openvino). --- .gitattributes | 1 + .github/CODEOWNERS | 4 + .pre-commit-config.yaml | 42 +- .pylintrc | 3 +- CMakeLists.txt | 131 +- INSTALL.md | 144 + README.md | 151 +- api/CMakeLists.txt | 10 +- api/vpl/mfx.h | 25 + api/vpl/mfxadapter.h | 2 +- api/vpl/mfxbrc.h | 2 +- api/vpl/mfxcommon.h | 17 +- api/vpl/mfxdefs.h | 144 +- api/vpl/mfxdispatcher.h | 64 +- api/vpl/mfxdispatcherprefixedfunctions.h | 2 +- api/vpl/mfximplcaps.h | 4 +- api/vpl/mfxjpeg.h | 2 +- api/vpl/mfxmvc.h | 2 +- api/vpl/mfxpcp.h | 2 +- api/vpl/mfxsession.h | 13 +- api/vpl/mfxstructures.h | 276 +- api/vpl/mfxvideo++.h | 82 +- api/vpl/mfxvideo.h | 2 +- api/vpl/mfxvp8.h | 2 +- api/vpl/preview/README.txt | 2 + api/vpl/preview/bitstream.hpp | 301 + api/vpl/preview/defs.hpp | 284 + api/vpl/preview/detail/frame_interface.hpp | 151 + api/vpl/preview/detail/sdk_callable.hpp | 85 + api/vpl/preview/detail/string_helpers.hpp | 426 ++ api/vpl/preview/detail/variant.hpp | 124 + api/vpl/preview/exception.hpp | 167 + api/vpl/preview/extension_buffer.hpp | 1010 ++++ api/vpl/preview/extension_buffer_list.hpp | 957 +++ api/vpl/preview/frame_pool.hpp | 82 + api/vpl/preview/frame_surface.hpp | 290 + api/vpl/preview/future.hpp | 196 + api/vpl/preview/impl_caps.hpp | 745 +++ api/vpl/preview/impl_selector.hpp | 139 + api/vpl/preview/options.hpp | 87 + api/vpl/preview/payload.hpp | 190 + api/vpl/preview/property_name.hpp | 303 + api/vpl/preview/session.hpp | 894 +++ api/vpl/preview/source_reader.hpp | 344 ++ api/vpl/preview/stat.hpp | 147 + api/vpl/preview/video_param.hpp | 775 +++ api/vpl/preview/vpl.hpp | 25 + cmake/CompileOptions.cmake | 43 + cmake/oneAPIInstallDirs.cmake | 85 +- dispatcher/CMakeLists.txt | 74 +- dispatcher/cmake/VPLConfig.cmake.in | 74 +- dispatcher/cmake/VPLConfigVersion.cmake.in | 2 +- dispatcher/linux/device_ids.h | 12 +- dispatcher/pkgconfig/vpl.pc.in | 4 +- dispatcher/vpl/mfx_dispatcher_vpl.cpp | 27 +- dispatcher/vpl/mfx_dispatcher_vpl.h | 174 +- dispatcher/vpl/mfx_dispatcher_vpl_config.cpp | 495 +- dispatcher/vpl/mfx_dispatcher_vpl_loader.cpp | 612 +- dispatcher/vpl/mfx_dispatcher_vpl_log.cpp | 63 + dispatcher/vpl/mfx_dispatcher_vpl_log.h | 75 + dispatcher/vpl/mfx_dispatcher_vpl_msdk.cpp | 315 +- dispatcher/windows/main.cpp | 3 +- dispatcher/windows/mfx_dxva2_device.cpp | 11 + dispatcher/windows/mfx_dxva2_device.h | 3 + dispatcher/windows/mfx_library_iterator.cpp | 46 +- dispatcher/windows/mfx_library_iterator.h | 13 +- docker/Dockerfile-centos-7 | 3 +- docker/Dockerfile-centos-8 | 3 +- docker/Dockerfile-rhel-8 | 9 +- docker/Dockerfile-ubuntu-18.04 | 1 + docker/Dockerfile-ubuntu-19.10 | 52 - docker/Dockerfile-ubuntu-20.04 | 1 + docker/README.md | 26 + docker/build_docker_images.sh | 8 +- docker/tutorial/Dockerfile | 35 - docker/tutorial/README.md | 155 - docker/tutorial/run.sh | 5 - doxygen/Doxyfile | 2663 +++++++++ doxygen/assets/custom.js | 6 + doxygen/assets/customdoxygen.css | 547 ++ doxygen/build_docs.bat | 12 + doxygen/build_docs.sh | 11 + doxygen/footer.html | 11 + doxygen/header.html | 52 + doxygen/mainpage.md | 158 + env/CMakeLists.txt | 39 +- env/bash/vars.sh | 116 - env/cmd/vars.bat | 54 +- env/cmd/{vars32.bat => varsxx.bat.in} | 27 +- env/sh/vars.sh.in | 213 + examples/CMakeLists.txt | 46 +- examples/CPPLINT.cfg | 1 + .../legacy-decode/CMakeLists.txt | 28 +- .../legacy-decode}/License.txt | 0 .../legacy-decode/README.md | 0 .../legacy-decode/sample.json | 0 .../legacy-decode/src/legacy-decode.cpp | 9 +- .../util => coreAPI/legacy-decode/src}/util.h | 73 +- .../legacy-encode/CMakeLists.txt | 28 +- .../legacy-encode}/License.txt | 0 .../legacy-encode}/PreLoad.cmake | 0 .../legacy-encode/README.md | 0 .../legacy-encode/sample.json | 0 .../legacy-encode/src/legacy-encode.cpp | 9 +- examples/coreAPI/legacy-encode/src/util.h | 628 ++ .../legacy-vpp/CMakeLists.txt | 28 +- .../legacy-vpp}/License.txt | 0 .../{preview => coreAPI}/legacy-vpp/README.md | 0 .../legacy-vpp/sample.json | 0 .../legacy-vpp/src/legacy-vpp.cpp | 8 +- examples/coreAPI/legacy-vpp/src/util.h | 628 ++ examples/dpcpp-blur/CMakeLists.txt | 96 - examples/dpcpp-blur/README.md | 141 - examples/dpcpp-blur/sample.json | 36 - examples/dpcpp-blur/src/dpcpp-blur.cpp | 424 -- examples/hello-decode/README.md | 135 - examples/hello-decode/sample.json | 35 - examples/hello-decode/src/hello-decode.cpp | 223 - examples/hello-encode/CMakeLists.txt | 76 - examples/hello-encode/README.md | 130 - examples/hello-encode/sample.json | 35 - examples/hello-encode/src/hello-encode.cpp | 208 - examples/hello-vpp/CMakeLists.txt | 76 - examples/hello-vpp/PreLoad.cmake | 6 - examples/hello-vpp/README.md | 130 - examples/hello-vpp/src/hello-vpp.cpp | 212 - .../hello-createsession/CMakeLists.txt | 30 +- .../hello-createsession}/License.txt | 0 .../hello-createsession/PreLoad.cmake | 0 .../{ => hello}/hello-createsession/README.md | 2 +- .../hello-createsession/sample.json | 0 .../src/hello-createsession.cpp | 20 +- examples/hello/hello-createsession/src/util.h | 628 ++ examples/hello/hello-decode/README.md | 1 + .../{ => hello}/hello-decvpp/CMakeLists.txt | 30 +- .../hello-decvpp}/License.txt | 0 .../hello-decvpp}/PreLoad.cmake | 0 examples/{ => hello}/hello-decvpp/README.md | 0 examples/{ => hello}/hello-decvpp/sample.json | 0 .../hello-decvpp/src/hello-decvpp.cpp | 204 +- examples/hello/hello-decvpp/src/util.h | 628 ++ examples/hello/hello-encode/README.md | 1 + .../hello-transcode/CMakeLists.txt | 30 +- .../{ => hello}/hello-transcode/License.txt | 0 .../{ => hello}/hello-transcode/README.md | 0 .../{ => hello}/hello-transcode/sample.json | 0 .../hello-transcode/src/hello-transcode.cpp | 91 +- examples/hello/hello-transcode/src/util.h | 628 ++ examples/hello/hello-vpp/README.md | 1 + .../advanced-decvpp-infer/CMakeLists.txt | 98 + .../advanced-decvpp-infer}/CPPLINT.cfg | 0 .../advanced-decvpp-infer}/License.txt | 0 .../advanced-decvpp-infer}/PreLoad.cmake | 0 .../interop/advanced-decvpp-infer/README.md | 113 + .../advanced-decvpp-infer}/sample.json | 22 +- .../src/advanced-decvpp-infer.cpp | 411 ++ .../interop/advanced-decvpp-infer/src/util.h | 593 ++ examples/interop/dpcpp-blur/README.md | 1 + .../hello-decode-infer/CMakeLists.txt | 28 +- .../hello-decode-infer}/CPPLINT.cfg | 0 .../hello-decode-infer/License.txt | 0 .../hello-decode-infer}/PreLoad.cmake | 0 .../hello-decode-infer/README.md | 0 .../hello-decode-infer/sample.json | 0 .../src/hello-decode-infer.cpp | 63 +- .../interop/hello-decode-infer/src/util.h | 628 ++ .../legacy-decode-infer/CMakeLists.txt | 28 +- .../interop/legacy-decode-infer/CPPLINT.cfg | 1 + .../legacy-decode-infer}/License.txt | 0 .../legacy-decode-infer/README.md | 0 .../legacy-decode-infer/sample.json | 0 .../src/legacy-decode-infer.cpp | 10 +- .../interop/legacy-decode-infer/src/util.h | 628 ++ .../preview/hello-decode-infer/PreLoad.cmake | 6 - .../legacy-createsession/CMakeLists.txt | 69 - .../preview/legacy-createsession/README.md | 119 - .../preview/legacy-createsession/sample.json | 35 - .../src/legacy-createsession.cpp | 83 - examples/preview/legacy-encode/License.txt | 18 - examples/preview/legacy-encode/PreLoad.cmake | 6 - examples/preview/legacy-vpp/License.txt | 18 - examples/util/CMakeLists.txt | 27 - modulefiles/CMakeLists.txt | 2 +- modulefiles/vpl | 43 +- preview/CMakeLists.txt | 4 + preview/README.txt | 6 + preview/cplusplus/CMakeLists.txt | 7 + preview/cplusplus/api/CMakeLists.txt | 20 + preview/cplusplus/examples/CMakeLists.txt | 16 + preview/cplusplus/examples/CPPLINT.cfg | 1 + .../examples/hello-decode-cpp/CMakeLists.txt | 31 + .../examples/hello-decode-cpp}/License.txt | 0 .../hello-decode-cpp/src/hello-decode.cpp | 237 + .../examples/hello-decode-cpp/src/util.hpp | 346 ++ .../examples/hello-encode-cpp/CMakeLists.txt | 31 + .../examples/hello-encode-cpp}/License.txt | 0 .../hello-encode-cpp/src/hello-encode.cpp | 182 + .../examples/hello-encode-cpp/src/util.hpp | 346 ++ preview/cplusplus/test/CMakeLists.txt | 10 + .../test/test-prop-cpp/CMakeLists.txt | 23 + .../cplusplus/test/test-prop-cpp/src/main.cpp | 97 + preview/python/CMakeLists.txt | 16 + preview/python/binding/CMakeLists.txt | 75 + preview/python/binding/CPPLINT.cfg | 1 + preview/python/binding/bitstream.cpp | 154 + preview/python/binding/defs.cpp | 262 + preview/python/binding/exception.cpp | 15 + preview/python/binding/extension_buffer.cpp | 390 ++ .../python/binding/extension_buffer_list.cpp | 88 + preview/python/binding/frame_pool.cpp | 18 + preview/python/binding/frame_surface.cpp | 44 + preview/python/binding/future.cpp | 10 + preview/python/binding/impl_caps.cpp | 248 + preview/python/binding/impl_selector.cpp | 19 + preview/python/binding/mfxstructures.cpp | 1766 ++++++ preview/python/binding/options.cpp | 63 + preview/python/binding/payload.cpp | 27 + preview/python/binding/property_name.cpp | 21 + preview/python/binding/session.cpp | 240 + preview/python/binding/source_reader.cpp | 126 + preview/python/binding/stat.cpp | 39 + preview/python/binding/video_param.cpp | 653 +++ preview/python/binding/vpl_python.cpp | 62 + preview/python/binding/vpl_python.hpp | 20 + preview/python/examples/CMakeLists.txt | 13 + .../examples/hello-decode-py/hello-decode.py | 122 + .../examples/hello-encode-py/hello-encode.py | 150 + .../python/examples/hello-vpp-py/hello-vpp.py | 136 + preview/python/unittest/test_extbuf.py | 941 +++ preview/python/unittest/test_general.py | 179 + requirements-dev.txt | 1 - requirements.txt | 1 + script/README.md | 4 + script/_buildopts.bat | 4 +- script/_buildopts.sh | 2 +- script/bootstrap | 5 +- script/bootstrap.bat | 9 +- script/build | 4 +- script/build.bat | 5 +- script/lint | 5 +- script/lint.bat | 7 +- third-party-programs.txt | 580 +- tools/cli/CMakeLists.txt | 34 +- .../cli/decvpp_tool}/CMakeLists.txt | 44 +- tools/cli/decvpp_tool/CPPLINT.cfg | 3 + tools/cli/decvpp_tool/decvpp_tool.cpp | 335 ++ tools/cli/decvpp_tool/util.hpp | 1028 ++++ tools/cli/vpl-common.h | 145 - tools/cli/vpl-decenc.cpp | 1153 ---- tools/cli/vpl-decode.cpp | 1088 ---- tools/cli/vpl-decvpp.cpp | 684 --- tools/cli/vpl-encode.cpp | 1260 ---- tools/cli/vpl-inspect.cpp | 14 +- tools/cli/vpl-new-dispatcher.cpp | 345 -- tools/cli/vpl-vpp.cpp | 1398 ----- tools/cli/vpl-vppenc.cpp | 1436 ----- tools/legacy/CMakeLists.txt | 3 +- .../CMakeLists.txt | 11 + .../mfx_multi_vpp.h | 90 + .../mfxastructures.h | 145 + .../mfxaudio.h | 57 + .../mfxdeprecated.h | 167 + .../mfxplugin.h | 528 ++ .../rotate_plugin_api.h | 29 + tools/legacy/metrics_monitor/CMakeLists.txt | 2 +- .../metrics_monitor/sample/CMakeLists.txt | 2 +- tools/legacy/sample_common/CMakeLists.txt | 18 +- .../sample_common/include/plugin_utils.h | 5 +- .../sample_common/include/sample_utils.h | 56 +- .../sample_common/include/sample_vpl_common.h | 38 - .../sample_common/include/time_statistics.h | 12 +- .../include/vpl_implementation_loader.h | 77 + .../legacy/sample_common/src/plugin_utils.cpp | 12 +- .../legacy/sample_common/src/sample_utils.cpp | 146 +- .../src/vpl_implementation_loader.cpp | 256 + tools/legacy/sample_decode/CMakeLists.txt | 2 +- .../sample_decode/include/pipeline_decode.h | 18 +- .../sample_decode/src/pipeline_decode.cpp | 66 +- .../sample_decode/src/sample_decode.cpp | 31 + tools/legacy/sample_encode/CMakeLists.txt | 2 +- .../sample_encode/include/pipeline_encode.h | 66 +- .../sample_encode/src/pipeline_encode.cpp | 570 +- .../sample_encode/src/sample_encode.cpp | 129 +- .../sample_multi_transcode/CMakeLists.txt | 55 + .../include/pipeline_transcode.h | 1146 ++++ .../include/sample_multi_transcode.h | 113 + .../include/transcode_utils.h | 106 + .../src/pipeline_transcode.cpp | 5215 +++++++++++++++++ .../src/sample_multi_transcode.cpp | 1708 ++++++ .../src/transcode_utils.cpp | 2778 +++++++++ tools/legacy/sample_vpp/CMakeLists.txt | 2 +- .../sample_vpp/include/sample_vpp_config.h | 2 - .../sample_vpp/include/sample_vpp_utils.h | 14 + tools/legacy/sample_vpp/src/sample_vpp.cpp | 190 +- .../sample_vpp/src/sample_vpp_parser.cpp | 22 +- .../sample_vpp/src/sample_vpp_utils.cpp | 135 +- version.txt | 2 +- 297 files changed, 42280 insertions(+), 12577 deletions(-) create mode 100644 .github/CODEOWNERS create mode 100644 INSTALL.md create mode 100644 api/vpl/mfx.h create mode 100644 api/vpl/preview/README.txt create mode 100644 api/vpl/preview/bitstream.hpp create mode 100644 api/vpl/preview/defs.hpp create mode 100644 api/vpl/preview/detail/frame_interface.hpp create mode 100644 api/vpl/preview/detail/sdk_callable.hpp create mode 100644 api/vpl/preview/detail/string_helpers.hpp create mode 100644 api/vpl/preview/detail/variant.hpp create mode 100644 api/vpl/preview/exception.hpp create mode 100644 api/vpl/preview/extension_buffer.hpp create mode 100644 api/vpl/preview/extension_buffer_list.hpp create mode 100644 api/vpl/preview/frame_pool.hpp create mode 100644 api/vpl/preview/frame_surface.hpp create mode 100644 api/vpl/preview/future.hpp create mode 100644 api/vpl/preview/impl_caps.hpp create mode 100644 api/vpl/preview/impl_selector.hpp create mode 100644 api/vpl/preview/options.hpp create mode 100644 api/vpl/preview/payload.hpp create mode 100644 api/vpl/preview/property_name.hpp create mode 100644 api/vpl/preview/session.hpp create mode 100644 api/vpl/preview/source_reader.hpp create mode 100644 api/vpl/preview/stat.hpp create mode 100644 api/vpl/preview/video_param.hpp create mode 100644 api/vpl/preview/vpl.hpp create mode 100644 dispatcher/vpl/mfx_dispatcher_vpl_log.cpp create mode 100644 dispatcher/vpl/mfx_dispatcher_vpl_log.h delete mode 100644 docker/Dockerfile-ubuntu-19.10 delete mode 100644 docker/tutorial/Dockerfile delete mode 100644 docker/tutorial/README.md delete mode 100755 docker/tutorial/run.sh create mode 100644 doxygen/Doxyfile create mode 100644 doxygen/assets/custom.js create mode 100644 doxygen/assets/customdoxygen.css create mode 100644 doxygen/build_docs.bat create mode 100644 doxygen/build_docs.sh create mode 100644 doxygen/footer.html create mode 100644 doxygen/header.html create mode 100644 doxygen/mainpage.md delete mode 100644 env/bash/vars.sh rename env/cmd/{vars32.bat => varsxx.bat.in} (54%) create mode 100644 env/sh/vars.sh.in rename examples/{preview => coreAPI}/legacy-decode/CMakeLists.txt (72%) rename examples/{dpcpp-blur => coreAPI/legacy-decode}/License.txt (100%) rename examples/{preview => coreAPI}/legacy-decode/README.md (100%) rename examples/{preview => coreAPI}/legacy-decode/sample.json (100%) rename examples/{preview => coreAPI}/legacy-decode/src/legacy-decode.cpp (96%) rename examples/{util/util => coreAPI/legacy-decode/src}/util.h (86%) rename examples/{preview => coreAPI}/legacy-encode/CMakeLists.txt (73%) rename examples/{hello-createsession => coreAPI/legacy-encode}/License.txt (100%) rename examples/{dpcpp-blur => coreAPI/legacy-encode}/PreLoad.cmake (100%) rename examples/{preview => coreAPI}/legacy-encode/README.md (100%) rename examples/{preview => coreAPI}/legacy-encode/sample.json (100%) rename examples/{preview => coreAPI}/legacy-encode/src/legacy-encode.cpp (96%) create mode 100644 examples/coreAPI/legacy-encode/src/util.h rename examples/{preview => coreAPI}/legacy-vpp/CMakeLists.txt (73%) rename examples/{hello-decode => coreAPI/legacy-vpp}/License.txt (100%) rename examples/{preview => coreAPI}/legacy-vpp/README.md (100%) rename examples/{preview => coreAPI}/legacy-vpp/sample.json (100%) rename examples/{preview => coreAPI}/legacy-vpp/src/legacy-vpp.cpp (96%) create mode 100644 examples/coreAPI/legacy-vpp/src/util.h delete mode 100644 examples/dpcpp-blur/CMakeLists.txt delete mode 100644 examples/dpcpp-blur/README.md delete mode 100644 examples/dpcpp-blur/sample.json delete mode 100644 examples/dpcpp-blur/src/dpcpp-blur.cpp delete mode 100644 examples/hello-decode/README.md delete mode 100644 examples/hello-decode/sample.json delete mode 100644 examples/hello-decode/src/hello-decode.cpp delete mode 100644 examples/hello-encode/CMakeLists.txt delete mode 100644 examples/hello-encode/README.md delete mode 100644 examples/hello-encode/sample.json delete mode 100644 examples/hello-encode/src/hello-encode.cpp delete mode 100644 examples/hello-vpp/CMakeLists.txt delete mode 100644 examples/hello-vpp/PreLoad.cmake delete mode 100644 examples/hello-vpp/README.md delete mode 100644 examples/hello-vpp/src/hello-vpp.cpp rename examples/{ => hello}/hello-createsession/CMakeLists.txt (70%) rename examples/{hello-decvpp => hello/hello-createsession}/License.txt (100%) rename examples/{ => hello}/hello-createsession/PreLoad.cmake (100%) rename examples/{ => hello}/hello-createsession/README.md (97%) rename examples/{ => hello}/hello-createsession/sample.json (100%) rename examples/{ => hello}/hello-createsession/src/hello-createsession.cpp (75%) create mode 100644 examples/hello/hello-createsession/src/util.h create mode 100644 examples/hello/hello-decode/README.md rename examples/{ => hello}/hello-decvpp/CMakeLists.txt (70%) rename examples/{hello-encode => hello/hello-decvpp}/License.txt (100%) rename examples/{hello-decode => hello/hello-decvpp}/PreLoad.cmake (100%) rename examples/{ => hello}/hello-decvpp/README.md (100%) rename examples/{ => hello}/hello-decvpp/sample.json (100%) rename examples/{ => hello}/hello-decvpp/src/hello-decvpp.cpp (56%) create mode 100644 examples/hello/hello-decvpp/src/util.h create mode 100644 examples/hello/hello-encode/README.md rename examples/{ => hello}/hello-transcode/CMakeLists.txt (70%) rename examples/{ => hello}/hello-transcode/License.txt (100%) rename examples/{ => hello}/hello-transcode/README.md (100%) rename examples/{ => hello}/hello-transcode/sample.json (100%) rename examples/{ => hello}/hello-transcode/src/hello-transcode.cpp (78%) create mode 100644 examples/hello/hello-transcode/src/util.h create mode 100644 examples/hello/hello-vpp/README.md create mode 100644 examples/interop/advanced-decvpp-infer/CMakeLists.txt rename examples/{preview/hello-decode-infer => interop/advanced-decvpp-infer}/CPPLINT.cfg (100%) rename examples/{hello-vpp => interop/advanced-decvpp-infer}/License.txt (100%) rename examples/{hello-decvpp => interop/advanced-decvpp-infer}/PreLoad.cmake (100%) create mode 100644 examples/interop/advanced-decvpp-infer/README.md rename examples/{hello-vpp => interop/advanced-decvpp-infer}/sample.json (54%) create mode 100644 examples/interop/advanced-decvpp-infer/src/advanced-decvpp-infer.cpp create mode 100644 examples/interop/advanced-decvpp-infer/src/util.h create mode 100644 examples/interop/dpcpp-blur/README.md rename examples/{preview => interop}/hello-decode-infer/CMakeLists.txt (75%) rename examples/{preview/legacy-decode-infer => interop/hello-decode-infer}/CPPLINT.cfg (100%) rename examples/{preview => interop}/hello-decode-infer/License.txt (100%) rename examples/{hello-encode => interop/hello-decode-infer}/PreLoad.cmake (100%) rename examples/{preview => interop}/hello-decode-infer/README.md (100%) rename examples/{preview => interop}/hello-decode-infer/sample.json (100%) rename examples/{preview => interop}/hello-decode-infer/src/hello-decode-infer.cpp (82%) create mode 100644 examples/interop/hello-decode-infer/src/util.h rename examples/{preview => interop}/legacy-decode-infer/CMakeLists.txt (75%) create mode 100644 examples/interop/legacy-decode-infer/CPPLINT.cfg rename examples/{preview/legacy-createsession => interop/legacy-decode-infer}/License.txt (100%) rename examples/{preview => interop}/legacy-decode-infer/README.md (100%) rename examples/{preview => interop}/legacy-decode-infer/sample.json (100%) rename examples/{preview => interop}/legacy-decode-infer/src/legacy-decode-infer.cpp (97%) create mode 100644 examples/interop/legacy-decode-infer/src/util.h delete mode 100644 examples/preview/hello-decode-infer/PreLoad.cmake delete mode 100644 examples/preview/legacy-createsession/CMakeLists.txt delete mode 100644 examples/preview/legacy-createsession/README.md delete mode 100644 examples/preview/legacy-createsession/sample.json delete mode 100644 examples/preview/legacy-createsession/src/legacy-createsession.cpp delete mode 100644 examples/preview/legacy-encode/License.txt delete mode 100644 examples/preview/legacy-encode/PreLoad.cmake delete mode 100644 examples/preview/legacy-vpp/License.txt delete mode 100644 examples/util/CMakeLists.txt create mode 100644 preview/CMakeLists.txt create mode 100644 preview/README.txt create mode 100644 preview/cplusplus/CMakeLists.txt create mode 100644 preview/cplusplus/api/CMakeLists.txt create mode 100644 preview/cplusplus/examples/CMakeLists.txt create mode 100644 preview/cplusplus/examples/CPPLINT.cfg create mode 100644 preview/cplusplus/examples/hello-decode-cpp/CMakeLists.txt rename {examples/preview/legacy-decode-infer => preview/cplusplus/examples/hello-decode-cpp}/License.txt (100%) create mode 100644 preview/cplusplus/examples/hello-decode-cpp/src/hello-decode.cpp create mode 100644 preview/cplusplus/examples/hello-decode-cpp/src/util.hpp create mode 100644 preview/cplusplus/examples/hello-encode-cpp/CMakeLists.txt rename {examples/preview/legacy-decode => preview/cplusplus/examples/hello-encode-cpp}/License.txt (100%) create mode 100644 preview/cplusplus/examples/hello-encode-cpp/src/hello-encode.cpp create mode 100644 preview/cplusplus/examples/hello-encode-cpp/src/util.hpp create mode 100644 preview/cplusplus/test/CMakeLists.txt create mode 100644 preview/cplusplus/test/test-prop-cpp/CMakeLists.txt create mode 100644 preview/cplusplus/test/test-prop-cpp/src/main.cpp create mode 100644 preview/python/CMakeLists.txt create mode 100644 preview/python/binding/CMakeLists.txt create mode 100644 preview/python/binding/CPPLINT.cfg create mode 100644 preview/python/binding/bitstream.cpp create mode 100644 preview/python/binding/defs.cpp create mode 100644 preview/python/binding/exception.cpp create mode 100644 preview/python/binding/extension_buffer.cpp create mode 100644 preview/python/binding/extension_buffer_list.cpp create mode 100644 preview/python/binding/frame_pool.cpp create mode 100644 preview/python/binding/frame_surface.cpp create mode 100644 preview/python/binding/future.cpp create mode 100644 preview/python/binding/impl_caps.cpp create mode 100644 preview/python/binding/impl_selector.cpp create mode 100644 preview/python/binding/mfxstructures.cpp create mode 100644 preview/python/binding/options.cpp create mode 100644 preview/python/binding/payload.cpp create mode 100644 preview/python/binding/property_name.cpp create mode 100644 preview/python/binding/session.cpp create mode 100644 preview/python/binding/source_reader.cpp create mode 100644 preview/python/binding/stat.cpp create mode 100644 preview/python/binding/video_param.cpp create mode 100644 preview/python/binding/vpl_python.cpp create mode 100644 preview/python/binding/vpl_python.hpp create mode 100644 preview/python/examples/CMakeLists.txt create mode 100644 preview/python/examples/hello-decode-py/hello-decode.py create mode 100644 preview/python/examples/hello-encode-py/hello-encode.py create mode 100644 preview/python/examples/hello-vpp-py/hello-vpp.py create mode 100644 preview/python/unittest/test_extbuf.py create mode 100644 preview/python/unittest/test_general.py create mode 100644 requirements.txt rename {examples/hello-decode => tools/cli/decvpp_tool}/CMakeLists.txt (59%) create mode 100644 tools/cli/decvpp_tool/CPPLINT.cfg create mode 100644 tools/cli/decvpp_tool/decvpp_tool.cpp create mode 100644 tools/cli/decvpp_tool/util.hpp delete mode 100644 tools/cli/vpl-common.h delete mode 100644 tools/cli/vpl-decenc.cpp delete mode 100644 tools/cli/vpl-decode.cpp delete mode 100644 tools/cli/vpl-decvpp.cpp delete mode 100644 tools/cli/vpl-encode.cpp delete mode 100644 tools/cli/vpl-new-dispatcher.cpp delete mode 100644 tools/cli/vpl-vpp.cpp delete mode 100644 tools/cli/vpl-vppenc.cpp create mode 100644 tools/legacy/media_sdk_compatibility_headers/CMakeLists.txt create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfx_multi_vpp.h create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxastructures.h create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxaudio.h create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxdeprecated.h create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxplugin.h create mode 100644 tools/legacy/media_sdk_compatibility_headers/rotate_plugin_api.h create mode 100644 tools/legacy/sample_common/include/vpl_implementation_loader.h create mode 100644 tools/legacy/sample_common/src/vpl_implementation_loader.cpp create mode 100644 tools/legacy/sample_multi_transcode/CMakeLists.txt create mode 100644 tools/legacy/sample_multi_transcode/include/pipeline_transcode.h create mode 100644 tools/legacy/sample_multi_transcode/include/sample_multi_transcode.h create mode 100644 tools/legacy/sample_multi_transcode/include/transcode_utils.h create mode 100644 tools/legacy/sample_multi_transcode/src/pipeline_transcode.cpp create mode 100644 tools/legacy/sample_multi_transcode/src/sample_multi_transcode.cpp create mode 100644 tools/legacy/sample_multi_transcode/src/transcode_utils.cpp diff --git a/.gitattributes b/.gitattributes index 4813a91e..b30c7199 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,6 +3,7 @@ # force line endings for scripts *.sh eol=lf +*.sh.in eol=lf *.py eol=lf script/* eol=lf *.bat eol=crlf diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..2ef32a31 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# Each line is a file pattern followed by one or more owners. +# last matching pattern takes the most precedence. + +* @intel-innersource/onevpl-maintainer diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1bc5e96b..76fa8848 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,8 +1,12 @@ +# pre-commit configuration file +# You may automatically run pre-commit when committing +# by installing hooks as follows: +# pre-commit install +# pre-commit install --hook-type commit-msg --- fail_fast: false default_language_version: python: python3 -exclude: ^test/unit/googletest/ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.5.0 @@ -12,25 +16,33 @@ repos: rev: v0.29.0 hooks: - id: yapf - - repo: https://github.com/pocc/pre-commit-hooks - rev: python + - repo: https://github.com/PyCQA/pylint + rev: v2.8.2 hooks: - - id: clang-format + - id: pylint + args: + [ + "--disable=import-error,no-name-in-module,duplicate-code", + ] - repo: https://github.com/iconmaster5326/cmake-format-pre-commit-hook - rev: master + rev: v0.6.9 hooks: - id: cmake-format - - repo: local + - repo: https://github.com/pocc/pre-commit-hooks + rev: v1.1.1 hooks: - - id: pylint - name: pylint - entry: pylint - language: system - types: [python] - - repo: local + - id: clang-format + args: [-i] + - repo: https://github.com/cpplint/cpplint + rev: 1.5.5 hooks: - id: cpplint - name: cpplint - entry: cpplint - language: system files: \.(h|hh|hpp|hxx|h|c|cc|cpp|cxx|c)$ + - repo: https://github.com/jorisroovers/gitlint + rev: v0.15.1 + hooks: + - id: gitlint + - repo: https://github.com/PyCQA/bandit + rev: 1.7.0 + hooks: + - id: bandit diff --git a/.pylintrc b/.pylintrc index 2ab65180..c88deebe 100644 --- a/.pylintrc +++ b/.pylintrc @@ -139,7 +139,8 @@ disable=print-statement, deprecated-sys-function, exception-escape, comprehension-escape, - R0801 + R0801, + no-member # Enable the message, report, category or checker with the given id(s). You can # either give multiple identifier separated by comma (,) or put this option diff --git a/CMakeLists.txt b/CMakeLists.txt index 3461776d..c236c22a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,7 +27,47 @@ if(NOT CMAKE_BUILD_TYPE) endif() # Project options -option(OPTION_COMPILE_PREVIEW_EXAMPLES "Build examples." OFF) +set(BUILD_DISPATCHER + ON + CACHE BOOL "Build dispatcher.") +set(BUILD_DEV + ON + CACHE BOOL "Build files that are only needed for development.") + +# Off by default while this is a preview +set(BUILD_PYTHON_BINDING + OFF + CACHE BOOL "Build Python binding.") + +option(BUILD_DISPATCHER_ONLY "Build dispatcher only." OFF) +option(BUILD_DEV_ONLY "Build only developer package." OFF) +option(BUILD_PYTHON_BINDING_ONLY "Build only Python binding." OFF) + +if(BUILD_DISPATCHER_ONLY) + set(BUILD_DEV OFF) + set(BUILD_PYTHON_BINDING OFF) +endif() +if(BUILD_DEV_ONLY) + set(BUILD_DISPATCHER OFF) + set(BUILD_PYTHON_BINDING OFF) +endif() +if(BUILD_PYTHON_BINDING_ONLY) + set(BUILD_DEV OFF) + set(BUILD_DISPATCHER OFF) +endif() + +option(USE_ONEAPI_INSTALL_LAYOUT "Use oneAPI install layout instead of FHS" OFF) + +if(USE_ONEAPI_INSTALL_LAYOUT) + set(CMAKE_INSTALL_DOCDIR "documentation") + set(CMAKE_INSTALL_LIBDIR "lib") + set(ONEAPI_INSTALL_ENVDIR "env") + set(ONEAPI_INSTALL_SYSCHECKDIR "sys_check") + set(ONEAPI_INSTALL_MODFILEDIR "modulefiles") + set(ONEAPI_INSTALL_EXAMPLEDIR "examples") + set(ONEAPI_INSTALL_LICENSEDIR "licensing/oneVPL") + set(ONEAPI_INSTALL_PYTHONDIR "python/lib") +endif() # Set output directories set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}) @@ -43,20 +83,97 @@ include(cmake/CompileOptions.cmake) add_subdirectory(api) add_subdirectory(dispatcher) -add_subdirectory(env) -add_subdirectory(modulefiles) -add_subdirectory(tools) -add_subdirectory(examples) +if(BUILD_DEV) + add_subdirectory(env) + add_subdirectory(modulefiles) + add_subdirectory(tools) + add_subdirectory(examples) +endif() +add_subdirectory(preview) install( FILES third-party-programs.txt - DESTINATION ${CMAKE_INSTALL_LICENSEDIR} + DESTINATION ${ONEAPI_INSTALL_LICENSEDIR} COMPONENT license) install( FILES LICENSE RENAME license.txt - DESTINATION ${CMAKE_INSTALL_LICENSEDIR} + DESTINATION ${ONEAPI_INSTALL_LICENSEDIR} COMPONENT license) +if(USE_ONEAPI_INSTALL_LAYOUT) + install( + FILES LICENSE + RENAME license.txt + DESTINATION "licensing" + COMPONENT license) +endif() + include(cmake/PackageTarget.cmake) + +message( + STATUS "---------------- Configuration summary ------------------------------" +) +message(STATUS "CMake:") +message(STATUS " CMAKE_VERSION : ${CMAKE_VERSION}") +message(STATUS " CMAKE_GENERATOR : ${CMAKE_GENERATOR}") +message(STATUS " CMAKE_BUILD_TOOL : ${CMAKE_BUILD_TOOL}") +message(STATUS "Target:") +message(STATUS " CMAKE_SYSTEM_NAME : ${CMAKE_SYSTEM_NAME}") +message(STATUS " CMAKE_SYSTEM_VERSION : ${CMAKE_SYSTEM_VERSION}") +message(STATUS " CMAKE_SYSTEM_PROCESSOR : ${CMAKE_SYSTEM_PROCESSOR}") +message(STATUS "General:") +message(STATUS " CMAKE_BUILD_TYPE : ${CMAKE_BUILD_TYPE}") +message(STATUS " CMAKE_TOOLCHAIN_FILE : ${CMAKE_TOOLCHAIN_FILE}") +message(STATUS " CMAKE_C_COMPILER : ${CMAKE_C_COMPILER}") +message(STATUS " CMAKE_CXX_COMPILER : ${CMAKE_CXX_COMPILER}") +if(CMAKE_SIZEOF_VOID_P EQUAL 8) + message(STATUS " Build architecture : 64-bit") +elseif(CMAKE_SIZEOF_VOID_P EQUAL 4) + message(STATUS " Build architecture : 32-bit") +endif() +message(STATUS "Flags:") +message(STATUS " CMAKE_C_FLAGS : ${CMAKE_C_FLAGS}") +message(STATUS " CMAKE_CXX_FLAGS : ${CMAKE_CXX_FLAGS}") +message(STATUS "Release flags:") +message(STATUS " CMAKE_C_FLAGS_RELEASE : ${CMAKE_C_FLAGS_RELEASE}") +message(STATUS " CMAKE_CXX_FLAGS_RELEASE : ${CMAKE_CXX_FLAGS_RELEASE}") +message(STATUS "Debug flags:") +message(STATUS " CMAKE_C_FLAGS_DEBUG : ${CMAKE_C_FLAGS_DEBUG}") +message(STATUS " CMAKE_CXX_FLAGS_DEBUG : ${CMAKE_CXX_FLAGS_DEBUG}") +message(STATUS "RelWithDebRT flags:") +message( + STATUS " CMAKE_C_FLAGS_RELWITHDEBRT : ${CMAKE_C_FLAGS_RELWITHDEBRT}") +message( + STATUS " CMAKE_CXX_FLAGS_RELWITHDEBRT : ${CMAKE_CXX_FLAGS_RELWITHDEBRT}") +message(STATUS "Install:") +message(STATUS " CMAKE_INSTALL_PREFIX : ${CMAKE_INSTALL_PREFIX}") +message( + STATUS " CMAKE_INSTALL_FULL_BINDIR : ${CMAKE_INSTALL_FULL_BINDIR}") +message( + STATUS " CMAKE_INSTALL_FULL_INCLUDEDIR : ${CMAKE_INSTALL_FULL_INCLUDEDIR}") +message( + STATUS " CMAKE_INSTALL_FULL_LIBDIR : ${CMAKE_INSTALL_FULL_LIBDIR}") +message( + STATUS " CMAKE_INSTALL_FULL_DOCDIR : ${CMAKE_INSTALL_FULL_DOCDIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_BIN32DIR : ${ONEAPI_INSTALL_FULL_BIN32DIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_LIB32DIR : ${ONEAPI_INSTALL_FULL_LIB32DIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_ENVDIR : ${ONEAPI_INSTALL_FULL_ENVDIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_SYSCHECKDIR: ${ONEAPI_INSTALL_FULL_SYSCHECKDIR}" +) +message( + STATUS " ONEAPI_INSTALL_FULL_MODFILEDIR : ${ONEAPI_INSTALL_FULL_MODFILEDIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_EXAMPLEDIR : ${ONEAPI_INSTALL_FULL_EXAMPLEDIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_LICENSEDIR : ${ONEAPI_INSTALL_FULL_LICENSEDIR}") +message( + STATUS " ONEAPI_INSTALL_FULL_PYTHONDIR : ${ONEAPI_INSTALL_FULL_PYTHONDIR}") +message(STATUS "Build:") +message(STATUS " BUILD_DEV : ${BUILD_DEV}") +message(STATUS " BUILD_DISPATCHER : ${BUILD_DISPATCHER}") diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 00000000..4672f30f --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,144 @@ +# Build/Install oneAPI Video Processing Library from Source + +This document describes how to build from the source code in this repo. +Please note: this repo contains only headers, dispatcher, examples, and tools. +In most cases an implementation must also be installed. + +## Prerequisites + +To build this project you will need: + +- A compiler with C++11 support +- CMake 3.10 or newer + +On Windows, you will also need: + +- Visual Studio Build Tools 2017 + * Visual C++ ATL for x86 and x64 +- Visual Studio 2019 + * C++ ATL for latest 'X' build tools (x86 & x64) + +## Basic build and installation of this package + +Build the project with the following commands: + +Linux: +``` +cd +export VPL_INSTALL_DIR=`pwd`/_vplbuild +mkdir _build +mkdir $VPL_INSTALL_DIR +cd _build +cmake .. -DCMAKE_INSTALL_PREFIX=$VPL_INSTALL_DIR +cmake --build . --config Release +cmake --build . --config Release --target install +``` + +Windows DOS cmd prompt: +``` +cd +export VPL_INSTALL_DIR=%cd%/_vplbuild +mkdir _build +mkdir %VPL_INSTALL_DIR% +cd _build +cmake .. -DCMAKE_INSTALL_PREFIX=%VPL_INSTALL_DIR% +cmake --build . --config Release +cmake --build . --config Release --target install +``` + +You can find the build output in the location chosen for CMAKE_INSTALL_PREFIX, VPL_INSTALL_DIR. + +For more build/install information see INSTALL.md + +## Helper scripts and options + +Additionally, helper scripts are available in the `script` folder to run these cmake commands. +For more details see script/README.md + +You can build the project using the helper scripts with the following commands. + +First, set VPL_INSTALL_DIR if you wish to override the defaults and supply your own build/install location. +``` +cd +script/bootstrap +script/build +script/install +``` +The build script can take an additional argument for 32-bit builds in Windows: +``` +script/build -A x86_32 +``` + +Note that on Linux the default vpl install location is /usr/local and may require sudo for write access + +Note that on Windows there may be an error with the following message: +``` +Cannot open include file: 'atlbase.h': No such file or directory +``` +Ensure that the ATL build tools are installed through Visual Studio and that the path to the file is on the include path that the Visual Studio compiler uses + +## Getting an Implementation + +The base package is limited to the dispatcher and samples. To use oneVPL for video processing you need to install at least one implementation. Current implementations: + +- [oneVPL-cpu](https://github.com/oneapi-src/oneVPL-cpu) for use on CPU +- [oneVPL-intel-gpu](https://github.com/oneapi-src/oneVPL-intel-gpu) for use on Intel Xe graphics and newer +- [Media SDK](https://github.com/Intel-Media-SDK/MediaSDK) for use on legacy Intel graphics + +Follow the instructions on the respective repos to install the desired implementation + +## End-To-End Scripts for oneVPL base and CPU implementation + +You can build oneVPL base and CPU implementation with the End-To-End scripts provided in the scripts folder. Refer to the script/README.md for more details regarding the scripts. + +These scripts assume oneVPL and oneVPL-cpu are cloned into the same parent folder. They also assume that the prerequisites have been met for their respective platform + +Note: `.bat` versions are also provided for Windows. + +Note: On Windows the e2e scripts need to first clean intermediate build results that were built outside the script + +Use the following commands to run the e2e scripts: + +``` +cd +oneVPL/script/e2e/bootstrap +oneVPL/script/e2e/build +``` + +Optionally you may set the environment variables VPL_INSTALL_DIR and +VPL_BUILD_DEPENDENCIES to specify a location to install the project and to +store the built dependencies respectivly. + + +``` +cd + +export VPL_BUILD_DEPENDENCIES= +export VPL_INSTALL_DIR= + +oneVPL/script/e2e/bootstrap +oneVPL/script/e2e/build +``` + +You can also clear build results by calling the clean script. +Note, if VPL_INSTALL_DIR is set it will be cleared too. + + +``` +cd + +oneVPL/script/e2e/clean +``` + +A complete rebuild can be forced by cleaning and then rebuilding. + +``` +cd + +export VPL_BUILD_DEPENDENCIES= +export VPL_INSTALL_DIR= + +oneVPL/script/e2e/clean +oneVPL/script/e2e/bootstrap +oneVPL/script/e2e/build +``` diff --git a/README.md b/README.md index 0cb42991..a8cf44e6 100644 --- a/README.md +++ b/README.md @@ -18,151 +18,15 @@ See the [oneAPI Specification](https://spec.oneapi.com) and the The version of the oneVPL API is listed in the [mfxdefs.h](./api/vpl/mfxdefs.h) file. -## Prerequisites +## Installation -To build this project you will need: +You can install oneVPL: -- A compiler with C++11 support -- CMake 3.10 or newer +- from [oneVPL home page](https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/onevpl.html) as a part of Intel® oneAPI Base Toolkit. -## Build and Installation of this package +### Installation from Source +See [Installation from Sources](INSTALL.md) for details. -Build the project with the following commands: - -``` -cd - -mkdir _build -cd _build -cmake .. -DCMAKE_INSTALL_PREFIX= -cmake --build . --config Release -# optional, create a portable zip file from the build -# cmake --build . --config Release --target package -cmake --build . --config Release --target install -``` - -You can find the build output in ``. - -Helper scripts are avalible in the `script` folder. - -- bootstrap : builds any dependencies (none at this time). Built dependencies will be placed in the location stored in VPL_BUILD_DEPENDENCIES if the variable is defined. -- clean : removes intermediate build results -- build : builds the package (all but the last step above) -- install : installs the package (the last step above). Package will be installed in the location stored in VPL_INSTALL_DIR if the variable is defined. -- test : run any smoke testing on the installed package - -You can build the project using the scripts with the follwoing commands -``` -cd -script/bootstrap -script/build -script/install -``` - -Optionaly the environment variable VPL_INSTALL_DIR can be set to specify a location for the scripts to install the project. - -## Getting an Implementation - -To use oneVPL for video processing you need to install at least one -implementation. Current implementations: - -- [oneVPL-cpu](https://github.com/oneapi-src/oneVPL-cpu), the CPU reference - implementation - -## Building Base and CPU Implementations - -Normally you don't just want to build the base package, which is limited to the dispatcher and samples. You want to -be able to do actual work like decoding video. To do this you need an implemetnation. As described above the CPU -implementation is delivered alongside the Base package. - -You can extend the project build commands above as follows to also build the CPU implementation. - -``` -cd - -mkdir _build -cd _build -cmake .. -DCMAKE_INSTALL_PREFIX= -cmake --build . --config Release -cmake --build . --config Release --target package -cmake --build . --config Release --target install - -cd - -# optional, specify an external cache folder to store dependencies -export VPL_BUILD_DEPENDENCIES= - -# Build 3rd party dependencies. -source script/bootstrap - -mkdir _build -cd _build -cmake .. -DCMAKE_INSTALL_PREFIX= -cmake --build . --config Release -cmake --build . --config Release --target package -cmake --build . --config Release --target install -``` - -You can find the build output in ``. - -Helper scripts to build Base and CPU implemenation are avalible in the `script/e2e` folder. - -- bootstrap : builds any dependencies. -- clean : removes intermediate build results -- build : builds and installs the package -- test : run any smoke testing on the installed package - -These scripts assume oneVPL and oneVPL-cpu are cloned into the same parent folder - -Note: `.bat` versions are also provided for Windows. - -### Using End-To-End Scripts - -You can build oneVPL base and CPU implementation with the End-To-End scripts using the following commands: - -``` -cd -oneVPL/script/e2e/bootstrap -oneVPL/script/e2e/build -``` - -Optionaly you may set the environment variables VPL_INSTALL_DIR and -VPL_BUILD_DEPENDENCIES to specify a location to install the project and to -store the built dependencies respectivly. - - -``` -cd - -export VPL_BUILD_DEPENDENCIES= -export VPL_INSTALL_DIR= - -oneVPL/script/e2e/bootstrap -oneVPL/script/e2e/build -``` - -You can also clear build results by calling the clean script. -Note, if VPL_INSTALL_DIR is set it will be cleared too. - - -``` -cd - -oneVPL/script/e2e/clean -``` - -A complete rebuild can be forced by cleaning and then rebuilding. - -``` -cd - -export VPL_BUILD_DEPENDENCIES= -export VPL_INSTALL_DIR= - -oneVPL/script/e2e/clean -oneVPL/script/e2e/bootstrap -oneVPL/script/e2e/build -``` ## Developer Usage @@ -174,15 +38,14 @@ headers. For Linux: ``` -source /env/vars.sh +source /share/oneVPL/env/vars.sh ``` For Windows: ``` -\env\vars.bat +\share\oneVPL\env\vars.bat ``` - ### Link to oneVPL with CMake Add the following code to your CMakeLists, assuming TARGET is defined as the diff --git a/api/CMakeLists.txt b/api/CMakeLists.txt index 3ec55b5f..ddf5cb5b 100644 --- a/api/CMakeLists.txt +++ b/api/CMakeLists.txt @@ -33,7 +33,9 @@ add_library(vpl-api INTERFACE) target_include_directories(vpl-api INTERFACE ${VPL_API_INCLUDE_DIR}) -install( - DIRECTORY ${VPL_API_INCLUDE_DIR}/vpl - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - COMPONENT dev) +if(BUILD_DEV) + install( + DIRECTORY ${VPL_API_INCLUDE_DIR}/vpl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + COMPONENT dev) +endif() diff --git a/api/vpl/mfx.h b/api/vpl/mfx.h new file mode 100644 index 00000000..92ad521a --- /dev/null +++ b/api/vpl/mfx.h @@ -0,0 +1,25 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFX_H__ +#define __MFX_H__ + +#include "mfxdefs.h" +#include "mfxcommon.h" +#include "mfxstructures.h" +#include "mfxdispatcher.h" +#include "mfximplcaps.h" +#include "mfxsession.h" +#include "mfxvideo.h" +#include "mfxadapter.h" + +#include "mfxbrc.h" +#include "mfxmvc.h" +#include "mfxpcp.h" +#include "mfxvp8.h" +#include "mfxjpeg.h" + +#endif /* __MFXDEFS_H__ */ diff --git a/api/vpl/mfxadapter.h b/api/vpl/mfxadapter.h index 4d040a06..5d0679f4 100644 --- a/api/vpl/mfxadapter.h +++ b/api/vpl/mfxadapter.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2019-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ diff --git a/api/vpl/mfxbrc.h b/api/vpl/mfxbrc.h index 9ddd69fb..bd876c38 100644 --- a/api/vpl/mfxbrc.h +++ b/api/vpl/mfxbrc.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2019-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ diff --git a/api/vpl/mfxcommon.h b/api/vpl/mfxcommon.h index 90a2f3d1..6dee96ef 100644 --- a/api/vpl/mfxcommon.h +++ b/api/vpl/mfxcommon.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2018-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ @@ -172,7 +172,7 @@ typedef struct { } mfxExtThreadsParam; MFX_PACK_END() -/*! The PlatformCodeName enumerator itemizes microarchitecture code names for the Legacy mode. +/*! The PlatformCodeName enumerator itemizes product code names for platforms. For details about Intel code names, see ark.intel.com. */ enum { MFX_PLATFORM_UNKNOWN = 0, /*!< Unknown platform. */ @@ -192,6 +192,11 @@ enum { MFX_PLATFORM_JASPERLAKE = 32, /*!< Code name Jasper Lake. */ MFX_PLATFORM_ELKHARTLAKE = 33, /*!< Code name Elkhart Lake. */ MFX_PLATFORM_TIGERLAKE = 40, /*!< Code name Tiger Lake. */ + MFX_PLATFORM_ROCKETLAKE = 42, /*!< Code name Rocket Lake. */ + MFX_PLATFORM_ALDERLAKE_S = 43, /*!< Code name Alder Lake S. */ + MFX_PLATFORM_ALDERLAKE_P = 44, /*!< Code name Alder Lake P. */ + MFX_PLATFORM_ARCTICSOUND_P = 45, + MFX_PLATFORM_XEHP_SDV = 45, /*!< Code name XeHP SDV. */ MFX_PLATFORM_KEEMBAY = 50, /*!< Code name Keem Bay. */ }; @@ -370,7 +375,6 @@ typedef enum { MFX_ACCEL_MODE_VIA_HDDLUNITE = 0x0500, /*!< Hardware acceleration goes through the HDDL* Unite*. */ } mfxAccelerationMode; - #define MFX_ACCELERATIONMODESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) MFX_PACK_BEGIN_STRUCT_W_PTR() @@ -427,7 +431,10 @@ MFX_PACK_END() /* The mfxImplCapsDeliveryFormat enumerator specifies delivery format of the implementation capability. */ typedef enum { MFX_IMPLCAPS_IMPLDESCSTRUCTURE = 1, /*!< Deliver capabilities as mfxImplDescription structure. */ - MFX_IMPLCAPS_IMPLEMENTEDFUNCTIONS = 2 /*!< Deliver capabilities as mfxImplementedFunctions structure. */ + MFX_IMPLCAPS_IMPLEMENTEDFUNCTIONS = 2, /*!< Deliver capabilities as mfxImplementedFunctions structure. */ + MFX_IMPLCAPS_IMPLPATH = 3 /*!< Deliver pointer to the null-terminated string with the path to the + implementation. String is delivered in a form of buffer of + mfxChar type. */ } mfxImplCapsDeliveryFormat; MFX_PACK_BEGIN_STRUCT_W_PTR() @@ -438,7 +445,7 @@ typedef struct { mfxU16 reserved[3]; /*!< Reserved for future use. */ mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ mfxExtBuffer **ExtParam; /*!< Points to an array of pointers to the extra configuration structures; see the ExtendedBufferID enumerator for a list of extended configurations. */ - mfxU32 VendorImplID; /*!< Vendor specific number with given implementation ID. Represents the same filed from mfxImplDescription. */ + mfxU32 VendorImplID; /*!< Vendor specific number with given implementation ID. Represents the same field from mfxImplDescription. */ mfxU32 reserved2[3]; /*!< Reserved for future use. */ } mfxInitializationParam; MFX_PACK_END() diff --git a/api/vpl/mfxdefs.h b/api/vpl/mfxdefs.h index 14cece02..4b4a6e30 100644 --- a/api/vpl/mfxdefs.h +++ b/api/vpl/mfxdefs.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2019-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ @@ -8,7 +8,7 @@ #define __MFXDEFS_H__ #define MFX_VERSION_MAJOR 2 -#define MFX_VERSION_MINOR 2 +#define MFX_VERSION_MINOR 4 // MFX_VERSION - version of API that 'assumed' by build may be provided externally // if it omitted then latest stable API derived from Major.Minor is assumed @@ -27,7 +27,7 @@ /*! The corresponding version of the Intel(r) Media SDK legacy API that is used as a basis for the current API. */ -#define MFX_LEGACY_VERSION 1034 +#define MFX_LEGACY_VERSION 1035 #ifdef __cplusplus @@ -85,52 +85,48 @@ extern "C" #define MFX_INFINITE 0xFFFFFFFF -#if !defined(MFX_DEPRECATED_OFF) && (MFX_VERSION < MFX_VERSION_NEXT) -#define MFX_DEPRECATED_OFF -#endif - #ifndef MFX_DEPRECATED_OFF - #if defined(__cplusplus) && __cplusplus >= 201402L - #define MFX_DEPRECATED [[deprecated]] - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg [[deprecated]] - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) - #elif defined(__clang__) - #define MFX_DEPRECATED __attribute__((deprecated)) - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) - #elif defined(__INTEL_COMPILER) - #if (defined(_WIN32) || defined(_WIN64)) - #define MFX_DEPRECATED __declspec(deprecated) - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) - #elif defined(__linux__) - #define MFX_DEPRECATED __attribute__((deprecated)) - #if defined(__cplusplus) - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) - #else - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg - #endif - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) - #endif - #elif defined(_MSC_VER) && _MSC_VER > 1200 // VS 6 doesn't support deprecation - #define MFX_DEPRECATED __declspec(deprecated) - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) - #elif defined(__GNUC__) - #define MFX_DEPRECATED __attribute__((deprecated)) - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) - #else - #define MFX_DEPRECATED - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) - #endif -#else - #define MFX_DEPRECATED - #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg - #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) -#endif - + #if defined(__cplusplus) && __cplusplus >= 201402L + #define MFX_DEPRECATED [[deprecated]] + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg [[deprecated]] + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) + #elif defined(__clang__) + #define MFX_DEPRECATED __attribute__((deprecated)) + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) + #elif defined(__INTEL_COMPILER) + #if (defined(_WIN32) || defined(_WIN64)) + #define MFX_DEPRECATED __declspec(deprecated) + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) + #elif defined(__linux__) + #define MFX_DEPRECATED __attribute__((deprecated)) + #if defined(__cplusplus) + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) + #else + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg + #endif + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) + #endif + #elif defined(_MSC_VER) && _MSC_VER > 1200 // VS 6 doesn't support deprecation + #define MFX_DEPRECATED __declspec(deprecated) + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) + #elif defined(__GNUC__) + #define MFX_DEPRECATED __attribute__((deprecated)) + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) + #else + #define MFX_DEPRECATED + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) + #endif + #else + #define MFX_DEPRECATED + #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg + #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) + #endif + typedef unsigned char mfxU8; /*!< Unsigned integer, 8 bit type. */ typedef char mfxI8; /*!< Signed integer, 8 bit type. */ typedef short mfxI16; /*!< Signed integer, 16 bit type. */ @@ -180,20 +176,35 @@ MFX_PACK_END() #define MFX_VARIANT_VERSION MFX_STRUCT_VERSION(1, 0) -/*! The mfxVariantType enumerator data types for mfxVarianf type. */ +/*! The mfxDataType enumerates data type for mfxDataType. */ +typedef enum { + MFX_DATA_TYPE_UNSET = 0, /*!< Undefined type. */ + MFX_DATA_TYPE_U8, /*!< 8-bit unsigned integer. */ + MFX_DATA_TYPE_I8, /*!< 8-bit signed integer. */ + MFX_DATA_TYPE_U16, /*!< 16-bit unsigned integer. */ + MFX_DATA_TYPE_I16, /*!< 16-bit signed integer. */ + MFX_DATA_TYPE_U32, /*!< 32-bit unsigned integer. */ + MFX_DATA_TYPE_I32, /*!< 32-bit signed integer. */ + MFX_DATA_TYPE_U64, /*!< 64-bit unsigned integer. */ + MFX_DATA_TYPE_I64, /*!< 64-bit signed integer. */ + MFX_DATA_TYPE_F32, /*!< 32-bit single precision floating point. */ + MFX_DATA_TYPE_F64, /*!< 64-bit double precision floating point. */ +}mfxDataType; + +/*! The mfxVariantType enumerator data types for mfxVariantType. */ typedef enum { - MFX_VARIANT_TYPE_UNSET = 0, /*!< Undefined type. */ - MFX_VARIANT_TYPE_U8 = 1, /*!< 8-bit unsigned integer. */ - MFX_VARIANT_TYPE_I8, /*!< 8-bit signed integer. */ - MFX_VARIANT_TYPE_U16, /*!< 16-bit unsigned integer. */ - MFX_VARIANT_TYPE_I16, /*!< 16-bit signed integer. */ - MFX_VARIANT_TYPE_U32, /*!< 32-bit unsigned integer. */ - MFX_VARIANT_TYPE_I32, /*!< 32-bit signed integer. */ - MFX_VARIANT_TYPE_U64, /*!< 64-bit unsigned integer. */ - MFX_VARIANT_TYPE_I64, /*!< 64-bit signed integer. */ - MFX_VARIANT_TYPE_F32, /*!< 32-bit single precision floating point. */ - MFX_VARIANT_TYPE_F64, /*!< 64-bit double precision floating point. */ - MFX_VARIANT_TYPE_PTR, /*!< Generic type pointer. */ + MFX_VARIANT_TYPE_UNSET = MFX_DATA_TYPE_UNSET, /*!< Undefined type. */ + MFX_VARIANT_TYPE_U8 = MFX_DATA_TYPE_U8, /*!< 8-bit unsigned integer. */ + MFX_VARIANT_TYPE_I8 = MFX_DATA_TYPE_I8, /*!< 8-bit signed integer. */ + MFX_VARIANT_TYPE_U16 = MFX_DATA_TYPE_U16, /*!< 16-bit unsigned integer. */ + MFX_VARIANT_TYPE_I16 = MFX_DATA_TYPE_I16, /*!< 16-bit signed integer. */ + MFX_VARIANT_TYPE_U32 = MFX_DATA_TYPE_U32, /*!< 32-bit unsigned integer. */ + MFX_VARIANT_TYPE_I32 = MFX_DATA_TYPE_I32, /*!< 32-bit signed integer. */ + MFX_VARIANT_TYPE_U64 = MFX_DATA_TYPE_U64, /*!< 64-bit unsigned integer. */ + MFX_VARIANT_TYPE_I64 = MFX_DATA_TYPE_I64, /*!< 64-bit signed integer. */ + MFX_VARIANT_TYPE_F32 = MFX_DATA_TYPE_F32, /*!< 32-bit single precision floating point. */ + MFX_VARIANT_TYPE_F64 = MFX_DATA_TYPE_F64, /*!< 64-bit double precision floating point. */ + MFX_VARIANT_TYPE_PTR, /*!< Generic type pointer. */ } mfxVariantType; MFX_PACK_BEGIN_STRUCT_W_PTR() @@ -298,6 +309,17 @@ typedef enum } mfxStatus; +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Represents Globally Unique Identifier (GUID) with memory layout + compliant to RFC 4122. See https://www.rfc-editor.org/info/rfc4122 for details. */ +typedef struct +{ + mfxU8 Data[16]; /*!< Array to keep GUID. */ +} mfxGUID; +MFX_PACK_END() + + + // Application #if defined(MFX_DISPATCHER_EXPOSED_PREFIX) diff --git a/api/vpl/mfxdispatcher.h b/api/vpl/mfxdispatcher.h index 8db716b6..cbf07dfb 100644 --- a/api/vpl/mfxdispatcher.h +++ b/api/vpl/mfxdispatcher.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ @@ -65,66 +65,6 @@ mfxConfig MFX_CDECL MFXCreateConfig(mfxLoader loader); @note Each new call with the same parameter name will overwrite the previously set value. This may invalidate other properties. @note Each new call with another parameter name will delete the previous property and create a new property based on new name's value. - Simple usage example: - @code - mfxLoader loader = MFXLoad(); - mfxConfig cfg = MFXCreateConfig(loader); - mfxVariant ImplValue; - ImplValue.Type = MFX_VARIANT_TYPE_U32; - ImplValue.Data.U32 = MFX_IMPL_TYPE_HARDWARE; - MFXSetConfigFilterProperty(cfg,"mfxImplDescription.Impl",ImplValue); - MFXCreateSession(loader,0,&session); - @endcode - - Usage example with two sessions (multiple loaders): - @code - // Create session with software based implementation - mfxLoader loader1 = MFXLoad(); - mfxConfig cfg1 = MFXCreateConfig(loader1); - mfxVariant ImplValueSW; - ImplValueSW.Type = MFX_VARIANT_TYPE_U32; - ImplValueSW.Data.U32 = MFX_IMPL_TYPE_SOFTWARE; - MFXSetConfigFilterProperty(cfg1,"mfxImplDescription.Impl",ImplValueSW); - MFXCreateSession(loader1,0,&sessionSW); - - // Create session with hardware based implementation - mfxLoader loader2 = MFXLoad(); - mfxConfig cfg2 = MFXCreateConfig(loader2); - mfxVariant ImplValueHW; - ImplValueHW.Type = MFX_VARIANT_TYPE_U32; - ImplValueHW.Data.U32 = MFX_IMPL_TYPE_HARDWARE; - MFXSetConfigFilterProperty(cfg2,"mfxImplDescription.Impl",ImplValueHW); - MFXCreateSession(loader2,0,&sessionHW); - - // use both sessionSW and sessionHW - // ... - // Close everything - MFXClose(sessionSW); - MFXClose(sessionHW); - MFXUnload(loader1); // cfg1 will be destroyed here. - MFXUnload(loader2); // cfg2 will be destroyed here. - @endcode - - Usage example with two decoders (multiple config objects): - @code - mfxLoader loader = MFXLoad(); - - mfxConfig cfg1 = MFXCreateConfig(loader); - mfxVariant ImplValue; - val.Type = MFX_VARIANT_TYPE_U32; - val.Data.U32 = MFX_CODEC_AVC; - MFXSetConfigFilterProperty(cfg1,"mfxImplDescription.mfxDecoderDescription.decoder.CodecID",ImplValue); - - mfxConfig cfg2 = MFXCreateConfig(loader); - mfxVariant ImplValue; - val.Type = MFX_VARIANT_TYPE_U32; - val.Data.U32 = MFX_CODEC_HEVC; - MFXSetConfigFilterProperty(cfg2,"mfxImplDescription.mfxDecoderDescription.decoder.CodecID",ImplValue); - - MFXCreateSession(loader,0,&sessionAVC); - MFXCreateSession(loader,0,&sessionHEVC); - @endcode - @param[in] config Config handle. @param[in] name Name of the parameter (see mfxImplDescription structure and example). @param[in] value Value of the parameter. @@ -193,7 +133,7 @@ mfxStatus MFX_CDECL MFXCreateSession(mfxLoader loader, mfxU32 i, mfxSession* ses /*! @brief - Destroys handle allocated by the MFXQueryImplsCapabilities function. + Destroys handle allocated by the MFXEnumImplementations function. @param[in] loader Loader handle. @param[in] hdl Handle to destroy. Can be equal to NULL. diff --git a/api/vpl/mfxdispatcherprefixedfunctions.h b/api/vpl/mfxdispatcherprefixedfunctions.h index 8bfdeabb..c9985654 100644 --- a/api/vpl/mfxdispatcherprefixedfunctions.h +++ b/api/vpl/mfxdispatcherprefixedfunctions.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2017-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ diff --git a/api/vpl/mfximplcaps.h b/api/vpl/mfximplcaps.h index 16851d0c..5c7f7638 100644 --- a/api/vpl/mfximplcaps.h +++ b/api/vpl/mfximplcaps.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ @@ -33,7 +33,7 @@ mfxHDL* MFX_CDECL MFXQueryImplsDescription(mfxImplCapsDeliveryFormat format, mfx /*! @brief - Destroys the handle allocated by the MFXQueryImplsCapabilities function. + Destroys the handle allocated by the MFXQueryImplsDescription function. Implementation must remember which handles are released. Once the last handle is released, this function must release memory allocated for the array of handles. diff --git a/api/vpl/mfxjpeg.h b/api/vpl/mfxjpeg.h index a5111fac..9faba266 100644 --- a/api/vpl/mfxjpeg.h +++ b/api/vpl/mfxjpeg.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2017-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ diff --git a/api/vpl/mfxmvc.h b/api/vpl/mfxmvc.h index 155d506a..e183acfd 100644 --- a/api/vpl/mfxmvc.h +++ b/api/vpl/mfxmvc.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2017-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ diff --git a/api/vpl/mfxpcp.h b/api/vpl/mfxpcp.h index 19c0ad03..efbfc590 100644 --- a/api/vpl/mfxpcp.h +++ b/api/vpl/mfxpcp.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2019-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ diff --git a/api/vpl/mfxsession.h b/api/vpl/mfxsession.h index e9c7127d..4dc4220f 100644 --- a/api/vpl/mfxsession.h +++ b/api/vpl/mfxsession.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2017-2020 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ @@ -49,6 +49,9 @@ typedef struct _mfxSession *mfxSession; MFX_ERR_UNSUPPORTED The function cannot find the desired legacy Intel(r) Media SDK implementation or version. @since This function is available since API version 1.0. + + @deprecated Deprecated in API version 2.3. Use MFXLoad and MFXCreateSession to initialize the session. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. */ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session); @@ -56,8 +59,7 @@ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSes @brief Creates and initializes a session in the legacy mode for compatibility with Intel(r) Media SDK applications. This function is deprecated starting from API version 2.0, applications must use MFXLoad with mfxCreateSession - to select the implementation and initialize the session. - + to select the implementation and initialize the session. Call this function before calling any other API functions. If the desired implementation specified by ``par`` is MFX_IMPL_AUTO, the function will search for @@ -72,7 +74,7 @@ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSes For example, if an application uses only H.264 decoding as described in API v1.0, the application should initialize the library with API v1.0. This ensures backward compatibility. The argument ``par.ExternalThreads`` specifies threading mode. Value 0 means that the implementation should create and - handle work threads internally (this is essentially the equivalent of the regular MFXInit). I + handle work threads internally (this is essentially the equivalent of the regular MFXInit). @param[in] par mfxInitParam structure that indicates the desired implementation, minimum library version and desired threading mode. @param[out] session Pointer to the session handle. @@ -82,6 +84,9 @@ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSes MFX_ERR_UNSUPPORTED The function cannot find the desired implementation or version. @since This function is available since API version 1.14. + + @deprecated Deprecated in API version 2.3. Use MFXLoad and MFXCreateSession to initialize the session. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. */ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInitEx(mfxInitParam par, mfxSession *session); diff --git a/api/vpl/mfxstructures.h b/api/vpl/mfxstructures.h index f2859797..9c8dd2b1 100644 --- a/api/vpl/mfxstructures.h +++ b/api/vpl/mfxstructures.h @@ -1,5 +1,5 @@ /*############################################################################ - # Copyright (C) 2018-2021 Intel Corporation + # Copyright Intel Corporation # # SPDX-License-Identifier: MIT ############################################################################*/ @@ -40,13 +40,13 @@ MFX_PACK_BEGIN_USUAL_STRUCT() /*! Specifies properties of video frames. See also "Configuration Parameter Constraints" chapter. */ typedef struct { mfxU32 reserved[4]; /*!< Reserved for future use. */ - /*! The unique ID of each VPP channel set by application. It's required that during Init/Reset application fills ChannelId for - each mfxVideoChannelParam provided by the application and the SDK sets it back to the correspondent - mfxSurfaceArray::mfxFrameSurface1 to distinguish different channels. It's expected that surfaces for some channels might be - returned with some delay so application has to use mfxFrameInfo::ChannelId to distinguish what returned surface belongs to - what VPP channel. Decoder's initialization parameters are always sent through channel with mfxFrameInfo::ChannelId equals to + /*! The unique ID of each VPP channel set by application. It's required that during Init/Reset application fills ChannelId for + each mfxVideoChannelParam provided by the application and the SDK sets it back to the correspondent + mfxSurfaceArray::mfxFrameSurface1 to distinguish different channels. It's expected that surfaces for some channels might be + returned with some delay so application has to use mfxFrameInfo::ChannelId to distinguish what returned surface belongs to + what VPP channel. Decoder's initialization parameters are always sent through channel with mfxFrameInfo::ChannelId equals to zero. It's allowed to skip setting of decoder's parameters for simplified decoding procedure */ - mfxU16 ChannelId; + mfxU16 ChannelId; /*! Number of bits used to represent luma samples. @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ mfxU16 BitDepthLuma; @@ -166,6 +166,8 @@ enum { MFX_FOURCC_I010 = MFX_MAKEFOURCC('I', '0', '1', '0'), /*!< 10-bit YUV 4:2:0, each component has its own plane. */ MFX_FOURCC_I420 = MFX_FOURCC_IYUV, /*!< Alias for the IYUV color format. */ MFX_FOURCC_BGRA = MFX_FOURCC_RGB4, /*!< Alias for the RGB4 color format. */ + /*! BGR 24 bit planar layout (3 separate channels, 8-bits per sample each). This format should be mapped to VA_FOURCC_BGRP. */ + MFX_FOURCC_BGRP = MFX_MAKEFOURCC('B','G','R','P'), }; /* PicStruct */ @@ -552,23 +554,42 @@ typedef struct mfxFrameSurfaceInterface { MFX_ERR_UNKNOWN Any internal error. */ mfxStatus (MFX_CDECL *Synchronize)(mfxFrameSurface1* surface, mfxU32 wait); - + /*! @brief - The library calls the function after complete of associated video operation - notifying the application that frame surface is ready. - - @attention This is callback function and intended to be called by - the library only. - - It is expected that the function is low-intrusive designed otherwise it may - impact performance. + The library calls the function after complete of associated video operation + notifying the application that frame surface is ready. + + @attention This is callback function and intended to be called by + the library only. + + It is expected that the function is low-intrusive designed otherwise it may + impact performance. @param[in] sts The status of completed operation. */ void (MFX_CDECL *OnComplete)(mfxStatus sts); - mfxHDL reserved2[3]; + /*! @brief + Returns an interface defined by the GUID. If the returned interface is a reference + counted object the caller should release the obtained interface to avoid memory leaks. + + @param[in] surface Valid surface. + @param[in] guid GUID of the requested interface. + @param[out] iface Interface. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface or surface is NULL. \n + MFX_ERR_UNSUPPORTED If requested interface is not supported. \n + MFX_ERR_NOT_IMPLEMENTED If requested interface is not implemented. \n + MFX_ERR_NOT_INITIALIZED If requested interface is not available (not created or already deleted). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *QueryInterface)(mfxFrameSurface1* surface, mfxGUID guid, mfxHDL* iface); + + mfxHDL reserved2[2]; } mfxFrameSurfaceInterface; MFX_PACK_END() @@ -719,22 +740,22 @@ typedef struct { return MFX_ERR_REALLOC_SURFACE. See the CodingOptionValue enumerator for values of this option. Use the Query API function to check if this feature is supported. */ mfxU16 EnableReallocRequest; - /*! Special parameter for AV1 decoder. Indicates presence/absence of film grain parameters in bitstream. - Also controls decoding behavior for streams with film grain parameters. MFXVideoDECODE_DecodeHeader returns nonzero FilmGrain + /*! Special parameter for AV1 decoder. Indicates presence/absence of film grain parameters in bitstream. + Also controls decoding behavior for streams with film grain parameters. MFXVideoDECODE_DecodeHeader returns nonzero FilmGrain for streams with film grain parameters and zero for streams w/o them. Decoding with film grain requires additional output surfaces. If FilmGrain` is non-zero then MFXVideoDECODE_QueryIOSurf will request more surfaces in case of external allocated video memory at decoder output. FilmGrain is passed to MFXVideoDECODE_Init function to control decoding operation for AV1 streams with film grain parameters. - If FilmGrain is nonzero decoding of each frame require two output surfaces (one for reconstructed frame and one for output frame with film grain applied). + If FilmGrain is nonzero decoding of each frame require two output surfaces (one for reconstructed frame and one for output frame with film grain applied). The decoder returns MFX_ERR_MORE_SURFACE from MFXVideoDECODE_DecodeFrameAsync if it has insufficient output surfaces to decode frame. - Application can forcibly disable the feature passing zero value of `FilmGrain` to `MFXVideoDECODE_Init`. - In this case the decoder will output reconstructed frames w/o film grain applied. + Application can forcibly disable the feature passing zero value of `FilmGrain` to `MFXVideoDECODE_Init`. + In this case the decoder will output reconstructed frames w/o film grain applied. Application can retrieve film grain parameters for a frame by attaching extended buffer mfxExtAV1FilmGrainParam to mfxFrameSurface1. If stream has no film grain parameters `FilmGrain` passed to `MFXVideoDECODE_Init` is ignored by the decoder. */ mfxU16 FilmGrain; /*! If not zero, it forces SDK to attempt to decode bitstream even if a decoder may not support all features associated with given CodecLevel. Decoder may produce visual artifacts. Only AVC decoder supports this field. */ mfxU16 IgnoreLevelConstrain; /*! This flag is used to disable output of main decoding channel. When it's ON SkipOutput = MFX_CODINGOPTION_ON decoder outputs only video processed channels. For pure decode this flag should be always disabled. */ - mfxU16 SkipOutput; + mfxU16 SkipOutput; mfxU16 reserved2[4]; }; struct { /* JPEG Decoding Options */ @@ -898,7 +919,7 @@ enum { MFX_LEVEL_AVC_6 =60, MFX_LEVEL_AVC_61 =61, MFX_LEVEL_AVC_62 =62, - /*! @} */ + /*! @} */ /*! @{ */ /* MPEG2 Profiles. */ @@ -1484,8 +1505,7 @@ typedef struct { mfxU16 WinBRCSize; /*! When rate control method is MFX_RATECONTROL_QVBR, this parameter specifies quality factor. -Values are in the 1 to 51 range, - where 1 corresponds to the best quality. + Values are in the 1 to 51 range, where 1 corresponds to the best quality. */ mfxU16 QVBRQuality; /*! @@ -1664,12 +1684,16 @@ Values are in the 1 to 51 range, @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ mfxU16 EnableNalUnitType; - /*! - Turn OFF to prevent Adaptive marking of Long Term Reference Frames when using ExtBRC. When set to ON and using ExtBRC, encoders will mark, - modify, or remove LTR frames based on encoding parameters and content properties. The application must set each input frame's - mfxFrameData::FrameOrder for correct operation of LTR. - */ - mfxU16 ExtBrcAdaptiveLTR; /* Tri-state option for ExtBRC. */ + + union { + mfxU16 ExtBrcAdaptiveLTR; /* Deprecated */ + + /*! + If this flag is set to ON, encoder will mark, modify, or remove LTR frames based on encoding parameters and content + properties. Turn OFF to prevent Adaptive marking of Long Term Reference Frames. + */ + mfxU16 AdaptiveLTR; + }; /*! If this flag is set to ON, encoder adaptively selects one of implementation-defined quantization matrices for each frame. Non-default quantization matrices aim to improve subjective visual quality under certain conditions. @@ -1678,7 +1702,13 @@ Values are in the 1 to 51 range, This parameter is valid only during initialization. */ mfxU16 AdaptiveCQM; - mfxU16 reserved[162]; + /*! + If this flag is set to ON, encoder adaptively selects list of reference frames to imrove encoding quality. + Enabling of the flag can increase computation complexity and introduce additional delay. + If this flag is set to OFF, regular reference frames are used for encoding. + */ + mfxU16 AdaptiveRef; + mfxU16 reserved[161]; } mfxExtCodingOption3; MFX_PACK_END() @@ -2024,13 +2054,21 @@ enum { See the mfxExtInCrops structure for details. */ MFX_EXTBUFF_CROPS = MFX_MAKEFOURCC('C', 'R', 'O', 'P'), - + /*! See the mfxExtAV1FilmGrainParam structure for more details. */ - MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM = MFX_MAKEFOURCC('A','1','F','G') + MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM = MFX_MAKEFOURCC('A','1','F','G'), - + /*! + See the mfxExtHyperModeParam structure for more details. + */ + MFX_EXTBUFF_HYPER_MODE_PARAM = MFX_MAKEFOURCC('H', 'Y', 'P', 'M'), + + /*! + See the mfxExtVPP3DLut structure for more details. + */ + MFX_EXTBUFF_VPP_3DLUT = MFX_MAKEFOURCC('T','D','L','T'), }; /* VPP Conf: Do not use certain algorithms */ @@ -2088,6 +2126,94 @@ typedef struct { } mfxExtVPPDenoise2; MFX_PACK_END() +/*! The mfx3DLutChannelMapping enumerator specifies the channel mapping of 3DLUT. */ +typedef enum { + MFX_3DLUT_CHANNEL_MAPPING_DEFAULT = 0, /*!< Default 3DLUT channel mapping. The library selects the most appropriate 3DLUT channel mapping. */ + MFX_3DLUT_CHANNEL_MAPPING_RGB_RGB = 1, /*!< 3DLUT RGB channels map to RGB channels. */ + MFX_3DLUT_CHANNEL_MAPPING_YUV_RGB = 2, /*!< 3DLUT YUV channels map to RGB channels. */ + MFX_3DLUT_CHANNEL_MAPPING_VUY_RGB = 3, /*!< 3DLUT VUY channels map to RGB channels. */ +} mfx3DLutChannelMapping; + +/*! The mfx3DLutMemoryLayout enumerator specifies the memory layout of 3DLUT. */ +typedef enum { + MFX_3DLUT_MEMORY_LAYOUT_DEFAULT = 0, /*!< Default 3DLUT memory layout. The library selects the most appropriate 3DLUT memory layout.*/ + + MFX_3DLUT_MEMORY_LAYOUT_VENDOR = 0x1000, /*!< The enumeration to separate default above and vendor specific.*/ + /*! + Intel specific memory layout. The enumerator indicates the attributes and memory layout of 3DLUT. + 3DLUT size is 17(the number of elements per dimension), 4 channels(3 valid channels, 1 channel is reserved), every channel must be 16-bit unsigned integer. + 3DLUT contains 17x17x32 entries with holes that are not filled. Take RGB as example, the nodes RxGx17 to RxGx31 are not filled, are "don't care" bits, and not accessed for the 17x17x17 nodes. + */ + MFX_3DLUT_MEMORY_LAYOUT_INTEL_17LUT = MFX_3DLUT_MEMORY_LAYOUT_VENDOR + 1, + /*! + Intel specific memory layout. The enumerator indicates the attributes and memory layout of 3DLUT. + 3DLUT size is 33(the number of elements per dimension), 4 channels(3 valid channels, 1 channel is reserved), every channel must be 16-bit unsigned integer. + 3DLUT contains 33x33x64 entries with holes that are not filled. Take RGB as example, the nodes RxGx33 to RxGx63 are not filled, are "don't care" bits, and not accessed for the 33x33x33 nodes. + */ + MFX_3DLUT_MEMORY_LAYOUT_INTEL_33LUT = MFX_3DLUT_MEMORY_LAYOUT_VENDOR + 2, + /*! + Intel specific memory layout. The enumerator indicates the attributes and memory layout of 3DLUT. + 3DLUT size is 65(the number of elements per dimension), 4 channels(3 valid channels, 1 channel is reserved), every channel must be 16-bit unsigned integer. + 3DLUT contains 65x65x128 entries with holes that are not filled. Take RGB as example, the nodes RxGx65 to RxGx127 are not filled, are "don't care" bits, and not accessed for the 65x65x65 nodes. + */ + MFX_3DLUT_MEMORY_LAYOUT_INTEL_65LUT = MFX_3DLUT_MEMORY_LAYOUT_VENDOR + 3, +} mfx3DLutMemoryLayout; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + A hint structure that configures the data channel. +*/ +typedef struct { + mfxDataType DataType; /*!< Data type, mfxDataType enumerator.*/ + mfxU32 Size; /*!< Size of Look up table, the number of elements per dimension.*/ + union + { + mfxU8* Data; /*!< The pointer to 3DLUT data, 8 bit unsigned integer.*/ + mfxU16* Data16; /*!< The pointer to 3DLUT data, 16 bit unsigned integer.*/ + }; + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxChannel; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures 3DLUT system buffer. +*/ +typedef struct { + mfxChannel Channel[3]; /*!< 3 Channels, can be RGB or YUV, mfxChannel structure.*/ + mfxU32 reserved[8]; /*!< Reserved for future extension.*/ +} mfx3DLutSystemBuffer; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures 3DLUT video buffer. +*/ +typedef struct { + mfxDataType DataType; /*!< Data type, mfxDataType enumerator.*/ + mfx3DLutMemoryLayout MemLayout; /*!< Indicates 3DLUT memory layout. mfx3DLutMemoryLayout enumerator.*/ + mfxMemId MemId; /*!< Memory ID for holding the lookup table data. One MemID is dedicated for one instance of VPP.*/ + mfxU32 reserved[8]; /*!< Reserved for future extension.*/ +} mfx3DLutVideoBuffer; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures 3DLUT filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_3DLUT..*/ + mfx3DLutChannelMapping ChannelMapping; /*!< Indicates 3DLUT channel mapping. mfx3DLutChannelMapping enumerator.*/ + mfxResourceType BufferType; /*!< Indicates 3DLUT buffer type. mfxResourceType enumerator, can be system memory, VA surface, DX11 texture/buffer etc.*/ + union + { + mfx3DLutSystemBuffer SystemBuffer; /*!< The 3DLUT system buffer. mfx3DLutSystemBuffer structure describes the details of the buffer.*/ + mfx3DLutVideoBuffer VideoBuffer; /*!< The 3DLUT video buffer. mfx3DLutVideoBuffer describes the details of 3DLUT video buffer.*/ + }; + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxExtVPP3DLut; +MFX_PACK_END() + MFX_PACK_BEGIN_USUAL_STRUCT() /*! A hint structure that configures the VPP detail/edge enhancement filter algorithm. @@ -2488,10 +2614,10 @@ MFX_PACK_BEGIN_STRUCT_W_PTR() Each filter may be included in the pipeline in one of two different ways: @li Adding a filter ID to this structure. In this method, - the default filter parameters are used. - + the default filter parameters are used. + @li Attaching a filter configuration structure directly to the mfxVideoParam structure. - In this method, adding filter ID to the mfxExtVPPDoUse structure is optional. + In this method, adding filter ID to the mfxExtVPPDoUse structure is optional. See Table ā€œConfigurable VPP filtersā€ for complete list of configurable filters, their IDs, and configuration structures. @@ -2590,7 +2716,7 @@ MFX_PACK_BEGIN_USUAL_STRUCT() On some platforms this filter is not supported. To query its support, the application should use the same approach that it uses to configure VPP filters: adding the filter ID to the mfxExtVPPDoUse structure or by attaching the mfxExtVPPImageStab structure - directly to the mfxVideoParam structure and calling the MFXVideoVPP_Query function. + directly to the mfxVideoParam structure and calling the MFXVideoVPP_Query function. If this filter is supported, the function returns a MFX_ERR_NONE status and copies the content of the input structure to the output structure. If the filter is not supported, the function returns MFX_WRN_FILTER_SKIPPED, removes the @@ -2617,14 +2743,14 @@ enum { MFX_PACK_BEGIN_USUAL_STRUCT() /*! - Configures the HDR SEI message. + Configures the HDR SEI message. If the application attaches this structure to the mfxEncodeCtrl structure - at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. + at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. If the application attaches this structure to the mfxVideoParam structure during initialization or reset, the encoder inserts the HDR SEI message based on InsertPayloadToggle. - + Field semantics are defined in ITU-T* H.265 Annex D. */ typedef struct { @@ -2633,10 +2759,10 @@ typedef struct { mfxU16 InsertPayloadToggle; /*!< InsertHDRPayload enumerator value. */ mfxU16 DisplayPrimariesX[3]; /*!< Color primaries for a video source in increments of 0.00002. Consist of RGB x coordinates and - define how to convert colors from RGB color space to CIE XYZ color space. Fields range is + define how to convert colors from RGB color space to CIE XYZ color space. Fields range is 0 to 50000. */ mfxU16 DisplayPrimariesY[3]; /*!< Color primaries for a video source in increments of 0.00002. Consists of RGB y coordinates and - defines how to convert colors from RGB color space to CIE XYZ color space. Field range is + defines how to convert colors from RGB color space to CIE XYZ color space. Field range is 0 to 50000. */ mfxU16 WhitePointX; /*!< White point X coordinate. */ mfxU16 WhitePointY; /*!< White point Y coordinate. */ @@ -2649,14 +2775,14 @@ MFX_PACK_END() MFX_PACK_BEGIN_USUAL_STRUCT() /*! - Configures the HDR SEI message. + Configures the HDR SEI message. If the application attaches this structure to the mfxEncodeCtrl - structure at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. + structure at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. If the application attaches this structure to the mfxVideoParam structure during initialization or reset, the encoder inserts the HDR SEI message based on - InsertPayloadToggle. + InsertPayloadToggle. Field semantics are defined in ITU-T* H.265 Annex D. */ @@ -3659,12 +3785,8 @@ enum { MFX_SCALING_MODE_DEFAULT = 0, /*!< Default scaling mode. The library selects the most appropriate scaling method. */ MFX_SCALING_MODE_LOWPOWER = 1, /*!< Low power scaling mode which is applicable for library implementations. The exact scaling algorithm is defined by the library. */ - MFX_SCALING_MODE_QUALITY = 2, /*!< The best quality scaling mode. */ - - + MFX_SCALING_MODE_QUALITY = 2, /*!< The best quality scaling mode. */ MFX_SCALING_MODE_VENDOR = 1000, /*!< The enumeration to separate common scaling controls above and vendor specific. */ - - MFX_SCALING_MODE_INTEL_GEN_COMPUTE = MFX_SCALING_MODE_VENDOR + 1, /*! The mode to run scaling operation on Execution Units (EUs). */ MFX_SCALING_MODE_INTEL_GEN_VDBOX = MFX_SCALING_MODE_VENDOR + 2, /*! The special optimization mode where scaling operation running on SFC (Scaler & Format Converter) is coupled with VDBOX (also known as Multi-Format Codec fixed-function engine). This mode is applicable for DECODE_VPP domain functions. */ MFX_SCALING_MODE_INTEL_GEN_VEBOX = MFX_SCALING_MODE_VENDOR + 3 /*! The special optimization mode where scaling operation running on SFC is coupled with VEBOX (HW video processing pipe). */ @@ -4040,14 +4162,14 @@ MFX_PACK_BEGIN_USUAL_STRUCT() */ typedef struct { mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_MCTF. */ - mfxU16 FilterStrength; /*!< Value in range of 0 to 20 (inclusive) to indicate the filter strength of MCTF. + mfxU16 FilterStrength; /*!< Value in range of 0 to 20 (inclusive) to indicate the filter strength of MCTF. The strength of the MCTF process controls the degree of possible change of pixel values eligible for MCTF - the greater the strength value, the larger the change. It is a dimensionless quantity - values in the range of 1 to 20 inclusively imply strength; value 0 stands for AUTO mode and is valid during initialization or reset only If an invalid value is given, it is fixed to the default value of 0. If the field value is in the range of 1 to 20 inclusive, MCTF operates in fixed-strength mode with the given strength of MCTF process. - + At runtime, values of 0 and greater than 20 are ignored. */ mfxU16 reserved[27]; } mfxExtVppMctf; @@ -4160,7 +4282,7 @@ typedef struct { } mfxExtDeviceAffinityMask; MFX_PACK_END() -/*! The FilmGrainFlags enumerator itemizes flags in AV1 film grain parameters. +/*! The FilmGrainFlags enumerator itemizes flags in AV1 film grain parameters. The flags are equivalent to respective syntax elements from film_grain_params() section of uncompressed header. */ enum { MFX_FILM_GRAIN_NO = 0, /*!< Film grain isn't added to this frame. */ @@ -4196,7 +4318,7 @@ typedef struct { mfxAV1FilmGrainPoint PointCb[10]; /*!< The array of points for Cb component. */ mfxAV1FilmGrainPoint PointCr[10]; /*!< The array of points for Cr component. */ - mfxU8 GrainScalingMinus8; /*!< The shift ā€“ 8 applied to the values of the chroma component. The grain_scaling_minus_8 can take values of 0..3 and + mfxU8 GrainScalingMinus8; /*!< The shift ā€“ 8 applied to the values of the chroma component. The grain_scaling_minus_8 can take values of 0..3 and determines the range and quantization step of the standard deviation of film grain.*/ mfxU8 ArCoeffLag; /*!< The number of auto-regressive coefficients for luma and chroma.*/ @@ -4204,8 +4326,8 @@ typedef struct { mfxU8 ArCoeffsCbPlus128[25]; /*!< Auto-regressive coefficients used for the Cb plane. */ mfxU8 ArCoeffsCrPlus128[25]; /*!< The number of points for the piece-wise linear scaling function of the Cr component.*/ - mfxU8 ArCoeffShiftMinus6; /*!< The range of the auto-regressive coefficients. - Values of 0, 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of + mfxU8 ArCoeffShiftMinus6; /*!< The range of the auto-regressive coefficients. + Values of 0, 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, 0.25) respectively.*/ mfxU8 GrainScaleShift; /*!< Downscaling factor of the grain synthesis process for the Gaussian random numbers .*/ @@ -4229,8 +4351,8 @@ MFX_PACK_BEGIN_STRUCT_W_PTR() typedef struct mfxSurfaceArray { mfxHDL Context; /*!< The context of the memory interface. User should not touch (change, set, null) this pointer. */ - mfxStructVersion Version; /*!< The version of the structure. */ - mfxU16 reserved[3]; + mfxStructVersion Version; /*!< The version of the structure. */ + mfxU16 reserved[3]; /*! @brief Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the (*Release) function. (*AddRef) should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. @@ -4242,11 +4364,11 @@ typedef struct mfxSurfaceArray MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n MFX_ERR_UNKNOWN Any internal error. - */ - mfxStatus (*AddRef)(struct mfxSurfaceArray* surface_array); + */ + mfxStatus (*AddRef)(struct mfxSurfaceArray* surface_array); /*! @brief - Decrements the internal reference counter of the surface. (*Release) should be called after using the (*AddRef) function to add a - surface or when allocation logic requires it. + Decrements the internal reference counter of the surface. (*Release) should be called after using the (*AddRef) function to add a + surface or when allocation logic requires it. @param[in] surface_array Valid mfxSurfaceArray. @@ -4257,7 +4379,7 @@ typedef struct mfxSurfaceArray MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n MFX_ERR_UNKNOWN Any internal error. */ - mfxStatus (*Release)(struct mfxSurfaceArray* surface_array); + mfxStatus (*Release)(struct mfxSurfaceArray* surface_array); /*! @brief Returns current reference counter of mfxSurfaceArray structure. @@ -4270,10 +4392,10 @@ typedef struct mfxSurfaceArray MFX_ERR_NULL_PTR If surface or counter is NULL. \n MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n MFX_ERR_UNKNOWN Any internal error. - */ + */ mfxStatus (*GetRefCounter)(struct mfxSurfaceArray* surface_array, mfxU32* counter); - mfxFrameSurface1** Surfaces; /*!< The array of pointers to mfxFrameSurface1. mfxFrameSurface1 surfaces are allocated by the same + mfxFrameSurface1** Surfaces; /*!< The array of pointers to mfxFrameSurface1. mfxFrameSurface1 surfaces are allocated by the same agent who allocates mfxSurfaceArray. */ mfxU32 NumSurfaces; /*! +#include +#include +#include + +#include "vpl/preview/defs.hpp" +#include "vpl/preview/exception.hpp" + +#include "vpl/preview/detail/sdk_callable.hpp" +#include "vpl/preview/detail/string_helpers.hpp" +#include "vpl/mfxstructures.h" + +namespace oneapi { +namespace vpl { + +#define iDECLARE_MEMBER_ACCESS(type, owner, name) \ + /*! @brief Returns name value. */ \ + /*! @return name value. */ \ + type get_##name() const { \ + return owner.name; \ + } \ + /*! @brief Sets name value. */ \ + /*! @param[in] name Value. */ \ + void set_##name(type name) { \ + owner.name = name; \ + } + +/// @brief Defines the circlular buffer that holds compressed video data. +/// @todo Consider split of this class for decoder and for encoder as +/// there are different fields in use i decoder and encoder +class bitstream { +public: + /// Default compressed video data buffer lenght + enum buffer_len : uint32_t { DEFAULT_LENGHT = 2000000 }; + /// @brief Default ctor + bitstream() : bits_() { + bits_.TimeStamp = MFX_TIMESTAMP_UNKNOWN; + bits_.DecodeTimeStamp = MFX_TIMESTAMP_UNKNOWN; + bits_.Data = new uint8_t[bitstream::buffer_len::DEFAULT_LENGHT]; + bits_.MaxLength = bitstream::buffer_len::DEFAULT_LENGHT; + } + /// @brief Constructs bitstream object with given codec ID and default buffer length + /// @param[in] codecID codec's fourCC code + explicit bitstream(codec_format_fourcc codecID) : bits_() { + bits_.TimeStamp = MFX_TIMESTAMP_UNKNOWN; + bits_.DecodeTimeStamp = MFX_TIMESTAMP_UNKNOWN; + bits_.Data = new uint8_t[bitstream::buffer_len::DEFAULT_LENGHT]; + bits_.MaxLength = bitstream::buffer_len::DEFAULT_LENGHT; + bits_.CodecId = (uint32_t)codecID; + } + /// @brief Constructs bitstream object with given codec ID and given buffer length + /// @param[in] codecID codec's fourCC code + /// @param[in] buffersize circular buffer size in bytes + bitstream(codec_format_fourcc codecID, uint32_t buffersize) : bits_() { + bits_.TimeStamp = MFX_TIMESTAMP_UNKNOWN; + bits_.DecodeTimeStamp = MFX_TIMESTAMP_UNKNOWN; + bits_.Data = new uint8_t[buffersize]; + bits_.MaxLength = buffersize; + bits_.CodecId = (uint32_t)codecID; + } + + /// @brief default ctor + virtual ~bitstream() {} + + /// @brief Reallocs internal buffer with the given buffer size increase value. Valid data is copied into new buffer + /// @param[in] bufferinc Number of bytes to increase the buffer. + void realloc(uint32_t bufferinc = buffer_len::DEFAULT_LENGHT) { + uint8_t* new_buffer = new uint8_t[bufferinc + bits_.MaxLength]; + + if (bits_.DataOffset) { + std::copy(bits_.Data + bits_.DataOffset, + bits_.Data + bits_.DataOffset + bits_.DataLength, + bits_.Data); + bits_.DataOffset = 0; + } + + std::copy(bits_.Data, bits_.Data + bits_.DataLength, new_buffer); + delete[] bits_.Data; + bits_.Data = new_buffer; + bits_.MaxLength = bufferinc + bits_.MaxLength; + } + + /*! @brief Returns codec fourCC value. */ + /*! @return codec fourCC value. */ + codec_format_fourcc get_CodecId() const { + return (codec_format_fourcc)bits_.CodecId; + } + /*! @brief Sets codec fourCC value. */ + /*! @param[in] CodecID codec fourCC. */ + void set_CodecId(codec_format_fourcc CodecID) { + bits_.CodecId = (uint32_t)CodecID; + } + + iDECLARE_MEMBER_ACCESS(int64_t, bits_, DecodeTimeStamp); + iDECLARE_MEMBER_ACCESS(uint64_t, bits_, TimeStamp); + iDECLARE_MEMBER_ACCESS(uint16_t, bits_, PicStruct); + iDECLARE_MEMBER_ACCESS(uint16_t, bits_, FrameType); + iDECLARE_MEMBER_ACCESS(uint16_t, bits_, DataFlag); + iDECLARE_MEMBER_ACCESS(uint16_t, bits_, DataOffset); + iDECLARE_MEMBER_ACCESS(uint16_t, bits_, DataLength); + + /// @brief Returns pointer to the head of internal circular buffer. + /// @return Pointer to the head of internal circular buffer. + uint8_t* get_buffer_ptr() const { + return bits_.Data; + } + + /// @brief Returns internal circular buffer in bytes. + /// @return internal circular buffer in bytes. + uint32_t get_max_buffer_length() const { + return bits_.MaxLength; + } + + /// @brief Returns pair with pointer to the first valid byte in the bitstream and + /// length of the valid data in bytes. + /// @return Pair with pointer to the first valid byte in the bitstream and + /// length of the valid data in bytes. + auto get_valid_data() { + return std::pair(bits_.Data + bits_.DataOffset, bits_.DataLength); + } + + /// @brief Resets data in the buffer. + void reset() { + bits_.DataLength = 0; + bits_.DataOffset = 0; + return; + } + + /// @brief Returns pointer to the mfxBitream oneVPL's structure. + /// @return Pointer to the mfxBitream oneVPL's structure. + mfxBitstream* operator()() { + return &(this->bits_); + } + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] b Reference to the bitstream instance to dump the state. + /// @return Reference to the stream. + friend std::ostream& operator<<(std::ostream& out, const bitstream& b); + +protected: + /// @brief mfxBitstream structure instance. + mfxBitstream bits_; +}; + +inline std::ostream& operator<<(std::ostream& out, const bitstream& b) { + out << detail::space(detail::INTENT, out, "CodecId = ") + << detail::FourCC2String(b.bits_.CodecId) << std::endl; + out << detail::space(detail::INTENT, out, "DecodeTimeStamp = ") + << detail::TimeStamp2String(static_cast(b.bits_.DecodeTimeStamp)) << std::endl; + out << detail::space(detail::INTENT, out, "TimeStamp = ") << b.bits_.TimeStamp + << std::endl; + out << detail::space(detail::INTENT, out, "DataOffset = ") << b.bits_.DataOffset + << std::endl; + out << detail::space(detail::INTENT, out, "DataLength = ") << b.bits_.DataLength + << std::endl; + out << detail::space(detail::INTENT, out, "PicStruct = ") + << detail::PicStruct2String(b.bits_.PicStruct) << std::endl; + out << detail::space(detail::INTENT, out, "FrameType = ") << b.bits_.FrameType + << std::endl; + out << detail::space(detail::INTENT, out, "DataFlag = ") << b.bits_.DataFlag + << std::endl; + + return out; +} + +/// @brief Defines the circular buffer that holds compressed video data. Used as the input to decoder. +class bitstream_as_src : public bitstream { +public: + /// @brief Default ctor + bitstream_as_src() : bitstream() {} + /// @brief Constructs bitstream object with given codec ID and default buffer length + /// @param[in] codecID codec's fourCC code + explicit bitstream_as_src(codec_format_fourcc codecID) : bitstream(codecID) {} + /// @brief Constructs bitstream object with given codec ID and given buffer length + /// @param[in] codecID codec's fourCC code + /// @param[in] buffersize circular buffer size in bytes + bitstream_as_src(codec_format_fourcc codecID, uint32_t buffersize) + : bitstream(codecID, buffersize) {} + + /// @brief Stores maximum possible portion of data in the circular buffer. Data is strored after + /// unused portion of the buffer in the length of avialable space in the buffer. + /// @param[in] reader source reader callback. + void pull_in(std::function reader) { + bool eosFlag = false; + if (bits_.DataOffset) { + std::copy(bits_.Data + bits_.DataOffset, + bits_.Data + bits_.DataOffset + bits_.DataLength, + bits_.Data); + bits_.DataOffset = 0; + } + bits_.DataLength += (uint32_t)reader(bits_.Data + bits_.DataLength, + bits_.MaxLength - bits_.DataLength, + eosFlag); + // if(eosFlag) bits_.DataFlag = MFX_BITSTREAM_EOS; + } +}; + +/// @brief Defines the buffer that holds compressed video data. Used as the output from encoder. +class bitstream_as_dst : public bitstream { +public: + /// @brief Default ctor + bitstream_as_dst() : bitstream(), sp_(nullptr), session_(nullptr), valid_(false) {} + /// @brief Constructs bitstream object with given codec ID and given buffer length + /// @param[in] codecID codec's fourCC code + /// @param[in] buffersize circular buffer size in bytes + bitstream_as_dst(codec_format_fourcc codecID, uint32_t buffersize) + : bitstream(codecID, buffersize), + sp_(nullptr), + session_(nullptr), + valid_(false) {} + + /// @brief Indefinitely waits for operation completion. + void wait() { + if (sp_) { + detail::c_api_invoker(detail::default_checker, + MFXVideoCORE_SyncOperation, + session_, + sp_, + MFX_INFINITE); + valid_ = true; + } + } + + /// @brief Temporal method to assotiate externally allocated surface with sync point generated + /// by the processing function. + /// @param[in] context Pair of session handle and sync point. + void associate_context(std::pair context) { + session_ = std::get<0>(context); + sp_ = std::get<1>(context); + } + /// @brief Waits for the operation completion. Waits for the result to become available. Blocks until + /// specified timeout_duration has elapsed or the result becomes available, whichever comes first. Returns + /// value identifying the state of the result. + /// @param timeout_duration Maximum duration to block for. + /// @return Wait status. + template + async_op_status wait_for(const std::chrono::duration& timeout_duration) const { + async_op_status surf_sts; + auto wait_ms = std::chrono::duration_cast(timeout_duration); + + detail::c_api_invoker e({ [](mfxStatus s) { + switch (s) { + case MFX_ERR_NONE: + return false; + case MFX_WRN_IN_EXECUTION: + return false; + case MFX_ERR_ABORTED: + return false; + case MFX_ERR_UNKNOWN: + return false; + default: + break; + } + + bool ret = (s < 0) ? true : false; + return ret; + } }, + MFXVideoCORE_SyncOperation, + session_, + sp_, + (uint32_t)wait_ms.count()); + + switch (e.sts_) { + case MFX_ERR_NONE: + surf_sts = async_op_status::ready; + break; + case MFX_WRN_IN_EXECUTION: + surf_sts = async_op_status::timeout; + break; + case MFX_ERR_ABORTED: + surf_sts = async_op_status::aborted; + break; + case MFX_ERR_UNKNOWN: + surf_sts = async_op_status::unknown; + break; + default: + throw base_exception(e.sts_); + } + return surf_sts; + } + +protected: + /// Sync point handle + mfxSyncPoint sp_; + /// Session handle + mfxSession session_; + /// @todo Remove it nafik. + bool valid_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/defs.hpp b/api/vpl/preview/defs.hpp new file mode 100644 index 00000000..f2058d91 --- /dev/null +++ b/api/vpl/preview/defs.hpp @@ -0,0 +1,284 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include + +#include "vpl/mfxstructures.h" + +namespace oneapi { +namespace vpl { + +#define ENABLE_BIT_OPERATORS_WITH_ENUM(Enum) \ +inline Enum operator|(Enum lhs, Enum rhs) { \ + using underlying = typename std::underlying_type::type; \ + return static_cast(static_cast(lhs) | static_cast(rhs)); \ +} \ +inline Enum operator&(Enum lhs, Enum rhs) { \ + using underlying = typename std::underlying_type::type; \ + return static_cast(static_cast(lhs) & static_cast(rhs)); \ +} + +/// @brief Asyncroniouse operation status +enum class component { + decoder, ///! Decoder component. + encoder, ///! Encoder component. + vpp, ///! VPP component. + decoder_vpp, ///! decode+vvpp component. + unknown, ///! decode+vvpp component. +}; + +/// @brief Asyncroniouse operation status +enum class async_op_status { + ready, ///! Asyncroniouse operation complited and data is ready. + timeout, ///! Asyncroniouse operation is in the progress and data is not yet ready. + aborted, ///! Asyncroniouse operation aborted. + unknown, ///! Asyncroniouse operation status unknown. + cancelled ///! Asyncroniouse operation cancelled due to issues raised during schedulling. +}; + +enum class status : int { + Ok = 0, + ExecutionInProgress = 1, + DeviceBusy = 2, + VideoParamChanged = 3, + PartialAcceleration = 4, + IncompartibleVideoParam = 5, + ValueNotChanged = 6, + OutOfRange = 7, + TaskWorking = 8, + TaskBusy = 9, + FilterSkipped = 10, + PartialOutput = 12, + NotEnoughData = -10, + NotEnoughSurface = -11, + NotEnoughBuffer = -5, + EndOfStreamReached = -100, + Unknown = (std::numeric_limits::min)() +}; + +// C API enums + +enum class codec_format_fourcc : uint32_t { + avc = MFX_CODEC_AVC, + hevc = MFX_CODEC_HEVC, + mpeg2 = MFX_CODEC_MPEG2, + vc1 = MFX_CODEC_VC1, + capture = MFX_CODEC_CAPTURE, + vp9 = MFX_CODEC_VP9, + av1 = MFX_CODEC_AV1 +}; + +enum class color_format_fourcc : uint32_t { + nv12 = MFX_FOURCC_NV12, + yv12 = MFX_FOURCC_YV12, + nv16 = MFX_FOURCC_NV16, + yuy2 = MFX_FOURCC_YUY2, + rgb465 = MFX_FOURCC_RGB565, + rgbp = MFX_FOURCC_RGBP, + rgb3 = MFX_FOURCC_RGB3, + bgra = MFX_FOURCC_RGB4, // not a bug + p8 = MFX_FOURCC_P8, + p8_texture = MFX_FOURCC_P8_TEXTURE, + p010 = MFX_FOURCC_P010, + p016 = MFX_FOURCC_P016, + p210 = MFX_FOURCC_P210, + bgr4 = MFX_FOURCC_BGR4, + a2rgb10 = MFX_FOURCC_A2RGB10, + argb16 = MFX_FOURCC_ARGB16, + abgr16 = MFX_FOURCC_ABGR16, + r16 = MFX_FOURCC_R16, + ayuv = MFX_FOURCC_AYUV, + ayuv_rgb4 = MFX_FOURCC_AYUV_RGB4, + uyvy = MFX_FOURCC_UYVY, + y210 = MFX_FOURCC_Y210, + y410 = MFX_FOURCC_Y410, + y216 = MFX_FOURCC_Y216, + y416 = MFX_FOURCC_Y416, + nv21 = MFX_FOURCC_NV21, + i420 = MFX_FOURCC_IYUV, + i010 = MFX_FOURCC_I010, + bgrp = MFX_FOURCC_BGRP, +}; + +enum class chroma_format_idc : uint32_t { + monochrome = MFX_CHROMAFORMAT_MONOCHROME, + yuv420 = MFX_CHROMAFORMAT_YUV420, + yuv422 = MFX_CHROMAFORMAT_YUV422, + yuv444 = MFX_CHROMAFORMAT_YUV444, + yuv400 = MFX_CHROMAFORMAT_YUV400, + yuv411 = MFX_CHROMAFORMAT_YUV411, + yuv422h = MFX_CHROMAFORMAT_YUV422H, + yuv422v = MFX_CHROMAFORMAT_YUV422V +}; + +enum class target_usage : uint32_t { + t1 = MFX_TARGETUSAGE_1, + t2 = MFX_TARGETUSAGE_2, + t3 = MFX_TARGETUSAGE_3, + t4 = MFX_TARGETUSAGE_4, + t5 = MFX_TARGETUSAGE_5, + t6 = MFX_TARGETUSAGE_6, + t7 = MFX_TARGETUSAGE_7, + unknown = MFX_TARGETUSAGE_UNKNOWN, + best_quality = t1, + balanced = t4, + best_speed = t7, +}; + +enum class rate_control_method : uint32_t { + cbr = MFX_RATECONTROL_CBR, + vbr = MFX_RATECONTROL_VBR, + cqp = MFX_RATECONTROL_CQP, + avbr = MFX_RATECONTROL_AVBR, + la = MFX_RATECONTROL_LA, + icq = MFX_RATECONTROL_ICQ, + vcm = MFX_RATECONTROL_VCM, + la_icq = MFX_RATECONTROL_LA_ICQ, + la_hrd = MFX_RATECONTROL_LA_HRD, + qvbr = MFX_RATECONTROL_QVBR +}; + +enum class io_pattern : uint32_t { + in_device_memory = MFX_IOPATTERN_IN_VIDEO_MEMORY, + in_system_memory = MFX_IOPATTERN_IN_SYSTEM_MEMORY, + out_device_memory = MFX_IOPATTERN_OUT_VIDEO_MEMORY, + out_system_memory = MFX_IOPATTERN_OUT_SYSTEM_MEMORY, + io_system_memory = in_system_memory | out_system_memory, +}; +ENABLE_BIT_OPERATORS_WITH_ENUM(io_pattern); + +enum class pic_struct : uint16_t { + unknown = MFX_PICSTRUCT_UNKNOWN, + progressive = MFX_PICSTRUCT_PROGRESSIVE, + field_tff = MFX_PICSTRUCT_FIELD_TFF, + field_bff = MFX_PICSTRUCT_FIELD_BFF, + + field_repeated = MFX_PICSTRUCT_FIELD_REPEATED, + frame_doubling = MFX_PICSTRUCT_FRAME_DOUBLING, + frame_tripling = MFX_PICSTRUCT_FRAME_TRIPLING, + + field_single = MFX_PICSTRUCT_FIELD_SINGLE, + field_top = MFX_PICSTRUCT_FIELD_TOP, + field_bottom = MFX_PICSTRUCT_FIELD_BOTTOM, + field_paired_prev = MFX_PICSTRUCT_FIELD_PAIRED_PREV, + field_paired_next = MFX_PICSTRUCT_FIELD_PAIRED_NEXT, +}; +ENABLE_BIT_OPERATORS_WITH_ENUM(pic_struct); + +enum class memory_access : uint32_t { + read = MFX_MAP_READ, + write = MFX_MAP_WRITE, + read_write = MFX_MAP_READ_WRITE, + nowait = MFX_MAP_NOWAIT +}; + +enum class hevc_nal_unit_type : uint16_t { + unknown = MFX_HEVC_NALU_TYPE_UNKNOWN, + trail_n = MFX_HEVC_NALU_TYPE_TRAIL_N, + trail_r = MFX_HEVC_NALU_TYPE_TRAIL_R, + radl_n = MFX_HEVC_NALU_TYPE_RADL_N, + radl_r = MFX_HEVC_NALU_TYPE_RADL_R, + rasl_n = MFX_HEVC_NALU_TYPE_RASL_N, + rasl_r = MFX_HEVC_NALU_TYPE_RASL_R, + idr_w_radl = MFX_HEVC_NALU_TYPE_IDR_W_RADL, + idr_n_lp = MFX_HEVC_NALU_TYPE_IDR_N_LP, + cra_nut = MFX_HEVC_NALU_TYPE_CRA_NUT, +}; + +enum class frame_type : uint16_t { + unknown = MFX_FRAMETYPE_UNKNOWN, + i = MFX_FRAMETYPE_I, + p = MFX_FRAMETYPE_P, + b = MFX_FRAMETYPE_B, + s = MFX_FRAMETYPE_S, + ref = MFX_FRAMETYPE_REF, + idr = MFX_FRAMETYPE_IDR, + xi = MFX_FRAMETYPE_xI, + xp = MFX_FRAMETYPE_xP, + xb = MFX_FRAMETYPE_xB, + xs = MFX_FRAMETYPE_xS, + xref = MFX_FRAMETYPE_xREF, + xidr = MFX_FRAMETYPE_xIDR, +}; + +ENABLE_BIT_OPERATORS_WITH_ENUM(frame_type); + +static status mfxstatus_to_onevplstatus(mfxStatus s) { + switch (s) { + case MFX_ERR_NONE: + return status::Ok; + case MFX_WRN_IN_EXECUTION: + return status::ExecutionInProgress; + case MFX_WRN_DEVICE_BUSY: + return status::DeviceBusy; + case MFX_WRN_VIDEO_PARAM_CHANGED: + return status::VideoParamChanged; + case MFX_WRN_PARTIAL_ACCELERATION: + return status::PartialAcceleration; + case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM: + return status::IncompartibleVideoParam; + case MFX_WRN_VALUE_NOT_CHANGED: + return status::ValueNotChanged; + case MFX_WRN_OUT_OF_RANGE: + return status::OutOfRange; + case MFX_TASK_WORKING: + return status::TaskWorking; + case MFX_TASK_BUSY: + return status::TaskBusy; + case MFX_WRN_FILTER_SKIPPED: + return status::FilterSkipped; + case MFX_ERR_NONE_PARTIAL_OUTPUT: + return status::PartialOutput; + //// Errors but they need to be treat as positive status in some cases. + case MFX_ERR_NOT_ENOUGH_BUFFER: + return status::NotEnoughBuffer; + case MFX_ERR_MORE_DATA: + return status::NotEnoughData; + case MFX_ERR_MORE_SURFACE: + return status::NotEnoughSurface; + default: + return status::Unknown; + } +} + +enum class implementation : uint32_t { + automatic = MFX_IMPL_AUTO, + unsupported = MFX_IMPL_UNSUPPORTED, + software = MFX_IMPL_SOFTWARE, + hardware = MFX_IMPL_HARDWARE, + auto_any = MFX_IMPL_AUTO_ANY, + hardware_any = MFX_IMPL_HARDWARE_ANY, + hardware_2 = MFX_IMPL_HARDWARE2, + hardware_3 = MFX_IMPL_HARDWARE3, + hardware_4 = MFX_IMPL_HARDWARE4, + hardware_runtime = MFX_IMPL_RUNTIME, +}; + +enum class implementation_via : uint32_t { + any = MFX_IMPL_VIA_ANY, + d3d9 = MFX_IMPL_VIA_D3D9, + d3d11 = MFX_IMPL_VIA_D3D11, + vaapi = MFX_IMPL_VIA_VAAPI, + hddlunite = MFX_IMPL_VIA_HDDLUNITE, + none = 0 +}; + +enum class handle_type : uint32_t { + d3d9_device_manager = MFX_HANDLE_D3D9_DEVICE_MANAGER, + d3d11_device_manager = MFX_HANDLE_D3D11_DEVICE, + va_display = MFX_HANDLE_VA_DISPLAY, + va_config_id = MFX_HANDLE_VA_CONFIG_ID, + va_context_id = MFX_HANDLE_VA_CONTEXT_ID, + cm_device = MFX_HANDLE_CM_DEVICE, + hddlunite_workloadcontext = MFX_HANDLE_HDDLUNITE_WORKLOADCONTEXT, +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/detail/frame_interface.hpp b/api/vpl/preview/detail/frame_interface.hpp new file mode 100644 index 00000000..dfe5106e --- /dev/null +++ b/api/vpl/preview/detail/frame_interface.hpp @@ -0,0 +1,151 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include + +#include "vpl/mfxvideo.h" + +namespace oneapi { +namespace vpl { +namespace detail { + +/// @brief This strucure holds context used in the mfxFrameInterface to map/unpam/sync the data +/// when surface is allocated by the application. This hack is needed to unite DX when user works with +/// internally and externally allocated surfaces. +typedef struct _surfCtx__ { + mfxSession s; ///< MFX Session handle + /// Syncronization point provided by the processing functio. Later this sync point is ingested + /// into the context by Session class by using rude hack. + mfxSyncPoint sp; + mfxU32 cnt; ///< References counter + void (*deleter)(mfxFrameSurface1* surface); ///< Allocator provided Data buffer deleter. +} surfCtx__; + +inline void add_data_deleter(mfxFrameSurface1* surface, + void (*deleter)(mfxFrameSurface1* surface)) { + surfCtx__* cnt = reinterpret_cast(surface->FrameInterface->Context); + cnt->deleter = deleter; +} + +inline mfxStatus AddRef__(mfxFrameSurface1* surface) { + surfCtx__* cnt = reinterpret_cast(surface->FrameInterface->Context); + cnt->cnt++; + return MFX_ERR_NONE; +} + +inline mfxStatus Release__(mfxFrameSurface1* surface) { + surfCtx__* cnt = reinterpret_cast(surface->FrameInterface->Context); + cnt->cnt--; + + // std::cout << "i have " << cnt->cnt << std::endl; + if (0 == cnt->cnt) { + // std::cout << "Patched Real destroy of the surface" << std::endl; + if (cnt->deleter) { + cnt->deleter(surface); + } + delete cnt; + delete surface->FrameInterface; + std::memset(surface, 0, sizeof(mfxFrameSurface1)); + delete surface; + } + return MFX_ERR_NONE; +} + +inline mfxStatus GetRefCounter__(mfxFrameSurface1* surface, mfxU32* counter) { + surfCtx__* cnt = reinterpret_cast(surface->FrameInterface->Context); + *counter = cnt->cnt; + return MFX_ERR_NONE; +} + +inline mfxStatus Map__(mfxFrameSurface1* surface, mfxU32 flags) { + surfCtx__* cnt = reinterpret_cast(surface->FrameInterface->Context); + if (flags & MFX_MAP_WRITE && cnt->cnt > 1) { + return MFX_ERR_LOCK_MEMORY; + } + return MFX_ERR_NONE; +} + +inline mfxStatus Unmap__(mfxFrameSurface1* surface) { + return MFX_ERR_NONE; +} + +inline mfxStatus GetNativeHandle__(mfxFrameSurface1* surface, + mfxHDL* resource, + mfxResourceType* resource_type) { + return MFX_ERR_UNSUPPORTED; +} + +inline mfxStatus GetDeviceHandle__(mfxFrameSurface1* surface, + mfxHDL* device_handle, + mfxHandleType* device_type) { + return MFX_ERR_UNSUPPORTED; +} + +inline mfxStatus Synchronize__(mfxFrameSurface1* surface, mfxU32 wait) { + surfCtx__* cnt = reinterpret_cast(surface->FrameInterface->Context); + if (cnt->sp && cnt->s) { + detail::c_api_invoker e(detail::default_checker, + MFXVideoCORE_SyncOperation, + cnt->s, + cnt->sp, + wait); + } + return MFX_ERR_NONE; +} + +inline void OnComplete__(mfxStatus sts) { + // not supported +} + +inline mfxStatus QueryInterface__(mfxFrameSurface1* surface, mfxGUID guid, mfxHDL* iface) { + return MFX_ERR_UNSUPPORTED; +} + + +inline void deleter_Y(mfxFrameSurface1* data) { + delete[] data->Data.Y; +} + +inline void deleter_B(mfxFrameSurface1* data) { + delete[] data->Data.B; +} + +inline auto alloc_i420(const frame_info& info, mfxFrameSurface1* data) { + auto [width, height] = info.get_frame_size(); + + mfxU32 bytes = width * height + (width >> 1) * (height >> 1) + (width >> 1) * (height >> 1); + mfxU8* rawbuffer = new mfxU8[bytes]; + + data->Info = info(); + data->Data.Y = rawbuffer; + data->Data.U = data->Data.Y + width * height; + data->Data.V = data->Data.U + ((width / 2) * (height / 2)); + data->Data.Pitch = width; + + return deleter_Y; +} + +inline auto alloc_bgra(const frame_info& info, mfxFrameSurface1* data) { + auto [width, height] = info.get_frame_size(); + + mfxU32 bytes = width * height * 4; + mfxU8* rawbuffer = new mfxU8[bytes]; + + data->Info = info(); + data->Data.B = rawbuffer; + data->Data.G = data->Data.B + 1; + data->Data.R = data->Data.G + 1; + data->Data.A = data->Data.R + 1; + data->Data.Pitch = width * 4; + + return deleter_B; +} + +} // namespace detail +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/detail/sdk_callable.hpp b/api/vpl/preview/detail/sdk_callable.hpp new file mode 100644 index 00000000..8c400a3d --- /dev/null +++ b/api/vpl/preview/detail/sdk_callable.hpp @@ -0,0 +1,85 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include + +#include "vpl/mfxvideo.h" +#include "vpl/preview/exception.hpp" + +namespace oneapi { +namespace vpl { +namespace detail { + +/// @brief Underlying C API Functions table. It is initialized either for encoder or foe decoder or forVPP. +struct sdk_c_api { + /// @brief MFXVideo***_Query function + std::function query; + /// @brief MFXVideo***_Init function + std::function init; + /// @brief MFXVideo***_Reset function + std::function reset; + /// @brief MFXVideo***_GetVideoParams function + std::function params; + /// @brief MFXVideo***_Close function + std::function close; +}; + +template +struct CAPI { + static inline sdk_c_api Decoder = { MFXVideoDECODE_Query, + MFXVideoDECODE_Init, + MFXVideoDECODE_Reset, + MFXVideoDECODE_GetVideoParam, + MFXVideoDECODE_Close }; + + static inline sdk_c_api Encoder = { MFXVideoENCODE_Query, + MFXVideoENCODE_Init, + MFXVideoENCODE_Reset, + MFXVideoENCODE_GetVideoParam, + MFXVideoENCODE_Close }; + + static inline sdk_c_api VPP = { MFXVideoVPP_Query, + MFXVideoVPP_Init, + MFXVideoVPP_Reset, + MFXVideoVPP_GetVideoParam, + MFXVideoVPP_Close }; +}; + +/// @brief Safely calls C functions and throw exception in case of negative error code. User can provide own +/// function to verify error code. +class c_api_invoker { +public: + /// @brief Construct executer and call the C function. Throws exception if error code verification permits it. + /// @tparam Function C type. + /// @tparam ... C function arguments. + /// @param bad_status_checker Lambda function to check error code. If True is returned, exception is thrown. + /// @param f C function name + /// @param args C function arguments + template + explicit c_api_invoker(std::function bad_status_checker, + Function&& f, + Args&&... args) { + sts_ = std::invoke(std::forward(f), std::forward(args)...); + if (bad_status_checker(sts_)) { + throw base_exception(sts_); + } + } + /// @brief C function call status + mfxStatus sts_; +}; + +/// @brief Verifies error code and returns true if it negative +inline bool default_checker(mfxStatus s) { + bool ret = (s < 0) ? true : false; + return ret; +} + +} // namespace detail +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/detail/string_helpers.hpp b/api/vpl/preview/detail/string_helpers.hpp new file mode 100644 index 00000000..0090935e --- /dev/null +++ b/api/vpl/preview/detail/string_helpers.hpp @@ -0,0 +1,426 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include + +#include "vpl/preview/defs.hpp" +#include "vpl/mfxstructures.h" + +namespace oneapi { +namespace vpl { +namespace detail { + +constexpr unsigned int INTENT = 4; + +template +const T& space(int space, std::ostream& out, const T& arg) { + for (int i = 0; i < space; i++) { + out << ' '; + } + return arg; +} + +inline std::string Boolean2String(uint16_t code) { + if (0 == code) { + return ("False"); + } + return (std::string("True")); +} + +inline std::string FourCC2String(uint32_t code) { + if (0 != code) { + const char* b = (const char*)&code; + return (std::string(b, 4)); + } + return (std::string("Unset")); +} + +inline std::string NotSpecifyed0(uint16_t code) { + if (0 == code) { + return (std::string("Not Specifyed")); + } + return (std::to_string(code)); +} + +inline std::string IOPattern2String(uint16_t code) { + std::string iop; + bool carry = false; + bool isset = false; + if (0 == code) { + return (std::string("Unset")); + } + if (code & MFX_IOPATTERN_IN_VIDEO_MEMORY) { + iop += "In Video"; + carry = true; + isset = true; + } + if (code & MFX_IOPATTERN_IN_SYSTEM_MEMORY) { + if (carry) { + iop += " & "; + } + iop += "In System"; + carry = true; + isset = true; + } + if (code & MFX_IOPATTERN_OUT_VIDEO_MEMORY) { + if (carry) { + iop += " & "; + } + iop += "Out Video"; + carry = true; + isset = true; + } + if (code & MFX_IOPATTERN_OUT_SYSTEM_MEMORY) { + if (carry) { + iop += " & "; + } + iop += "Out Syatem"; + isset = true; + } + if (isset) { + iop += " Memory"; + } + return (iop); +} + +inline std::string TriState2String(uint16_t code) { + switch (code) { + case MFX_CODINGOPTION_ON: + return (std::string("ON")); + case MFX_CODINGOPTION_OFF: + return (std::string("OFF")); + case MFX_CODINGOPTION_ADAPTIVE: + return (std::string("Adaptive")); + default: + return (std::string("Unset")); + } + return (std::string("Unset")); +} + +inline std::string PicStruct2String(uint16_t code) { + switch (code) { + case MFX_PICSTRUCT_PROGRESSIVE: + return (std::string("Progressive Picture")); + case MFX_PICSTRUCT_FIELD_TFF: + return (std::string("Top field")); + case MFX_PICSTRUCT_FIELD_BFF: + return (std::string("Bottom field")); + case MFX_PICSTRUCT_FIELD_REPEATED: + return (std::string("First field repeated")); + case MFX_PICSTRUCT_FRAME_DOUBLING: + return (std::string("Double the frame")); + case MFX_PICSTRUCT_FRAME_TRIPLING: + return (std::string("Triple the frame")); + case MFX_PICSTRUCT_FIELD_SINGLE: + return (std::string("Single field")); + case MFX_PICSTRUCT_FIELD_TOP: + return (std::string("Top field in a picture")); + case MFX_PICSTRUCT_FIELD_BOTTOM: + return (std::string("Bottom field in a picture")); + case MFX_PICSTRUCT_FIELD_PAIRED_PREV: + return (std::string("Paired with previouse field")); + case MFX_PICSTRUCT_FIELD_PAIRED_NEXT: + return (std::string("Paired with nect field")); + case MFX_PICSTRUCT_UNKNOWN: + default: + return (std::string("Unset")); + } + return (std::string("Unset")); +} + +inline std::string ChromaFormat2String(uint16_t code) { + switch (code) { + case MFX_CHROMAFORMAT_MONOCHROME: + return (std::string("Monochrome")); + case MFX_CHROMAFORMAT_YUV420: + return (std::string("4:2:0")); + case MFX_CHROMAFORMAT_YUV422: + return (std::string("4:2:2")); + case MFX_CHROMAFORMAT_YUV444: + return (std::string("4:4:4")); + case MFX_CHROMAFORMAT_YUV411: + return (std::string("4:1:1")); + case MFX_CHROMAFORMAT_YUV422V: + return (std::string("4:2:2 vertical")); + default: + return (std::string("Unset")); + } + return (std::string("Unset")); +} + +inline std::string TimeStampCalc2String(uint16_t code) { + switch (code) { + case MFX_TIMESTAMPCALC_TELECINE: + return (std::string("Telecine")); + default: + return (std::string("Not specifyed")); + } + return (std::string("Not specifyed")); +} + +inline std::string GopOptFlag2String(uint16_t code) { + switch (code) { + case MFX_GOP_CLOSED: + return (std::string("Closed")); + case MFX_GOP_STRICT: + return (std::string("Strict")); + } + return (std::string("Value is out of possible values")); +} + +inline std::string RateControlMethod2String(uint16_t code) { + switch (code) { + case MFX_RATECONTROL_CBR: + return (std::string("CBR")); + case MFX_RATECONTROL_VBR: + return (std::string("VBR")); + case MFX_RATECONTROL_CQP: + return (std::string("CQP")); + case MFX_RATECONTROL_AVBR: + return (std::string("AVBR")); + case MFX_RATECONTROL_LA: + return (std::string("LA")); + case MFX_RATECONTROL_ICQ: + return (std::string("ICQ")); + case MFX_RATECONTROL_VCM: + return (std::string("VCM")); + case MFX_RATECONTROL_LA_ICQ: + return (std::string("LA ICQ")); + case MFX_RATECONTROL_LA_HRD: + return (std::string("LA HRD")); + case MFX_RATECONTROL_QVBR: + return (std::string("QVBR")); + default: + return (std::string("Unknown")); + } + return (std::string("Not specifyed")); +} + +inline std::string MemType2String(uint16_t code) { + std::string res; + bool carry = false; + if (code & MFX_MEMTYPE_INTERNAL_FRAME) { + res += "Internal frame"; + carry = true; + } + else if (code & MFX_MEMTYPE_EXTERNAL_FRAME) { + res += "External frame"; + carry = true; + } + else if (code & MFX_MEMTYPE_EXPORT_FRAME) { + res += "Export frame"; + carry = true; + } + + if (code & MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET) { + res += carry ? " " : ""; + res += "in dec video memory target"; + } + else if (code & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) { + res += carry ? " " : ""; + res += "in VPP video memory target"; + } + else if (code & MFX_MEMTYPE_SYSTEM_MEMORY) { + res += carry ? " " : ""; + res += "in system memory"; + } + else if (code & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) { + res += carry ? " " : ""; + res += "in enc video memory target"; + } + else { + carry = false; + } + + if (code & MFX_MEMTYPE_FROM_ENCODE) { + res += carry ? " " : ""; + res += "alocated by enc"; + } + else if (code & MFX_MEMTYPE_FROM_DECODE) { + res += carry ? " " : ""; + res += "alocated by dec"; + } + else if (code & MFX_MEMTYPE_FROM_VPPIN) { + res += carry ? " " : ""; + res += "alocated by vpp for in"; + } + else if (code & MFX_MEMTYPE_FROM_VPPOUT) { + res += carry ? " " : ""; + res += "alocated by vpp for out"; + } + if (res.size() == 0) + return (std::string("Invalid")); + return (res); +} + +inline std::string TimeStamp2String(uint64_t tms) { + if (tms == (uint64_t)MFX_TIMESTAMP_UNKNOWN) + return (std::string("Unknown")); + return (std::to_string(tms)); +} + +inline std::string TimeStamp2String(int64_t tms) { + if (tms == (int64_t)MFX_TIMESTAMP_UNKNOWN) + return (std::string("Unknown")); + return (std::to_string(tms)); +} + +inline std::string TimeStamp2String(uint16_t code) { + if (code == MFX_FRAMEDATA_ORIGINAL_TIMESTAMP) + return (std::string("Original timestamp.")); + return ("Calculated timestamp"); +} + +inline std::string Corruption2String(uint16_t code) { + switch (code) { + case MFX_CORRUPTION_MINOR: + return (std::string("Minor")); + case MFX_CORRUPTION_MAJOR: + return (std::string("Major")); + case MFX_CORRUPTION_ABSENT_TOP_FIELD: + return (std::string("Top field corrupted")); + case MFX_CORRUPTION_ABSENT_BOTTOM_FIELD: + return (std::string("Bottom field corrupted")); + case MFX_CORRUPTION_REFERENCE_FRAME: + return (std::string("Corrupted reference frame")); + case MFX_CORRUPTION_REFERENCE_LIST: + return (std::string("corrupted reference list")); + default: + return (std::string("No corruption")); + } + return (std::string("Not specifyed")); +} + +inline std::string ResourceType2String(mfxResourceType code) { + switch (code) { + case MFX_RESOURCE_SYSTEM_SURFACE: + return (std::string("System buffer")); + case MFX_RESOURCE_VA_SURFACE: + return (std::string("VA Surface")); + case MFX_RESOURCE_VA_BUFFER: + return (std::string("VA buffer")); + case MFX_RESOURCE_DX9_SURFACE: + return (std::string("DX9 Surface")); + case MFX_RESOURCE_DX11_TEXTURE: + return (std::string("DX11 Texture")); + case MFX_RESOURCE_DX12_RESOURCE: + return (std::string("DX12 Resource")); + case MFX_RESOURCE_DMA_RESOURCE: + return (std::string("DMA buffer")); + default: + return (std::string("Unknown resource type")); + } + return (std::string("Not specifyed")); +} + +inline std::string ImplType2String(mfxImplType code) { + switch (code) { + case MFX_IMPL_TYPE_SOFTWARE: + return (std::string("Software")); + case MFX_IMPL_TYPE_HARDWARE: + return (std::string("Hardware")); + default: + return (std::string("Unknown type")); + } + return (std::string("Not specifyed")); +} + +inline std::string AccelerationMode2String(mfxAccelerationMode code) { + switch (code) { + case MFX_ACCEL_MODE_NA: + return (std::string("No HW acceleration")); + case MFX_ACCEL_MODE_VIA_D3D9: + return (std::string("HW acceleration via Microsoft* Direct3D9*")); + case MFX_ACCEL_MODE_VIA_D3D11: + return (std::string("HW acceleration via Microsoft* Direct3D11*")); + case MFX_ACCEL_MODE_VIA_VAAPI: + return (std::string("HW acceleration via Linux* VA-API")); + default: + return (std::string("Unknown resource type")); + } + return (std::string("Not specifyed")); +} + +inline std::string component2String(component c) { + switch (c) { + case component::decoder: + return (std::string("Decoder")); + case component::encoder: + return (std::string("Encoder")); + case component::vpp: + return (std::string("VPP")); + case component::decoder_vpp: + return (std::string("Decoder+VPP")); + default: + return (std::string("Unknown component")); + } + return (std::string("Unknown component")); +} + +inline std::string status2Str(status s) { + switch (s) { + case status::Ok: + return (std::string("Ok")); + break; + case status::ExecutionInProgress: + return (std::string("ExecutionInProgress")); + break; + case status::DeviceBusy: + return (std::string("DeviceBusy")); + break; + case status::VideoParamChanged: + return (std::string("VideoParamChanged")); + break; + case status::PartialAcceleration: + return (std::string("PartialAcceleration")); + break; + case status::IncompartibleVideoParam: + return (std::string("IncompartibleVideoParam")); + break; + case status::ValueNotChanged: + return (std::string("ValueNotChanged")); + break; + case status::OutOfRange: + return (std::string("OutOfRange")); + break; + case status::TaskWorking: + return (std::string("TaskWorking")); + break; + case status::TaskBusy: + return (std::string("TaskBusy")); + break; + case status::FilterSkipped: + return (std::string("FilterSkipped")); + break; + case status::PartialOutput: + return (std::string("PartialOutput")); + break; + case status::NotEnoughData: + return (std::string("NotEnoughData")); + break; + case status::NotEnoughSurface: + return (std::string("NotEnoughSurface")); + break; + case status::NotEnoughBuffer: + return (std::string("NotEnoughBuffer")); + break; + case status::EndOfStreamReached: + return (std::string("EndOfStreamReached")); + break; + case status::Unknown: + default: + return (std::string("Unknown")); + break; + } +} + +} // namespace detail +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/detail/variant.hpp b/api/vpl/preview/detail/variant.hpp new file mode 100644 index 00000000..633e2814 --- /dev/null +++ b/api/vpl/preview/detail/variant.hpp @@ -0,0 +1,124 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +// #include +#include + +#include "vpl/mfxcommon.h" +#include "vpl/mfxdefs.h" + +namespace oneapi { +namespace vpl { +namespace detail { + +/// @brief This class represents variant-like datatype of selected mfx* types, including pointer +class variant { +public: + /// @brief Default ctor. Initializes variand with value of unset data type. + variant() { + v_.Type = MFX_VARIANT_TYPE_UNSET; + v_.Data.U64 = 0; + } + + /// @brief Parametrized ctor. Accepts values of fixed set of mfx* types, including pointer. + /// @tparam T Type of value + /// @param[in] t Value + template + explicit variant(T t) : v_({0}){ + type_init(t); + } + + /// @brief Returns instance of mfxVariant C type. + /// @return instance of mfxVariant C type. + mfxVariant get_variant() const { + return v_; + } + +private: + /// @brief Ctor's helper to check of value of uint8_t data type. + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.U8 = t; + v_.Type = MFX_VARIANT_TYPE_U8; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.U8 = t; + v_.Type = MFX_VARIANT_TYPE_U8; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.I8 = t; + v_.Type = MFX_VARIANT_TYPE_I8; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.U16 = t; + v_.Type = MFX_VARIANT_TYPE_U16; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.I16 = t; + v_.Type = MFX_VARIANT_TYPE_I16; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.U32 = t; + v_.Type = MFX_VARIANT_TYPE_U32; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.I32 = t; + v_.Type = MFX_VARIANT_TYPE_I32; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.U64 = t; + v_.Type = MFX_VARIANT_TYPE_U64; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.I64 = t; + v_.Type = MFX_VARIANT_TYPE_I64; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.F32 = t; + v_.Type = MFX_VARIANT_TYPE_F32; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.F64 = t; + v_.Type = MFX_VARIANT_TYPE_F64; + } + + template + typename std::enable_if::value>::type type_init(T t) { + v_.Data.Ptr = t; + v_.Type = MFX_VARIANT_TYPE_PTR; + } + +protected: + /// Instance of mfxVariant where all data is stored and used by C API + mfxVariant v_; +}; + +} // namespace detail +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/exception.hpp b/api/vpl/preview/exception.hpp new file mode 100644 index 00000000..de54c874 --- /dev/null +++ b/api/vpl/preview/exception.hpp @@ -0,0 +1,167 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include + +#include "vpl/mfxdefs.h" + +namespace oneapi { +namespace vpl { + +/// @brief Base class to represents oneVPL exception (negative) C API error codes +class base_exception : virtual public std::exception { +public: + /// @brief Default ctor + /// @param[in] status Operation ststus code + explicit base_exception(mfxStatus status) : status_(status), text_(), res_() { + res_ = "oneVPL: " + text_ + ": " + status_to_string(); + } + + /// @brief Default ctor + /// @param[in] text Additional text to add to status string + /// @param[in] status Operation status code + explicit base_exception(std::string text, mfxStatus status) + : status_(status), + text_(text), + res_() { + res_ = "oneVPL: " + text_ + ": " + status_to_string(); + } + + base_exception(const base_exception& ex) + : status_(ex.status_), + text_(ex.text_), + res_(ex.res_) {} + + /// @brief Assignment operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + base_exception& operator=(const base_exception& other) = default; + + /// @brief Move ctor + /// @param[in] other another object to use as data source + base_exception(base_exception&& other) = default; + + /// @brief Move operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + base_exception& operator=(base_exception&& other) = default; + + /// @brief Returns exception description in text form + /// @return null terminated string with the exception details + virtual const char* what() const noexcept { + return res_.c_str(); + } + /// @brief Provides C API status code + /// @return C API status code + const mfxStatus get_status() const noexcept { + return status_; + } + +protected: + /// @brief Converts C API status code in to the text form + /// @return C API status code min text form + std::string status_to_string() const noexcept { + switch (status_) { + case MFX_ERR_NONE: + return "No error."; + case MFX_ERR_UNKNOWN: + return "Unknown error."; + case MFX_ERR_NULL_PTR: + return "NULL pointer."; + case MFX_ERR_UNSUPPORTED: + return "Unsupported."; + case MFX_ERR_MEMORY_ALLOC: + return "Memory allocation error."; + case MFX_ERR_NOT_ENOUGH_BUFFER: + return "Not enough buffer."; + case MFX_ERR_INVALID_HANDLE: + return "Invalide handle."; + case MFX_ERR_LOCK_MEMORY: + return "Lock memory error."; + case MFX_ERR_NOT_INITIALIZED: + return "Not initialized."; + case MFX_ERR_NOT_FOUND: + return "Not found."; + case MFX_ERR_MORE_DATA: + return "Not enough data."; + case MFX_ERR_MORE_SURFACE: + return "Not enough surfaces."; + case MFX_ERR_ABORTED: + return "Operation aborted."; + case MFX_ERR_DEVICE_LOST: + return "Decice lost."; + case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM: + return "Incompartible video parameter."; + case MFX_ERR_INVALID_VIDEO_PARAM: + return "Invlid video parameter."; + case MFX_ERR_UNDEFINED_BEHAVIOR: + return "Behaviour is undefined."; + case MFX_ERR_DEVICE_FAILED: + return "Device failed."; + case MFX_ERR_MORE_BITSTREAM: + return "Not enough bitstream."; + case MFX_ERR_GPU_HANG: + return "Device hang."; + case MFX_ERR_REALLOC_SURFACE: + return "Bigger output surface required."; + case MFX_ERR_RESOURCE_MAPPED: + return "Resource mapping failed."; + case MFX_ERR_NOT_IMPLEMENTED: + return "Not implemetned."; + default: + return "Unregistered unknown error."; + } + return "Unregistered unknown error."; + } + /// @brief C API status code + mfxStatus status_; + /// @brief String with additional error text + std::string text_; + /// @brief String with error code + std::string res_; +}; + +/// @brief File exception class to represent oneVPL exception (negative) C API error codes +class file_exception : virtual public std::exception { +public: + /// @brief Default ctor + /// @param[in] text Additional text to add to status string + explicit file_exception(const std::string& text) : res_(text) { + res_ = "oneVPL File IO: " + text; + } + + file_exception(const file_exception& ex) : res_(ex.res_) {} + + /// @brief Assignment operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + file_exception& operator=(const file_exception& other) = default; + + /// @brief Move ctor + /// @param[in] other another object to use as data source + file_exception(file_exception&& other) = default; + + /// @brief Move operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + file_exception& operator=(file_exception&& other) = default; + + /// @brief Returns exception description in text form + /// @return null terminated string with the exception details + virtual const char* what() const noexcept { + return res_.c_str(); + } + +protected: + /// @brief String with error code + std::string res_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/extension_buffer.hpp b/api/vpl/preview/extension_buffer.hpp new file mode 100644 index 00000000..9f5f9ccd --- /dev/null +++ b/api/vpl/preview/extension_buffer.hpp @@ -0,0 +1,1010 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include +#include + +#include "vpl/mfxstructures.h" + +#include "vpl/preview/payload.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief Interface definition for extension buffers. Extension buffers are used to provide additional data +/// for the encoders/decoders/vpp instances or to retrieve additional data. +/// Each extension buffer reflects corresppnding structure from C API. +class extension_buffer_base { +public: + /// @brief Default ctor. + extension_buffer_base() {} + + /// @brief Default copy ctor. + /// @param[in] other another object to use as data source + extension_buffer_base(const extension_buffer_base& other) = default; + + /// @brief Default copy operator. + /// @param[in] other another object to use as data source + /// @returns Reference to this object + extension_buffer_base& operator=(const extension_buffer_base& other) = default; + + /// @brief Dtor. + virtual ~extension_buffer_base() {} + + /// @brief Interface to retieve extension buffer ID in a form of FourCC code. + /// @return Extension buffer ID. + virtual uint32_t get_ID() const = 0; + + /// @brief Interface to retieve raw pointer to the C header of C sructure. + /// @return Pointer to the header of extension buffer C strucure. + virtual mfxExtBuffer* get_ptr() = 0; +}; + +/// @brief Utilitary intermediate class to typify extension buffer interface with +/// assotiated ID and C structure +/// @tparam T C structure +/// @tparam ID Assotiated ID with C structure +template +class extension_buffer : public extension_buffer_base { +protected: + /// @brief Utilitary meta class to verify that @p T type is real C type of extension buffers. + class is_extension_buffer { + private: + typedef char Yes; + typedef int No; + + template + static Yes& check(decltype(&C::Header)); + template + static No& check(...); + + public: + /// @brief Meta enum for type check + enum { value = sizeof(check(0)) == sizeof(Yes) }; + }; + +public: + /// @brief Default ctor + template < + typename check = typename std::enable_if::type> + extension_buffer() : buffer_() { + buffer_.Header.BufferSz = sizeof(T); + buffer_.Header.BufferId = ID; + } + + /// @brief Default copy ctor + /// @param[in] other another object to use as data source + extension_buffer(const extension_buffer& other) = default; + + /// @brief Default copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + extension_buffer& operator=(const extension_buffer& other) = default; + virtual ~extension_buffer() {} + +public: + /// @brief Returns ID of the extension buffer in a form of FourCC code. + /// @return Buffer ID + uint32_t get_ID() const { + return buffer_.Header.BufferId; + } + + /// @brief Returns size of the extension buffer in bytes. + /// @return Size in bytes + uint32_t get_size() const { + return buffer_.Header.BufferSz; + } + + /// @brief Returns reference to underlying C structure with the extension buffer. + /// @return Reference to underlying C structure. + virtual T& get_ref() { + return buffer_; + } + + /// @brief Returns instance of underlying C structure with the extension buffer. + /// @return Instance underlying C structure. + T get() const { + return buffer_; + } + + /// @brief Returns raw pointer to underlying C structure with the extension buffer. + /// @return Raw pointer to underlying C structure. + mfxExtBuffer* get_ptr() { + return reinterpret_cast(&buffer_); + } + +protected: + /// @brief Underlying C structure + T buffer_; +}; + +/// @brief Utilitary intermediate class to keep extension buffers without pointers. For such classes +/// default copy ctor and operator is used. +/// @tparam T C structure +/// @tparam ID Assotiated ID with C structure +template +class extension_buffer_trival : public extension_buffer { +public: + /// @brief Default ctor + extension_buffer_trival() {} + + /// @brief Default copy ctor + /// @param[in] other another object to use as data source + extension_buffer_trival(const extension_buffer_trival& other) = default; + + /// @brief Default copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + extension_buffer_trival& operator=(const extension_buffer_trival& other) = default; +}; + +/// @brief Utilitary intermediate class to keep extension buffers with pointers. For such classes +/// copy ctor and operator must be implemented. +/// @tparam T C structure +/// @tparam ID Assotiated ID with C structure +template +class extension_buffer_with_ptrs : public extension_buffer { +public: + /// @brief Default ctor + extension_buffer_with_ptrs() {} + + /// @brief Default copy ctor + /// @param[in] other another object to use as data source + extension_buffer_with_ptrs(const extension_buffer_with_ptrs& other) = default; + + /// @brief Default copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + extension_buffer_with_ptrs& operator=(const extension_buffer_with_ptrs& other) = default; + +protected: + /// @brief Prohibited method for structure with pointers + /// @returns Reference to the raw object + virtual T& get_ref() { + return extension_buffer::get_ref(); // this is dangerouse for pointers! + } +}; + +#define REGISTER_TRIVIAL_EXT_BUFFER(className, extBuffer, bufferID) \ + /*! @brief Instantiation of the extension_buffer template class for given C structure and ID.*/ \ + class className : public extension_buffer_trival { \ + public: \ + /*! @brief Default ctor. */ \ + className() : extension_buffer_trival() {} \ + }; + +REGISTER_TRIVIAL_EXT_BUFFER(ExtCodingOption, mfxExtCodingOption, MFX_EXTBUFF_CODING_OPTION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtCodingOption2, mfxExtCodingOption2, MFX_EXTBUFF_CODING_OPTION2) +REGISTER_TRIVIAL_EXT_BUFFER(ExtCodingOption3, mfxExtCodingOption3, MFX_EXTBUFF_CODING_OPTION3) + +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPDenoise, mfxExtVPPDenoise, MFX_EXTBUFF_VPP_DENOISE) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPDetail, mfxExtVPPDetail, MFX_EXTBUFF_VPP_DETAIL) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPProcAmp, mfxExtVPPProcAmp, MFX_EXTBUFF_VPP_PROCAMP) + +/*! @brief Instantiation of the extension_buffer template class for given C structure and ID.*/ +class ExtVppAuxData : public extension_buffer_trival { +public: + explicit ExtVppAuxData(pic_struct picStruct) : extension_buffer_trival() { + this->buffer_.PicStruct = (uint16_t)picStruct; + } +}; + +// I would assign special status for mfxEncodeCtrl structure for now +REGISTER_TRIVIAL_EXT_BUFFER(ExtVideoSignalInfo, + mfxExtVideoSignalInfo, + MFX_EXTBUFF_VIDEO_SIGNAL_INFO) +REGISTER_TRIVIAL_EXT_BUFFER(ExtAVCRefListCtrl, mfxExtAVCRefListCtrl, MFX_EXTBUFF_AVC_REFLIST_CTRL) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPFrameRateConversion, + mfxExtVPPFrameRateConversion, + MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPImageStab, + mfxExtVPPImageStab, + MFX_EXTBUFF_VPP_IMAGE_STABILIZATION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtMasteringDisplayColourVolume, + mfxExtMasteringDisplayColourVolume, + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME) +REGISTER_TRIVIAL_EXT_BUFFER(ExtContentLightLevelInfo, + mfxExtContentLightLevelInfo, + MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO) +REGISTER_TRIVIAL_EXT_BUFFER(ExtPictureTimingSEI, + mfxExtPictureTimingSEI, + MFX_EXTBUFF_PICTURE_TIMING_SEI) +REGISTER_TRIVIAL_EXT_BUFFER(ExtAvcTemporalLayers, + mfxExtAvcTemporalLayers, + MFX_EXTBUFF_AVC_TEMPORAL_LAYERS) +REGISTER_TRIVIAL_EXT_BUFFER(ExtEncoderCapability, + mfxExtEncoderCapability, + MFX_EXTBUFF_ENCODER_CAPABILITY) +REGISTER_TRIVIAL_EXT_BUFFER(ExtEncoderResetOption, + mfxExtEncoderResetOption, + MFX_EXTBUFF_ENCODER_RESET_OPTION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtAVCEncodedFrameInfo, + mfxExtAVCEncodedFrameInfo, + MFX_EXTBUFF_ENCODED_FRAME_INFO) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPVideoSignalInfo, + mfxExtVPPVideoSignalInfo, + MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO) +REGISTER_TRIVIAL_EXT_BUFFER(ExtEncoderROI, mfxExtEncoderROI, MFX_EXTBUFF_ENCODER_ROI) +REGISTER_TRIVIAL_EXT_BUFFER(ExtAVCRefLists, mfxExtAVCRefLists, MFX_EXTBUFF_AVC_REFLISTS) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPDeinterlacing, + mfxExtVPPDeinterlacing, + MFX_EXTBUFF_VPP_DEINTERLACING) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPFieldProcessing, + mfxExtVPPFieldProcessing, + MFX_EXTBUFF_VPP_FIELD_PROCESSING) +REGISTER_TRIVIAL_EXT_BUFFER(ExtDecVideoProcessing, + mfxExtDecVideoProcessing, + MFX_EXTBUFF_DEC_VIDEO_PROCESSING) +REGISTER_TRIVIAL_EXT_BUFFER(ExtChromaLocInfo, mfxExtChromaLocInfo, MFX_EXTBUFF_CHROMA_LOC_INFO) +REGISTER_TRIVIAL_EXT_BUFFER(ExtInsertHeaders, mfxExtInsertHeaders, MFX_EXTBUFF_INSERT_HEADERS) +REGISTER_TRIVIAL_EXT_BUFFER(ExtHEVCTiles, mfxExtHEVCTiles, MFX_EXTBUFF_HEVC_TILES) +REGISTER_TRIVIAL_EXT_BUFFER(ExtHEVCParam, mfxExtHEVCParam, MFX_EXTBUFF_HEVC_PARAM) +REGISTER_TRIVIAL_EXT_BUFFER(ExtDecodeErrorReport, + mfxExtDecodeErrorReport, + MFX_EXTBUFF_DECODE_ERROR_REPORT) + +/*! @brief Instantiation of the extension_buffer template class for given C structure and ID.*/ +class ExtDecodedFrameInfo + : public extension_buffer_trival { +public: + /*! @brief Default ctor. */ + ExtDecodedFrameInfo() : extension_buffer_trival() {} + + explicit ExtDecodedFrameInfo(frame_type frameType) : extension_buffer_trival() { + this->buffer_.FrameType = (uint16_t)frameType; + } +}; + +REGISTER_TRIVIAL_EXT_BUFFER(ExtTimeCode, mfxExtTimeCode, MFX_EXTBUFF_TIME_CODE) +REGISTER_TRIVIAL_EXT_BUFFER(ExtHEVCRegion, mfxExtHEVCRegion, MFX_EXTBUFF_HEVC_REGION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtPredWeightTable, + mfxExtPredWeightTable, + MFX_EXTBUFF_PRED_WEIGHT_TABLE) +REGISTER_TRIVIAL_EXT_BUFFER(ExtAVCRoundingOffset, + mfxExtAVCRoundingOffset, + MFX_EXTBUFF_AVC_ROUNDING_OFFSET) +REGISTER_TRIVIAL_EXT_BUFFER(ExtDirtyRect, mfxExtDirtyRect, MFX_EXTBUFF_DIRTY_RECTANGLES) +REGISTER_TRIVIAL_EXT_BUFFER(ExtMoveRect, mfxExtMoveRect, MFX_EXTBUFF_MOVING_RECTANGLES) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPRotation, mfxExtVPPRotation, MFX_EXTBUFF_VPP_ROTATION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPScaling, mfxExtVPPScaling, MFX_EXTBUFF_VPP_SCALING) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPMirroring, mfxExtVPPMirroring, MFX_EXTBUFF_VPP_MIRRORING) +REGISTER_TRIVIAL_EXT_BUFFER(ExtMVOverPicBoundaries, + mfxExtMVOverPicBoundaries, + MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVPPColorFill, mfxExtVPPColorFill, MFX_EXTBUFF_VPP_COLORFILL) +REGISTER_TRIVIAL_EXT_BUFFER(ExtColorConversion, + mfxExtColorConversion, + MFX_EXTBUFF_VPP_COLOR_CONVERSION) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVP9TemporalLayers, + mfxExtVP9TemporalLayers, + MFX_EXTBUFF_VP9_TEMPORAL_LAYERS) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVP9Param, mfxExtVP9Param, MFX_EXTBUFF_VP9_PARAM) +REGISTER_TRIVIAL_EXT_BUFFER(ExtVppMctf, mfxExtVppMctf, MFX_EXTBUFF_VPP_MCTF) +REGISTER_TRIVIAL_EXT_BUFFER(ExtPartialBitstreamParam, + mfxExtPartialBitstreamParam, + MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM) + +// extension buffers with pointers below + +#define SCALAR_SETTER(type, name) \ + /*! @brief Sets name value. */ \ + /*! @param[in] name Value. */ \ + void set_##name(type name) { \ + this->buffer_.name = name; \ + } + +#define ARRAY_SETTER(type, name, len) \ + /*! @brief Sets name value. */ \ + /*! @param[in] name Value. */ \ + void set_##name(const type name[len]) { \ + std::copy(name, name + len, this->buffer_.name); \ + } + +#define REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(className, \ + extBuffer, \ + bufferID, \ + ptr, \ + ptrType, \ + numElems) \ + /*! @brief Instantiation of the extension_buffer template class for given C structure and ID.*/ \ + class className : public extension_buffer_with_ptrs { \ + public: \ + /*! @brief Creates object and initialize underlying strucure with data from the pointer. */ \ + /*! @param[in] ptr Ponter to the data.*/ \ + explicit className(const std::vector& ptr) : extension_buffer_with_ptrs() { \ + if (ptr.size()) { \ + buffer_.numElems = (decltype(buffer_.numElems))ptr.size(); \ + buffer_.ptr = new ptrType[buffer_.numElems]; \ + std::copy(ptr.begin(), ptr.end(), buffer_.ptr); \ + } \ + else { \ + buffer_.numElems = 0; \ + buffer_.ptr = NULL; \ + } \ + } \ + \ + /*! @brief Copy ctor. */ \ + /*! @param[in] other another object to use as data source. */ \ + className(const className& other) { \ + this->buffer_ = other.buffer_; \ + if (other.buffer_.numElems) { \ + this->buffer_.numElems = other.buffer_.numElems; \ + this->buffer_.ptr = new ptrType[buffer_.numElems]; \ + std::copy(other.buffer_.ptr, \ + other.buffer_.ptr + other.buffer_.numElems, \ + this->buffer_.ptr); \ + } \ + } \ + \ + /*! @brief Dtor. */ \ + ~className() { \ + delete[] buffer_.ptr; \ + buffer_.numElems = 0; \ + } \ + /*! @brief Copy operator. */ \ + /*! @param[in] other another object to use as data source. */ \ + /*! @returns Reference to this object */ \ + virtual className& operator=(const className& other) { \ + if (&other == this) \ + return *this; \ + \ + if (this->buffer_.ptr) \ + delete[] this->buffer_.ptr; \ + this->buffer_ = other.buffer_; \ + \ + if (other.buffer_.numElems) { \ + this->buffer_.numElems = other.buffer_.numElems; \ + this->buffer_.ptr = new ptrType[buffer_.numElems]; \ + std::copy(other.buffer_.ptr, \ + other.buffer_.ptr + other.buffer_.numElems, \ + this->buffer_.ptr); \ + } \ + else { \ + buffer_.numElems = 0; \ + buffer_.ptr = NULL; \ + } \ + \ + return *this; \ + } + +#define REGISTER_SINGLE_POINTER_EXT_BUFFER_END \ + } \ + ; + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtCodingOptionVPS, + mfxExtCodingOptionVPS, + MFX_EXTBUFF_CODING_OPTION_VPS, + VPSBuffer, + uint8_t, + VPSBufSize) +SCALAR_SETTER(uint16_t, VPSId) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtVPPComposite, + mfxExtVPPComposite, + MFX_EXTBUFF_CODING_OPTION_VPS, + InputStream, + mfxVPPCompInputStream, + NumInputStream) +SCALAR_SETTER(uint16_t, Y) +SCALAR_SETTER(uint16_t, R) +SCALAR_SETTER(uint16_t, U) +SCALAR_SETTER(uint16_t, G) +SCALAR_SETTER(uint16_t, V) +SCALAR_SETTER(uint16_t, B) +SCALAR_SETTER(uint16_t, NumTiles) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtEncoderIPCMArea, + mfxExtEncoderIPCMArea, + MFX_EXTBUFF_ENCODER_IPCM_AREA, + Areas, + mfxExtEncoderIPCMArea::area, + NumArea); +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtMBForceIntra, + mfxExtMBForceIntra, + MFX_EXTBUFF_MB_FORCE_INTRA, + Map, + uint8_t, + MapSize) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtMBDisableSkipMap, + mfxExtMBDisableSkipMap, + MFX_EXTBUFF_MB_DISABLE_SKIP_MAP, + Map, + uint8_t, + MapSize) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtEncodedSlicesInfo, + mfxExtEncodedSlicesInfo, + MFX_EXTBUFF_ENCODED_SLICES_INFO, + SliceSize, + uint16_t, + NumSliceSizeAlloc) +SCALAR_SETTER(uint16_t, SliceSizeOverflow) +SCALAR_SETTER(uint16_t, NumSliceNonCopliant) +SCALAR_SETTER(uint16_t, NumEncodedSlice) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtVP9Segmentation, + mfxExtVP9Segmentation, + MFX_EXTBUFF_VP9_SEGMENTATION, + SegmentId, + uint8_t, + NumSegmentIdAlloc) +SCALAR_SETTER(uint16_t, NumSegments) +SCALAR_SETTER(uint16_t, SegmentIdBlockSize) +ARRAY_SETTER(mfxVP9SegmentParam, Segment, 8) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +REGISTER_SINGLE_POINTER_EXT_BUFFER_BEGIN(ExtEncodedUnitsInfo, + mfxExtEncodedUnitsInfo, + MFX_EXTBUFF_ENCODED_UNITS_INFO, + UnitInfo, + mfxEncodedUnitInfo, + NumUnitsAlloc) +SCALAR_SETTER(uint16_t, NumUnitsEncoded) +REGISTER_SINGLE_POINTER_EXT_BUFFER_END + +// Complex extensions with more than 1 pointer + +/// @brief represents class to manage VPP algorithms exclude list +class ExtVPPDoNotUse + : public extension_buffer_with_ptrs { +public: + /// @brief Constructs object with the list of VPP algorithms to exclude from the processing + /// @param[in] algos List of VPP algorithms + ExtVPPDoNotUse(const std::initializer_list& algos) : extension_buffer_with_ptrs() { + buffer_.NumAlg = static_cast(algos.size()); + buffer_.AlgList = new uint32_t[buffer_.NumAlg]; + + std::copy(std::begin(algos), std::end(algos), this->buffer_.AlgList); + } + + /// @brief Constructs object with the list of VPP algorithms to exclude from the processing + /// @param[in] algos List of VPP algorithms + explicit ExtVPPDoNotUse(const std::vector& algos) : extension_buffer_with_ptrs() { + buffer_.NumAlg = static_cast(algos.size()); + buffer_.AlgList = new uint32_t[buffer_.NumAlg]; + + std::copy(std::begin(algos), std::end(algos), this->buffer_.AlgList); + } + + /// @brief Copy ctor + /// @param[in] other another object to use as data source + explicit ExtVPPDoNotUse(const ExtVPPDoNotUse& other) { + this->buffer_.NumAlg = other.buffer_.NumAlg; + this->buffer_.AlgList = new uint32_t[other.buffer_.NumAlg]; + + std::copy(other.buffer_.AlgList, + other.buffer_.AlgList + other.buffer_.NumAlg, + this->buffer_.AlgList); + } + + /// @brief Dtor + ~ExtVPPDoNotUse() { + delete[] buffer_.AlgList; + buffer_.NumAlg = 0; + } + + /// @brief Copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + virtual ExtVPPDoNotUse& operator=(const ExtVPPDoNotUse& other) { + if (&other == this) + return *this; + + if (this->buffer_.AlgList) + delete[] this->buffer_.AlgList; + + this->buffer_.NumAlg = other.buffer_.NumAlg; + this->buffer_.AlgList = new uint32_t[other.buffer_.NumAlg]; + + std::copy(other.buffer_.AlgList, + other.buffer_.AlgList + other.buffer_.NumAlg, + this->buffer_.AlgList); + return *this; + } +}; + +/// @brief Manages VPP algorithms exclude list +class ExtVPPDoUse : public extension_buffer_with_ptrs { +public: + /// @brief Constructs object with the list of VPP algorithms to include into the processing + /// @param[in] algos List of VPP algorithms + ExtVPPDoUse(const std::initializer_list& algos) : extension_buffer_with_ptrs() { + buffer_.NumAlg = static_cast(algos.size()); + buffer_.AlgList = new uint32_t[buffer_.NumAlg]; + + std::copy(std::begin(algos), std::end(algos), this->buffer_.AlgList); + } + + /// @brief Constructs object with the list of VPP algorithms to include into the processing + /// @param[in] algos List of VPP algorithms + explicit ExtVPPDoUse(const std::vector& algos) : extension_buffer_with_ptrs() { + buffer_.NumAlg = static_cast(algos.size()); + buffer_.AlgList = new uint32_t[buffer_.NumAlg]; + + std::copy(std::begin(algos), std::end(algos), this->buffer_.AlgList); + } + + /// @brief Copy ctor + /// @param[in] other another object to use as data source + explicit ExtVPPDoUse(const ExtVPPDoUse& other) { + this->buffer_.NumAlg = other.buffer_.NumAlg; + this->buffer_.AlgList = new uint32_t[other.buffer_.NumAlg]; + + std::copy(other.buffer_.AlgList, + other.buffer_.AlgList + other.buffer_.NumAlg, + this->buffer_.AlgList); + } + + /// @brief Dtor + ~ExtVPPDoUse() { + delete[] buffer_.AlgList; + buffer_.NumAlg = 0; + } + + /// @brief Copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + virtual ExtVPPDoUse& operator=(const ExtVPPDoUse& other) { + if (&other == this) + return *this; + + if (this->buffer_.AlgList) + delete[] this->buffer_.AlgList; + + this->buffer_.NumAlg = other.buffer_.NumAlg; + this->buffer_.AlgList = new uint32_t[other.buffer_.NumAlg]; + + std::copy(other.buffer_.AlgList, + other.buffer_.AlgList + other.buffer_.NumAlg, + this->buffer_.AlgList); + return *this; + } +}; + +/// @brief Manages SPS and PPS buffers +class ExtCodingOptionSPSPPS : public extension_buffer_with_ptrs { +public: + /// @brief Constructs object with SPS and PPB vectors + /// @param[in] SPS SPS buffer + /// @param[in] PPS PPS buffer + ExtCodingOptionSPSPPS(const std::vector& SPS, const std::vector& PPS) + : extension_buffer_with_ptrs() { + // make a copy for now. Behaviour TBD later. + if (SPS.size()) { + buffer_.SPSBufSize = (uint16_t)SPS.size(); + buffer_.SPSBuffer = new uint8_t[buffer_.SPSBufSize]; + std::copy(SPS.begin(), SPS.end(), buffer_.SPSBuffer); + } + else { + buffer_.SPSBufSize = 0; + buffer_.SPSBuffer = NULL; + } + + if (PPS.size()) { + buffer_.PPSBufSize = (uint16_t)PPS.size(); + buffer_.PPSBuffer = new uint8_t[buffer_.PPSBufSize]; + std::copy(PPS.begin(), PPS.end(), buffer_.PPSBuffer); + } + else { + buffer_.PPSBufSize = 0; + buffer_.PPSBuffer = NULL; + } + } + + /// @brief Copy ctor + /// @param[in] other another object to use as data source + ExtCodingOptionSPSPPS(const ExtCodingOptionSPSPPS& other) { + if (other.buffer_.SPSBufSize) { + this->buffer_.SPSBufSize = other.buffer_.SPSBufSize; + this->buffer_.SPSBuffer = new uint8_t[buffer_.SPSBufSize]; + std::copy(other.buffer_.SPSBuffer, + other.buffer_.SPSBuffer + other.buffer_.SPSBufSize, + this->buffer_.SPSBuffer); + } + + if (other.buffer_.PPSBufSize) { + this->buffer_.PPSBufSize = other.buffer_.PPSBufSize; + this->buffer_.PPSBuffer = new uint8_t[buffer_.PPSBufSize]; + std::copy(other.buffer_.PPSBuffer, + other.buffer_.PPSBuffer + other.buffer_.PPSBufSize, + this->buffer_.PPSBuffer); + } + + this->buffer_.SPSId = other.buffer_.SPSId; + this->buffer_.PPSId = other.buffer_.PPSId; + } + + /// @brief Dtor + ~ExtCodingOptionSPSPPS() { + delete[] buffer_.SPSBuffer; + buffer_.SPSBufSize = 0; + delete[] buffer_.PPSBuffer; + buffer_.PPSBufSize = 0; + } + + /// @brief Copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + virtual ExtCodingOptionSPSPPS& operator=(const ExtCodingOptionSPSPPS& other) { + if (&other == this) + return *this; + + if (this->buffer_.SPSBuffer) + delete[] this->buffer_.SPSBuffer; + if (this->buffer_.PPSBuffer) + delete[] this->buffer_.PPSBuffer; + + if (other.buffer_.SPSBufSize) { + this->buffer_.SPSBufSize = other.buffer_.SPSBufSize; + this->buffer_.SPSBuffer = new uint8_t[buffer_.SPSBufSize]; + std::copy(other.buffer_.SPSBuffer, + other.buffer_.SPSBuffer + other.buffer_.SPSBufSize, + this->buffer_.SPSBuffer); + } + else { + buffer_.SPSBufSize = 0; + buffer_.SPSBuffer = NULL; + } + + if (other.buffer_.PPSBufSize) { + this->buffer_.PPSBufSize = other.buffer_.PPSBufSize; + this->buffer_.PPSBuffer = new uint8_t[buffer_.PPSBufSize]; + std::copy(other.buffer_.PPSBuffer, + other.buffer_.PPSBuffer + other.buffer_.PPSBufSize, + this->buffer_.PPSBuffer); + } + else { + buffer_.PPSBufSize = 0; + buffer_.PPSBuffer = NULL; + } + + this->buffer_.SPSId = other.buffer_.SPSId; + this->buffer_.PPSId = other.buffer_.PPSId; + + return *this; + } + SCALAR_SETTER(uint16_t, SPSId) + SCALAR_SETTER(uint16_t, PPSId) +}; + +/// @brief Manages per macro-block QP use strategies +class ExtMBQP : public extension_buffer_with_ptrs { +public: + /// @brief Constructs object with QP array + /// @param[in] Qp QP value + explicit ExtMBQP(const std::vector& Qp) : extension_buffer_with_ptrs() { + // make a copy for now. Behaviour TBD later. + buffer_.Mode = MFX_MBQP_MODE_QP_VALUE; + if (Qp.size()) { + buffer_.NumQPAlloc = static_cast(Qp.size()); + buffer_.QP = new uint8_t[buffer_.NumQPAlloc]; + std::copy(Qp.begin(), Qp.end(), buffer_.QP); + } + else { + buffer_.NumQPAlloc = 0; + buffer_.QP = NULL; + } + } + + /// @brief Constructs object with array of QP deltas + /// @param[in] DeltaQP Delta QP value + explicit ExtMBQP(const std::vector& DeltaQP) : extension_buffer_with_ptrs() { + // make a copy for now. Behaviour TBD later. + buffer_.Mode = MFX_MBQP_MODE_QP_DELTA; + if (DeltaQP.size()) { + buffer_.NumQPAlloc = static_cast(DeltaQP.size()); + buffer_.DeltaQP = new mfxI8[buffer_.NumQPAlloc]; + std::copy(DeltaQP.begin(), DeltaQP.end(), buffer_.DeltaQP); + } + else { + buffer_.NumQPAlloc = 0; + buffer_.DeltaQP = NULL; + } + } + + /// @brief Constructs object with QP mode values: QP or Delta QP + /// @param[in] QPmode QP mode value + explicit ExtMBQP(const std::vector& QPmode) : extension_buffer_with_ptrs() { + // make a copy for now. Behaviour TBD later. + buffer_.Mode = MFX_MBQP_MODE_QP_ADAPTIVE; + if (QPmode.size()) { + buffer_.NumQPAlloc = static_cast(QPmode.size()); + buffer_.QPmode = new mfxQPandMode[buffer_.NumQPAlloc]; + std::copy(QPmode.begin(), QPmode.end(), buffer_.QPmode); + } + else { + buffer_.NumQPAlloc = 0; + buffer_.QPmode = NULL; + } + } + + /// @brief Copy ctor + /// @param[in] other another object to use as data source + explicit ExtMBQP(const ExtMBQP& other) { + buffer_.Mode = other.buffer_.Mode; + + if (other.buffer_.NumQPAlloc) { + this->buffer_.NumQPAlloc = other.buffer_.NumQPAlloc; + if (buffer_.Mode == MFX_MBQP_MODE_QP_VALUE) { + this->buffer_.QP = new uint8_t[buffer_.NumQPAlloc]; + std::copy(other.buffer_.QP, + other.buffer_.QP + other.buffer_.NumQPAlloc, + this->buffer_.QP); + } + else if (buffer_.Mode == MFX_MBQP_MODE_QP_DELTA) { + this->buffer_.DeltaQP = new mfxI8[buffer_.NumQPAlloc]; + std::copy(other.buffer_.DeltaQP, + other.buffer_.DeltaQP + other.buffer_.NumQPAlloc, + this->buffer_.DeltaQP); + } + else if (buffer_.Mode == MFX_MBQP_MODE_QP_ADAPTIVE) { + this->buffer_.QPmode = new mfxQPandMode[buffer_.NumQPAlloc]; + std::copy(other.buffer_.QPmode, + other.buffer_.QPmode + other.buffer_.NumQPAlloc, + this->buffer_.QPmode); + } + else { + this->buffer_.QPmode = NULL; + } + } + + this->buffer_.BlockSize = other.buffer_.BlockSize; + } + + /// @brief Dtor + ~ExtMBQP() { + if (this->buffer_.Mode == MFX_MBQP_MODE_QP_VALUE) + delete[] this->buffer_.QP; + if (this->buffer_.Mode == MFX_MBQP_MODE_QP_DELTA) + delete[] this->buffer_.DeltaQP; + if (this->buffer_.Mode == MFX_MBQP_MODE_QP_ADAPTIVE) + delete[] this->buffer_.QPmode; + buffer_.NumQPAlloc = 0; + } + + /// @brief Copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + virtual ExtMBQP& operator=(const ExtMBQP& other) { + if (&other == this) + return *this; + + if (this->buffer_.NumQPAlloc) { + if (this->buffer_.Mode == MFX_MBQP_MODE_QP_VALUE) + delete[] this->buffer_.QP; + if (this->buffer_.Mode == MFX_MBQP_MODE_QP_DELTA) + delete[] this->buffer_.DeltaQP; + if (this->buffer_.Mode == MFX_MBQP_MODE_QP_ADAPTIVE) + delete[] this->buffer_.QPmode; + } + + buffer_.Mode = other.buffer_.Mode; + + if (other.buffer_.NumQPAlloc) { + this->buffer_.NumQPAlloc = other.buffer_.NumQPAlloc; + if (buffer_.Mode == MFX_MBQP_MODE_QP_VALUE) { + this->buffer_.QP = new uint8_t[buffer_.NumQPAlloc]; + std::copy(other.buffer_.QP, + other.buffer_.QP + other.buffer_.NumQPAlloc, + this->buffer_.QP); + } + else if (buffer_.Mode == MFX_MBQP_MODE_QP_DELTA) { + this->buffer_.DeltaQP = new mfxI8[buffer_.NumQPAlloc]; + std::copy(other.buffer_.DeltaQP, + other.buffer_.DeltaQP + other.buffer_.NumQPAlloc, + this->buffer_.DeltaQP); + } + else if (buffer_.Mode == MFX_MBQP_MODE_QP_ADAPTIVE) { + this->buffer_.QPmode = new mfxQPandMode[buffer_.NumQPAlloc]; + std::copy(other.buffer_.QPmode, + other.buffer_.QPmode + other.buffer_.NumQPAlloc, + this->buffer_.QPmode); + } + else { + this->buffer_.QPmode = NULL; + } + } + + this->buffer_.BlockSize = other.buffer_.BlockSize; + + return *this; + } + SCALAR_SETTER(uint16_t, BlockSize) +}; + +/// @brief Manages DeviceAffinityMask +class ExtDeviceAffinityMask : public extension_buffer_with_ptrs { +public: + /// @brief Constructs object with the list of VPP algorithms to inlclude into the processing + /// @param[in] deviceID String with DeviceID + /// @param[in] numSubDevices Number of subdevices in DeviceID + /// @param[in] mask mask buffer + ExtDeviceAffinityMask(const std::string deviceID, + uint32_t numSubDevices, + const std::vector& mask) + : extension_buffer_with_ptrs(), + mask_len_(0) { + mask_len_ = buffer_.NumSubDevices = numSubDevices; + buffer_.Mask = new uint8_t[mask.size()]; + + std::copy(mask.begin(), mask.end(), this->buffer_.Mask); + std::copy_n(std::begin(deviceID), + (std::min)(deviceID.size(), (size_t)MFX_STRFIELD_LEN), + this->buffer_.DeviceID); + } + + /// @brief Copy ctor + /// @param[in] other another object to use as data source + ExtDeviceAffinityMask(const ExtDeviceAffinityMask& other) { + this->mask_len_ = other.mask_len_; + this->buffer_.NumSubDevices = other.buffer_.NumSubDevices; + buffer_.Mask = new uint8_t[mask_len_]; + + std::copy(other.buffer_.Mask, other.buffer_.Mask + this->mask_len_, this->buffer_.Mask); + std::copy_n(std::begin(other.buffer_.DeviceID), MFX_STRFIELD_LEN, this->buffer_.DeviceID); + } + + /// @brief Dtor + ~ExtDeviceAffinityMask() { + delete[] buffer_.Mask; + buffer_.NumSubDevices = 0; + mask_len_ = 0; + buffer_.DeviceID[0] = '\0'; + } + + /// @brief Copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + virtual ExtDeviceAffinityMask& operator=(const ExtDeviceAffinityMask& other) { + if (&other == this) + return *this; + + if (this->buffer_.Mask) + delete[] this->buffer_.Mask; + + this->mask_len_ = other.mask_len_; + this->buffer_.NumSubDevices = other.buffer_.NumSubDevices; + this->buffer_.Mask = new uint8_t[this->mask_len_]; + + std::copy(other.buffer_.Mask, other.buffer_.Mask + this->mask_len_, this->buffer_.Mask); + std::copy_n(std::begin(other.buffer_.DeviceID), MFX_STRFIELD_LEN, this->buffer_.DeviceID); + return *this; + } + +protected: + /// @brief Data buffer length in bytes. + uint32_t mask_len_; +}; + +/// @brief Manages Encode controller +class EncodeCtrl : public extension_buffer_with_ptrs { +public: + /// @brief Constructs object with the user payload + /// @param[in] userPayload Payload + explicit EncodeCtrl(const std::vector &userPayload) + : extension_buffer_with_ptrs(), + payload_(userPayload) { + set_payload(); + } + + /// @brief Constructs object with the user payload + /// @param[in] frameType Frame Type + /// @param[in] userPayload Payload + explicit EncodeCtrl(frame_type frameType, std::vector userPayload = {}) + : extension_buffer_with_ptrs(), + payload_(userPayload) { + this->buffer_.FrameType = (uint16_t)frameType; + set_payload(); + } + + /// @brief Constructs object with the user payload + /// @param[in] frameType Frame Type + /// @param[in] SkipFrame SkipFrame + /// @param[in] QP QP + /// @param[in] userPayload Payload + explicit EncodeCtrl(frame_type frameType, + uint16_t SkipFrame, + uint16_t QP, + std::vector userPayload = {}) + : extension_buffer_with_ptrs(), + payload_(userPayload) { + this->buffer_.FrameType = (uint16_t)frameType; + this->buffer_.SkipFrame = SkipFrame; + this->buffer_.QP = QP; + set_payload(); + } + + /// @brief Constructs object with the user payload + /// @param[in] MfxNalUnitType MfxNalUnitType + /// @param[in] frameType Frame Type + /// @param[in] SkipFrame SkipFrame + /// @param[in] QP QP + /// @param[in] userPayload Payload + explicit EncodeCtrl(uint16_t MfxNalUnitType, + frame_type frameType, + uint16_t SkipFrame, + uint16_t QP, + std::vector payload = {}) + : extension_buffer_with_ptrs(), + payload_(payload) { + this->buffer_.MfxNalUnitType = MfxNalUnitType; + this->buffer_.FrameType = (uint16_t)frameType; + this->buffer_.SkipFrame = SkipFrame; + this->buffer_.QP = QP; + set_payload(); + } + + /// @brief Copy ctor + /// @param[in] other another object to use as data source + EncodeCtrl(const EncodeCtrl& other) { + this->buffer_.MfxNalUnitType = other.buffer_.MfxNalUnitType; + this->buffer_.FrameType = other.buffer_.FrameType; + this->buffer_.SkipFrame = other.buffer_.SkipFrame; + this->buffer_.QP = other.buffer_.QP; + this->payload_ = other.payload_; + + set_payload(); + } + + /// @brief Dtor + ~EncodeCtrl() { + delete[] buffer_.Payload; + buffer_.Payload = 0; + } + + /// @brief Copy operator + /// @param[in] other another object to use as data source + /// @returns Reference to this object + virtual EncodeCtrl& operator=(const EncodeCtrl& other) { + if (&other == this) + return *this; + + if (this->buffer_.Payload) + delete[] this->buffer_.Payload; + + this->buffer_.MfxNalUnitType = other.buffer_.MfxNalUnitType; + this->buffer_.FrameType = other.buffer_.FrameType; + this->buffer_.SkipFrame = other.buffer_.SkipFrame; + this->buffer_.QP = other.buffer_.QP; + this->payload_ = other.payload_; + + set_payload(); + return *this; + } + +protected: + /// @brief Set payload + void set_payload() { + this->buffer_.NumPayload = static_cast(payload_.size()); + if (this->buffer_.NumPayload) { + int i = 0; + this->buffer_.Payload = new mfxPayload*[this->buffer_.NumPayload]; + for (auto& p : payload_) { + this->buffer_.Payload[i] = p.get_raw_ptr(); + i++; + } + } + } + std::vector payload_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/extension_buffer_list.hpp b/api/vpl/preview/extension_buffer_list.hpp new file mode 100644 index 00000000..00b2fff6 --- /dev/null +++ b/api/vpl/preview/extension_buffer_list.hpp @@ -0,0 +1,957 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include + +#include "vpl/preview/extension_buffer.hpp" + +namespace oneapi { +namespace vpl { + +#define IGNORE_LIST_LEN 2 +static constexpr uint32_t ignore_ID_list[IGNORE_LIST_LEN] = { 0, MFX_EXTBUFF_VPP_AUXDATA }; + +/// @brief Base class to replerent list of extension buffers. +/// Buffer pointers are stored as a map, so a single occurance of the same +/// extension buffer is possible. +class buffer_list { +public: + /// @brief default ctor + buffer_list() : mfxBuffers_(0), extBuffers_() {} + + buffer_list(const buffer_list& other) : mfxBuffers_(0), extBuffers_(other.extBuffers_){} + buffer_list& operator=(const buffer_list& other){ + if(mfxBuffers_ != other.mfxBuffers_){ + if(mfxBuffers_){ + delete[] mfxBuffers_; + mfxBuffers_ = nullptr; + } + extBuffers_ = other.extBuffers_; + } + return *this; + } + + /// @brief dtor + virtual ~buffer_list() { + delete[] mfxBuffers_; + } + + /// @brief returns reference to the map with extension buffers. Key is buffer ID in the form of FourCC codes + /// value is the pointer to the extension buffer. + /// @return reference to the map with the pointers to the extension buffers + std::map& get_buffers() { + return extBuffers_; + } + + /// @brief Reurns number of extension buffers in the map. + /// @return Number of extension buffers in the map. + std::size_t get_size() const { + return extBuffers_.size(); + } + /// @brief adds extension buffer pointer to the map + /// @param[in] o pointer to the extension buffer + void add_buffer(extension_buffer_base* o) { + // extBuffers_.insert(std::pair(o.get_ID(),o)); // this is language hack. ref can't be in the std::map + extBuffers_[o->get_ID()] = o; + } + + /// @brief verifies that map contains given key (extension buffer) + /// @tparam ID extension buffer ID in the form of FourCC code. + /// @return true if buffer exists in the map. + template + bool has_buffer() { + if (extBuffers_.find(ID) != extBuffers_.end()) + return true; + return false; + } + + /// @brief verifies that map contains given key (extension buffer) + /// @tparam ID extension buffer ID in the form of FourCC code. + /// @return true if buffer exists in the map. + bool has_buffer(uint32_t ID) { + if (extBuffers_.find(ID) != extBuffers_.end()) + return true; + return false; + } + + /// @brief returns extension buffer of given type and ID. + /// @tparam T extension buffer class. + /// @tparam ID extension buffer ID in the form of FourCC code. + /// @return pointer to the extension buffer or nullptr is that buffer doesn't in the map + template + T* get_buffer() { + auto buff = extBuffers_.find(ID); + if (buff != extBuffers_.end()) { + return *buff; + } + return nullptr; + } + + /// @brief returns extension buffer of given type and ID. + /// @tparam T extension buffer class. + /// @tparam ID extension buffer ID in the form of FourCC code. + /// @return pointer to the extension buffer or nullptr if that buffer isn't in the map + template + T* get_buffer(uint32_t ID) { + auto buff = extBuffers_.find(ID); + if (buff != extBuffers_.end()) { + return buff->second; + } + return nullptr; + } + + /// @brief returns pair of array of pointers to the extension buffer and number of buffers + /// @return pair of array of pointers to the extension buffer and number of buffers + /// @todo output unique_ptr instead of pointer to the member variable + auto get_raw_ext_buffers() { + uint32_t ignoreNum = 0; + + std::for_each(ignore_ID_list, ignore_ID_list + IGNORE_LIST_LEN, [&](uint32_t id) { + if (has_buffer(id)) + ignoreNum++; + }); + + delete[] mfxBuffers_; + mfxBuffers_ = new mfxExtBuffer*[extBuffers_.size() - ignoreNum]; + int i = 0; + + for (const auto& buf : extBuffers_) { + auto& id = buf.first; + auto& value = buf.second; + auto exists_ignore = std::any_of(ignore_ID_list, + ignore_ID_list + IGNORE_LIST_LEN, + [&id](uint32_t ignore_id) { + return id == ignore_id; + }); + if (exists_ignore) + continue; + mfxBuffers_[i] = value->get_ptr(); + i++; + } + return std::pair(mfxBuffers_, extBuffers_.size() - ignoreNum); + } + +protected: + /// Map of extension buffers with key equal to the buffer ID + /// @tparam extension_buffer_base* pointer to the extension buffer class. + /// @tparam uint32_t extension buffer ID in the form of FourCC code. + std::map extBuffers_; + /// @todo remove + mfxExtBuffer** mfxBuffers_; +}; + +/// @brief This class hold list of extension buffers used during decoder's initialization stage +/// Those buffers are attached to the mfxVideoParam structure before Init call. +class decoder_init_reset_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers + : std::conditional::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + AllBuffers, + std::false_type>::type {}; + +public: + decoder_init_reset_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtDecVideoProcessing, + /// ExtHEVCParam, + /// ExtDecodeErrorReport, + /// ExtDecodedFrameInfo, + /// ExtVP9Param, + /// ExtDeviceAffinityMask + /// @param[in] Opts List of property objects + template ::value>::type> + explicit decoder_init_reset_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit decoder_init_reset_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_DEC_VIDEO_PROCESSING: + case MFX_EXTBUFF_HEVC_PARAM: + case MFX_EXTBUFF_DECODE_ERROR_REPORT: + case MFX_EXTBUFF_DECODED_FRAME_INFO: + case MFX_EXTBUFF_VP9_PARAM: + case MFX_EXTBUFF_DEVICE_AFFINITY_MASK: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type + ctor_helper(OptT Opt, OptsT... Opts) { + buffer_list::add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +/// @brief This class hold list of extension buffers used during decoder's initialization stage +/// Those buffers are attached to the mfxVideoParam structure before DecodeHeader call. +class decoder_init_header_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers : std::conditional::value, + AllBuffers, + std::false_type>::type {}; + +public: + decoder_init_header_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtCodingOptionSPSPPS + /// @param[in] Opts List of property objects + template ::value>::type> + explicit decoder_init_header_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit decoder_init_header_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_CODING_OPTION_SPSPPS: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if::value>::type ctor_helper( + OptT Opt, + OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +/// @brief This class hold list of extension buffers used during decoder's processing stage +/// Those buffers are attached to the mfxVideoParam structure before DecodeFrameAsync call. +class decoder_process_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers : std::conditional::value, + AllBuffers, + std::false_type>::type {}; + +public: + decoder_process_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtDecodeErrorReport + /// @param[in] Opts List of property objects + template ::value>::type> + explicit decoder_process_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit decoder_process_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_DECODE_ERROR_REPORT: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if::value>::type ctor_helper( + OptT Opt, + OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +// Encoders ext buffers lists + +/// @brief This class hold list of extension buffers used during encoder's initialization stage +/// Those buffers are attached to the mfxVideoParam structure before Init call. +class encoder_init_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers + : std::conditional::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + AllBuffers, + std::false_type>::type {}; + +public: + encoder_init_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtCodingOption, + /// ExtCodingOption2, + /// ExtCodingOption3, + /// ExtCodingOptionSPSPPS, + /// ExtCodingOptionVPS, + /// ExtMasteringDisplayColourVolume, + /// ExtContentLightLevelInfo, + /// ExtPictureTimingSEI, + /// ExtAvcTemporalLayers, + /// ExtEncoderROI, + /// ExtHEVCTiles, + /// ExtHEVCParam, + /// ExtHEVCRegion, + /// ExtDirtyRect, + /// ExtMVOverPicBoundaries, + /// ExtVP9Segmentation, + /// ExtVP9TemporalLayers, + /// ExtVP9Param, + /// ExtPartialBitstreamParam, + /// ExtDeviceAffinityMask + /// @param[in] Opts List of property objects + template ::value>::type> + explicit encoder_init_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit encoder_init_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_CODING_OPTION: + case MFX_EXTBUFF_CODING_OPTION2: + case MFX_EXTBUFF_CODING_OPTION3: + case MFX_EXTBUFF_CODING_OPTION_SPSPPS: + case MFX_EXTBUFF_CODING_OPTION_VPS: + case MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME: + case MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO: + case MFX_EXTBUFF_PICTURE_TIMING_SEI: + case MFX_EXTBUFF_AVC_TEMPORAL_LAYERS: + case MFX_EXTBUFF_ENCODER_ROI: + case MFX_EXTBUFF_HEVC_TILES: + case MFX_EXTBUFF_HEVC_PARAM: + case MFX_EXTBUFF_HEVC_REGION: + case MFX_EXTBUFF_DIRTY_RECTANGLES: + case MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES: + case MFX_EXTBUFF_VP9_SEGMENTATION: + case MFX_EXTBUFF_VP9_TEMPORAL_LAYERS: + case MFX_EXTBUFF_VP9_PARAM: + case MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM: + case MFX_EXTBUFF_DEVICE_AFFINITY_MASK: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if< + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type + ctor_helper(OptT Opt, OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +/// @brief This class hold list of extension buffers used during encoder's reset stage +/// Those buffers are attached to the mfxVideoParam structure before Init call. +class encoder_reset_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers + : std::conditional::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + AllBuffers, + std::false_type>::type {}; + +public: + encoder_reset_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtCodingOption, + /// ExtCodingOption2, + /// ExtCodingOption3, + /// ExtCodingOptionSPSPPS, + /// ExtCodingOptionVPS, + /// ExtMasteringDisplayColourVolume, + /// ExtContentLightLevelInfo, + /// ExtPictureTimingSEI, + /// ExtAvcTemporalLayers, + /// ExtEncoderROI, + /// ExtHEVCTiles, + /// ExtHEVCParam, + /// ExtHEVCRegion, + /// ExtDirtyRect, + /// ExtMVOverPicBoundaries, + /// ExtVP9Segmentation, + /// ExtVP9TemporalLayers, + /// ExtVP9Param, + /// ExtPartialBitstreamParam, + /// mfxExtEncoderResetOption, + /// ExtDeviceAffinityMask + /// @param[in] Opts List of property objects + template ::value>::type> + explicit encoder_reset_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit encoder_reset_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_CODING_OPTION: + case MFX_EXTBUFF_CODING_OPTION2: + case MFX_EXTBUFF_CODING_OPTION3: + case MFX_EXTBUFF_CODING_OPTION_SPSPPS: + case MFX_EXTBUFF_CODING_OPTION_VPS: + case MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME: + case MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO: + case MFX_EXTBUFF_PICTURE_TIMING_SEI: + case MFX_EXTBUFF_AVC_TEMPORAL_LAYERS: + case MFX_EXTBUFF_ENCODER_ROI: + case MFX_EXTBUFF_HEVC_TILES: + case MFX_EXTBUFF_HEVC_PARAM: + case MFX_EXTBUFF_HEVC_REGION: + case MFX_EXTBUFF_DIRTY_RECTANGLES: + case MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES: + case MFX_EXTBUFF_VP9_SEGMENTATION: + case MFX_EXTBUFF_VP9_TEMPORAL_LAYERS: + case MFX_EXTBUFF_VP9_PARAM: + case MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM: + case MFX_EXTBUFF_ENCODER_RESET_OPTION: + case MFX_EXTBUFF_DEVICE_AFFINITY_MASK: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if< + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type + ctor_helper(OptT Opt, OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +/// @brief This class hold list of extension buffers used during encoder's processing stage +/// Those buffers are attached to the mfxVideoParam structure before Init call. +class encoder_process_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers + : std::conditional::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + AllBuffers, + std::false_type>::type {}; + +public: + encoder_process_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtCodingOption2, + /// ExtCodingOption3, + /// ExtMasteringDisplayColourVolume, + /// ExtContentLightLevelInfo, + /// ExtPictureTimingSEI, + /// ExtAVCEncodedFrameInfo, + /// ExtEncoderROI, + /// ExtMBQP, + /// ExtInsertHeaders, + /// ExtMBForceIntra, + /// ExtMBDisableSkipMap, + /// ExtPredWeightTable, + /// ExtAVCRoundingOffset, + /// ExtDirtyRect, + /// ExtMoveRect, + /// ExtEncodedSlicesInfo, + /// ExtVP9Segmentation, + /// ExtEncodedUnitsInfo, + /// ExtDeviceAffinityMask + /// @param[in] Opts List of property objects + template ::value>::type> + explicit encoder_process_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit encoder_process_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_CODING_OPTION2: + case MFX_EXTBUFF_CODING_OPTION3: + case MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME: + case MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO: + case MFX_EXTBUFF_PICTURE_TIMING_SEI: + case MFX_EXTBUFF_ENCODED_FRAME_INFO: + case MFX_EXTBUFF_AVC_TEMPORAL_LAYERS: + case MFX_EXTBUFF_ENCODER_ROI: + case MFX_EXTBUFF_MBQP: + case MFX_EXTBUFF_INSERT_HEADERS: + case MFX_EXTBUFF_MB_FORCE_INTRA: + case MFX_EXTBUFF_MB_DISABLE_SKIP_MAP: + case MFX_EXTBUFF_PRED_WEIGHT_TABLE: + case MFX_EXTBUFF_AVC_ROUNDING_OFFSET: + case MFX_EXTBUFF_DIRTY_RECTANGLES: + case MFX_EXTBUFF_MOVING_RECTANGLES: + case MFX_EXTBUFF_ENCODED_SLICES_INFO: + case MFX_EXTBUFF_VP9_SEGMENTATION: + case MFX_EXTBUFF_ENCODED_UNITS_INFO: + case MFX_EXTBUFF_DEVICE_AFFINITY_MASK: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if< + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value>::type + ctor_helper(OptT Opt, OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +// VPPs ext buffers lists + +/// @brief This class hold list of extension buffers used during VPP's initialization and/or reset stage +/// Those buffers are attached to the mfxVideoParam structure before Init call. +class vpp_init_reset_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers + : std::conditional::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value, + AllBuffers, + std::false_type>::type {}; + +public: + vpp_init_reset_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtVPPDoNotUse, + /// ExtVPPDenoise, + /// ExtVPPDetail, + /// ExtVPPProcAmp, + /// ExtVPPDoUse, + /// ExtVPPFrameRateConversion, + /// ExtVPPImageStab, + /// ExtVPPComposite, + /// ExtVPPVideoSignalInfo, + /// ExtVPPDeinterlacing, + /// ExtVPPFieldProcessing, + /// ExtVPPRotation, + /// ExtVPPScaling, + /// ExtVPPMirroring, + /// ExtVPPColorFill, + /// ExtColorConversion, + /// ExtVppMctf, + /// ExtDeviceAffinityMask + /// @param[in] Opts List of property objects + template ::value>::type> + explicit vpp_init_reset_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit vpp_init_reset_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_VPP_DONOTUSE: + case MFX_EXTBUFF_VPP_DENOISE: + case MFX_EXTBUFF_VPP_DETAIL: + case MFX_EXTBUFF_VPP_PROCAMP: + case MFX_EXTBUFF_VPP_DOUSE: + case MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION: + case MFX_EXTBUFF_VPP_IMAGE_STABILIZATION: + case MFX_EXTBUFF_CODING_OPTION_VPS: + case MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO: + case MFX_EXTBUFF_VPP_DEINTERLACING: + case MFX_EXTBUFF_VPP_FIELD_PROCESSING: + case MFX_EXTBUFF_VPP_ROTATION: + case MFX_EXTBUFF_VPP_SCALING: + case MFX_EXTBUFF_VPP_MIRRORING: + case MFX_EXTBUFF_VPP_COLORFILL: + case MFX_EXTBUFF_VPP_COLOR_CONVERSION: + case MFX_EXTBUFF_VPP_MCTF: + case MFX_EXTBUFF_DEVICE_AFFINITY_MASK: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if< + std::is_same::value || std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || std::is_same::value || + std::is_same::value>::type + ctor_helper(OptT Opt, OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; + +/// @brief This class hold list of extension buffers used during VPP's processing stage +/// Those buffers are attached to the mfxVideoParam structure before Init call. +class vpp_process_list : public buffer_list { + template + struct AllBuffers : std::true_type {}; + template + struct AllBuffers + : std::conditional::value || + std::is_same::value, + AllBuffers, + std::false_type>::type {}; + +public: + vpp_process_list() { + ctor_helper(); + } + + /// @brief Variadic length ctor. + /// This ctor accepts list of pointers to the extension buffers of pre-defined type: + /// ExtVppAuxData, + /// ExtDeviceAffinityMask + /// @param[in] Opts List of property objects + template ::value>::type> + explicit vpp_process_list(OptsT... Opts) { + ctor_helper(Opts...); + } + + /// @brief ctor + /// @param[in] Opts Vector of Extension Buffers + explicit vpp_process_list(std::vector Opts) { + for (auto opt : Opts) { + add_buffer(opt); + } + } + + /// @brief Add extension buffer to list + /// @param[in] o Extension Buffer + void add_buffer(extension_buffer_base* o) { + switch (o->get_ID()) { + case MFX_EXTBUFF_VPP_AUXDATA: + case MFX_EXTBUFF_DEVICE_AFFINITY_MASK: + buffer_list::add_buffer(o); + return; + } + throw base_exception("Invalid buffer type", MFX_ERR_UNKNOWN); + } + +protected: + /// @brief Empty ctor helper + void ctor_helper() {} + + /// @brief Variadic length ctor helper. It adds extension buffers one by one to the map of buffers + /// @param[in] Opt First property + /// @param[in] Opts Remaining properties + /// @return Nothing + template + typename std::enable_if::value || + std::is_same::value>::type + ctor_helper(OptT Opt, OptsT... Opts) { + add_buffer(Opt); + ctor_helper(Opts...); + } +}; +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/frame_pool.hpp b/api/vpl/preview/frame_pool.hpp new file mode 100644 index 00000000..68b5a98c --- /dev/null +++ b/api/vpl/preview/frame_pool.hpp @@ -0,0 +1,82 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include + +#include "vpl/preview/frame_surface.hpp" +#include "vpl/preview/video_param.hpp" + +#include "vpl/preview/detail/frame_interface.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief Temporal class to allocate and manage pool of the surfaces. +/// @todo remove during migration to the API 2.1 +class temporal_frame_allocator { +public: + /// @brief Type of the allocated surfaces. + using ptr_type = std::unique_ptr; + + /// @brief Default ctor + temporal_frame_allocator() : info_() {} + + /// @brief Update class instance with the frame information which is used to allocate proper + /// buffer for surface data. + /// Use this method only once. This class has no protection to handle changes of the frame info. + /// @todo Handle frame info change during reset operation. + /// @param[in] info Frame info + void attach_frame_info(frame_info info) { + info_ = info; + } + + /// @brief Returns available surface. + /// @return Pointer to the allocated surface. + ptr_type acquire() { + mfxFrameSurface1 *surf_data = new mfxFrameSurface1; + std::memset(surf_data, 0, sizeof(mfxFrameSurface1)); + + surf_data->FrameInterface = new mfxFrameSurfaceInterface; + surf_data->FrameInterface->Context = new detail::surfCtx__; + std::memset(surf_data->FrameInterface->Context, 0, sizeof(detail::surfCtx__)); + + switch (info_.get_FourCC()) { + case color_format_fourcc::i420: + detail::add_data_deleter(surf_data, detail::alloc_i420(info_, surf_data)); + break; + case color_format_fourcc::bgra: + detail::add_data_deleter(surf_data, detail::alloc_bgra(info_, surf_data)); + break; + default: + throw base_exception(MFX_ERR_NOT_IMPLEMENTED); + } + + surf_data->FrameInterface->AddRef = detail::AddRef__; + surf_data->FrameInterface->Release = detail::Release__; + surf_data->FrameInterface->GetRefCounter = detail::GetRefCounter__; + surf_data->FrameInterface->Map = detail::Map__; + surf_data->FrameInterface->Unmap = detail::Unmap__; + surf_data->FrameInterface->GetNativeHandle = detail::GetNativeHandle__; + surf_data->FrameInterface->GetDeviceHandle = detail::GetDeviceHandle__; + surf_data->FrameInterface->Synchronize = detail::Synchronize__; + surf_data->FrameInterface->OnComplete = detail::OnComplete__; + surf_data->FrameInterface->QueryInterface = detail::QueryInterface__; + + return std::make_unique(surf_data, true); + } + +protected: + /// @brief Frame information for the allocation + frame_info info_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/frame_surface.hpp b/api/vpl/preview/frame_surface.hpp new file mode 100644 index 00000000..429131c3 --- /dev/null +++ b/api/vpl/preview/frame_surface.hpp @@ -0,0 +1,290 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include + +#include "vpl/mfxstructures.h" + +#include "vpl/preview/defs.hpp" +#include "vpl/preview/exception.hpp" +#include "vpl/preview/video_param.hpp" + +#include "vpl/preview/detail/sdk_callable.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief Manages lifecycle of the surface with the frame data. This class works on top of the mfxFrameSurface1 object, +/// which provides interface to access the data and has an internal reference counting mechanism. +class frame_surface : public std::enable_shared_from_this { +public: + /// @brief Default dtor + frame_surface() : surface_(nullptr), lazy_sync_(false) {} + + /// @brief Creates object on top of mfxFrameSurface1 object. + /// Increments mfxFrameSurface1 reference counter value. + /// @param[in] surface Pointer to the mfxFrameSurface1 object + /// @param[in] lazy_sync Temporal flag indicating that lazy sync technique must be used. + /// @todo Remove flag with API 2.1 support + explicit frame_surface(mfxFrameSurface1* surface, bool lazy_sync = false) + : surface_(surface), + lazy_sync_(lazy_sync) { + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->AddRef, + surface_); + } + + /// @brief Copy ctor. + /// Increments mfxFrameSurface1 reference counter value. + /// @param[in] other another object to use as data source + frame_surface(const frame_surface& other) { + surface_ = other.surface_; + lazy_sync_ = other.lazy_sync_; + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->AddRef, + surface_); + } + + /// @brief Move ctor. + /// mfxFrameSurface1 reference counter value isn't incremented + /// @param[in] other another object to use as data source + frame_surface(frame_surface&& other) { + lazy_sync_ = other.lazy_sync_; + surface_ = std::move(other.surface_); + } + + /// @brief Copy operator. + /// Increments mfxFrameSurface1 reference counter value. + /// @param[in] other another object to use as data source + /// @returns Reference to this object + frame_surface& operator=(const frame_surface& other) { + surface_ = other.surface_; + lazy_sync_ = other.lazy_sync_; + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->AddRef, + surface_); + return *this; + } + + /// @brief Dtor. + /// Decrements mfxFrameSurface1 reference counter value. + virtual ~frame_surface() { + if (surface_) { + if (surface_->FrameInterface) { + if (surface_->FrameInterface->Synchronize) { + } + } + else { + } + } + else { + } + + if (surface_) { + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->Release, + surface_); + } + else { + } + } + + /// @brief Inject mfxFrameSurface1 object to take care of it. This is temporal method until VPL RT will support all + /// functions for the internal memory allocation + /// @todo Check reference counter correctness. + /// @param[in] surface mfxFrameSurface1 surface to use. + /// @param[in] n_times Reference counter increment. + /// @param[in] lazy_sync Do lazy sync or not. + void inject(mfxFrameSurface1* surface, unsigned int n_times, bool lazy_sync = false) { + if (!surface_) { + uint32_t c; + surface_ = surface; + lazy_sync_ = lazy_sync; + surface_->FrameInterface->GetRefCounter(surface_, &c); + for (unsigned int i = 0; i < n_times; i++) { + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->AddRef, + surface_); + } + surface_->FrameInterface->GetRefCounter(surface_, &c); + } + } + + /// @brief Indefinetely wait for operation completion. + void wait() { + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->Synchronize, + surface_, + MFX_INFINITE); + } + + /// @brief Waits for the operation completion. Waits for the result to become available. Blocks until specified + /// timeout_duration has elapsed or the result becomes available, whichever comes first. Returns value identifying + /// the state of the result. + /// @param timeout_duration Maximum duration to block for. + /// @return Wait ststus. + template + async_op_status wait_for(const std::chrono::duration& timeout_duration) const { + async_op_status surf_sts; + auto wait_ms = std::chrono::duration_cast(timeout_duration); + + detail::c_api_invoker e({ [](mfxStatus s) { + switch (s) { + case MFX_ERR_NONE: + return false; + case MFX_WRN_IN_EXECUTION: + return false; + case MFX_ERR_ABORTED: + return false; + case MFX_ERR_UNKNOWN: + return false; + default: + break; + } + + bool ret = (s < 0) ? true : false; + return ret; + } }, + surface_->FrameInterface->Synchronize, + surface_, + (uint32_t)wait_ms.count()); + + switch (e.sts_) { + case MFX_ERR_NONE: + surf_sts = async_op_status::ready; + break; + case MFX_WRN_IN_EXECUTION: + surf_sts = async_op_status::timeout; + break; + case MFX_ERR_ABORTED: + surf_sts = async_op_status::aborted; + break; + case MFX_ERR_UNKNOWN: + surf_sts = async_op_status::unknown; + break; + default: + throw base_exception(e.sts_); + } + return surf_sts; + } + + /// @brief Provide frame information. + /// @return Return instance of frame_info class + frame_info get_frame_info() { + return frame_info(surface_->Info); + } + + /// @brief Maps data to the system memory. + /// @param flags Data access flag: read or write. + /// @return Pair of pointers to the surface info structure and surface data strucuture in the system memory + auto map(memory_access flags) { + wait(); + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->Map, + surface_, + (mfxMemoryFlags)flags); + return std::pair(frame_info(surface_->Info), frame_data(surface_->Data)); + } + + /// @brief Unmaps data to the system memory. + void unmap() { + detail::c_api_invoker(detail::default_checker, surface_->FrameInterface->Unmap, surface_); + } + + /// @brief Provides native surface handle of the surface. + /// @return Pair of native surface handle and its type + auto get_native_handle() { + void* resource; + mfxResourceType resource_type; + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->GetNativeHandle, + surface_, + &resource, + &resource_type); + + return std::pair(resource, resource_type); + } + + /// @brief Provides native device handle of the surface. + /// @return Pair of native device handle and its type + auto get_device_handle() { + void* device_handle; + mfxHandleType device_type; + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->GetDeviceHandle, + surface_, + &device_handle, + &device_type); + return std::pair(device_handle, device_type); + } + + /// @brief Provides current reference counter value. + /// @return reference counter value. + uint32_t get_ref_counter() { + uint32_t counter; + detail::c_api_invoker(detail::default_checker, + surface_->FrameInterface->GetRefCounter, + surface_, + &counter); + return counter; + } + + /// @brief Provides pointer to the raw data. + /// @return Pointer to the raw data. + mfxFrameSurface1* get_raw_ptr() { + return surface_; + } + + /// @brief Temporal method to assotiate externally allocated surface with sync point generated + /// by the processing function. + /// @param[in] session Session handle. + /// @param[in] sp sync point. + void associate_context(mfxSession session, mfxSyncPoint sp) { + if (lazy_sync_) { + void* d = reinterpret_cast(surface_->FrameInterface->Context); + mfxSession* s = reinterpret_cast(d); + s[0] = session; + + mfxSyncPoint* sps = reinterpret_cast(d); + sps[1] = sp; + } + return; + } + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] f Referebce to the frame_surface instance to dump the state. + /// @return Reference to the stream. + friend std::ostream& operator<<(std::ostream& out, const frame_surface& f); + +protected: + /// @brief Pointer to the mfxFrameSurface1 object. + mfxFrameSurface1* surface_; + /// @brief Flag indicating that lazy sync technique must be used. + bool lazy_sync_; +}; + +inline std::ostream& operator<<(std::ostream& out, const frame_surface& f) { + out << "frame_surface class" << std::endl; + out << detail::space(detail::INTENT, out, "Lazy sync = ") + << detail::Boolean2String(f.lazy_sync_) << std::endl; + out << "frame_info" << std::endl; + frame_info i(f.surface_->Info); + out << i << std::endl; + out << "frame_data" << std::endl; + frame_data d(f.surface_->Data); + out << d << std::endl; + + return out; +} + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/future.hpp b/api/vpl/preview/future.hpp new file mode 100644 index 00000000..083102ff --- /dev/null +++ b/api/vpl/preview/future.hpp @@ -0,0 +1,196 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include +#include + +#include "vpl/preview/bitstream.hpp" +#include "vpl/preview/defs.hpp" +#include "vpl/preview/frame_surface.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief This structure represents schedulling status of the asyncroniouse execution of single +/// processing (decode/encode/vpp) +/// operation. +struct operation_status { + /// @brief Ctor. Initializes structure with default values. + /// @param[in] component Type of the component generated from the status. + /// @param[in] owner Pointer to the component generated from this status. + operation_status(component component, void *owner) + : schedule_status_(status::Unknown), + exec_status_(status::Unknown), + fatal_(false), + component_(component), + owner_(owner) {} + + /// @brief Operation's schedulling status for the execution. + status schedule_status_; + /// @todo not in use. Candidate for removal. + status exec_status_; + /// @brief Flag to indicate that fatal error occured. See schedule_status_ value for the status code. + bool fatal_; + /// @brief Domain of the component which generated this operation. + component component_; + /// @brief Pointer to the Session class. + /// @todo need to define session_base class and use its type here instead of void. + void *owner_; +}; + +inline std::ostream &operator<<(std::ostream &out, const operation_status &o) { + out << detail::space(detail::INTENT, out, "Component = ") + << detail::component2String(o.component_) << std::endl; + out << detail::space(detail::INTENT, out, "SS = ") + << detail::status2Str(o.schedule_status_) << std::endl; + out << detail::space(detail::INTENT, out, "ES = ") << detail::status2Str(o.exec_status_) + << std::endl; + out << detail::space(detail::INTENT, out, "Fatalilty = ") << std::boolalpha << o.fatal_ + << std::noboolalpha << std::endl; + return out; +} + +/// @brief This class represent future data container and used to glue processing of the individual components +/// into the pipeline. Once component which is down in the pipeline recieved that object, it must use it to wait for +/// the data. States of the data in this object: +/// @li Not sync'd. Use the wait or wait_for methods to sync it. +/// @li Data is ready. Use Map method to get it mapped to the system memory. +/// @li More data is required. Data processing buffered in the pipe above the element. This means +/// that data won't be delivered into this future. Stop it's usage. +/// @li End of stream is reached. Future won't contain any data. Close the pipeline processing. +/// @tparam data frame_surface class or bitstream_as_dst class +/// @todo Remove "more data is required" state. +template , data>::value || + std::is_base_of, data>::value>::type> +class future { +public: + /// @brief Default ctor + /// @param[in] future_data Data object to take care about. + explicit future(data future_data) : data_(future_data), fatal_happened_(false) {} + + /// @brief Indefinitely waits for operation completion. + void wait() { + if (have_to_wait() && data_) { + data_->wait(); + } + } + + /// @brief Provides syncronized data. Waits indefinitely for the synchronization. + /// @return Synchronized data. Use Map method of the data container to access the data. + data &get() { + wait(); + return data_; + } + /// @brief Waits for the operation completion. Waits for the result to become available. Blocks until specified + /// timeout_duration has elapsed or the result becomes available, whichever comes first. Returns value identifying + /// the state of the result. + /// @param timeout_duration Maximum duration to block for. + /// @return Wait ststus. + template + async_op_status wait_for(const std::chrono::duration &timeout_duration) const { + if (have_to_wait() && data_) + return data_->wait_for(timeout_duration); + return async_op_status::cancelled; + } + + /// @brief add current operation scheduling status into the history of the future. + /// @param[in] op Operation's status + void add_operation(operation_status op) { + history_.push_back(op); + fatal_happened_ = op.fatal_; + } + + /// @brief retrieve last operation scheduling status + /// @return operation scheduling status + status get_last_schedule_status() { + return history_.back().schedule_status_; + } + + /// @brief retrieve last operation exec status + /// @return operation exec status + status get_last_exec_status() { + return history_.back().exec_status_; + } + + /// @brief Check if fatal error happened. + /// @return true if fatal error happened. + bool had_fatal() { + return fatal_happened_; + } + + /// @brief Returns components with fatal status. + /// @return Components with fatal status. + component get_fatal_component() { + component c = component::unknown; + std::for_each(history_.rbegin(), history_.rend(), [&](operation_status s) { + if (s.fatal_) + return c = s.component_; + }); + return c; + } + + /// @brief Propagate processing history from previous future object in the pipeline. + /// @param old Reference to the previouse future object in the pipeline + /// @tparam T Type of the data container + template + void propagate_history(const future &old) { + std::for_each(old.history_.rbegin(), old.history_.rend(), [&](operation_status s) { + history_.push_front(s); + }); + } + + /// Processing history + std::deque history_; + +protected: + /// @brief Checks if we need to wait for the data or skip the processing. + /// @return true if wait operation is required. + bool have_to_wait() const { + if (history_.empty()) + return false; + return ((status::Ok == history_.back().schedule_status_) && + (false == history_.back().fatal_)); + } + /// Data container + data data_; + + /// Global fatal flag. Updated when first operation in the pipeline provided fatal status code. + bool fatal_happened_; + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] p Reference to the future instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const future &p) { + std::string mangled_name(typeid(data).name()); + if (auto it = mangled_name.find("bitstream_as_dst"); it != std::string::npos) { + out << "Future data type: " + << "Bitstream" << std::endl; + } + else { + out << "Future data type: " + << "Frame" << std::endl; + } + out << detail::space(detail::INTENT, out, "History:") << std::endl; + for (auto it : p.history_) { + out << it << std::endl; + } + return out; + } +}; + +using future_surface_t = future>; +using future_bitstream_t = future>; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/impl_caps.hpp b/api/vpl/preview/impl_caps.hpp new file mode 100644 index 00000000..bce8d416 --- /dev/null +++ b/api/vpl/preview/impl_caps.hpp @@ -0,0 +1,745 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "vpl/preview/defs.hpp" +#include "vpl/preview/exception.hpp" + +#include "vpl/mfxcommon.h" + +#include "vpl/preview/detail/string_helpers.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief Base class to store implementation capabilities +class base_implementation_capabilities { +public: + /// @brief Default ctor + /// @param ID of the implementation capabilities format ID. + explicit base_implementation_capabilities(uint32_t ID) : id_(ID) {} + + /// @brief returns implementation capabilities format ID. + /// @return ID of the implementation capabilities format type. + uint32_t get_id() const { + return id_; + } + +protected: + /// ID of the implementation capabilities format type. + uint32_t id_; +}; + +/// @brief Store and parse implementation capabilities in a form of implementation description structure +class implementation_capabilities : public base_implementation_capabilities { +public: + /// @brief Default ctor + /// @param caps pointer to raw data. + explicit implementation_capabilities(mfxImplDescription *caps) + : base_implementation_capabilities(MFX_IMPLCAPS_IMPLDESCSTRUCTURE), + caps_(caps) {} + +public: + /// @brief Provides information about supported memory for codecs + /// @tparam T Encoder of decoder identifier. + template + class codec_memory { + public: + /// @brief Default ctor + /// @param memdesc Memory description + explicit codec_memory(T memdesc) : memdesc_(memdesc) {} + + /// @brief provides supported memory type. + /// @return Memory type. + mfxResourceType get_mem_type() const { + return memdesc_.MemHandleType; + } + + /// @brief provides minimal supported width and height. + /// @return minimal supported width and height. + auto get_min_size() const { + return std::pair(memdesc_.Width.Min, memdesc_.Height.Min); + } + + /// @brief provides maximal supported width and height. + /// @return maximal supported width and height. + auto get_max_size() const { + return std::pair(memdesc_.Width.Max, memdesc_.Height.Max); + } + + /// @brief provides increment value for width and height. + /// @return increment value for width and height. + auto get_size_step() const { + return std::pair(memdesc_.Width.Step, memdesc_.Height.Step); + } + + /// @brief Provides list of supported output memory types. + /// @return List of supported output memory types. + std::vector get_out_mem_types() const { + return std::vector(memdesc_.ColorFormats, + memdesc_.ColorFormats + memdesc_.NumColorFormats); + } + + protected: + /// Raw data + T memdesc_; + }; + + /// Defines decoder memory description class + typedef codec_memory decoder_memory; + /// Defines encoder memory description class + typedef codec_memory encoder_memory; + + /// @brief Provides information about supported memory formats for VPP filters + class vpp_memory_format { + public: + /// @brief Default ctor + /// @param fmt Memory format + explicit vpp_memory_format(mfxVPPDescription::filter::memdesc::format fmt) : fmt_(fmt) {} + + /// @brief Returns input memory type in a form of FourCC code + /// @return input memory type in a form of FourCC code + uint32_t get_input_format() const { + return fmt_.InFormat; + } + + /// @brief Returns iterable list of output memory types in a form of FourCC code + /// @return list of output memory types + std::vector get_out_format() const { + return std::vector(fmt_.OutFormats, fmt_.OutFormats + fmt_.NumOutFormat); + } + + protected: + /// Raw data + mfxVPPDescription::filter::memdesc::format fmt_; + }; + + /// @brief Provides information about supported memory for VPP filters + class vpp_memory { + public: + /// @brief Default ctor + /// @param memdesc Memory description + explicit vpp_memory(mfxVPPDescription::filter::memdesc memdesc) : memdesc_(memdesc) {} + + /// @brief provides supported memory type. + /// @return Memory type. + mfxResourceType get_mem_type() const { + return memdesc_.MemHandleType; + } + + /// @brief provides minimal supported width and height. + /// @return minimal supported width and height. + auto get_min_size() const { + return std::pair(memdesc_.Width.Min, memdesc_.Height.Min); + } + + /// @brief provides maximal supported width and height. + /// @return maximal supported width and height. + auto get_max_size() const { + return std::pair(memdesc_.Width.Max, memdesc_.Height.Max); + } + + /// @brief provides increment value for width and height. + /// @return increment value for width and height. + auto get_size_step() const { + return std::pair(memdesc_.Width.Step, memdesc_.Height.Step); + } + + /// @brief Provides list of supported memory formats. + /// @return List of supported memory formats. + std::vector get_memory_formats() const { + std::vector formats; + + std::for_each(memdesc_.Formats, + memdesc_.Formats + memdesc_.NumInFormats, + [&](mfxVPPDescription::filter::memdesc::format fmt) { + formats.push_back(vpp_memory_format(fmt)); + }); + + return formats; + } + + protected: + /// Raw data + mfxVPPDescription::filter::memdesc memdesc_; + }; + + /// @brief Provides information about supported profiles by the decoder + class decoder_profile { + public: + /// @brief Default ctor + /// @param profile Decoder profile + explicit decoder_profile(mfxDecoderDescription::decoder::decprofile profile) + : profile_(profile) {} + + /// @brief provides ID of the profile. + /// @return ID of the profile. + uint16_t get_profile() const { + return profile_.Profile; + } + + /// @brief Provides list of memory types. + /// @return list of memory types. + std::vector get_decoder_mem_types() const { + std::vector memories; + + std::for_each(profile_.MemDesc, + profile_.MemDesc + profile_.NumMemTypes, + [&](mfxDecoderDescription::decoder::decprofile::decmemdesc memdesc) { + memories.push_back(decoder_memory(memdesc)); + }); + + return memories; + } + + protected: + /// Raw data + mfxDecoderDescription::decoder::decprofile profile_; + }; + + /// @brief Provides information about supported profiles by the encoder + class encoder_profile { + public: + /// @brief Default ctor + /// @param profile Encoder profile + explicit encoder_profile(mfxEncoderDescription::encoder::encprofile profile) + : profile_(profile) {} + + /// @brief provides ID of the profile. + /// @return ID of the profile. + uint16_t get_profile() const { + return profile_.Profile; + } + + /// @brief Provides list of memory types. + /// @return list of memory types. + std::vector get_encoder_mem_types() const { + std::vector memories; + + std::for_each(profile_.MemDesc, + profile_.MemDesc + profile_.NumMemTypes, + [&](mfxEncoderDescription::encoder::encprofile::encmemdesc memdesc) { + memories.push_back(encoder_memory(memdesc)); + }); + + return memories; + } + + protected: + /// Raw data + mfxEncoderDescription::encoder::encprofile profile_; + }; + + /// @brief Provides information about supported decoders + class decoder { + public: + /// @brief Default ctor + /// @param dec decoder + explicit decoder(mfxDecoderDescription::decoder dec) : dec_(dec) {} + + /// @brief Provides codec ID. + /// @return Codec ID. + uint32_t get_codec_id() const { + return dec_.CodecID; + } + + /// @brief Provides maximum supported codec's level. + /// @return maximum supported codec's level. + uint16_t get_max_codec_level() const { + return dec_.MaxcodecLevel; + } + + /// @brief Provides list of supported profiles. + /// @return list of profiles. + std::vector get_profiles() const { + std::vector profiles; + + std::for_each(dec_.Profiles, + dec_.Profiles + dec_.NumProfiles, + [&](mfxDecoderDescription::decoder::decprofile profile) { + profiles.push_back(decoder_profile(profile)); + }); + + return profiles; + } + + protected: + /// Raw data + mfxDecoderDescription::decoder dec_; + }; + + /// @brief Provides information about supported encoders + class encoder { + public: + /// @brief Default ctor + /// @param enc encoder + explicit encoder(mfxEncoderDescription::encoder enc) : enc_(enc) {} + + /// @brief Provides codec ID. + /// @return Codec ID. + uint32_t get_codec_id() const { + return enc_.CodecID; + } + + /// @brief Provides maximum supported codec's level. + /// @return maximum supported codec's level. + uint16_t get_max_codec_level() const { + return enc_.MaxcodecLevel; + } + + /// @brief Provides information about bidirectional prediction support. + /// @return True if bidirectional prediction supported. + uint16_t get_bidirectional_prediction_support() const { + return enc_.BiDirectionalPrediction; + } + + /// @brief Provides list of supported profiles. + /// @return list of profiles. + std::vector get_profiles() const { + std::vector profiles; + + std::for_each(enc_.Profiles, + enc_.Profiles + enc_.NumProfiles, + [&](mfxEncoderDescription::encoder::encprofile profile) { + profiles.push_back(encoder_profile(profile)); + }); + + return profiles; + } + + protected: + /// Raw data + mfxEncoderDescription::encoder enc_; + }; + + /// @brief Provides information about supported VPP filters + class vpp_filter { + public: + /// @brief Default ctor + /// @param flt filter + explicit vpp_filter(mfxVPPDescription::filter flt) : flt_(flt) {} + + /// @brief Provides VPP filter ID. + /// @return Filter ID. + uint32_t get_filter_id() const { + return flt_.FilterFourCC; + } + + /// @brief Provides maximum introduced delay by this filter. + /// @return Delay in frames. + uint16_t get_max_delay_in_frames() const { + return flt_.MaxDelayInFrames; + } + + /// @brief Provides list of supported memory type. + /// @return list of memory types. + std::vector get_memory_types() const { + std::vector memories; + + std::for_each(flt_.MemDesc, + flt_.MemDesc + flt_.NumMemTypes, + [&](mfxVPPDescription::filter::memdesc memdesc) { + memories.push_back(vpp_memory(memdesc)); + }); + + return memories; + } + + protected: + /// Raw data + mfxVPPDescription::filter flt_; + }; + + /// @brief Provides type of the implementation: SW or HW. + /// @return Type of the implementation. + mfxImplType get_impl_type() const { + return caps_->Impl; + } + + /// @brief Provides acceleration mode of the implementation. + /// @return Type of the implementation. + /// @todo Port to api 2.1 is reqired + mfxAccelerationMode get_acceleration_mode() const { + return caps_->AccelerationMode; + } + + /// @brief Provides supported API version of the implementation. + /// @return API version. + mfxVersion get_api_version() const { + return caps_->ApiVersion; + } + + /// @brief Provides name of the implementation. + /// @return Null terminated string with the name of the implementation. + std::string get_impl_name() const { + return std::string(caps_->ImplName); + } + + /// @brief Provides license of the implementation. + /// @return Null terminated string with the license of the implementation. + std::string get_license_name() const { + return std::string(caps_->License); + } + + /// @brief Provides keywords of the implementation. + /// @return Null terminated string with the keywords of the implementation. + std::string get_keywords_name() const { + return std::string(caps_->Keywords); + } + + /// @brief Provides vendor ID. + /// @return Vendor ID. + uint32_t get_vendor_id() const { + return caps_->VendorID; + } + + /// @brief Provides vendor's implementation ID. + /// @return vendor's implementation ID. + uint32_t get_vendor_impl_id() const { + return caps_->VendorImplID; + } + + /// @brief Provides target device for the implementation. + /// @return Null terminated string with device ID (or name). + std::string get_target_device_id() const { + return std::string(caps_->Dev.DeviceID); + } + + /// @brief Provides list of supported target subdevice IDs. + /// @return list of supported target subdevice IDs. + std::vector get_target_subdevice_ids() const { + std::vector subdevices; + + std::for_each(caps_->Dev.SubDevices, + caps_->Dev.SubDevices + caps_->Dev.NumSubDevices, + [&](mfxDeviceDescription::subdevices sb) { + subdevices.push_back(std::string(sb.SubDeviceID)); + }); + + return subdevices; + } + + /// @brief Provides list of supported acceleration modes. + /// @return list of supported modes. + std::vector get_accel_modes() const { + std::vector accelmodes; + + if (caps_->AccelerationModeDescription.NumAccelerationModes > 0) { + std::for_each(caps_->AccelerationModeDescription.Mode, + caps_->AccelerationModeDescription.Mode + + caps_->AccelerationModeDescription.NumAccelerationModes, + [&](mfxAccelerationMode mode) { + accelmodes.push_back(detail::AccelerationMode2String(mode)); + }); + } + + return accelmodes; + } + + /// @brief Provides list of supported decoders. + /// @return list of supported decoders. + std::vector get_decoders() const { + std::vector decoders; + + std::for_each(caps_->Dec.Codecs, + caps_->Dec.Codecs + caps_->Dec.NumCodecs, + [&](mfxDecoderDescription::decoder dec) { + decoders.push_back(decoder(dec)); + }); + + return decoders; + } + + /// @brief Provides list of supported encoders. + /// @return list of supported encoders. + std::vector get_encoders() const { + std::vector encoders; + + std::for_each(caps_->Enc.Codecs, + caps_->Enc.Codecs + caps_->Enc.NumCodecs, + [&](mfxEncoderDescription::encoder enc) { + encoders.push_back(encoder(enc)); + }); + + return encoders; + } + + /// @brief Provides list of supported VPP filters. + /// @return list of supported VPP filters. + std::vector get_vpp_filters() const { + std::vector filters; + + std::for_each(caps_->VPP.Filters, + caps_->VPP.Filters + caps_->VPP.NumFilters, + [&](mfxVPPDescription::filter flt) { + filters.push_back(vpp_filter(flt)); + }); + + return filters; + } + +protected: + /// Raw data + mfxImplDescription *caps_; + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] f Referebce to the implementation_capabilities instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const implementation_capabilities &f); +}; + +/// @brief Factory class to create implementation capabilities report class based on the format ID. +class implementation_capabilities_factory { +public: + /// @brief Default ctor + implementation_capabilities_factory() { + map_[MFX_IMPLCAPS_IMPLDESCSTRUCTURE] = [](void *handle) { + return std::make_shared( + reinterpret_cast(handle)); + }; + } + + /// @brief Creates instance of implementation capabilities report class based on the format ID + /// @param[in] id Requested format ID + /// @param[in] handle Handle to read-only raw data to interpret by the implementation capabilities report class + /// @return instance of implementation capabilities report class based on the format ID + std::shared_ptr create(uint32_t id, void *handle) { + if (auto it = map_.find(id); it != map_.end()) + return it->second(handle); + throw base_exception(MFX_ERR_UNSUPPORTED); + } + +protected: + /// @brief Map of format ID and interpreter instance class creator + std::map(void *handle)>> + map_; +}; + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::decoder_memory &m) { + out << detail::space(detail::INTENT * 5, out, "MemHandleType = ") + << detail::ResourceType2String(m.get_mem_type()) << std::endl; + out << detail::space(detail::INTENT * 5, out, "Frame size range = [") + << std::get<0>(m.get_min_size()) << "," << std::get<1>(m.get_min_size()) << "]:[" + << std::get<0>(m.get_max_size()) << "," << std::get<1>(m.get_max_size()) << "]" + << std::endl; + std::vector fmts = m.get_out_mem_types(); + out << detail::space(detail::INTENT * 5, out, "# of color formats = ") << fmts.size() + << std::endl; + std::for_each(fmts.begin(), fmts.end(), [&](uint32_t fmt) { + out << detail::space(detail::INTENT * 6, out, "color format = ") + << detail::FourCC2String(fmt) << std::endl; + }); + + return out; +} + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::encoder_memory &m) { + out << detail::space(detail::INTENT * 5, out, "MemHandleType = ") + << detail::ResourceType2String(m.get_mem_type()) << std::endl; + out << detail::space(detail::INTENT * 5, out, "Frame size range = [") + << std::get<0>(m.get_min_size()) << "," << std::get<1>(m.get_min_size()) << "]:[" + << std::get<0>(m.get_max_size()) << "," << std::get<1>(m.get_max_size()) << "]" + << std::endl; + std::vector fmts = m.get_out_mem_types(); + out << detail::space(detail::INTENT * 5, out, "# of color formats = ") << fmts.size() + << std::endl; + std::for_each(fmts.begin(), fmts.end(), [&](uint32_t fmt) { + out << detail::space(detail::INTENT * 6, out, "color format = ") + << detail::FourCC2String(fmt) << std::endl; + }); + + return out; +} + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::decoder_profile &p) { + out << detail::space(detail::INTENT * 4, out, "Profile = ") << p.get_profile() << std::endl; + + std::vector dm = p.get_decoder_mem_types(); + out << detail::space(detail::INTENT * 4, out, "# memory types = ") << dm.size() << std::endl; + std::for_each(dm.begin(), dm.end(), [&](implementation_capabilities::decoder_memory dec_m) { + out << dec_m; + }); + + return out; +} + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::encoder_profile &p) { + out << detail::space(detail::INTENT * 4, out, "Profile = ") << p.get_profile() << std::endl; + + std::vector em = p.get_encoder_mem_types(); + out << detail::space(detail::INTENT * 4, out, "# memory types = ") << em.size() << std::endl; + std::for_each(em.begin(), em.end(), [&](implementation_capabilities::encoder_memory enc_m) { + out << enc_m; + }); + + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const implementation_capabilities::decoder &d) { + out << detail::space(detail::INTENT * 3, out, "CodecID = ") + << detail::FourCC2String(d.get_codec_id()) << std::endl; + out << detail::space(detail::INTENT * 3, out, "MaxcodecLevel = ") << d.get_max_codec_level() + << std::endl; + + std::vector dp = d.get_profiles(); + out << detail::space(detail::INTENT * 3, out, "# of profiles = ") << dp.size() << std::endl; + std::for_each(dp.begin(), dp.end(), [&](implementation_capabilities::decoder_profile dec_p) { + out << dec_p; + }); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const implementation_capabilities::encoder &e) { + out << detail::space(detail::INTENT * 3, out, "CodecID = ") + << detail::FourCC2String(e.get_codec_id()) << std::endl; + out << detail::space(detail::INTENT * 3, out, "MaxcodecLevel = ") << e.get_max_codec_level() + << std::endl; + + std::vector ep = e.get_profiles(); + out << detail::space(detail::INTENT * 3, out, "# of profiles = ") << ep.size() << std::endl; + std::for_each(ep.begin(), ep.end(), [&](implementation_capabilities::encoder_profile enc_p) { + out << enc_p; + }); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::vpp_memory_format &mf) { + out << detail::space(detail::INTENT * 5, out, "Input Format = ") + << detail::FourCC2String(mf.get_input_format()) << std::endl; + + std::vector fmts = mf.get_out_format(); + out << detail::space(detail::INTENT * 5, out, "# of output formats = ") << fmts.size() + << std::endl; + + std::for_each(fmts.begin(), fmts.end(), [&](uint32_t fmt) { + out << detail::space(detail::INTENT * 6, out, "color format = ") + << detail::FourCC2String(fmt) << std::endl; + }); + + return out; +} + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::vpp_memory &m) { + out << detail::space(detail::INTENT * 4, out, "MemHandleType = ") + << detail::ResourceType2String(m.get_mem_type()) << std::endl; + out << detail::space(detail::INTENT * 4, out, "Frame size range = [") + << std::get<0>(m.get_min_size()) << "," << std::get<1>(m.get_min_size()) << "]:[" + << std::get<0>(m.get_max_size()) << "," << std::get<1>(m.get_max_size()) << "]" + << std::endl; + std::vector fmts = m.get_memory_formats(); + out << detail::space(detail::INTENT * 4, out, "# of input formats = ") << fmts.size() + << std::endl; + std::for_each(fmts.begin(), + fmts.end(), + [&](implementation_capabilities::vpp_memory_format vpp_mf) { + out << vpp_mf; + }); + + return out; +} + +inline std::ostream &operator<<(std::ostream &out, + const implementation_capabilities::vpp_filter &f) { + out << detail::space(detail::INTENT * 3, out, "FilterID = ") + << detail::FourCC2String(f.get_filter_id()) << std::endl; + out << detail::space(detail::INTENT * 3, out, "Max delay In Frames= ") + << f.get_max_delay_in_frames() << std::endl; + + std::vector vm = f.get_memory_types(); + out << detail::space(detail::INTENT * 3, out, "# of memory types = ") << vm.size() << std::endl; + std::for_each(vm.begin(), vm.end(), [&](implementation_capabilities::vpp_memory vpp_m) { + out << vpp_m; + }); + return out; +} + +inline std::ostream &operator<<(std::ostream &out, const implementation_capabilities &f) { + std::cout << "FImplementation:" << std::endl; + + out << detail::space(detail::INTENT, out, "Impl = ") + << detail::ImplType2String(f.caps_->Impl) << std::endl; + out << detail::space(detail::INTENT, out, "AccelerationMode = ") + << detail::AccelerationMode2String(f.caps_->AccelerationMode) << std::endl; + + out << detail::space(detail::INTENT, out, "API Version = ") << f.caps_->ApiVersion.Major + << "." << f.caps_->ApiVersion.Minor << std::endl; + out << detail::space(detail::INTENT, out, "ImplName = ") << f.caps_->ImplName + << std::endl; + out << detail::space(detail::INTENT, out, "License = ") << f.caps_->License + << std::endl; + out << detail::space(detail::INTENT, out, "Keywords = ") << f.caps_->Keywords + << std::endl; + out << detail::space(detail::INTENT, out, "VendorID = ") << std::hex << std::showbase + << f.caps_->VendorID << std::endl; + out << detail::space(detail::INTENT, out, "VendorImplID = ") << f.caps_->VendorImplID + << std::dec << std::endl; + + if (f.caps_->AccelerationModeDescription.NumAccelerationModes > 0) { + std::vector accelmodes = f.get_accel_modes(); + out << detail::space(detail::INTENT, out, "AccelerationModes:") << std::endl; + std::for_each(accelmodes.begin(), accelmodes.end(), [&](std::string mode) { + out << mode << std::endl; + }); + } + + out << detail::space(detail::INTENT, out, "Target Device:") << std::endl; + out << detail::space(detail::INTENT * 2, out, "DeviceID = ") << f.caps_->Dev.DeviceID + << std::endl; + out << detail::space(detail::INTENT * 2, out, "# of subdevices = ") + << f.caps_->Dev.NumSubDevices << std::endl; + for (int i = 0; i < f.caps_->Dev.NumSubDevices; i++) { + out << detail::space(detail::INTENT * 2, out, "SubdeviceID[") << i + << "] = " << f.caps_->Dev.SubDevices[i].SubDeviceID << std::endl; + } + + std::vector decoders = f.get_decoders(); + out << detail::space(detail::INTENT, out, "Decoders:") << std::endl; + out << detail::space(detail::INTENT * 2, out, "# of decoders = ") << decoders.size() + << std::endl; + + std::for_each(decoders.begin(), decoders.end(), [&](implementation_capabilities::decoder dec) { + out << dec; + }); + + std::vector encoders = f.get_encoders(); + out << detail::space(detail::INTENT, out, "Encoders:") << std::endl; + out << detail::space(detail::INTENT * 2, out, "# of encoders = ") << encoders.size() + << std::endl; + + std::for_each(encoders.begin(), encoders.end(), [&](implementation_capabilities::encoder enc) { + out << enc; + }); + + std::vector filters = f.get_vpp_filters(); + out << detail::space(detail::INTENT, out, "VPP Filters:") << std::endl; + out << detail::space(detail::INTENT * 2, out, "# of filters = ") << filters.size() << std::endl; + + std::for_each(filters.begin(), filters.end(), [&](implementation_capabilities::vpp_filter flt) { + out << flt; + }); + + return out; +} + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/impl_selector.hpp b/api/vpl/preview/impl_selector.hpp new file mode 100644 index 00000000..e48aa5ba --- /dev/null +++ b/api/vpl/preview/impl_selector.hpp @@ -0,0 +1,139 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include + +#include "vpl/preview/detail/sdk_callable.hpp" +#include "vpl/preview/exception.hpp" +#include "vpl/preview/impl_caps.hpp" +#include "vpl/mfxdispatcher.h" +#include "vpl/preview/options.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief Selects oneVPL implementation according to the specified properties. +/// @details This object iterates over the available implementations and selects an appropriate one +/// based on the @p list of properties. API user can create an instance of that class. If user +/// wants to change the implementation selection behaviour they need to subslass and +/// implement operator (). +class implemetation_selector { +protected: + /// @brief Protected ctor. + /// @param list List of properties + explicit implemetation_selector(std::initializer_list list = {}) + : opts_(list), + format_(MFX_IMPLCAPS_IMPLDESCSTRUCTURE) {} + + /// @brief Protected ctor. + /// @param list List of properties + explicit implemetation_selector(const std::vector &list) + : opts_(list), + format_(MFX_IMPLCAPS_IMPLDESCSTRUCTURE) {} + +public: + /// @brief dtor + virtual ~implemetation_selector() {} + + /// @brief Creates session which has the requested properties. Session class object calls + /// this method at the ctor and takes care on deletion of loader and session handles. + /// @return Pair of loader handle and associated session handle. + auto session() const { + mfxStatus sts; + implementation_capabilities_factory factory; + auto loader = MFXLoad(); + // convert options to mfxConfig + + std::for_each(opts_.begin(), opts_.end(), [&](auto opt) { + auto cfg = MFXCreateConfig(loader); + detail::c_api_invoker e(detail::default_checker, + MFXSetConfigFilterProperty, + cfg, + (const uint8_t *)opt.get_name().c_str(), + opt.GetValue()); + }); + + uint32_t idx = 0; + while (true) { + void *h; + sts = MFXEnumImplementations(loader, idx, format_, &h); + // break if no idx + if (sts == MFX_ERR_NOT_FOUND) + break; + if (sts < 0) + throw base_exception(sts); + + std::shared_ptr caps = factory.create(format_, h); + + if (this->operator()(caps)) { + mfxSession s; + detail::c_api_invoker e(detail::default_checker, MFXCreateSession, loader, idx, &s); + return std::pair(loader, s); + } + idx++; + } + MFXUnload(loader); + throw base_exception(MFX_ERR_NOT_INITIALIZED); + } + +protected: + /// @brief This operator is applyed to any found oneVPL implementation. If operator returns true, a session based + /// on found implementation is created. Otherwise, search is continued. + /// @param caps Pointer to the session capabilities information in the requested format. + /// @return True, if implementation is good to go, false if search must continue. + virtual bool operator()(std::shared_ptr caps) const = 0; + + /// @brief List of properties + std::vector opts_; + + /// @brief Implementation capabilities report format + /// @todo Replace either with enum or typename + mfxImplCapsDeliveryFormat format_; +}; + +/// @brief Default implemetation selector. It accepts first implementation matching provided properties. +class default_selector : public implemetation_selector { +public: + /// @brief Protected ctor. + /// @param list List of properties + explicit default_selector(std::initializer_list list = {}) + : implemetation_selector(list) {} + + /// @brief Protected ctor. + /// @param list List of properties + explicit default_selector(const std::vector &list) : implemetation_selector(list) {} + + /// @brief Acccept first found implementation. + /// @return True if implementation found. + bool operator()(std::shared_ptr) const override { + return true; + } +}; + +/// @brief Default SW based implementation selector. It accepts first implementation with SW based acceleration. +class cpu_selector : public default_selector { +public: + /// @brief Default ctor. + cpu_selector() + : default_selector({ property(property_name("mfxImplDescription") / "Impl", + (uint32_t)MFX_IMPL_TYPE_SOFTWARE) }) {} +}; + +/// @brief Default HW based implementation selector. It accepts first implementation with HW based acceleration. +class gpu_selector : public default_selector { +public: + /// @brief Default ctor. + gpu_selector() + : default_selector({ property(property_name("mfxImplDescription") / "Impl", + (uint32_t)MFX_IMPL_TYPE_HARDWARE) }) {} +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/options.hpp b/api/vpl/preview/options.hpp new file mode 100644 index 00000000..40328799 --- /dev/null +++ b/api/vpl/preview/options.hpp @@ -0,0 +1,87 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include + +#include "vpl/preview/detail/variant.hpp" +#include "vpl/preview/property_name.hpp" + +#include "vpl/mfxcommon.h" +#include "vpl/mfxdefs.h" + +namespace oneapi { +namespace vpl { + +/// @brief Represents implementation properties for the dispatcher +/// @todo Rename class +class property { +public: + /// @brief Default ctor + property() : name_(), value_() {} + + /// @brief Constucts property with given name and the value + /// @tparam T Type of the value + /// @param[in] name Name of the property + /// @param[in] value Value + template + property(property_name &name, T value) : value_(value), + name_(name.get_name()) {} + /// @brief Constucts property with given name and the value + /// @tparam T Type of the value + /// @param[in] name Name of the property + /// @param[in] value Value + template + property(std::string &name, T value) : value_(value), + name_(name) {} + /// @brief Copy ctor + /// @param[in] other another object to use as data source + property(const property &other) : value_(other.value_), name_(other.name_) {} + /// @brief Dtor + virtual ~property() {} + + /// @brief Assignment operator. + /// @param[in] other another object to use as data source + /// @returns Reference to this object + property &operator=(const property &other) { + name_ = other.get_name(); + value_ = other.value_; + return *this; + } + /// @brief Returns type of the property's value + /// @return Type of the property's value + /// @todo Consider remove + mfxVariantType get_type() const { + return value_.get_variant().Type; + } + /// @brief Returns name of the property's value + /// @return Name of the property's value + std::string get_name() const { + return name_; + } + /// @brief Returns property's value + /// @return Property's value + mfxVariant::data get_data() const { + return value_.get_variant().Data; + } + /// @brief Converts propery into mfxVariant type + /// @return Property type and value + mfxVariant GetValue() const { + return value_.get_variant(); + } + +protected: + /// @brief Name of the property + std::string name_; + /// @brief Value of the property + detail::variant value_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/payload.hpp b/api/vpl/preview/payload.hpp new file mode 100644 index 00000000..ac0ab7ce --- /dev/null +++ b/api/vpl/preview/payload.hpp @@ -0,0 +1,190 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include + +#include "vpl/preview/defs.hpp" +#include "vpl/preview/exception.hpp" +#include "vpl/mfxstructures.h" + +namespace oneapi { +namespace vpl { + +/// @brief Represents user's payload data. For encoding, these payloads can be +/// inserted into the bitstream. The payload buffer must contain a valid formatted payload. +/// For decoding, these payloads can be retrieved as the decoder parses the bitstream and +/// caches them in an internal buffer. +class payload { +public: + /// @brief Specialized contructor for the MPEG-2 codec's payload data. + /// @param[in] data Payload data + /// @param[in] numBit Payload data length in bits + payload(const std::vector &data, uint32_t numBit) + : payload_(), + codec_id_(codec_format_fourcc::mpeg2) { + ctor_helper(data, numBit); + } + + /// @brief Specialized contructor for the AVC codec's payload data. + /// @param[in] data Payload data + /// @param[in] numBit Payload data length in bits + /// @param[in] type SEI message type + payload(const std::vector &data, uint32_t numBit, uint16_t type) + : payload_(), + codec_id_(codec_format_fourcc::avc) { + ctor_helper(data, numBit, type); + } + + /// @brief Specialized contructor for the HEVC codec's payload data. + /// @tparam CID codec FourCC code + /// @param[in] data Payload data + /// @param[in] numBit Payload data length in bits + /// @param[in] type SEI message type + /// @param[in] suffix Boolean flag to attach data as suffix. + payload(const std::vector &data, uint32_t numBit, uint16_t type, bool suffix) + : payload_(), + codec_id_(codec_format_fourcc::hevc) { + ctor_helper(data, numBit, type, suffix); + } + + /// @brief Dtor + virtual ~payload() { + delete[] payload_.Data; + payload_.Data = 0; + } + + /// @brief Copy ctor. + /// @param[in] other Object to copy. + payload(const payload& other) { + ctor_helper(other.get_payload_data(), + other.payload_.NumBit, + other.payload_.Type, + other.payload_.CtrlFlags); + } + + /// @brief Move ctor. + /// @param[in] other Object to move + payload(payload&& other) { + payload_.Type = other.payload_.Type; + payload_.CtrlFlags = other.payload_.CtrlFlags; + payload_.NumBit = other.payload_.NumBit; + payload_.BufSize = other.payload_.BufSize; + payload_.Data = other.payload_.Data; + + other.payload_.Data = 0; + } + + /// @brief Assignment operator. + /// @param[in] other another object to use as data source + /// @returns Reference to this object + payload& operator=(const payload& other) { + if (&other == this) + return *this; + + if (this->payload_.Data) + delete[] this->payload_.Data; + + ctor_helper(other.get_payload_data(), + other.payload_.NumBit, + other.payload_.Type, + other.payload_.CtrlFlags); + return *this; + } + + /// @brief Move operator. + /// @param[in] other another object to use as data source + /// @returns Reference to this object + payload& operator=(payload&& other) { + if (&other == this) + return *this; + + if (this->payload_.Data) + delete[] this->payload_.Data; + + payload_.Type = other.payload_.Type; + payload_.CtrlFlags = other.payload_.CtrlFlags; + payload_.NumBit = other.payload_.NumBit; + payload_.BufSize = other.payload_.BufSize; + payload_.Data = other.payload_.Data; + + other.payload_.Data = 0; + return *this; + } + + /// @brief Returns codec FourCC code + /// @return Codec FourCC code + codec_format_fourcc get_codec_id() const { + return codec_id_; + } + + /// @brief Returns SEI message type. Only enables for AVC and HEVC codecs + /// @return SEI message type. + uint16_t get_type() const { + if (codec_id_ == codec_format_fourcc::hevc || codec_id_ == codec_format_fourcc::avc) + return payload_.Type; + throw(base_exception(MFX_ERR_UNDEFINED_BEHAVIOR)); + } + + /// @brief Returns boolean suffix flag. Only enables for HEVC codec + /// @return boolean suffix flag. + bool is_suffix() const { + if (codec_id_ == codec_format_fourcc::hevc) { + if (MFX_PAYLOAD_CTRL_SUFFIX == payload_.CtrlFlags) + return true; + return false; + } + throw(base_exception(MFX_ERR_UNDEFINED_BEHAVIOR)); + } + + /// @brief Returns number of bits in the payload + /// @return Number of bits in the payload + uint16_t get_num_bits() const { + return payload_.NumBit; + } + + /// @brief Returns container with payload data + /// @return Number Container with payload data + std::vector get_payload_data() const { + return std::vector(payload_.Data, payload_.Data + payload_.BufSize); + } + + /// @brief Returns pointer to the raw data + /// @return Pointer to the raw data + mfxPayload* get_raw_ptr() { + return &payload_; + } + +protected: + /// @brief Internal helper function for ctor. + /// @param[in] data Payload data + /// @param[in] numBit Payload data length in bits + /// @param[in] type SEI message type + /// @param[in] suffix Boolean flag to attach data as suffix. + void ctor_helper(std::vector data, + uint32_t numBit, + uint16_t type = 0x01B2, + bool suffix = false) { + payload_.Type = type; + if (suffix) { + payload_.CtrlFlags = MFX_PAYLOAD_CTRL_SUFFIX; + } + payload_.NumBit = numBit; + payload_.BufSize = static_cast(data.size()); + payload_.Data = new uint8_t[payload_.BufSize]; + std::copy(data.begin(), data.end(), payload_.Data); + } + /// @brief Raw data + mfxPayload payload_; + + /// @brief Codec FourCC code + codec_format_fourcc codec_id_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/property_name.hpp b/api/vpl/preview/property_name.hpp new file mode 100644 index 00000000..5d6d6254 --- /dev/null +++ b/api/vpl/preview/property_name.hpp @@ -0,0 +1,303 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include + +// leave table formatting alone +// clang-format off + +namespace oneapi { +namespace vpl { + +#define MARKER 0x7fffffff + +/// @brief Item of the layer. +/// @details +/// We parse name of the value to extrac parents structures and verify correctness of the parameter. Let's imagine +/// we have parameter: "mfxImplDescription.Impl". Here we have two layers: "mfxImplDescription" with ID = 1 and "Impl" +/// with ID = 2. "Impl" has parentID = 1. Finally we will have two instances of the structure. +struct layer { + unsigned int ID; /// Unique ID of the parameter. + unsigned int parentID; /// ID of the parent name. + const char* name; /// Name of the parameter. +}; + +/// @brief This structure represents array of layers in the params hierarchy, +/// @todo Should go to the detail namespace. +struct layers { + const struct layer* pLayer; /// Pointer to the layer +}; + +#define ENTRY(id, parent, propname) \ + { id, parent, propname } + +#define END_OF_LAYER \ + { MARKER, MARKER, "end" } + +const struct layer layer_0[] = { + ENTRY(0, MARKER, "mfxImplDescription"), + ENTRY(1, MARKER, "mfxImplementedFunctions"), + ENTRY(2, MARKER, "DXGIAdapterIndex"), + ENTRY(3, MARKER, "mfxHandleType"), + ENTRY(4, MARKER, "mfxHDL"), + END_OF_LAYER +}; + +const struct layer layer_1[] = { + ENTRY(101, 0, "Impl"), + ENTRY(102, 0, "AccelerationMode"), + ENTRY(103, 0, "ApiVersion"), + ENTRY(104, 0, "ImplName"), + ENTRY(105, 0, "License"), + ENTRY(106, 0, "Keywords"), + ENTRY(107, 0, "VendorID"), + ENTRY(108, 0, "VendorImplID"), + ENTRY(109, 0, "mfxDeviceDescription"), + ENTRY(110, 0, "mfxDecoderDescription"), + ENTRY(111, 0, "mfxEncoderDescription"), + ENTRY(112, 0, "mfxVPPDescription"), + ENTRY(113, 1, "FunctionsName"), + END_OF_LAYER +}; + +const struct layer layer_2[] = { + ENTRY(201, 103, "Minor"), + ENTRY(202, 103, "Major"), + ENTRY(203, 109, "device"), + ENTRY(204, 110, "decoder"), // Small letter in use by dispatcher + ENTRY(205, 111, "encoder"), + ENTRY(206, 112, "filter"), + ENTRY(207, 103, "Version"), + END_OF_LAYER +}; + +const struct layer layer_3[] = { + ENTRY(301, 203, "DeviceID"), + ENTRY(302, 204, "CodecID"), + ENTRY(303, 204, "MaxcodecLevel"), + ENTRY(304, 204, "decprofile"), + ENTRY(305, 205, "CodecID"), + ENTRY(306, 205, "MaxcodecLevel"), + ENTRY(307, 205, "BiDirectionalPrediction"), + ENTRY(308, 205, "encprofile"), + ENTRY(309, 206, "FilterFourCC"), + ENTRY(310, 206, "MaxDelayInFrames"), + ENTRY(311, 206, "memdesc"), + END_OF_LAYER +}; + +const struct layer layer_4[] = { + ENTRY(401, 304, "Profile"), + ENTRY(402, 304, "decmemdesc"), + ENTRY(403, 308, "Profile"), + ENTRY(404, 308, "encmemdesc"), + ENTRY(405, 311, "MemHandleType"), + ENTRY(406, 311, "Width"), + ENTRY(407, 311, "Height"), + ENTRY(408, 311, "format"), + END_OF_LAYER +}; + +const struct layer layer_5[] = { + ENTRY(501, 402, "MemHandleType"), + ENTRY(502, 402, "Width"), + ENTRY(503, 402, "Height"), + ENTRY(504, 402, "ColorFormats"), + ENTRY(505, 404, "MemHandleType"), + ENTRY(506, 404, "Width"), + ENTRY(507, 404, "Height"), + ENTRY(508, 404, "ColorFormats"), + ENTRY(509, 408, "InFormat"), + ENTRY(510, 408, "OutFormats"), + END_OF_LAYER +}; + +constexpr struct layers layers_[] = { layer_0, layer_1, layer_2, layer_3, layer_4, layer_5 }; + +#define MAX_LEVEL 6 + +// end table formatting +// clang-format on + +/// @brief Forms string at compile time for dispatcher with the property name. String is built from the series of +/// substrings where nested subnames are separated by the `.`. On each step, subname value is verified that it +/// is allowed for that level. If wrong subname is provided - exception is raised. +/// @details Usage example: +/// @code +/// oneapi::vpl::property_name p1; +/// oneapi::vpl::property opt2(p2 / "mfxImplDescription" / "mfxDecoderDescription" / "decoder" / "CodecID" +/// , (uint32_t)MFX_CODEC_HEVC); +/// @endcode +class property_name { +public: + /// @brief Default ctor. Initializes empty object + constexpr property_name() : names_(), level_(0), ID_(MARKER) {} + /// @brief Construct object by assuming that @p name is the first level name, + /// @param name Allpowed first level name. + constexpr explicit property_name(const char* name) : names_(), level_(0), ID_(MARKER) { + std::string_view n(name); + size_t end_pos = n.find_first_of(std::string_view("."), 0), curr_read_pos = 0; + if (end_pos == std::string_view::npos) { + // Single parameter case. No need to tokenize + int i = 0; + ID_ = check_value(name, 0, MARKER); + for (i = 0; name[i] != '\0'; i++) { + names_[0][i] = name[i]; + } + names_[0][i] = '\0'; + level_ = 1; + } + else if (end_pos != 0) { + while (curr_read_pos != std::string_view::npos) { + std::string_view n1 = n.substr(curr_read_pos, (end_pos - curr_read_pos)); + add_item(n1); + if (end_pos == std::string_view::npos) { + curr_read_pos = std::string_view::npos; + } + else { + curr_read_pos = end_pos + 1; + } + end_pos = n.find_first_of(std::string_view(".\0"), end_pos + 1); + } + } + else { + error_happened(0); // This is workaround for GCC bug. + } + } + /// @brief Adds next subname to the name. Subname value is verified that it is valid for the current + /// level of hierarchy. + /// @param subname Constant string with the subname + /// @return Reference to the updated object. + constexpr property_name& operator/(const char* subname) { + int i = 0; + ID_ = check_value(subname, level_, ID_); + + for (i = 0; subname[i] != '\0'; i++) { + names_[level_][i] = subname[i]; + } + names_[level_][i] = '\0'; + level_++; + return *this; + } + /// @brief Non compile time member. Creates std::string object with the name, where all given + /// subnames are separated by `.`. + /// @return Dot separated string. + std::string get_name() { + std::string n; + for (unsigned int i = 0; i < level_; i++) { + if (i) + n += "."; + n += names_[i]; + } + return n; + } + +protected: + /// @brief Array withe subnames for each level. + char names_[MAX_LEVEL][128]; + /// @brief Current hierarchy level + unsigned int level_; + /// @brief ID of the previous subname + unsigned int ID_; + +private: + /// @brief Throw logic error + /// @param n error value + /// @return Throw error or 1 + constexpr auto error_happened(int n) -> int { + return n <= 0 ? throw std::logic_error("absent property") : 1; + } + + /// @brief Check value in layer + /// @param name Subname + /// @param l Layer + /// @param prevID ID of the previous subname + /// @return Value in layer + constexpr unsigned int check_value_in_layer(const char* name, + const struct layer* l, + unsigned int prevID) { + std::string_view n1(name); + for (int i = 0;; i++) { + if (l[i].ID == MARKER) + break; + if (prevID == l[i].parentID) { + std::string_view n2(l[i].name); + if (n1 == n2) { + return l[i].ID; + } + } + } + error_happened(0); // This is workaround for GCC bug. + return MARKER; + } + + /// @brief Check value + /// @param name Subname + /// @param level Hierarchy level + /// @param prevID ID of the previous subname + /// @return Value + constexpr unsigned int check_value(const char* name, unsigned int level, unsigned int prevID) { + if (level >= sizeof(layers_) / sizeof(layers_[0])) + std::logic_error("Too deep property"); + return check_value_in_layer(name, layers_[level].pLayer, prevID); + } + + /// @brief Check value in layer + /// @param n1 string_view + /// @param l Layer + /// @param prevID ID of the previous subname + /// @return Value + constexpr unsigned int check_value_in_layer(std::string_view n1, + const struct layer* l, + unsigned int prevID) { + for (int i = 0;; i++) { + if (l[i].ID == MARKER) + break; + if (prevID == l[i].parentID) { + std::string_view n2(l[i].name); + if (n1 == n2) { + return l[i].ID; + } + } + } + error_happened(0); // This is workaround for GCC bug. + return MARKER; + } + + /// @brief Check value + /// @param name Subname + /// @param level Hierarchy level + /// @param prevID ID of the previous subname + /// @return Value + constexpr unsigned int check_value(std::string_view name, + unsigned int level, + unsigned int prevID) { + if (level >= sizeof(layers_) / sizeof(layers_[0])) + std::logic_error("Too deep property"); + return check_value_in_layer(name, layers_[level].pLayer, prevID); + } + + /// @brief Add item + /// @param subname Subname + constexpr void add_item(std::string_view subname) { + int i = 0; + ID_ = check_value(subname, level_, ID_); + + for (i = 0; i < subname.size(); i++) { + names_[level_][i] = subname[i]; + } + names_[level_][i] = '\0'; + level_++; + } +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/session.hpp b/api/vpl/preview/session.hpp new file mode 100644 index 00000000..79999bc4 --- /dev/null +++ b/api/vpl/preview/session.hpp @@ -0,0 +1,894 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include + +#include "vpl/preview/defs.hpp" +#include "vpl/preview/exception.hpp" +#include "vpl/preview/extension_buffer_list.hpp" +#include "vpl/preview/frame_pool.hpp" +#include "vpl/preview/frame_surface.hpp" +#include "vpl/preview/future.hpp" +#include "vpl/preview/impl_selector.hpp" +#include "vpl/preview/source_reader.hpp" +#include "vpl/preview/stat.hpp" +#include "vpl/preview/video_param.hpp" + +#include "vpl/mfxvideo.h" + +#include "vpl/preview/detail/sdk_callable.hpp" + +#ifdef LIBVA_SUPPORT + #include "va/va.h" + #include "va/va_drm.h" + #include +#endif + +namespace oneapi { +namespace vpl { + +/// @brief Base class to manage any session. User doesn't have ability to create instanse of this class. +/// only specialized classes for decoder or encoder or VPP sessions must be used. +/// General note: negative status is sent thought exceptions, warnings are delivered as a status codes. +/// @tparam VideoParams Class to manage Sesson paramers +/// @tparam InitList Class to manage extensio buffers for Init stage +/// @tparam ResetList Class to manage extensio buffers for Reset stage +template +class session { +protected: + /// @brief Session's data processing state. + enum class state : unsigned int { + Processing = 0, ///< Session process the input data. + Draining = 1, ///< Session's source reported EOS, so session is draining. + Done = 2, ///< All processing is done. No cached data remains in the session. + }; + /// @brief Protected ctor. Creates session by using supplyed implementation selector. + /// @param[in] sel Implementation selector + /// @param[in] callable C API functions table + session(const implemetation_selector &sel, detail::sdk_c_api callable) + : c_api_callable_(callable), + state_(state::Processing), + component_(component::unknown), + accelerator_handle(nullptr) { + auto [l_, s_] = sel.session(); + this->loader_ = l_; + this->session_ = s_; + + mfxStatus sts = MFXQueryIMPL(this->session_, &this->selected_impl_); + if (sts != MFX_ERR_NONE) { + this->selected_impl_ = 0; + } + this->version_ = { 0, 0 }; + sts = MFXQueryVersion(this->session_, &this->version_); + if (sts != MFX_ERR_NONE) { + this->version_ = { 0, 0 }; + } + init_accelerator_handle(); + } + +public: + /// @brief Dtor. Additionaly it closes loader. + virtual ~session() { + c_api_callable_.close(session_); + MFXClose(session_); + MFXUnload(loader_); + free_accelerator_handle(); + } + + /// @brief Returns implementation capabilities. + /// @return Implementation capabilities. + std::shared_ptr Caps() { + std::shared_ptr caps = std::make_shared(); + detail::c_api_invoker e(detail::default_checker, + c_api_callable_.query, + session_, + nullptr, + caps->getMfx()); + return caps; + } + + /// @brief Verifyes that implementation supports such capabilities. On output, corrected capabilities are returned + /// @param[in] param Pointer to the imaplementation capabiliies. + /// @return Corrected implementation capabilities. + std::shared_ptr Verify(VideoParams *param) { + std::shared_ptr out = std::make_shared(); + detail::c_api_invoker e( + detail::default_checker, + std::bind(c_api_callable_.query, session_, param->getMfx(), out->getMfx())); + return out; + } + + /// @brief Initializes the session by using provided parameters + /// @param[in] par Init parameters + /// @param[in] list List of extension buffers. + /// @return Status of the initialization. + status Init(VideoParams *par, InitList list = {}) { + if (list.get_size()) { + if (auto [buffers, size] = list.get_raw_ext_buffers(); size) { + par->set_extension_buffers(buffers, static_cast(size)); + } + } + detail::c_api_invoker e(detail::default_checker, + std::bind(c_api_callable_.init, session_, par->getMfx())); + par->clear_extension_buffers(); + + return mfxstatus_to_onevplstatus(e.sts_); + } + + /// @brief Resets the session by using provided parameters + /// @param[in] par Reset parameters + /// @param[in] list List of extension buffers. + /// @return Status of the reset. + status Reset(VideoParams *par, ResetList list) { + if (list.get_size()) { + if (auto [buffers, size] = list.get_raw_ext_buffers(); size) { + par->set_extension_buffers(buffers, static_cast(size)); + } + } + + detail::c_api_invoker e(detail::default_checker, + std::bind(c_api_callable_.reset, session_, par->getMfx()), + std::bind(c_api_callable_.init, session_, par->getMfx())); + state_ = state::Processing; + par->clear_extension_buffers(); + return mfxstatus_to_onevplstatus(e.sts_); + } + + /// @brief Retrieves current session parameters. + /// @return Session parameters. + std::shared_ptr working_params() { + std::shared_ptr out = std::make_shared(); + detail::c_api_invoker e(detail::default_checker, + c_api_callable_.params, + session_, + out->getMfx()); + return out; + } + + /// @brief Returns session's domain + /// @return Session's domain + component get_component_domain() const { + return component_; + } + + /// @brief Returns implementation + /// @return implementation + mfxIMPL get_implementation() { + return selected_impl_; + } + + /// @brief Returns version + /// @return version + mfxVersion get_version() { + return version_; + } + +protected: + /// @brief Session handle. + mfxSession session_; + /// @brief Functions table. + detail::sdk_c_api c_api_callable_; + /// @brief Processing state of the session. + state state_; + /// @brief Session's type identifier. Domain in other words + component component_; + + /// @brief Selected actual implementation + mfxIMPL selected_impl_; + + /// @brief Version of implementation + mfxVersion version_; + + void init_accelerator_handle() { + mfxIMPL impl; + mfxStatus sts = MFXQueryIMPL(session_, &impl); + if (sts != MFX_ERR_NONE) + return; + + #ifdef LIBVA_SUPPORT + if ((impl & MFX_IMPL_VIA_VAAPI) == MFX_IMPL_VIA_VAAPI) { + VADisplay va_dpy = NULL; + int fd; + // initialize VAAPI context and set session handle (req in Linux) + fd = open("/dev/dri/renderD128", O_RDWR); + if (fd >= 0) { + va_dpy = vaGetDisplayDRM(fd); + if (va_dpy) { + int major_version = 0, minor_version = 0; + if (VA_STATUS_SUCCESS == vaInitialize(va_dpy, &major_version, &minor_version)) { + MFXVideoCORE_SetHandle(session_, + static_cast(MFX_HANDLE_VA_DISPLAY), + va_dpy); + } + } + } + accelerator_handle = va_dpy; + } + #endif + } + + void free_accelerator_handle() { + #ifdef LIBVA_SUPPORT + vaTerminate((VADisplay)accelerator_handle); + accelerator_handle = nullptr; + #endif + } + + + /// @brief Accelerator handle + void *accelerator_handle; + +private: + mfxLoader loader_; +}; + +/// @brief Manages decoder's sessions. +/// @tparam Reader Bitstream reader class +/// @todo SFINAE it +template +class decode_session + : public session { +public: + /// @brief Constructs decoder session + /// @param[in] sel Implementation selector + /// @param[in] codecID Codec ID + /// @param[in] rdr Bitstream reader + decode_session(const implemetation_selector &sel, codec_format_fourcc codecID, Reader *rdr) + : session(sel, detail::CAPI<>::Decoder), + bits_(codecID), + rdr_(rdr), + params_(), + list_() { + component_ = component::decoder; + params_.set_CodecId(codecID); + params_.clear_extension_buffers(); + } + + /// @brief Constructs decoder session + /// @param[in] sel Implementation selector + /// @param[in] params Video params + /// @param[in] rdr Bitstream reader + decode_session(const implemetation_selector &sel, + const decoder_video_param ¶ms, + Reader *rdr) + : session(sel, detail::CAPI<>::Decoder), + bits_((codec_format_fourcc)params.get_CodecId()), + rdr_(rdr), + params_(params), + list_() { + component_ = component::decoder; + params_.clear_extension_buffers(); + } + + /// @brief Constructs decoder session + /// @param[in] sel Implementation selector + /// @param[in] codecID Codec ID + /// @param[in] rdr Bitstream reader + /// @param[in] list Process list + decode_session(const implemetation_selector &sel, + codec_format_fourcc codecID, + Reader *rdr, + const decoder_process_list &list) + : session(sel, detail::CAPI<>::Decoder), + bits_(codecID), + rdr_(rdr), + params_(), + list_(list) { + component_ = component::decoder; + params_.set_CodecId(codecID); + params_.clear_extension_buffers(); + } + + /// @brief Constructs decoder session + /// @param[in] sel Implementation selector + /// @param[in] params Video params + /// @param[in] rdr Bitstream reader + /// @param[in] list Process list + decode_session(const implemetation_selector &sel, + const decoder_video_param ¶ms, + Reader *rdr, + const decoder_process_list &list) + : session(sel, detail::CAPI<>::Decoder), + bits_((codec_format_fourcc)params.get_CodecId()), + rdr_(rdr), + params_(params), + list_(list) { + component_ = component::decoder; + params_.clear_extension_buffers(); + } + + /// @brief Dtor + ~decode_session() {} + + /// @brief Initialize the session by using bitream portion. This step can be omitted if the codec ID is known or + /// we don't need to get SSP or PPS data from the bitstream. + /// @param[in] decHeaderList List of extension buffers for InitHeader stage. Can be NULL. + /// @param[in] initList List of extension buffers for Init stage. Can be NULL. + /// @return Ok or warnings + status init_by_header(decoder_init_header_list decHeaderList = {}, + decoder_init_reset_list initList = {}) { + mfxStatus sts = MFX_ERR_MORE_DATA; + + if (decHeaderList.get_size()) { + if (auto [buffers, size] = decHeaderList.get_raw_ext_buffers(); size) { + params_.set_extension_buffers(buffers, static_cast(size)); + } + } + + do { + rdr_->get_data(&bits_); + + detail::c_api_invoker e({ [](mfxStatus s) { + switch (s) { + case MFX_ERR_MORE_DATA: + return false; + default: + break; + } + + bool ret = (s < 0) ? true : false; + return ret; + } }, + MFXVideoDECODE_DecodeHeader, + session_, + bits_(), + params_.getMfx()); + sts = e.sts_; + } while (sts == MFX_ERR_MORE_DATA && !rdr_->is_EOS()); + + if (sts != MFX_ERR_NONE && rdr_->is_EOS()) + return status::EndOfStreamReached; + if (sts != MFX_ERR_NONE) + mfxstatus_to_onevplstatus(sts); + auto result = Init(¶ms_, initList); + params_.clear_extension_buffers(); + return result; + } + + /// @brief Decodes frame + /// @param[out] out_surface Future object with decoded data. + /// @param[in] list List of extension buffers to attach to bitstream. + /// @return Ok or warning + status decode_frame(std::shared_ptr out_surface, + decoder_process_list list = {}) { + mfxSyncPoint syncp; + mfxFrameSurface1 *surf = NULL; + + rdr_->get_data(&bits_); + + mfxBitstream *bts; + if (bits_.get_DataLength() == 0 && rdr_->is_EOS()) { + bts = nullptr; + state_ = state::Draining; + } + else { + bts = bits_(); + if (auto [buffers, size] = list.get_raw_ext_buffers(); size) { + bts->NumExtParam = static_cast(size); + bts->ExtParam = buffers; + } + else { + bts->NumExtParam = 0; + bts->ExtParam = nullptr; + } + } + + detail::c_api_invoker e({ [](mfxStatus s) { + switch (s) { + case MFX_ERR_MORE_DATA: + return false; + case MFX_ERR_MORE_SURFACE: + return false; + default: + break; + } + + bool ret = (s < 0) ? true : false; + return ret; + } }, + MFXVideoDECODE_DecodeFrameAsync, + session_, + bts, + nullptr, + &surf, + &syncp); + + if (surf) { + // out_surface = std::make_shared(surf); + // out_surface.reset(new frame_surface(surf)); + // std::shared_ptr tmp = std::make_shared(surf); + // out_surface.swap(tmp); + out_surface->inject(surf, out_surface.use_count() + 1); + } + + if (e.sts_ == MFX_ERR_MORE_DATA && state_ == state::Draining) { + state_ = state::Done; + return status::EndOfStreamReached; + } + return mfxstatus_to_onevplstatus(e.sts_); + } + + /// @brief Decodes frame + /// @param[in] list List of extension buffers to attach to bitstream + /// @return Future object with decoded data + std::shared_ptr>> process( + decoder_process_list list = {}) { + std::shared_ptr surface = std::make_shared(); + std::shared_ptr f; + + operation_status op(component_, this); + + if (state_ != state::Done) { + try { + status schedule_status; + schedule_status = decode_frame(surface, list); + f = std::make_shared(surface); + op.schedule_status_ = schedule_status; + } + catch (base_exception &e) { + f = std::make_shared(nullptr); + op.schedule_status_ = mfxstatus_to_onevplstatus(e.get_status()); + op.fatal_ = true; + } + } + else { + f = std::make_shared(nullptr); + op.schedule_status_ = status::EndOfStreamReached; + } + + f->add_operation(op); + return f; + } + /// @brief Retrieve decoder statistic + /// @return Decoder statistic + std::shared_ptr getStat() { + std::shared_ptr out = std::make_shared(); + decode_stat *dec_stat = out.get(); + detail::c_api_invoker e(detail::default_checker, + MFXVideoDECODE_GetDecodeStat, + session_, + dec_stat->get_raw()); + return out; + } + + /// @brief Get video params + /// @return params + decoder_video_param getParams() { + return params_; + } + +protected: + /// @brief Bitstream keeper + bitstream_as_src bits_; + /// @brief Bitstream reader + Reader *rdr_; + /// @brief Video params + decoder_video_param params_; + /// @brief Process list + decoder_process_list list_; +}; + +/// @brief Manages encoder's sessions. +/// @todo SFINAE it +class encode_session : public session { +public: + /// @brief Constructs encoder session + /// @param[in] sel Implementation selector + explicit encode_session(const implemetation_selector &sel) + : session(sel, detail::CAPI<>::Encoder), + rdr_(nullptr) { + component_ = component::encoder; + } + + /// @brief Constructs encoder session + /// @param[in] sel Implementation selector + /// @param[in] rdr Pointer to the raw frame reader + encode_session(const implemetation_selector &sel, frame_source_reader *rdr) + : session(sel, detail::CAPI<>::Encoder), + rdr_(rdr) { + component_ = component::encoder; + } + + /// @brief Dtor + ~encode_session() {} + + /// @brief Allocate and return shared pointer to the surface + /// @todo temporary method + /// @return Shared pointer to the allocated surface + auto alloc_input() { + mfxFrameSurface1 *surface = nullptr; + detail::c_api_invoker e(detail::default_checker, + MFXMemory_GetSurfaceForEncode, + session_, + &surface); + + return std::make_shared(surface); + } + + /// @brief Temporal method to sync the surface's data. + /// @todo remove during migration to 2.1 + /// @param[in] sp Synchronization point handle. + /// @param[in] to Time to wait. + void sync(mfxSyncPoint sp, int to) { + if (sp) { + detail::c_api_invoker e(detail::default_checker, + MFXVideoCORE_SyncOperation, + session_, + sp, + to); + } + } + /// @brief Encodes frame + /// @param[in] in_surface Object with the data to encode. + /// @param[out] bs Future object with bitstream portion. + /// @param[in] list List of extension buffers to use + /// @return Ok or warning + status encode_frame(std::shared_ptr in_surface, + std::shared_ptr bs, + encoder_process_list list = {}) { + mfxSyncPoint sp; + mfxFrameSurface1 *surf = in_surface.get() ? in_surface.get()->get_raw_ptr() : nullptr; + + if (nullptr == surf) { + state_ = state::Draining; + } + detail::c_api_invoker e({ [](mfxStatus s) { + switch (s) { + case MFX_ERR_MORE_DATA: + return false; + case MFX_ERR_NOT_ENOUGH_BUFFER: + return false; + default: + break; + } + + bool ret = (s < 0) ? true : false; + return ret; + } }, + MFXVideoENCODE_EncodeFrameAsync, + session_, + nullptr, + surf, + (*bs.get())(), + &sp); + bs->associate_context({ session_, sp }); + + if (e.sts_ == MFX_ERR_MORE_DATA && state_ == state::Draining) { + state_ = state::Done; + return status::EndOfStreamReached; + } + + return mfxstatus_to_onevplstatus(e.sts_); + } + + /// @brief Encodes frame by using provided source reader to get data to encode + /// @param[out] bs Future object with bitstream portion. + /// @param[in] list List of extension buffers to use + /// @return Ok or warning + status encode_frame(std::shared_ptr bs, encoder_process_list list = {}) { + status sts; + if (!rdr_) + throw base_exception("NULL reader ptr", MFX_ERR_NULL_PTR); + + while (1) { + std::shared_ptr input_surface(nullptr); + + if (!rdr_->is_EOS()) { + input_surface = alloc_input(); + rdr_->get_data(input_surface); + if (rdr_->is_EOS()) + input_surface.reset(); + } + + sts = encode_frame(input_surface, bs, list); + + switch (sts) { + case status::Ok: + return status::Ok; + case status::EndOfStreamReached: + return status::EndOfStreamReached; + case status::NotEnoughData: + break; + case status::NotEnoughBuffer: { + bs->realloc(); + // Assume that frame was cached so we need to increase buffer size only and send new frame to enc + break; + } + default: + return sts; + } + } + + return sts; + } + + /// @brief Encode frame. Function returns the future object with the bitstream which will hold processed data. User + /// needs to sync up the future object before accessing. + /// This function expected to work in the chain and uses provided future object to get the data to process. + /// @param[in] in_future Future object with the surface from the previous operation. + /// @param[in] list List of extension buffers to use + /// @return Future object with the bitstream. + std::shared_ptr process(std::shared_ptr in_future, + encoder_process_list list = {}) { + std::shared_ptr bits; + std::shared_ptr f_out = std::make_shared(nullptr); + operation_status op(component_, this); + + /// @todo add smart wait with status propagation + std::shared_ptr in_surface = in_future->get(); + + if (state_ == state::Done) { + op.schedule_status_ = status::EndOfStreamReached; + } + else { + switch (in_future->get_last_schedule_status()) { + case status::Ok: + case status::EndOfStreamReached: { + try { + status schedule_status; + + bits = std::make_shared(); + schedule_status = encode_frame(in_surface, bits, list); + f_out = std::make_shared(bits); + f_out.reset(new future_bitstream_t(bits)); + op.schedule_status_ = schedule_status; + } + catch (base_exception &e) { + std::cout << "encoder gonna die" << std::endl << std::flush; + op.schedule_status_ = mfxstatus_to_onevplstatus(e.get_status()); + op.fatal_ = true; + } + } break; + default: { + op.schedule_status_ = in_future->get_last_schedule_status(); + } break; + } + } + + f_out->add_operation(op); + f_out->propagate_history(*(in_future.get())); + return f_out; + } + + /// @brief Retrieve encoder statistic + /// @return Encoder statistic + std::shared_ptr getStat() { + std::shared_ptr out = std::make_shared(); + encode_stat *enc_stat = out.get(); + detail::c_api_invoker e(detail::default_checker, + MFXVideoENCODE_GetEncodeStat, + session_, + enc_stat->get_raw()); + return out; + } + +protected: + /// @brief Raw freames reader + frame_source_reader *rdr_; +}; + +/// @brief Manages VPP's sessions. +/// @todo SFINAE it +class vpp_session : public session { +public: + /// @brief Constructs encoder session + /// @param[in] sel Implementation selector + explicit vpp_session(const implemetation_selector &sel) + : session(sel, detail::CAPI<>::VPP), + rdr_(nullptr) { + component_ = component::vpp; + } + + /// @brief Constructs encoder session + /// @param[in] sel Implementation selector + /// @param[in] rdr Pointer to the raw frame reader + vpp_session(const implemetation_selector &sel, frame_source_reader *rdr) + : session(sel, detail::CAPI<>::VPP), + rdr_(rdr) { + component_ = component::vpp; + } + + /// @brief Dtor + ~vpp_session() {} + + /// @brief Allocate and return shared pointer to the surface + /// @todo temporary method + /// @return Shared pointer to the allocated surface + auto alloc_input() { + mfxFrameSurface1 *surface = nullptr; + detail::c_api_invoker e(detail::default_checker, + MFXMemory_GetSurfaceForVPP, + session_, + &surface); + + return std::make_shared(surface); + } + + /// @brief Initializes session with given parameters and extention buffers. + /// @param[in] par Pointer to the parameters. + /// @param[in] list List of extention buffers. + /// @return Initialization status + /// @todo This method brakes RAII concept. Need to move to ctor. + status Init(vpp_video_param *par, vpp_init_reset_list list = {}) { + status init_sts = session::Init(par, list); + mfxFrameAllocRequest request[2] = { 0 }; + + detail::c_api_invoker e(detail::default_checker, + MFXVideoVPP_QueryIOSurf, + session_, + par->getMfx(), + request); + out_frames_allocator_.attach_frame_info(oneapi::vpl::frame_info(request[1].Info)); + return init_sts; + } + + /// @brief Temporal method to sync rhe surface's data. + /// @todo remove during migration to 2.1 + /// @param[in] sp Synchronization point handle. + /// @param[in] to Time to wait. + void sync(mfxSyncPoint sp, int to) { + if (sp) { + detail::c_api_invoker e(detail::default_checker, + MFXVideoCORE_SyncOperation, + session_, + sp, + to); + } + } + /// @brief Process frame. Function returns the surface which will hold processed data. User need to sync up the + /// surface data before accessing. + /// @param[in] in_surface Pointer to the input surface. + /// @param[out] out_surface Placeholder for the allocated output surface. + /// @return Ok or warning + status process_frame(std::shared_ptr in_surface, + std::shared_ptr out_surface) { + mfxSyncPoint sp; + mfxFrameSurface1 *surf = in_surface.get() ? in_surface->get_raw_ptr() : nullptr; + + if (nullptr == surf) { + state_ = state::Draining; + } + out_surface = out_frames_allocator_.acquire(); + detail::c_api_invoker e({ [](mfxStatus s) { + switch (s) { + case MFX_ERR_MORE_DATA: + return false; + case MFX_ERR_MORE_SURFACE: + return false; + default: + break; + } + + bool ret = (s < 0) ? true : false; + return ret; + } }, + MFXVideoVPP_RunFrameVPPAsync, + session_, + surf, + out_surface->get_raw_ptr(), + nullptr, + &sp); + + if (out_surface) { + out_surface->associate_context(session_, sp); + } + + if (e.sts_ == MFX_ERR_MORE_DATA && state_ == state::Draining) { + state_ = state::Done; + out_surface.reset(); + return status::EndOfStreamReached; + } + + return mfxstatus_to_onevplstatus(e.sts_); + } + + /// @brief Process frame. Function returns the surface which will hold processed data. User need to sync up the + /// surface data before accessing. + /// @param[out] out_surface Placeholder for the allocated output surface. + /// @return Ok or warning + status process_frame(std::shared_ptr out_surface) { + status sts; + if (!rdr_) + throw base_exception("NULL reader ptr", MFX_ERR_NULL_PTR); + + while (1) { + std::shared_ptr input_surface(nullptr); + + if (!rdr_->is_EOS()) { + input_surface = alloc_input(); + rdr_->get_data(input_surface); + if (rdr_->is_EOS()) + input_surface.reset(); + } + + sts = process_frame(input_surface, out_surface); + + switch (sts) { + case status::Ok: + return status::Ok; + case status::EndOfStreamReached: + return status::EndOfStreamReached; + case status::NotEnoughData: + break; + default: + return sts; + } + } + + return sts; + } + + /// @brief Process frame. Function returns the future object with the surface which will hold processed data. User + /// need to sync up the future object before accessing. + /// This function expected to work in the chain and uses provided future object to get the data to process. + /// @param[in] in_future Future object with the surface from the previouse operation. + /// @return Future object with the surface. + std::shared_ptr process(std::shared_ptr in_future) { + std::shared_ptr surface; + std::shared_ptr f_out = std::make_shared(nullptr); + operation_status op(component_, this); + + /// @todo add smart wait with status propagation + std::shared_ptr in_surface = in_future->get(); + + if (state_ == state::Done) { + op.schedule_status_ = status::EndOfStreamReached; + } + else { + switch (in_future->get_last_schedule_status()) { + case status::Ok: + case status::EndOfStreamReached: { + try { + status schedule_status; + schedule_status = process_frame(in_surface, surface); + f_out.reset(new future_surface_t(surface)); + op.schedule_status_ = schedule_status; + } + catch (base_exception &e) { + op.schedule_status_ = mfxstatus_to_onevplstatus(e.get_status()); + op.fatal_ = true; + } + } break; + default: { + op.schedule_status_ = in_future->get_last_schedule_status(); + } break; + } + } + + f_out->add_operation(op); + f_out->propagate_history(*(in_future.get())); + + return f_out; + } + + /// @brief Retrieve encoder statistic + /// @return VPP statistic + std::shared_ptr getStat() { + std::shared_ptr out = std::make_shared(); + vpp_stat *vpp_stat = out.get(); + detail::c_api_invoker e(detail::default_checker, + MFXVideoVPP_GetVPPStat, + session_, + vpp_stat->get_raw()); + return out; + } + +protected: + /// @brief Raw freames reader + frame_source_reader *rdr_; + + /// @brief Temporal naive surfaces allocator. + /// @todo Replace the API 2.1 new functions for the memory allocation + temporal_frame_allocator out_frames_allocator_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/source_reader.hpp b/api/vpl/preview/source_reader.hpp new file mode 100644 index 00000000..1c9ece69 --- /dev/null +++ b/api/vpl/preview/source_reader.hpp @@ -0,0 +1,344 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include + +#include "vpl/preview/bitstream.hpp" +#include "vpl/preview/defs.hpp" +#include "vpl/preview/frame_surface.hpp" + +namespace oneapi { +namespace vpl { + +/// @brief Interface for the source data reader +/// @todo add externally requested reset and reposition +class source_reader { +public: + /// @brief Default ctor + source_reader() {} + + /// @brief Default dtor + virtual ~source_reader() {} + + /// @brief Checks and retrieve end of stream status + /// @return True if EOS reached + virtual bool is_EOS() const = 0; +}; + +/// @brief Interface for the frame source data reader +class frame_source_reader : public source_reader { +public: + /// @brief Default ctor + frame_source_reader() {} + + /// @brief Default dtor + virtual ~frame_source_reader() {} + + /// @brief Read and store portion of data into the @p bitstream object + /// @param[out] frame data storage + /// @return True if data was read + virtual bool get_data(std::shared_ptr frame) = 0; +}; + +/// @brief File based reader of uncomressed frames +class raw_frame_file_reader : public frame_source_reader { +public: + /// @brief Default ctor + /// @param[in] width Width of the frames. + /// @param[in] heigth Heigh of the frames. + /// @param[in] format Color format of the frames. + /// @param[in] ifl Input stream to read from. + raw_frame_file_reader(uint16_t width, + uint16_t heigth, + color_format_fourcc format, + std::ifstream& ifl) + : frame_source_reader(), + width_(width), + heigth_(heigth), + format_(format), + ifl_(ifl), + eof_(false) {} + + /// @brief Default dtor + virtual ~raw_frame_file_reader() {} + + /// @brief Read and store portion of data into the @p bitstream object + /// @param[out] frame data storage + /// @return True if data was read + virtual bool get_data(std::shared_ptr frame) { + auto [info, data] = frame->map(memory_access::write); + + /// @todo verify buffer availability + + uint32_t pitch = 0; + switch (format_) { + case oneapi::vpl::color_format_fourcc::i420: { + pitch = data.get_pitch(); + auto [Y, U, V] = data.get_plane_ptrs_3(); + + // read luminance plane (Y) + read_blob(Y, pitch, width_, heigth_); + + // read chrominance (U, V) + read_blob(U, pitch / 2, width_ / 2, heigth_ / 2); + read_blob(V, pitch / 2, width_ / 2, heigth_ / 2); + break; + } + case oneapi::vpl::color_format_fourcc::nv12: { + pitch = data.get_pitch(); + auto [Y, UV] = data.get_plane_ptrs_2(); + + // read luminance plane (Y) + read_blob(Y, pitch, width_, heigth_); + + // read chrominance (UV) + read_blob(UV, pitch, width_, heigth_ / 2); + break; + } + case oneapi::vpl::color_format_fourcc::bgra: { + pitch = data.get_pitch(); + auto [R, G, B, A] = data.get_plane_ptrs_4(); + + read_blob(B, pitch, width_ * 4, heigth_); + } + default: + throw base_exception("raw_frame_file_reader unsupported format", + MFX_ERR_NOT_IMPLEMENTED); + } + frame->unmap(); + return !eof_; + } + + /// @brief Checks and retrieve end of stream status + /// @return True if EOS reached + bool is_EOS() const { + return eof_; + } + +protected: + /// @brief Read continuous chunk of data from the stream + /// @param[in] ptr Pointer to the buffer to store the data + /// @param[in] pitch Pitch in the buffer + /// @param[in] b_width Width of the blob + /// @param[in] b_height Height of the blob + void read_blob(uint8_t* ptr, uint32_t pitch, uint16_t b_width, uint16_t b_height) { + for (uint16_t i = 0; i < b_height; i++) { + ifl_.read(reinterpret_cast(ptr + i * pitch), b_width); + if (ifl_.gcount() != b_width) + eof_ = true; + } + } + /// @brief Width of frame. + uint16_t width_; + /// @brief Height of frame. + uint16_t heigth_; + /// @brief Color format of frame. + color_format_fourcc format_; + /// @brief File handle. + std::ifstream& ifl_; + /// @brief End of stream flag. + bool eof_; +}; + +/// @brief File based reder of uncomressed frames +class raw_frame_file_reader_by_name : public frame_source_reader { +public: + /// @brief Default ctor + /// @param[in] width Width of the frames. + /// @param[in] heigth Heigh of the frames. + /// @param[in] format Color format of the frames. + /// @param[in] ifl Input stream to read from. + raw_frame_file_reader_by_name(uint16_t width, + uint16_t heigth, + color_format_fourcc format, + const std::string& name) + : frame_source_reader(), + width_(width), + heigth_(heigth), + format_(format), + eof_(false) { + if_.open(name, std::ios_base::in | std::ios_base::binary); + if (!if_) { + throw file_exception(std::string("Couldn't open ") + name); + } + if (if_.fail()) { + throw file_exception(std::string("Error opening ") + name); + } + } + + /// @brief Default dtor + virtual ~raw_frame_file_reader_by_name() {} + + /// @brief Read and store portion of data into the @p bitstream object + /// @param[out] frame data storage + /// @return True if data was read + virtual bool get_data(std::shared_ptr frame) { + auto [info, data] = frame->map(memory_access::write); + + /// @todo verify buffer avialability + uint32_t pitch = 0; + switch (format_) { + case oneapi::vpl::color_format_fourcc::i420: { + pitch = data.get_pitch(); + auto [Y, U, V] = data.get_plane_ptrs_3(); + + // read luminance plane (Y) + read_blob(Y, pitch, width_, heigth_); + + // read chrominance (U, V) + read_blob(U, pitch / 2, width_ / 2, heigth_ / 2); + read_blob(V, pitch / 2, width_ / 2, heigth_ / 2); + break; + } + case oneapi::vpl::color_format_fourcc::nv12: { + pitch = data.get_pitch(); + auto [Y, UV] = data.get_plane_ptrs_2(); + + // read luminance plane (Y) + read_blob(Y, pitch, width_, heigth_); + + // read chrominance (UV) + read_blob(UV, pitch, width_, heigth_ / 2); + break; + } + case oneapi::vpl::color_format_fourcc::bgra: { + pitch = data.get_pitch(); + auto [R, G, B, A] = data.get_plane_ptrs_4(); + + read_blob(B, pitch, width_ * 4, heigth_); + } + default: + throw base_exception("raw_frame_file_reader_by_name unsupported format", + MFX_ERR_NOT_IMPLEMENTED); + } + frame->unmap(); + return !eof_; + } + + /// @brief Checks and retrieve end of stream status + /// @return True if EOS reached + bool is_EOS() const { + return eof_; + } + +protected: + /// @brief Reads continiouse chunk of data from the stream + /// @param[in] ptr Pointer to the buffere to store the data + /// @param[in] pitch Pitch in the buffer + /// @param[in] b_width Width of the blob + /// @param[in] b_height Height of the blob + void read_blob(uint8_t* ptr, uint32_t pitch, uint16_t b_width, uint16_t b_height) { + for (uint16_t i = 0; i < b_height; i++) { + if_.read(reinterpret_cast(ptr + i * pitch), b_width); + if (if_.gcount() != b_width) + eof_ = true; + } + } + /// @brief Width of frame. + uint16_t width_; + /// @brief Height of frame. + uint16_t heigth_; + /// @brief Color format of frame. + color_format_fourcc format_; + /// @brief File handle + std::ifstream if_; + /// @brief End of stream flag. + bool eof_; +}; + +/// @brief Interface for the bitstream source data reader +class bitstream_source_reader : public source_reader { +public: + /// @brief Default ctor + bitstream_source_reader() {} + + /// @brief Default dtor + virtual ~bitstream_source_reader() {} + + /// @brief Read and store portion of data into the @p bitstream object + /// @param[out] bits data storage + /// @return True if data was read + virtual bool get_data(bitstream_as_src* bits) = 0; +}; + +/// @brief File based source data reader +class bitstream_file_reader : public bitstream_source_reader { +public: + /// @brief Constructs reader with given file handle + /// @param[in] ifl Reference to the file handle + explicit bitstream_file_reader(std::ifstream& ifl) : bitstream_source_reader(), if_(ifl) {} + + /// @brief Read and store portion of data into the @p bitstream object + /// @param[out] bits data storage + /// @return True if data was read + bool get_data(bitstream_as_src* bits) { + auto lambda = [&](uint8_t* ptr, uint32_t max, bool& eos) { + if_.read(reinterpret_cast(ptr), max); + if (if_.eof()) + eos = true; + return (uint32_t)if_.gcount(); + }; + bits->pull_in(lambda); + return true; + } + + /// @brief Checks and retrieve end of stream status + /// @return True if EOS reached + bool is_EOS() const { + return if_.eof(); + } + +protected: + /// @brief File handle + std::ifstream& if_; +}; + +class bitstream_file_reader_name : public bitstream_source_reader { +public: + /// @brief Constructs reader with given file handle + /// @param[in] ifl Reference to the file handle + explicit bitstream_file_reader_name(std::string& name) : bitstream_source_reader() { + if_.open(name, std::ios_base::in | std::ios_base::binary); + if (!if_) { + throw file_exception(std::string("Couldn't open ") + name); + } + if (if_.fail()) { + throw file_exception(std::string("Error opening ") + name); + } + } + + /// @brief Read and store portion of data into the @p bitstream object + /// @param[out] bits data storage + /// @return True if data was read + bool get_data(bitstream_as_src* bits) { + auto lambda = [&](uint8_t* ptr, uint32_t max, bool& eos) { + if_.read(reinterpret_cast(ptr), max); + if (if_.eof()) + eos = true; + return (uint32_t)if_.gcount(); + }; + bits->pull_in(lambda); + return true; + } + + /// @brief Checks and retrieve end of stream status + /// @return True if EOS reached + bool is_EOS() const { + return if_.eof(); + } + +protected: + /// @brief File handle + std::ifstream if_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/stat.hpp b/api/vpl/preview/stat.hpp new file mode 100644 index 00000000..9f871be0 --- /dev/null +++ b/api/vpl/preview/stat.hpp @@ -0,0 +1,147 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include "vpl/mfxstructures.h" +namespace oneapi { +namespace vpl { + +/// @brief Interface for the component's (session) run-time statistic +class stat { +public: + /// @brief Default ctor + stat() {} + + /// @brief Default dtor + virtual ~stat() {} + + /// @brief Retrieves number of processed frames + /// @return Number of processed frames + virtual uint32_t get_num_frame() const = 0; + + /// @brief Retrieves number of cached frames + /// @return Number of cached frames + virtual uint32_t get_num_cached_frame() const = 0; +}; + +/// @brief Decoder's session run-time statistic +class decode_stat : public stat { +public: + /// @brief Default ctor + decode_stat() : stat(), stat_() {} + + /// @brief Default dtor + virtual ~decode_stat() {} + + /// @brief Retrieves number of processed frames + /// @return Number of processed frames + virtual uint32_t get_num_frame() const { + return stat_.NumFrame; + } + + /// @brief Retrieves number of cached frames + /// @return Number of cached frames + virtual uint32_t get_num_cached_frame() const { + return stat_.NumCachedFrame; + } + + /// @brief Retrieves number of errors recovered + /// @return Number of errors recovered + virtual uint32_t get_num_error() const { + return stat_.NumError; + } + + /// @brief Retrieves number of skipped frames + /// @return Number of skipped frames + virtual uint32_t get_num_skipped_frame() const { + return stat_.NumSkippedFrame; + } + + /// @brief Retrieves raw data pointer + /// @return Raw data pointer + mfxDecodeStat* get_raw() { + return &(this->stat_); + } + +protected: + /// @brief Raw statistic data + mfxDecodeStat stat_; +}; + +/// @brief Encoder's session run-time statistic +class encode_stat : public stat { +public: + /// @brief Default ctor + encode_stat() : stat(), stat_() {} + + /// @brief Default dtor + virtual ~encode_stat() {} + + /// @brief Retrieves number of processed frames + /// @return Number of processed frames + virtual uint32_t get_num_frame() const { + return stat_.NumFrame; + } + + /// @brief Retrieves number of cached frames + /// @return Number of cached frames + virtual uint32_t get_num_cached_frame() const { + return stat_.NumCachedFrame; + } + + /// @brief Retrieves number of bits for all encoded frames + /// @return Number of bits for all encoded frames + virtual uint64_t get_num_bit() const { + return stat_.NumBit; + } + + /// @brief Retrieves raw data pointer + /// @return Raw data pointer + mfxEncodeStat* get_raw() { + return &(this->stat_); + } + +protected: + /// @brief Raw statistic data + mfxEncodeStat stat_; +}; + +/// @brief VPP's session run-time statistic +class vpp_stat : public stat { +public: + /// @brief Default ctor + vpp_stat() : stat(), stat_() {} + + /// @brief Default dtor + virtual ~vpp_stat() {} + + /// @brief Retrieves number of processed frames + /// @return Number of processed frames + virtual uint32_t get_num_frame() const { + return stat_.NumFrame; + } + + /// @brief Retrieves number of cached frames + /// @return Number of cached frames + virtual uint32_t get_num_cached_frame() const { + return stat_.NumCachedFrame; + } + + /// @brief Retrieves raw data pointer + /// @return Raw data pointer + mfxVPPStat* get_raw() { + return &(this->stat_); + } + +protected: + /// @brief Raw statistic data + mfxVPPStat stat_; +}; + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/video_param.hpp b/api/vpl/preview/video_param.hpp new file mode 100644 index 00000000..8d1f62b4 --- /dev/null +++ b/api/vpl/preview/video_param.hpp @@ -0,0 +1,775 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include +#include +#include +#include + +#include "vpl/preview/detail/string_helpers.hpp" + +namespace oneapi { +namespace vpl { + +#define DECLARE_MEMBER_ACCESS(father, type, name) \ + /*! @brief Returns name value. */ \ + /*! @return name value. */ \ + type get_##name() const { \ + return param_.name; \ + } \ + /*! @brief Sets name value. */ \ + /*! @param[in] name Value. */ \ + /*! @return Reference to the instance. */ \ + father &set_##name(type name) { \ + param_.name = name; \ + return *this; \ + } + +#define DECLARE_INNER_MEMBER_ACCESS(father, type, parent, name) \ + /*! @brief Returns name value. */ \ + /*! @return name value. */ \ + type get_##name() const { \ + return param_.parent.name; \ + } \ + /*! @brief Sets name value. */ \ + /*! @param[in] name Value. */ \ + /*! @return Reference to the instance. */ \ + father &set_##name(type name) { \ + param_.parent.name = name; \ + return *this; \ + } + +#define DECLARE_INNER_MEMBER_ARRAY_ACCESS(father, type, size, parent, name) \ + /*! @brief Returns name value. */ \ + /*! @return name value. */ \ + auto get_##name() const { \ + return param_.parent.name; \ + } \ + /*! @brief Sets name value. */ \ + /*! @param[in] name Value. */ \ + /*! @return Reference to the instance. */ \ + father &set_##name(type name[size]) { \ + std::copy(name, name + size, param_.parent.name); \ + return *this; \ + } + +/// @brief Holds general video params applicable for all kind of sessions. +class video_param { +public: + /// @brief Constructs params and initialize them with default values. + video_param() : param_() {} + video_param(const video_param ¶m) : param_(param.param_) { + clear_extension_buffers(); + } + + video_param& operator=(const video_param& other){ + param_ = other.param_; + clear_extension_buffers(); + return *this; + } + + /// @brief Dtor + virtual ~video_param() { + param_ = {}; + } + +public: + /// @brief Returns pointer to raw data + /// @return Pointer to raw data + mfxVideoParam *getMfx() { + return ¶m_; + } + +public: + DECLARE_MEMBER_ACCESS(video_param, uint32_t, AllocId) + DECLARE_MEMBER_ACCESS(video_param, uint16_t, AsyncDepth) + DECLARE_MEMBER_ACCESS(video_param, uint16_t, Protected) + + /// @brief Returns i/o memory pattern value. + /// @return i/o memory pattern value. + io_pattern get_IOPattern() const { + return (io_pattern)param_.IOPattern; + } + + /// @brief Sets i/o memory pattern value. + /// @param[in] IOPattern i/o memory pattern. + /// @return Reference to this object + video_param &set_IOPattern(io_pattern IOPattern) { + param_.IOPattern = (uint32_t)IOPattern; + return *this; + } + + /// @brief Attaches extension buffers to the video params + /// @param[in] buffer Array of extension buffers + /// @param[in] num Number of extension buffers + /// @return Reference to this object + video_param &set_extension_buffers(mfxExtBuffer **buffer, uint16_t num) { + param_.ExtParam = buffer; + param_.NumExtParam = num; + return *this; + } + + /// @brief Clear extension buffers from the video params + /// @param[in] buffer Array of extension buffers + /// @param[in] num Number of extension buffers + /// @return Reference to this object + video_param &clear_extension_buffers() { + param_.ExtParam = nullptr; + param_.NumExtParam = 0; + return *this; + } + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] p Referebce to the video_param instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const video_param &p); + +protected: + /// @brief Raw data + mfxVideoParam param_; +}; + +inline std::ostream &operator<<(std::ostream &out, const video_param &p) { + out << "Base:" << std::endl; + out << detail::space(detail::INTENT, out, "AllocId = ") << p.param_.AllocId << std::endl; + out << detail::space(detail::INTENT, out, "AsyncDepth = ") + << detail::NotSpecifyed0(p.param_.AsyncDepth) << std::endl; + out << detail::space(detail::INTENT, out, "Protected = ") << p.param_.Protected << std::endl; + out << detail::space(detail::INTENT, out, "IOPattern = ") + << detail::IOPattern2String(p.param_.IOPattern) << std::endl; + return out; +} + +class codec_video_param; +class vpp_video_param; + +/// @brief Holds general frame related params. +class frame_info { +public: + /// @brief Default ctor. + frame_info() : param_() {} + + /// @brief Copy ctor. + /// @param[in] other another object to use as data source + frame_info(const frame_info &other) { + param_ = other.param_; + } + + /// @brief Constructs object from the raw data. + /// @param[in] other another object to use as data source + explicit frame_info(const mfxFrameInfo &other) { + param_ = other; + } + + /// @brief Copy operator. + /// @param[in] other another object to use as data source + /// @returns Reference to this object + frame_info &operator=(const frame_info &other) { + param_ = other.param_; + return *this; + } + + DECLARE_MEMBER_ACCESS(frame_info, uint16_t, BitDepthLuma) + DECLARE_MEMBER_ACCESS(frame_info, uint16_t, BitDepthChroma) + DECLARE_MEMBER_ACCESS(frame_info, uint16_t, Shift) + DECLARE_MEMBER_ACCESS(frame_info, mfxFrameId, FrameId) + + /// @brief Returns color format fourCC value. + /// @return color format fourCC value. + color_format_fourcc get_FourCC() const { + return (color_format_fourcc)param_.FourCC; + } + + /// @brief Sets color format fourCC value. + /// @param[in] FourCC color format fourCC. + /// @return Reference to this object + frame_info &set_FourCC(color_format_fourcc FourCC) { + param_.FourCC = (uint32_t)FourCC; + return *this; + } + + /// @todo below group valid for formats != P8 + + /// @brief Returns frame size. + /// @return Pair of width and height. + auto get_frame_size() const { + return std::pair(param_.Width, param_.Height); + } + + /// @brief Sets frame size value. + /// @param[in] size pair of width and height. + /// @return Reference to this object + frame_info &set_frame_size(std::pair size) { + param_.Width = std::get<0>(size); + param_.Height = std::get<1>(size); + return *this; + } + + /// @brief Returns ROI. + /// @return Two pairs: pair of left corner and pair of size. + auto get_ROI() const { + return std::pair(std::pair(param_.CropX, param_.CropY), + std::pair(param_.CropW, param_.CropH)); + } + + /// @brief Sets ROI. + /// @param[in] roi Two pairs: pair of left corner and pair of size. + /// @return Reference to this object + frame_info &set_ROI( + std::pair, std::pair> roi) { + param_.CropX = std::get<0>(std::get<0>(roi)); + param_.CropY = std::get<1>(std::get<0>(roi)); + + param_.CropW = std::get<0>(std::get<1>(roi)); + param_.CropH = std::get<1>(std::get<1>(roi)); + return *this; + } + + /// @todo below method is valid for P8 format only + DECLARE_MEMBER_ACCESS(frame_info, uint64_t, BufferSize) + + /// @brief Returns frame rate value. + /// @return Pair of numerator and denominator. + auto get_frame_rate() const { + return std::pair(param_.FrameRateExtN, param_.FrameRateExtD); + } + + /// @brief Sets frame rate value. + /// @param[in] rate pair of numerator and denominator. + /// @return Reference to this object + frame_info &set_frame_rate(std::pair rate) { + param_.FrameRateExtN = std::get<0>(rate); + param_.FrameRateExtD = std::get<1>(rate); + return *this; + } + + /// @brief Returns aspect ratio. + /// @return Pair of width and height of aspect ratio. + auto get_aspect_ratio() const { + return std::pair(param_.AspectRatioW, param_.AspectRatioH); + } + + /// @brief Sets aspect ratio. + /// @param[in] ratio pair of width and height of aspect ratio. + /// @return Reference to this object + frame_info &set_aspect_ratio(std::pair ratio) { + param_.AspectRatioW = std::get<0>(ratio); + param_.AspectRatioH = std::get<1>(ratio); + return *this; + } + + /// @brief Returns picture structure value. + /// @return picture structure value. + pic_struct get_PicStruct() const { + return (pic_struct)param_.PicStruct; + } + + /// @brief Sets picture structure value. + /// @param[in] PicStruct picture structure. + /// @return Reference to this object + frame_info &set_PicStruct(pic_struct PicStruct) { + param_.PicStruct = (uint16_t)PicStruct; + return *this; + } + + /// @brief Returns chroma format value. + /// @return chroma format value. + chroma_format_idc get_ChromaFormat() const { + return (chroma_format_idc)param_.ChromaFormat; + } + + /// @brief Sets chroma format value. + /// @param[in] ChromaFormat chroma format. + /// @return Reference to this object + frame_info &set_ChromaFormat(chroma_format_idc ChromaFormat) { + param_.ChromaFormat = (uint32_t)ChromaFormat; + return *this; + } + + /// @brief Friend class + friend class codec_video_param; + /// @brief Friend class + friend class vpp_video_param; + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] p Reference to the codec_video_param instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const codec_video_param &p); + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] v Reference to the vpp_video_param instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const vpp_video_param &v); + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] f Reference to the frame_info instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const frame_info &f); + + /// @brief Provides raw data. + /// @return Raw data. + mfxFrameInfo operator()() const { + return param_; + } + +protected: + /// @brief Raw data + mfxFrameInfo param_; +}; + +inline std::ostream &operator<<(std::ostream &out, const frame_info &f) { + out << detail::space(detail::INTENT, out, "BitDepthLuma = ") << f.param_.BitDepthLuma + << std::endl; + out << detail::space(detail::INTENT, out, "BitDepthChroma = ") << f.param_.BitDepthChroma + << std::endl; + out << detail::space(detail::INTENT, out, "Shift = ") + << detail::NotSpecifyed0(f.param_.Shift) << std::endl; + out << detail::space(detail::INTENT, out, "Color Format = ") + << detail::FourCC2String(f.param_.FourCC) << std::endl; + if (f.param_.FourCC == MFX_FOURCC_P8) { + out << detail::space(detail::INTENT, out, "BufferSize = ") << f.param_.BufferSize + << std::endl; + } + else { + out << detail::space(detail::INTENT, out, "Size [W,H] = [") << f.param_.Width << "," + << f.param_.Height << "]" << std::endl; + out << detail::space(detail::INTENT, out, "ROI [X,Y,W,H] = [") << f.param_.CropX << "," + << f.param_.CropY << "," << f.param_.CropW << "," << f.param_.CropH << "]" << std::endl; + } + + out << detail::space(detail::INTENT, out, "FrameRate [N:D]= ") + << detail::NotSpecifyed0(f.param_.FrameRateExtN) << ":" + << detail::NotSpecifyed0(f.param_.FrameRateExtD) << std::endl; + + if (0 == f.param_.AspectRatioW && 0 == f.param_.AspectRatioH) { + out << detail::space(detail::INTENT, out, "AspecRato [W,H]= [") << "Unset" + << "]" << std::endl; + } + else { + out << detail::space(detail::INTENT, out, "AspecRato [W,H]= [") << f.param_.AspectRatioW + << "," << f.param_.AspectRatioH << "]" << std::endl; + } + + out << detail::space(detail::INTENT, out, "PicStruct = ") + << detail::PicStruct2String(f.param_.PicStruct) << std::endl; + out << detail::space(detail::INTENT, out, "ChromaFormat = ") + << detail::ChromaFormat2String(f.param_.ChromaFormat) << std::endl; + + return out; +} + +/// @brief Holds general frame related params. +class frame_data { +public: + /// @brief Default ctor. + frame_data() : param_() {} + + /// @brief Copy ctor. + /// @param[in] other another object to use as data source + frame_data(const frame_data &other) { + param_ = other.param_; + } + + /// @brief Constructs object from the raw data. + /// @param[in] other another object to use as data source + explicit frame_data(const mfxFrameData &other) { + param_ = other; + } + + /// @brief Copy operator. + /// @param[in] other another object to use as data source + /// @return Reference to this object + frame_data &operator=(const frame_data &other) { + param_ = other.param_; + return *this; + } + + DECLARE_MEMBER_ACCESS(frame_data, uint16_t, MemType) + + /// @brief Returns pitch value. + /// @return Pitch value. + uint32_t get_pitch() const { + return ((uint32_t)param_.PitchHigh << 16) | (uint32_t)(uint32_t)param_.PitchLow; + } + + /// @brief Sets pitch value. + /// @param[in] pitch Pitch. + void set_pitch(uint32_t pitch) { + param_.PitchHigh = (uint16_t)(pitch >> 16); + param_.PitchLow = (uint16_t)(pitch & 0xFFFF); + } + + DECLARE_MEMBER_ACCESS(frame_data, uint64_t, TimeStamp) + DECLARE_MEMBER_ACCESS(frame_data, uint32_t, FrameOrder) + DECLARE_MEMBER_ACCESS(frame_data, uint16_t, Locked) + DECLARE_MEMBER_ACCESS(frame_data, uint16_t, Corrupted) + DECLARE_MEMBER_ACCESS(frame_data, uint16_t, DataFlag) + + /// @brief Gets pointer for formats with 1 plane. + /// @return Pointer for formats with 1 plane. + auto get_plane_ptrs_1() const { + return param_.R; + } + + /// @brief Gets pointer for formats with 2 planes. + /// @return Pointers for formats with 2 planes. Pointers for planes layout is: Y, UV. + auto get_plane_ptrs_2() const { + return std::pair(param_.R, param_.G); + } + + /// @brief Gets pointer for formats with 3 planes. + /// @return Pointers for formats with 3 planes. Pointers for planes layout is: R, G, B or Y, U, V. + auto get_plane_ptrs_3() const { + return std::make_tuple(param_.R, param_.G, param_.B); + } + + /// @brief Gets pointer for formats with 4 planes. + /// @return Pointers for formats with 4 planes. Pointers for planes layout is: R, G, B, A. + auto get_plane_ptrs_4() const { + return std::make_tuple(param_.R, param_.G, param_.B, param_.A); + } + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] f Reference to the frame_data instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const frame_data &f); + +protected: + /// @brief Raw data + mfxFrameData param_; +}; + +inline std::ostream &operator<<(std::ostream &out, const frame_data &f) { + out << detail::space(detail::INTENT, out, "MemType = ") + << detail::MemType2String(f.param_.MemType) << std::endl; + out << detail::space(detail::INTENT, out, "PitchHigh = ") << f.param_.PitchHigh << std::endl; + out << detail::space(detail::INTENT, out, "PitchLow = ") << f.param_.PitchLow << std::endl; + out << detail::space(detail::INTENT, out, "TimeStamp = ") + << detail::TimeStamp2String(static_cast(f.param_.TimeStamp)) << std::endl; + out << detail::space(detail::INTENT, out, "FrameOrder = ") << f.param_.FrameOrder << std::endl; + out << detail::space(detail::INTENT, out, "Locked = ") << f.param_.Locked << std::endl; + out << detail::space(detail::INTENT, out, "Corrupted = ") + << detail::Corruption2String(f.param_.Corrupted) << std::endl; + out << detail::space(detail::INTENT, out, "DataFlag = ") + << detail::TimeStamp2String(f.param_.DataFlag) << std::endl; + + return out; +} + +/// @brief Holds general codec-specific params applicable for any decoder and encoder. +class codec_video_param : public video_param { +protected: + /// @brief Constructs params and initialize them with default values. + codec_video_param() : video_param() {} + codec_video_param(const codec_video_param ¶m) : video_param(param) {} + codec_video_param& operator=(const codec_video_param ¶m){ + video_param::operator=(param); + return *this; + } + +public: + DECLARE_INNER_MEMBER_ACCESS(codec_video_param, uint16_t, mfx, LowPower); + DECLARE_INNER_MEMBER_ACCESS(codec_video_param, uint16_t, mfx, BRCParamMultiplier); + + /// @brief Returns codec fourCC value. + /// @return codec fourCC value. + codec_format_fourcc get_CodecId() const { + return (codec_format_fourcc)param_.mfx.CodecId; + } + + /// @brief Sets codec fourCC value. + /// @param[in] CodecID codec fourCC. + /// @return Reference to this object + codec_video_param &set_CodecId(codec_format_fourcc CodecID) { + param_.mfx.CodecId = (uint32_t)CodecID; + return *this; + } + + DECLARE_INNER_MEMBER_ACCESS(codec_video_param, uint16_t, mfx, CodecProfile); + DECLARE_INNER_MEMBER_ACCESS(codec_video_param, uint16_t, mfx, CodecLevel); + DECLARE_INNER_MEMBER_ACCESS(codec_video_param, uint16_t, mfx, NumThread); + + /// @brief Returns frame_info value. + /// @return frame info value. + frame_info get_frame_info() const { + return frame_info(param_.mfx.FrameInfo); + } + + /// @brief Sets name value. + /// @param[in] name Value. + /// @return Reference to this object + codec_video_param &set_frame_info(frame_info name) { + param_.mfx.FrameInfo = name(); + return *this; + } + + /// Friend operator to print out state of the class in human readable form. + friend std::ostream &operator<<(std::ostream &out, const codec_video_param &p); +}; + +inline std::ostream &operator<<(std::ostream &out, const codec_video_param &p) { + const video_param &v = dynamic_cast(p); + out << v; + out << "Codec:" << std::endl; + out << detail::space(detail::INTENT, out, "LowPower = ") + << detail::TriState2String(p.param_.mfx.LowPower) << std::endl; + out << detail::space(detail::INTENT, out, "BRCParamMultiplier = ") + << p.param_.mfx.BRCParamMultiplier << std::endl; + out << detail::space(detail::INTENT, out, "CodecId = ") + << detail::FourCC2String(p.param_.mfx.CodecId) << std::endl; + out << detail::space(detail::INTENT, out, "CodecProfile = ") << p.param_.mfx.CodecProfile + << std::endl; + out << detail::space(detail::INTENT, out, "CodecLevel = ") << p.param_.mfx.CodecLevel + << std::endl; + out << detail::space(detail::INTENT, out, "NumThread = ") << p.param_.mfx.NumThread + << std::endl; + out << "FrameInfo:" << std::endl; + out << frame_info(p.param_.mfx.FrameInfo) << std::endl; + + return out; +} + +/// @brief Holds encoder specific params. +class encoder_video_param : public codec_video_param { +public: + /// @brief Constructs params and initialize them with default values. + encoder_video_param() : codec_video_param() {} + + /// @brief Returns TargetUsage value. + /// @return TargetUsage Target Usage value. + target_usage get_TargetUsage() const { + return (target_usage)param_.mfx.TargetUsage; + } + + /// @brief Sets Target Usage value. + /// @param[in] TargetUsage Target Usage. + /// @return Reference to this object + encoder_video_param &set_TargetUsage(target_usage TargetUsage) { + param_.mfx.CodecId = (uint32_t)TargetUsage; + return *this; + } + + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, GopPicSize); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint32_t, mfx, GopRefDist); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, GopOptFlag); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, IdrInterval); + + /// @brief Returns rate control method value. + /// @return rate control method value. + rate_control_method get_RateControlMethod() const { + return (rate_control_method)param_.mfx.RateControlMethod; + } + + /// @brief Sets rate control method value. + /// @param[in] RateControlMethod rate control method. + /// @return Reference to this object + encoder_video_param &set_RateControlMethod(rate_control_method RateControlMethod) { + param_.mfx.RateControlMethod = (uint32_t)RateControlMethod; + return *this; + } + + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, InitialDelayInKB); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, QPI); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, Accuracy); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, BufferSizeInKB); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, TargetKbps); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, QPP); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, ICQQuality); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, MaxKbps); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, QPB); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, Convergence); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, NumSlice); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, NumRefFrame); + DECLARE_INNER_MEMBER_ACCESS(encoder_video_param, uint16_t, mfx, EncodedOrder); + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] e Reference to the encoder_video_param instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const encoder_video_param &e); +}; + +inline std::ostream &operator<<(std::ostream &out, const encoder_video_param &e) { + const codec_video_param &c = dynamic_cast(e); + out << c; + out << "Encoder:" << std::endl; + out << detail::space(detail::INTENT, out, "TargetUsage = ") + << detail::NotSpecifyed0(e.param_.mfx.TargetUsage) << std::endl; + out << detail::space(detail::INTENT, out, "GopPicSize = ") + << detail::NotSpecifyed0(e.param_.mfx.GopPicSize) << std::endl; + out << detail::space(detail::INTENT, out, "GopRefDist = ") + << detail::NotSpecifyed0(e.param_.mfx.GopRefDist) << std::endl; + out << detail::space(detail::INTENT, out, "GopOptFlag = ") + << detail::GopOptFlag2String(e.param_.mfx.GopOptFlag) << std::endl; + out << detail::space(detail::INTENT, out, "IdrInterval = ") << e.param_.mfx.IdrInterval + << std::endl; + out << detail::space(detail::INTENT, out, "RateControlMethod = ") + << detail::RateControlMethod2String(e.param_.mfx.RateControlMethod) << std::endl; + out << detail::space(detail::INTENT, out, "InitialDelayInKB = ") + << e.param_.mfx.InitialDelayInKB << std::endl; + out << detail::space(detail::INTENT, out, "QPI = ") << e.param_.mfx.QPI + << std::endl; + out << detail::space(detail::INTENT, out, "Accuracy = ") << e.param_.mfx.Accuracy + << std::endl; + out << detail::space(detail::INTENT, out, "BufferSizeInKB = ") << e.param_.mfx.BufferSizeInKB + << std::endl; + out << detail::space(detail::INTENT, out, "TargetKbps = ") << e.param_.mfx.TargetKbps + << std::endl; + out << detail::space(detail::INTENT, out, "QPP = ") << e.param_.mfx.QPP + << std::endl; + out << detail::space(detail::INTENT, out, "ICQQuality = ") << e.param_.mfx.ICQQuality + << std::endl; + out << detail::space(detail::INTENT, out, "MaxKbps = ") << e.param_.mfx.MaxKbps + << std::endl; + out << detail::space(detail::INTENT, out, "QPB = ") << e.param_.mfx.QPB + << std::endl; + out << detail::space(detail::INTENT, out, "Convergence = ") << e.param_.mfx.Convergence + << std::endl; + out << detail::space(detail::INTENT, out, "NumSlice = ") + << detail::NotSpecifyed0(e.param_.mfx.NumSlice) << std::endl; + out << detail::space(detail::INTENT, out, "NumRefFrame = ") + << detail::NotSpecifyed0(e.param_.mfx.NumRefFrame) << std::endl; + out << detail::space(detail::INTENT, out, "EncodedOrder = ") + << detail::Boolean2String(e.param_.mfx.EncodedOrder) << std::endl; + + return out; +} + +/// @brief Holds decoder specific params. +class decoder_video_param : public codec_video_param { +public: + /// @brief Constructs params and initialize them with default values. + decoder_video_param() : codec_video_param() {} + explicit decoder_video_param(const codec_video_param &other) : codec_video_param(other) {} + + DECLARE_INNER_MEMBER_ACCESS(decoder_video_param, uint16_t, mfx, DecodedOrder); + DECLARE_INNER_MEMBER_ACCESS(decoder_video_param, uint16_t, mfx, ExtendedPicStruct); + DECLARE_INNER_MEMBER_ACCESS(decoder_video_param, uint32_t, mfx, TimeStampCalc); + DECLARE_INNER_MEMBER_ACCESS(decoder_video_param, uint16_t, mfx, SliceGroupsPresent); + DECLARE_INNER_MEMBER_ACCESS(decoder_video_param, uint16_t, mfx, MaxDecFrameBuffering); + DECLARE_INNER_MEMBER_ACCESS(decoder_video_param, uint16_t, mfx, EnableReallocRequest); + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] d Reference to the decoder_video_param instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const decoder_video_param &d); +}; + +inline std::ostream &operator<<(std::ostream &out, const decoder_video_param &d) { + const codec_video_param &c = dynamic_cast(d); + out << c; + out << "Decoder:" << std::endl; + out << detail::space(detail::INTENT, out, "DecodedOrder = ") + << detail::Boolean2String(d.param_.mfx.DecodedOrder) << std::endl; + + out << detail::space(detail::INTENT, out, "ExtendedPicStruct = ") + << detail::PicStruct2String(d.param_.mfx.ExtendedPicStruct) << std::endl; + + out << detail::space(detail::INTENT, out, "TimeStampCalc = ") + << detail::TimeStampCalc2String(d.param_.mfx.TimeStampCalc) << std::endl; + + out << detail::space(detail::INTENT, out, "SliceGroupsPresent = ") + << detail::Boolean2String(d.param_.mfx.SliceGroupsPresent) << std::endl; + + out << detail::space(detail::INTENT, out, "MaxDecFrameBuffering = ") + << detail::NotSpecifyed0(d.param_.mfx.MaxDecFrameBuffering) << std::endl; + + out << detail::space(detail::INTENT, out, "EnableReallocRequest = ") + << detail::TriState2String(d.param_.mfx.EnableReallocRequest) << std::endl; + + return out; +} + +/// @brief Holds JPEG decoder specific params. +class jpeg_decoder_video_param : public codec_video_param { +public: + /// @brief Constructs params and initialize them with default values. + jpeg_decoder_video_param() : codec_video_param() {} + + DECLARE_INNER_MEMBER_ACCESS(jpeg_decoder_video_param, uint16_t, mfx, JPEGChromaFormat); + DECLARE_INNER_MEMBER_ACCESS(jpeg_decoder_video_param, uint16_t, mfx, Rotation); + DECLARE_INNER_MEMBER_ACCESS(jpeg_decoder_video_param, uint32_t, mfx, JPEGColorFormat); + DECLARE_INNER_MEMBER_ACCESS(jpeg_decoder_video_param, uint16_t, mfx, InterleavedDec); + DECLARE_INNER_MEMBER_ARRAY_ACCESS(jpeg_decoder_video_param, uint8_t, 4, mfx, SamplingFactorH); + DECLARE_INNER_MEMBER_ARRAY_ACCESS(jpeg_decoder_video_param, uint8_t, 4, mfx, SamplingFactorV); +}; + +/// @brief Holds JPEG encoder specific params. +class jpeg_encoder_video_param : public codec_video_param { +public: + /// @brief Constructs params and initialize them with default values. + jpeg_encoder_video_param() : codec_video_param() {} + + DECLARE_INNER_MEMBER_ACCESS(jpeg_encoder_video_param, uint16_t, mfx, Interleaved); + DECLARE_INNER_MEMBER_ACCESS(jpeg_encoder_video_param, uint16_t, mfx, Quality); + DECLARE_INNER_MEMBER_ACCESS(jpeg_encoder_video_param, uint32_t, mfx, RestartInterval); +}; + +/// @brief Holds VPP specific params. +class vpp_video_param : public video_param { +public: + /// @brief Constructs params and initialize them with default values. + vpp_video_param() : video_param() {} + +public: + /// @brief Returns frame_info in value. + /// @return frame info in value. + frame_info get_in_frame_info() const { + return frame_info(param_.vpp.In); + } + + /// @brief Sets name value. + /// @param[in] name Value. + /// @return Reference to this object + vpp_video_param &set_in_frame_info(frame_info name) { + param_.vpp.In = name(); + return *this; + } + + /// @brief Returns frame_info out value. + /// @return frame info out value. + frame_info get_out_frame_info() const { + return frame_info(param_.vpp.Out); + } + + /// @brief Sets name value. + /// @param[in] name Value. + /// @return Reference to this object + vpp_video_param &set_out_frame_info(frame_info name) { + param_.vpp.Out = name(); + return *this; + } + + /// @brief Friend operator to print out state of the class in human readable form. + /// @param[inout] out Reference to the stream to write. + /// @param[in] v Reference to the vpp_video_param instance to dump the state. + /// @return Reference to the stream. + friend std::ostream &operator<<(std::ostream &out, const vpp_video_param &v); +}; + +inline std::ostream &operator<<(std::ostream &out, const vpp_video_param &vpp) { + const video_param &v = dynamic_cast(vpp); + out << v; + + out << "Input FrameInfo:" << std::endl; + out << frame_info(vpp.param_.vpp.In) << std::endl; + + out << "Output FrameInfo:" << std::endl; + out << frame_info(vpp.param_.vpp.Out) << std::endl; + + return out; +} + +} // namespace vpl +} // namespace oneapi diff --git a/api/vpl/preview/vpl.hpp b/api/vpl/preview/vpl.hpp new file mode 100644 index 00000000..c9ee1ec4 --- /dev/null +++ b/api/vpl/preview/vpl.hpp @@ -0,0 +1,25 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#pragma once + +#include "vpl/preview/bitstream.hpp" +#include "vpl/preview/defs.hpp" +#include "vpl/preview/exception.hpp" +#include "vpl/preview/extension_buffer.hpp" +#include "vpl/preview/extension_buffer_list.hpp" +#include "vpl/preview/frame_pool.hpp" +#include "vpl/preview/frame_surface.hpp" +#include "vpl/preview/future.hpp" +#include "vpl/preview/impl_caps.hpp" +#include "vpl/preview/impl_selector.hpp" +#include "vpl/preview/options.hpp" +#include "vpl/preview/payload.hpp" +#include "vpl/preview/property_name.hpp" +#include "vpl/preview/session.hpp" +#include "vpl/preview/source_reader.hpp" +#include "vpl/preview/stat.hpp" +#include "vpl/preview/video_param.hpp" diff --git a/cmake/CompileOptions.cmake b/cmake/CompileOptions.cmake index e1b790fc..ac9aa90e 100644 --- a/cmake/CompileOptions.cmake +++ b/cmake/CompileOptions.cmake @@ -31,3 +31,46 @@ else() set(CMAKE_CXX_FLAGS "-z relro -z now -z noexecstack ${CMAKE_CXX_FLAGS}") add_compile_options("-Wall") endif() + +# Define RelWithDebRT Build Mode +if(MSVC) + set(CMAKE_DEBUG_POSTFIX "d") + set(CMAKE_RELWITHDEBRT_POSTFIX "d") + set(CMAKE_CXX_FLAGS_RELWITHDEBRT + "${CMAKE_CXX_FLAGS_RELEASE}" + CACHE STRING "Flags used by the C++ compiler during RelWithDebRT builds." + FORCE) + set(CMAKE_C_FLAGS_RELWITHDEBRT + "${CMAKE_C_FLAGS_RELEASE}" + CACHE STRING "Flags used by the C compiler during RelWithDebRT builds." + FORCE) + + foreach(build_flag CMAKE_CXX_FLAGS_RELWITHDEBRT CMAKE_C_FLAGS_RELWITHDEBRT) + string(REPLACE "/MDd" "" ${build_flag} "${${build_flag}}") + string(REPLACE "/MTd" "" ${build_flag} "${${build_flag}}") + string(REPLACE "/MD" "" ${build_flag} "${${build_flag}}") + string(REPLACE "/MT" "" ${build_flag} "${${build_flag}}") + set(${build_flag} "${${build_flag}} /MDd /DEBUG:NONE") + endforeach() + + set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBRT + "${CMAKE_EXE_LINKER_FLAGS_RELEASE}" + CACHE STRING + "Flags used for linking binaries during RelWithDebRT builds." FORCE) + set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBRT + "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}" + CACHE + STRING + "Flags used by the shared libraries linker during RelWithDebRT builds." + FORCE) + set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBRT + "${CMAKE_MODULE_LINKER_FLAGS_RELEASE}" + CACHE STRING "Flags used by the linker during RelWithDebRT builds." FORCE) + mark_as_advanced( + CMAKE_CXX_FLAGS_RELWITHDEBRT CMAKE_C_FLAGS_RELWITHDEBRT + CMAKE_EXE_LINKER_FLAGS_RELWITHDEBRT CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBRT) + + # Add RelWithDebRT to avalible config types + set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES};RelWithDebRT") + +endif() diff --git a/cmake/oneAPIInstallDirs.cmake b/cmake/oneAPIInstallDirs.cmake index 184e19bf..2e8ce67b 100644 --- a/cmake/oneAPIInstallDirs.cmake +++ b/cmake/oneAPIInstallDirs.cmake @@ -8,24 +8,67 @@ # Set installation directories # -if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") - set(CMAKE_INSTALL_BINDIR bin32) - set(CMAKE_INSTALL_LIBDIR lib32) -else() - set(CMAKE_INSTALL_BINDIR bin) - set(CMAKE_INSTALL_LIBDIR lib) -endif() - -set(CMAKE_INSTALL_INCLUDEDIR include) -set(CMAKE_INSTALL_DOCDIR documentation) -set(CMAKE_INSTALL_ENVDIR env) -set(CMAKE_INSTALL_MODDIR modulefiles) -set(CMAKE_INSTALL_SYSCHECKDIR sys_check) -set(CMAKE_INSTALL_MODFILEDIR modulefiles) -set(CMAKE_INSTALL_REDISTDIR redist) -set(CMAKE_INSTALL_EXAMPLEDIR examples) -set(CMAKE_INSTALL_LICENSEDIR licensing) -set(CMAKE_INSTALL_TOOLSDIR tools) -set(CMAKE_INSTALL_SYSCONFDIR config) -set(CMAKE_INSTALL_SRCDIR src) -set(CMAKE_INSTALL_PYTHONDIR python/lib) +# See https://cmake.org/cmake/help/latest/module/GNUInstallDirs.html for +# variables GNUInstallDirs exposes. This project commonly uses: +# CMAKE_INSTALL_INCLUDEDIR CMAKE_INSTALL_DOCDIR CMAKE_INSTALL_BINDIR +# CMAKE_INSTALL_LIBDIR +include(GNUInstallDirs) + +if(NOT ONEAPI_INSTALL_BIN32DIR) + if(WIN32) + set(ONEAPI_INSTALL_BIN32DIR "${CMAKE_INSTALL_BINDIR}/x86") + else() + set(ONEAPI_INSTALL_BIN32DIR bin32) + endif() +endif() + +if(NOT ONEAPI_INSTALL_LIB32DIR) + if(WIN32) + set(ONEAPI_INSTALL_LIB32DIR "${CMAKE_INSTALL_LIBDIR}/x86") + else() + set(ONEAPI_INSTALL_LIB32DIR lib32) + endif() +endif() + +if(WIN32 AND "${CMAKE_SIZEOF_VOID_P}" STREQUAL "4") + set(CMAKE_INSTALL_BINDIR ${ONEAPI_INSTALL_BIN32DIR}) + set(CMAKE_INSTALL_LIBDIR ${ONEAPI_INSTALL_LIB32DIR}) +endif() + +if(NOT ONEAPI_INSTALL_ENVDIR) + set(ONEAPI_INSTALL_ENVDIR ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/env) +endif() + +if(NOT ONEAPI_INSTALL_SYSCHECKDIR) + set(ONEAPI_INSTALL_SYSCHECKDIR + ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/sys_check) +endif() +if(NOT ONEAPI_INSTALL_MODFILEDIR) + set(ONEAPI_INSTALL_MODFILEDIR + ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/modulefiles) +endif() +if(NOT ONEAPI_INSTALL_EXAMPLEDIR) + set(ONEAPI_INSTALL_EXAMPLEDIR + ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/examples) +endif() +if(NOT ONEAPI_INSTALL_LICENSEDIR) + set(ONEAPI_INSTALL_LICENSEDIR ${CMAKE_INSTALL_DOCDIR}) +endif() +if(NOT ONEAPI_INSTALL_PYTHONDIR) + set(ONEAPI_INSTALL_PYTHONDIR + ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}/python/lib) +endif() + +foreach( + dir + BIN32DIR + LIB32DIR + ENVDIR + SYSCHECKDIR + MODFILEDIR + EXAMPLEDIR + LICENSEDIR + PYTHONDIR) + gnuinstalldirs_get_absolute_install_dir(ONEAPI_INSTALL_FULL_${dir} + ONEAPI_INSTALL_${dir} ${dir}) +endforeach() diff --git a/dispatcher/CMakeLists.txt b/dispatcher/CMakeLists.txt index edc7e34e..02a84680 100644 --- a/dispatcher/CMakeLists.txt +++ b/dispatcher/CMakeLists.txt @@ -34,9 +34,14 @@ endif() add_definitions(-DMFX_DEPRECATED_OFF) -list(APPEND SOURCES vpl/mfx_dispatcher_vpl.cpp - vpl/mfx_dispatcher_vpl_loader.cpp vpl/mfx_dispatcher_vpl_config.cpp - vpl/mfx_dispatcher_vpl_msdk.cpp) +list( + APPEND + SOURCES + vpl/mfx_dispatcher_vpl.cpp + vpl/mfx_dispatcher_vpl_loader.cpp + vpl/mfx_dispatcher_vpl_config.cpp + vpl/mfx_dispatcher_vpl_log.cpp + vpl/mfx_dispatcher_vpl_msdk.cpp) add_library(${TARGET} SHARED "") @@ -78,26 +83,43 @@ endif() target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) -install( - TARGETS ${TARGET} - # EXPORT mfxTargets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT runtime - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT dev) - -# export(PACKAGE VPL) - -configure_file(cmake/VPLConfig.cmake.in cmake/VPLConfig.cmake @ONLY) -configure_file(cmake/VPLConfigVersion.cmake.in cmake/VPLConfigVersion.cmake - @ONLY) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/VPLConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/cmake/VPLConfigVersion.cmake" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/vpl" - COMPONENT dev) - -configure_file("pkgconfig/vpl.pc.in" "pkgconfig/vpl.pc" @ONLY) -install( - FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/vpl.pc" - DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" - COMPONENT dev) +if(BUILD_DISPATCHER) + install( + TARGETS ${TARGET} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT runtime + NAMELINK_SKIP + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime) +endif() + +if(BUILD_DEV) + install( + TARGETS ${TARGET} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT dev + NAMELINK_ONLY) + if(WIN32) + install(TARGETS ${TARGET} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT dev) + endif() + + configure_file(cmake/VPLConfig.cmake.in cmake/VPLConfig.cmake @ONLY) + configure_file(cmake/VPLConfigVersion.cmake.in cmake/VPLConfigVersion.cmake + @ONLY) + + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/cmake/VPLConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/cmake/VPLConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/vpl" + COMPONENT dev) + + file(RELATIVE_PATH pc_rel_prefix ${CMAKE_INSTALL_FULL_LIBDIR}/pkgconfig + ${CMAKE_INSTALL_PREFIX}) + set(pc_rel_prefix "$\{pcfiledir}/${pc_rel_prefix}") + + configure_file("pkgconfig/vpl.pc.in" "pkgconfig/vpl.pc" @ONLY) + install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/pkgconfig/vpl.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" + COMPONENT dev) +endif() diff --git a/dispatcher/cmake/VPLConfig.cmake.in b/dispatcher/cmake/VPLConfig.cmake.in index d6adaa2a..4678c8e8 100644 --- a/dispatcher/cmake/VPLConfig.cmake.in +++ b/dispatcher/cmake/VPLConfig.cmake.in @@ -14,8 +14,13 @@ set(VPL_INTERFACE_VERSION @API_VERSION_MAJOR@) get_filename_component(_vpl_config_file "${CMAKE_CURRENT_LIST_DIR}/VPLConfig.cmake" REALPATH) get_filename_component(_vpl_config_dir "${_vpl_config_file}" DIRECTORY) -get_filename_component(_vpl_install_prefix "${_vpl_config_dir}/../../.." - REALPATH) +if(WIN32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) + get_filename_component(_vpl_install_prefix "${_vpl_config_dir}/../../../.." + REALPATH) +else() + get_filename_component(_vpl_install_prefix "${_vpl_config_dir}/../../.." + REALPATH) +endif() get_filename_component(VPL_LIB_DIR "${_vpl_install_prefix}/@CMAKE_INSTALL_LIBDIR@" ABSOLUTE) get_filename_component( @@ -39,27 +44,58 @@ set(VPL_dispatcher_FOUND 0) set(vpl_system_name ${CMAKE_SYSTEM_NAME}) if(vpl_system_name STREQUAL "Linux") get_filename_component( - _dispatcher_lib "${VPL_LIB_DIR}/libvpl.so.${VPL_INTERFACE_VERSION}" + _dispatcher_dll "${VPL_LIB_DIR}/libvpl.so.${VPL_INTERFACE_VERSION}" + ABSOLUTE) + get_filename_component( + _dispatcher_debug_dll "${VPL_LIB_DIR}/libvpl.so.${VPL_INTERFACE_VERSION}" ABSOLUTE) elseif(vpl_system_name STREQUAL "Windows") - get_filename_component(_dispatcher_lib "${VPL_BIN_DIR}/libvpl.dll" ABSOLUTE) + get_filename_component(_dispatcher_dll "${VPL_BIN_DIR}/libvpl.dll" ABSOLUTE) + get_filename_component(_dispatcher_debug_dll "${VPL_BIN_DIR}/libvpld.dll" + ABSOLUTE) + get_filename_component(_dispatcher_lib "${VPL_LIB_DIR}/vpl.lib" ABSOLUTE) + get_filename_component(_dispatcher_debug_lib "${VPL_LIB_DIR}/vpld.lib" + ABSOLUTE) else() message(FATAL_ERROR "Unsupported OS name: ${vpl_system_name}") endif() -if(EXISTS "${_dispatcher_lib}") +if(EXISTS "${_dispatcher_dll}" OR EXISTS "${_dispatcher_debug_dll}") if(NOT TARGET VPL::dispatcher) add_library(VPL::dispatcher SHARED IMPORTED) set_target_properties( VPL::dispatcher PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${VPL_INCLUDE_DIR}") - if(EXISTS "${_dispatcher_lib}") - set_target_properties(VPL::dispatcher PROPERTIES IMPORTED_LOCATION - "${_dispatcher_lib}") - if(vpl_system_name STREQUAL "Windows") - set_target_properties( - VPL::dispatcher PROPERTIES IMPORTED_IMPLIB "${VPL_LIB_DIR}/vpl.lib") - endif() + set_target_properties(VPL::dispatcher PROPERTIES IMPORTED_LOCATION_RELEASE + ${_dispatcher_dll}) + set_target_properties( + VPL::dispatcher PROPERTIES IMPORTED_LOCATION_RELWITHDEBINFO + ${_dispatcher_dll}) + set_target_properties( + VPL::dispatcher PROPERTIES IMPORTED_LOCATION_MINSIZEREL + ${_dispatcher_dll}) + + set_target_properties(VPL::dispatcher PROPERTIES IMPORTED_LOCATION_DEBUG + ${_dispatcher_debug_dll}) + set_target_properties( + VPL::dispatcher PROPERTIES IMPORTED_LOCATION_RELWITHDEBRT + ${_dispatcher_debug_dll}) + + if(vpl_system_name STREQUAL "Windows") + set_target_properties(VPL::dispatcher PROPERTIES IMPORTED_IMPLIB_RELEASE + ${_dispatcher_lib}) + set_target_properties( + VPL::dispatcher PROPERTIES IMPORTED_IMPLIB_RELWITHDEBINFO + ${_dispatcher_lib}) + set_target_properties( + VPL::dispatcher PROPERTIES IMPORTED_IMPLIB_MINSIZEREL + ${_dispatcher_lib}) + + set_target_properties(VPL::dispatcher PROPERTIES IMPORTED_IMPLIB_DEBUG + ${_dispatcher_debug_lib}) + set_target_properties( + VPL::dispatcher PROPERTIES IMPORTED_IMPLIB_RELWITHDEBRT + ${_dispatcher_debug_lib}) endif() endif() list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) @@ -69,7 +105,7 @@ elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher) set(VPL_FOUND FALSE) endif() -unset(_dispatcher_lib) +unset(_dispatcher_dll) # VPL::api set(VPL_api_FOUND 0) @@ -82,3 +118,15 @@ if(EXISTS ${VPL_INCLUDE_DIR}) list(APPEND VPL_IMPORTED_TARGETS VPL::api) set(VPL_api_FOUND 1) endif() + +# VPL::cppapi +set(VPL_cppapi_FOUND 0) +if(EXISTS ${VPL_INCLUDE_DIR}) + if(NOT TARGET VPL::cppapi) + add_library(VPL::cppapi INTERFACE IMPORTED) + set_target_properties(VPL::cppapi PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${VPL_INCLUDE_DIR}") + endif() + list(APPEND VPL_IMPORTED_TARGETS VPL::cppapi) + set(VPL_cppapi_FOUND 1) +endif() diff --git a/dispatcher/cmake/VPLConfigVersion.cmake.in b/dispatcher/cmake/VPLConfigVersion.cmake.in index 93f0354c..ae75f578 100644 --- a/dispatcher/cmake/VPLConfigVersion.cmake.in +++ b/dispatcher/cmake/VPLConfigVersion.cmake.in @@ -4,7 +4,7 @@ # SPDX-License-Identifier: MIT # ############################################################################## -set(PACKAGE_VERSION "@PROJECT_VERSION@") +set(PACKAGE_VERSION "@API_VERSION_MAJOR@.@API_VERSION_MINOR@") # Check whether the requested PACKAGE_FIND_VERSION is compatible if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") diff --git a/dispatcher/linux/device_ids.h b/dispatcher/linux/device_ids.h index 73d7110a..410bed50 100644 --- a/dispatcher/linux/device_ids.h +++ b/dispatcher/linux/device_ids.h @@ -54,7 +54,7 @@ enum eMFXHWType { enum eMFXGTConfig { MFX_GT_UNKNOWN = 0, MFX_GT1 = 1, MFX_GT2 = 2, MFX_GT3 = 3, MFX_GT4 = 4 }; typedef struct { - int device_id; + unsigned int device_id; eMFXHWType platform; eMFXGTConfig config; } mfx_device_item; @@ -406,12 +406,12 @@ static const mfx_device_item listLegalDevIDs[] = { }; typedef struct { - int vendor_id; - int device_id; + unsigned int vendor_id; + unsigned int device_id; eMFXHWType platform; } Device; -static inline eMFXHWType get_platform(int device_id) { +static inline eMFXHWType get_platform(unsigned int device_id) { for (unsigned i = 0; i < sizeof(listLegalDevIDs) / sizeof(listLegalDevIDs[0]); ++i) { if (listLegalDevIDs[i].device_id == device_id) { return listLegalDevIDs[i].platform; @@ -435,9 +435,9 @@ static mfxStatus get_devices(std::vector &allDevices) { if (!file) continue; ret = fscanf(file, "%x", &device.vendor_id); + fclose(file); if (ret != 1) continue; - fclose(file); // Filter out non-Intel devices if (device.vendor_id != 0x8086) @@ -448,9 +448,9 @@ static mfxStatus get_devices(std::vector &allDevices) { if (!file) continue; ret = fscanf(file, "%x", &device.device_id); + fclose(file); if (ret != 1) continue; - fclose(file); device.platform = get_platform(device.device_id); diff --git a/dispatcher/pkgconfig/vpl.pc.in b/dispatcher/pkgconfig/vpl.pc.in index 17e16290..b66e3eb5 100644 --- a/dispatcher/pkgconfig/vpl.pc.in +++ b/dispatcher/pkgconfig/vpl.pc.in @@ -1,6 +1,6 @@ -prefix=@CMAKE_INSTALL_PREFIX@ +prefix=@pc_rel_prefix@ exec_prefix=${prefix} -libdir=${prefix}/@CMAKE_INSTALL_LIBDIR@ +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ # oneAPI Video Processing Library (oneVPL) diff --git a/dispatcher/vpl/mfx_dispatcher_vpl.cpp b/dispatcher/vpl/mfx_dispatcher_vpl.cpp index 5c2c609e..e999fc97 100644 --- a/dispatcher/vpl/mfx_dispatcher_vpl.cpp +++ b/dispatcher/vpl/mfx_dispatcher_vpl.cpp @@ -21,6 +21,12 @@ mfxLoader MFXLoad() { return nullptr; } + // initialize logging if appropriate environment variables are set + loaderCtx->InitDispatcherLog(); + + DispatcherLogVPL* dispLog = loaderCtx->GetLogger(); + DISP_LOG_FUNCTION(dispLog); + // search directories for candidate implementations based on search order in // spec mfxStatus sts = loaderCtx->BuildListOfCandidateLibs(); @@ -72,6 +78,9 @@ mfxConfig MFXCreateConfig(mfxLoader loader) { LoaderCtxVPL* loaderCtx = (LoaderCtxVPL*)loader; ConfigCtxVPL* configCtx; + DispatcherLogVPL* dispLog = loaderCtx->GetLogger(); + DISP_LOG_FUNCTION(dispLog); + try { std::unique_ptr pConfigCtx; pConfigCtx.reset(new ConfigCtxVPL{}); @@ -91,13 +100,18 @@ mfxStatus MFXSetConfigFilterProperty(mfxConfig config, const mfxU8* name, mfxVar return MFX_ERR_NULL_PTR; ConfigCtxVPL* configCtx = (ConfigCtxVPL*)config; + LoaderCtxVPL* loaderCtx = configCtx->m_parentLoader; + + DispatcherLogVPL* dispLog = loaderCtx->GetLogger(); + DISP_LOG_FUNCTION(dispLog); mfxStatus sts = configCtx->SetFilterProperty(name, value); + if (sts) + return sts; // update list of valid libraries based on updated set of // mfxConfig properties - LoaderCtxVPL* loaderCtx = configCtx->m_parentLoader; - loaderCtx->UpdateValidImplList(); + sts = loaderCtx->UpdateValidImplList(); return sts; } @@ -113,6 +127,9 @@ mfxStatus MFXEnumImplementations(mfxLoader loader, LoaderCtxVPL* loaderCtx = (LoaderCtxVPL*)loader; + DispatcherLogVPL* dispLog = loaderCtx->GetLogger(); + DISP_LOG_FUNCTION(dispLog); + mfxStatus sts = loaderCtx->QueryImpl(i, format, idesc); return sts; @@ -125,6 +142,9 @@ mfxStatus MFXCreateSession(mfxLoader loader, mfxU32 i, mfxSession* session) { LoaderCtxVPL* loaderCtx = (LoaderCtxVPL*)loader; + DispatcherLogVPL* dispLog = loaderCtx->GetLogger(); + DISP_LOG_FUNCTION(dispLog); + mfxStatus sts = loaderCtx->CreateSession(i, session); return sts; @@ -137,6 +157,9 @@ mfxStatus MFXDispReleaseImplDescription(mfxLoader loader, mfxHDL hdl) { LoaderCtxVPL* loaderCtx = (LoaderCtxVPL*)loader; + DispatcherLogVPL* dispLog = loaderCtx->GetLogger(); + DISP_LOG_FUNCTION(dispLog); + mfxStatus sts = loaderCtx->ReleaseImpl(hdl); return sts; diff --git a/dispatcher/vpl/mfx_dispatcher_vpl.h b/dispatcher/vpl/mfx_dispatcher_vpl.h index d9ca28c7..6432b943 100644 --- a/dispatcher/vpl/mfx_dispatcher_vpl.h +++ b/dispatcher/vpl/mfx_dispatcher_vpl.h @@ -8,6 +8,7 @@ #define DISPATCHER_VPL_MFX_DISPATCHER_VPL_H_ #include +#include #include #include #include @@ -16,6 +17,8 @@ #include "vpl/mfxdispatcher.h" #include "vpl/mfxvideo.h" +#include "./mfx_dispatcher_vpl_log.h" + #if defined(_WIN32) || defined(_WIN64) #include @@ -33,6 +36,7 @@ typedef wchar_t CHAR_TYPE; #include #include #include + #include // use standard char on Linux #define MAKE_STRING(x) x @@ -47,19 +51,14 @@ typedef char CHAR_TYPE; #define MAX_WINDOWS_ADAPTER_ID 3 // check adapterID in range [0,3] +#define MAX_NUM_IMPL_MSDK 4 + #define MAX_VPL_SEARCH_PATH 4096 -// OS-specific environment variables for implementation -// search paths as defined by spec -#if defined(_WIN32) || defined(_WIN64) - #define ENV_ONEVPL_SEARCH_PATH L"ONEVPL_SEARCH_PATH" - #define ENV_ONEVPL_PACKAGE_PATH L"VPL_BIN" - #define ENV_OS_PATH L"PATH" -#else - #define ENV_ONEVPL_SEARCH_PATH "ONEVPL_SEARCH_PATH" - #define ENV_ONEVPL_PACKAGE_PATH "VPL_BIN" - #define ENV_OS_PATH "LD_LIBRARY_PATH" -#endif +#define MAX_ENV_VAR_LEN 32768 + +#define DEVICE_ID_UNKNOWN 0xffffffff +#define ADAPTER_IDX_UNKNOWN 0xffffffff #define TAB_SIZE(type, tab) (sizeof(tab) / sizeof(type)) #define MAKE_MFX_VERSION(major, minor) \ @@ -125,11 +124,13 @@ struct VPLFunctionDesc { // priority of runtime loading, based on oneAPI-spec enum LibPriority { - LIB_PRIORITY_USER_DEFINED = 1, - LIB_PRIORITY_VPL_PACKAGE = 2, - LIB_PRIORITY_OS_PATH = 3, - LIB_PRIORITY_SYS_DEFAULT = 4, - LIB_PRIORITY_MSDK_PACKAGE = 5, + LIB_PRIORITY_01 = 1, + LIB_PRIORITY_02 = 2, + LIB_PRIORITY_03 = 3, + LIB_PRIORITY_04 = 4, + LIB_PRIORITY_05 = 5, + + LIB_PRIORITY_LEGACY = 9999, }; enum CfgPropState { @@ -138,6 +139,21 @@ enum CfgPropState { CFG_PROP_STATE_UNSUPPORTED, }; +enum PropRanges { + PROP_RANGE_DEC_W = 0, + PROP_RANGE_DEC_H, + PROP_RANGE_ENC_W, + PROP_RANGE_ENC_H, + PROP_RANGE_VPP_W, + PROP_RANGE_VPP_H, + + NUM_PROP_RANGES +}; + +// must match eProp_TotalProps, is checked with static_assert in _config.cpp +// (should throw error at compile time if !=) +#define NUM_TOTAL_FILTER_PROPS 38 + // typedef child structures for easier reading typedef struct mfxDecoderDescription::decoder DecCodec; typedef struct mfxDecoderDescription::decoder::decprofile DecProfile; @@ -189,10 +205,20 @@ struct VPPConfig { // these are updated with every call to ValidateConfig() and may // be used in MFXCreateSession() struct SpecialConfig { + bool bIsSet_deviceHandleType; mfxHandleType deviceHandleType; + + bool bIsSet_deviceHandle; mfxHDL deviceHandle; + + bool bIsSet_accelerationMode; mfxAccelerationMode accelerationMode; + + bool bIsSet_ApiVersion; mfxVersion ApiVersion; + + bool bIsSet_dxgiAdapterIdx; + mfxU32 dxgiAdapterIdx; }; // config class implementation @@ -205,61 +231,66 @@ class ConfigCtxVPL { mfxStatus SetFilterProperty(const mfxU8* name, mfxVariant value); // compare library caps vs. set of configuration filters - static mfxStatus ValidateConfig(mfxImplDescription* libImplDesc, - mfxImplementedFunctions* libImplFuncs, + static mfxStatus ValidateConfig(const mfxImplDescription* libImplDesc, + const mfxImplementedFunctions* libImplFuncs, std::list configCtxList, LibType libType, SpecialConfig* specialConfig); + // parse deviceID for x86 devices + static bool ParseDeviceIDx86(mfxChar* cDeviceID, mfxU32& deviceID, mfxU32& adapterIdx); + // loader object this config is associated with - needed to // rebuild valid implementation list after each calling // MFXSetConfigFilterProperty() class LoaderCtxVPL* m_parentLoader; private: - __inline std::string GetNextProp(std::list* s) { - if (s->empty()) + static __inline std::string GetNextProp(std::list& s) { + if (s.empty()) return ""; - std::string t = s->front(); - s->pop_front(); + std::string t = s.front(); + s.pop_front(); return t; } mfxStatus ValidateAndSetProp(mfxI32 idx, mfxVariant value); - mfxStatus SetFilterPropertyDec(mfxVariant value); - mfxStatus SetFilterPropertyEnc(mfxVariant value); - mfxStatus SetFilterPropertyVPP(mfxVariant value); + mfxStatus SetFilterPropertyDec(std::list& propParsedString, mfxVariant value); + mfxStatus SetFilterPropertyEnc(std::list& propParsedString, mfxVariant value); + mfxStatus SetFilterPropertyVPP(std::list& propParsedString, mfxVariant value); - static mfxStatus GetFlatDescriptionsDec(mfxImplDescription* libImplDesc, + static mfxStatus GetFlatDescriptionsDec(const mfxImplDescription* libImplDesc, std::list& decConfigList); - static mfxStatus GetFlatDescriptionsEnc(mfxImplDescription* libImplDesc, + static mfxStatus GetFlatDescriptionsEnc(const mfxImplDescription* libImplDesc, std::list& encConfigList); - static mfxStatus GetFlatDescriptionsVPP(mfxImplDescription* libImplDesc, + static mfxStatus GetFlatDescriptionsVPP(const mfxImplDescription* libImplDesc, std::list& vppConfigList); - static mfxStatus CheckPropsGeneral(mfxVariant cfgPropsAll[], mfxImplDescription* libImplDesc); + static mfxStatus CheckPropsGeneral(const mfxVariant cfgPropsAll[], + const mfxImplDescription* libImplDesc); - static mfxStatus CheckPropsDec(mfxVariant cfgPropsAll[], std::list decConfigList); + static mfxStatus CheckPropsDec(const mfxVariant cfgPropsAll[], + std::list decConfigList); - static mfxStatus CheckPropsEnc(mfxVariant cfgPropsAll[], std::list encConfigList); + static mfxStatus CheckPropsEnc(const mfxVariant cfgPropsAll[], + std::list encConfigList); - static mfxStatus CheckPropsVPP(mfxVariant cfgPropsAll[], std::list vppConfigList); + static mfxStatus CheckPropsVPP(const mfxVariant cfgPropsAll[], + std::list vppConfigList); - static mfxStatus CheckPropString(mfxChar* implString, std::string filtString); + static mfxStatus CheckPropString(const mfxChar* implString, const std::string filtString); - std::string m_propName; - mfxVariant m_propValue; - mfxI32 m_propIdx; - std::list m_propParsedString; + mfxVariant m_propVar[NUM_TOTAL_FILTER_PROPS]; // special containers for properties which are passed by pointer - // (save a copy of the whole object based on m_propName) - mfxRange32U m_propRange32U; + // (save a copy of the whole object based on property name) + mfxRange32U m_propRange32U[NUM_PROP_RANGES]; std::string m_implName; std::string m_implLicense; std::string m_implKeywords; + std::string m_deviceIdStr; std::string m_implFunctionName; }; @@ -274,10 +305,13 @@ class LoaderCtxMSDK { mfxStatus QueryMSDKCaps(STRING_TYPE libNameFull, mfxImplDescription** implDesc, mfxImplementedFunctions** implFuncs, - mfxIMPL* msdkAdapter); + mfxU32 adapterID); + + static mfxStatus QueryAPIVersion(STRING_TYPE libNameFull, mfxVersion* msdkVersion); // required by MFXCreateSession - mfxIMPL msdkAdapter; + mfxIMPL m_msdkAdapter; + mfxIMPL m_msdkAdapterD3D9; private: // session management @@ -288,9 +322,9 @@ class LoaderCtxMSDK { void CloseSession(mfxSession* session); // utility functions - mfxAccelerationMode CvtAccelType(mfxIMPL implType, mfxIMPL implMethod); - mfxStatus GetDefaultAccelType(mfxU32 adapterID, mfxIMPL* implDefault); - mfxStatus CheckAccelType(mfxU32 adapterID, mfxIMPL implTest); + static mfxAccelerationMode CvtAccelType(mfxIMPL implType, mfxIMPL implMethod); + static mfxStatus GetDefaultAccelType(mfxU32 adapterID, mfxIMPL* implDefault, mfxU64* luid); + static mfxStatus CheckD3D9Support(mfxU64 luid, STRING_TYPE libNameFull, mfxIMPL* implD3D9); // internal state variables STRING_TYPE m_libNameFull; @@ -325,7 +359,15 @@ struct LibInfo { // select MSDK functions for 1.x style caps query VPLFunctionPtr msdkFuncTable[NumMSDKFunctions]; // NOLINT - class LoaderCtxMSDK* msdkCtx; + + // loader context for legacy MSDK + LoaderCtxMSDK msdkCtx[MAX_NUM_IMPL_MSDK]; + + // API version of legacy MSDK + mfxVersion msdkVersion; + + // user-friendly version of path for MFX_IMPLCAPS_IMPLPATH query + mfxChar implCapsPath[MAX_VPL_SEARCH_PATH]; // avoid warnings LibInfo() @@ -336,12 +378,14 @@ struct LibInfo { hModuleVPL(nullptr), vplFuncTable(), msdkFuncTable(), - msdkCtx() {} + msdkCtx(), + msdkVersion(), + implCapsPath() {} - ~LibInfo() { - if (msdkCtx) - delete msdkCtx; - } +private: + // make this class non-copyable + LibInfo(const LibInfo&); + void operator=(const LibInfo&); }; struct ImplInfo { @@ -358,6 +402,12 @@ struct ImplInfo { mfxInitializationParam vplParam; mfxVersion version; + // if MSDK library, index of corresponding adapter (i.e. which LoaderCtxMSDK) + mfxU32 msdkImplIdx; + + // adapter index in multi-adapter systems + mfxU32 adapterIdx; + // local index for libraries with more than one implementation mfxU32 libImplIdx; @@ -371,6 +421,8 @@ struct ImplInfo { implFuncs(nullptr), vplParam(), version(), + msdkImplIdx(0), + adapterIdx(ADAPTER_IDX_UNKNOWN), libImplIdx(0), validImplIdx(-1) {} }; @@ -402,6 +454,10 @@ class LoaderCtxVPL { ConfigCtxVPL* AddConfigFilter(); mfxStatus FreeConfigFilters(); + // manage logging + mfxStatus InitDispatcherLog(); + DispatcherLogVPL* GetLogger(); + private: // helper functions mfxStatus LoadSingleLibrary(LibInfo* libInfo); @@ -409,6 +465,12 @@ class LoaderCtxVPL { mfxStatus UnloadSingleImplementation(ImplInfo* implInfo); VPLFunctionPtr GetFunctionAddr(void* hModuleVPL, const char* pName); + mfxU32 GetSearchPathsDriverStore(std::list& searchDirs); + mfxU32 GetSearchPathsSystemDefault(std::list& searchDirs); + mfxU32 GetSearchPathsCurrentExe(std::list& searchDirs); + mfxU32 GetSearchPathsCurrentDir(std::list& searchDirs); + mfxU32 GetSearchPathsLegacy(std::list& searchDirs); + mfxU32 ParseEnvSearchPaths(const CHAR_TYPE* envVarName, std::list& searchDirs); mfxU32 ParseLegacySearchPaths(std::list& searchDirs); @@ -417,21 +479,21 @@ class LoaderCtxVPL { mfxU32 priority); mfxStatus ValidateAPIExports(VPLFunctionPtr* vplFuncTable, mfxVersion reportedVersion); + bool IsValidX86GPU(ImplInfo* implInfo, mfxU32& deviceID, mfxU32& adapterIdx); + mfxStatus UpdateImplPath(LibInfo* libInfo); std::list m_libInfoList; std::list m_implInfoList; std::list m_configCtxList; - std::list m_userSearchDirs; - std::list m_packageSearchDirs; - std::list m_pathSearchDirs; - std::list m_legacySearchDirs; - STRING_TYPE m_vplPackageDir; - STRING_TYPE m_driverStoreDir; SpecialConfig m_specialConfig; mfxU32 m_implIdxNext; bool m_bKeepCapsUntilUnload; + CHAR_TYPE m_envVar[MAX_ENV_VAR_LEN]; + + // logger object - enabled with ONEVPL_DISPATCHER_LOG environment variable + DispatcherLogVPL m_dispLog; }; #endif // DISPATCHER_VPL_MFX_DISPATCHER_VPL_H_ diff --git a/dispatcher/vpl/mfx_dispatcher_vpl_config.cpp b/dispatcher/vpl/mfx_dispatcher_vpl_config.cpp index 98c3a5e0..020a7441 100644 --- a/dispatcher/vpl/mfx_dispatcher_vpl_config.cpp +++ b/dispatcher/vpl/mfx_dispatcher_vpl_config.cpp @@ -8,23 +8,31 @@ #include +#include + // implementation of config context (mfxConfig) // each loader instance can have one or more configs // associated with it - used for filtering implementations // based on what they support (codec types, etc.) ConfigCtxVPL::ConfigCtxVPL() - : m_propName(), - m_propValue(), - m_propIdx(), - m_propParsedString(), + : m_propVar(), m_propRange32U(), m_implName(), m_implLicense(), m_implKeywords(), + m_deviceIdStr(), m_implFunctionName() { - m_propValue.Version.Version = MFX_VARIANT_VERSION; - m_propValue.Type = MFX_VARIANT_TYPE_UNSET; - m_parentLoader = nullptr; + // initially set Type = unset (invalid) + // if valid property string and value are passed in, + // this will be updated + // otherwise loader will ignore this cfg during EnumImplementations + for (mfxU32 idx = 0; idx < NUM_TOTAL_FILTER_PROPS; idx++) { + m_propVar[idx].Version.Version = MFX_VARIANT_VERSION; + m_propVar[idx].Type = MFX_VARIANT_TYPE_UNSET; + m_propVar[idx].Data.U64 = 0; + } + + m_parentLoader = nullptr; return; } @@ -52,6 +60,7 @@ enum PropIdx { // settable config properties for mfxDeviceDescription ePropDevice_DeviceID, + ePropDevice_DeviceIDStr, // settable config properties for mfxDecoderDescription ePropDec_CodecID, @@ -84,6 +93,7 @@ enum PropIdx { // special properties not part of description struct ePropSpecial_HandleType, ePropSpecial_Handle, + ePropSpecial_DXGIAdapterIndex, // functions which must report as implemented ePropFunc_FunctionName, @@ -109,7 +119,8 @@ static const PropVariant PropIdxTab[] = { { "ePropMain_VendorID", MFX_VARIANT_TYPE_U32 }, { "ePropMain_VendorImplID", MFX_VARIANT_TYPE_U32 }, - { "ePropDevice_DeviceID", MFX_VARIANT_TYPE_U16 }, + { "ePropDevice_DeviceID", MFX_VARIANT_TYPE_U16 }, + { "ePropDevice_DeviceIDStr", MFX_VARIANT_TYPE_PTR }, { "ePropDec_CodecID", MFX_VARIANT_TYPE_U32 }, { "ePropDec_MaxcodecLevel", MFX_VARIANT_TYPE_U16 }, @@ -138,6 +149,7 @@ static const PropVariant PropIdxTab[] = { { "ePropSpecial_HandleType", MFX_VARIANT_TYPE_U32 }, { "ePropSpecial_Handle", MFX_VARIANT_TYPE_PTR }, + { "ePropSpecial_DXGIAdapterIndex", MFX_VARIANT_TYPE_U32 }, { "ePropFunc_FunctionName", MFX_VARIANT_TYPE_PTR }, }; @@ -149,6 +161,9 @@ static const PropVariant PropIdxTab[] = { static_assert((sizeof(PropIdxTab) / sizeof(PropVariant)) == eProp_TotalProps, "PropIdx and PropIdxTab are misaligned"); +static_assert(NUM_TOTAL_FILTER_PROPS == eProp_TotalProps, + "NUM_TOTAL_FILTER_PROPS and eProp_TotalProps are misaligned"); + mfxStatus ConfigCtxVPL::ValidateAndSetProp(mfxI32 idx, mfxVariant value) { if (idx < 0 || idx >= eProp_TotalProps) return MFX_ERR_NOT_FOUND; @@ -156,38 +171,60 @@ mfxStatus ConfigCtxVPL::ValidateAndSetProp(mfxI32 idx, mfxVariant value) { if (value.Type != PropIdxTab[idx].Type) return MFX_ERR_UNSUPPORTED; - m_propIdx = idx; - m_propValue.Type = value.Type; + m_propVar[idx].Version.Version = MFX_VARIANT_VERSION; + m_propVar[idx].Type = value.Type; if (value.Type == MFX_VARIANT_TYPE_PTR) { - if (value.Data.Ptr == nullptr) + if (value.Data.Ptr == nullptr) { + // unset property to avoid possibly dereferencing null if app ignores error code + m_propVar[idx].Type = MFX_VARIANT_TYPE_UNSET; return MFX_ERR_NULL_PTR; + } // save copy of data passed by pointer, into object of the appropriate type - switch (m_propIdx) { + switch (idx) { case ePropDec_Width: + m_propRange32U[PROP_RANGE_DEC_W] = *((mfxRange32U *)(value.Data.Ptr)); + m_propVar[idx].Data.Ptr = &(m_propRange32U[PROP_RANGE_DEC_W]); + break; case ePropDec_Height: + m_propRange32U[PROP_RANGE_DEC_H] = *((mfxRange32U *)(value.Data.Ptr)); + m_propVar[idx].Data.Ptr = &(m_propRange32U[PROP_RANGE_DEC_H]); + break; case ePropEnc_Width: + m_propRange32U[PROP_RANGE_ENC_W] = *((mfxRange32U *)(value.Data.Ptr)); + m_propVar[idx].Data.Ptr = &(m_propRange32U[PROP_RANGE_ENC_W]); + break; case ePropEnc_Height: + m_propRange32U[PROP_RANGE_ENC_H] = *((mfxRange32U *)(value.Data.Ptr)); + m_propVar[idx].Data.Ptr = &(m_propRange32U[PROP_RANGE_ENC_H]); + break; case ePropVPP_Width: + m_propRange32U[PROP_RANGE_VPP_W] = *((mfxRange32U *)(value.Data.Ptr)); + m_propVar[idx].Data.Ptr = &(m_propRange32U[PROP_RANGE_VPP_W]); + break; case ePropVPP_Height: - m_propRange32U = *((mfxRange32U *)(value.Data.Ptr)); - m_propValue.Data.Ptr = &(m_propRange32U); + m_propRange32U[PROP_RANGE_VPP_H] = *((mfxRange32U *)(value.Data.Ptr)); + m_propVar[idx].Data.Ptr = &(m_propRange32U[PROP_RANGE_VPP_H]); break; case ePropSpecial_Handle: - m_propValue.Data.Ptr = (mfxHDL)(value.Data.Ptr); + m_propVar[idx].Data.Ptr = (mfxHDL)(value.Data.Ptr); break; case ePropMain_ImplName: - m_implName = (char *)(value.Data.Ptr); - m_propValue.Data.Ptr = &(m_implName); + m_implName = (char *)(value.Data.Ptr); + m_propVar[idx].Data.Ptr = &(m_implName); break; case ePropMain_License: - m_implLicense = (char *)(value.Data.Ptr); - m_propValue.Data.Ptr = &(m_implLicense); + m_implLicense = (char *)(value.Data.Ptr); + m_propVar[idx].Data.Ptr = &(m_implLicense); break; case ePropMain_Keywords: - m_implKeywords = (char *)(value.Data.Ptr); - m_propValue.Data.Ptr = &(m_implKeywords); + m_implKeywords = (char *)(value.Data.Ptr); + m_propVar[idx].Data.Ptr = &(m_implKeywords); + break; + case ePropDevice_DeviceIDStr: + m_deviceIdStr = (char *)(value.Data.Ptr); + m_propVar[idx].Data.Ptr = &(m_deviceIdStr); break; case ePropFunc_FunctionName: // no need to save Data.Ptr - parsed in main loop @@ -198,23 +235,24 @@ mfxStatus ConfigCtxVPL::ValidateAndSetProp(mfxI32 idx, mfxVariant value) { } } else { - m_propValue.Data = value.Data; + m_propVar[idx].Data = value.Data; } return MFX_ERR_NONE; } -mfxStatus ConfigCtxVPL::SetFilterPropertyDec(mfxVariant value) { +mfxStatus ConfigCtxVPL::SetFilterPropertyDec(std::list &propParsedString, + mfxVariant value) { std::string nextProp; - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); // no settable top-level members if (nextProp != "decoder") return MFX_ERR_NOT_FOUND; // parse 'decoder' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "CodecID") { return ValidateAndSetProp(ePropDec_CodecID, value); } @@ -226,7 +264,7 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyDec(mfxVariant value) { } // parse 'decprofile' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "Profile") { return ValidateAndSetProp(ePropDec_Profile, value); } @@ -235,7 +273,7 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyDec(mfxVariant value) { } // parse 'decmemdesc' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "MemHandleType") { return ValidateAndSetProp(ePropDec_MemHandleType, value); } @@ -253,17 +291,18 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyDec(mfxVariant value) { return MFX_ERR_NOT_FOUND; } -mfxStatus ConfigCtxVPL::SetFilterPropertyEnc(mfxVariant value) { +mfxStatus ConfigCtxVPL::SetFilterPropertyEnc(std::list &propParsedString, + mfxVariant value) { std::string nextProp; - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); // no settable top-level members if (nextProp != "encoder") return MFX_ERR_NOT_FOUND; // parse 'encoder' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "CodecID") { return ValidateAndSetProp(ePropEnc_CodecID, value); } @@ -278,7 +317,7 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyEnc(mfxVariant value) { } // parse 'encprofile' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "Profile") { return ValidateAndSetProp(ePropEnc_Profile, value); } @@ -287,7 +326,7 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyEnc(mfxVariant value) { } // parse 'encmemdesc' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "MemHandleType") { return ValidateAndSetProp(ePropEnc_MemHandleType, value); } @@ -305,17 +344,18 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyEnc(mfxVariant value) { return MFX_ERR_NOT_FOUND; } -mfxStatus ConfigCtxVPL::SetFilterPropertyVPP(mfxVariant value) { +mfxStatus ConfigCtxVPL::SetFilterPropertyVPP(std::list &propParsedString, + mfxVariant value) { std::string nextProp; - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); // no settable top-level members if (nextProp != "filter") return MFX_ERR_NOT_FOUND; // parse 'filter' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "FilterFourCC") { return ValidateAndSetProp(ePropVPP_FilterFourCC, value); } @@ -327,7 +367,7 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyVPP(mfxVariant value) { } // parse 'memdesc' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "MemHandleType") { return ValidateAndSetProp(ePropVPP_MemHandleType, value); } @@ -342,7 +382,7 @@ mfxStatus ConfigCtxVPL::SetFilterPropertyVPP(mfxVariant value) { } // parse 'format' - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "InFormat") { return ValidateAndSetProp(ePropVPP_InFormat, value); } @@ -361,27 +401,19 @@ mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) { if (!name) return MFX_ERR_NULL_PTR; - m_propName = std::string((char *)name); - - m_propValue.Version.Version = MFX_VARIANT_VERSION; - - // initially set Type = unset (invalid) - // if valid property string and value are passed in, - // this will be updated - // otherwise loader will ignore this cfg during EnumImplementations - m_propValue.Type = MFX_VARIANT_TYPE_UNSET; - m_propValue.Data.U32 = 0; + std::list propParsedString; // parse property string into individual properties, // separated by '.' std::stringstream prop((char *)name); std::string s; + propParsedString.clear(); while (getline(prop, s, '.')) { - m_propParsedString.push_back(s); + propParsedString.push_back(s); } // get first property descriptor - std::string nextProp = GetNextProp(&m_propParsedString); + std::string nextProp = GetNextProp(propParsedString); // check for special-case properties, not part of mfxImplDescription if (nextProp == "mfxHandleType") { @@ -390,11 +422,19 @@ mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) { else if (nextProp == "mfxHDL") { return ValidateAndSetProp(ePropSpecial_Handle, value); } + else if (nextProp == "DXGIAdapterIndex") { +#if defined(_WIN32) || defined(_WIN64) + // this property is only valid on Windows + return ValidateAndSetProp(ePropSpecial_DXGIAdapterIndex, value); +#else + return MFX_ERR_NOT_FOUND; +#endif + } // to require that a specific function is implemented, use the property name // "mfxImplementedFunctions.FunctionsName" if (nextProp == "mfxImplementedFunctions") { - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "FunctionsName") { return ValidateAndSetProp(ePropFunc_FunctionName, value); } @@ -407,7 +447,7 @@ mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) { } // get next property descriptor - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); // property is a top-level member of mfxImplDescription if (nextProp == "Impl") { @@ -418,7 +458,7 @@ mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) { } else if (nextProp == "ApiVersion") { // ApiVersion may be passed as single U32 (Version) or two U16's (Major, Minor) - nextProp = GetNextProp(&m_propParsedString); + nextProp = GetNextProp(propParsedString); if (nextProp == "Version") return ValidateAndSetProp(ePropMain_ApiVersion, value); else if (nextProp == "Major") @@ -447,27 +487,33 @@ mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) { // property is a member of mfxDeviceDescription // currently only settable parameter is DeviceID if (nextProp == "mfxDeviceDescription") { - nextProp = GetNextProp(&m_propParsedString); - if (nextProp == "device") { - nextProp = GetNextProp(&m_propParsedString); - if (nextProp == "DeviceID") { + nextProp = GetNextProp(propParsedString); + // old version of table in spec had extra "device", just skip if present + if (nextProp == "device") + nextProp = GetNextProp(propParsedString); + + // special case - deviceID may be passed as U16 (default) or string (since API 2.4) + // for compatibility, both are supported (value.Type distinguishes between them) + if (nextProp == "DeviceID") { + if (value.Type == MFX_VARIANT_TYPE_PTR) + return ValidateAndSetProp(ePropDevice_DeviceIDStr, value); + else return ValidateAndSetProp(ePropDevice_DeviceID, value); - } } return MFX_ERR_NOT_FOUND; } // property is a member of mfxDecoderDescription if (nextProp == "mfxDecoderDescription") { - return SetFilterPropertyDec(value); + return SetFilterPropertyDec(propParsedString, value); } if (nextProp == "mfxEncoderDescription") { - return SetFilterPropertyEnc(value); + return SetFilterPropertyEnc(propParsedString, value); } if (nextProp == "mfxVPPDescription") { - return SetFilterPropertyVPP(value); + return SetFilterPropertyVPP(propParsedString, value); } return MFX_ERR_NOT_FOUND; @@ -480,7 +526,7 @@ mfxStatus ConfigCtxVPL::SetFilterProperty(const mfxU8 *name, mfxVariant value) { continue; \ } -mfxStatus ConfigCtxVPL::GetFlatDescriptionsDec(mfxImplDescription *libImplDesc, +mfxStatus ConfigCtxVPL::GetFlatDescriptionsDec(const mfxImplDescription *libImplDesc, std::list &decConfigList) { mfxU32 codecIdx = 0; mfxU32 profileIdx = 0; @@ -522,7 +568,7 @@ mfxStatus ConfigCtxVPL::GetFlatDescriptionsDec(mfxImplDescription *libImplDesc, return MFX_ERR_NONE; } -mfxStatus ConfigCtxVPL::GetFlatDescriptionsEnc(mfxImplDescription *libImplDesc, +mfxStatus ConfigCtxVPL::GetFlatDescriptionsEnc(const mfxImplDescription *libImplDesc, std::list &encConfigList) { mfxU32 codecIdx = 0; mfxU32 profileIdx = 0; @@ -565,7 +611,7 @@ mfxStatus ConfigCtxVPL::GetFlatDescriptionsEnc(mfxImplDescription *libImplDesc, return MFX_ERR_NONE; } -mfxStatus ConfigCtxVPL::GetFlatDescriptionsVPP(mfxImplDescription *libImplDesc, +mfxStatus ConfigCtxVPL::GetFlatDescriptionsVPP(const mfxImplDescription *libImplDesc, std::list &vppConfigList) { mfxU32 filterIdx = 0; mfxU32 memIdx = 0; @@ -612,8 +658,8 @@ mfxStatus ConfigCtxVPL::GetFlatDescriptionsVPP(mfxImplDescription *libImplDesc, (cfgPropsAll[(idx)].Data.type != val)) \ isCompatible = false; -mfxStatus ConfigCtxVPL::CheckPropsGeneral(mfxVariant cfgPropsAll[], - mfxImplDescription *libImplDesc) { +mfxStatus ConfigCtxVPL::CheckPropsGeneral(const mfxVariant cfgPropsAll[], + const mfxImplDescription *libImplDesc) { bool isCompatible = true; // check if this implementation includes @@ -622,25 +668,8 @@ mfxStatus ConfigCtxVPL::CheckPropsGeneral(mfxVariant cfgPropsAll[], CHECK_PROP(ePropMain_VendorID, U32, libImplDesc->VendorID); CHECK_PROP(ePropMain_VendorImplID, U32, libImplDesc->VendorImplID); - // confirm that API version of this implementation is >= requested version - mfxU32 versionRequested = 0; - if (cfgPropsAll[ePropMain_ApiVersion].Type != MFX_VARIANT_TYPE_UNSET) { - // version was passed as U32 = (Major | Minor) - versionRequested = (mfxU32)(cfgPropsAll[ePropMain_ApiVersion].Data.U32); - } - else if (cfgPropsAll[ePropMain_ApiVersion_Major].Type != MFX_VARIANT_TYPE_UNSET && - cfgPropsAll[ePropMain_ApiVersion_Minor].Type != MFX_VARIANT_TYPE_UNSET) { - // version was passed as 2x U16 - mfxVersion ver = {}; - ver.Major = (mfxU16)(cfgPropsAll[ePropMain_ApiVersion_Major].Data.U16); - ver.Minor = (mfxU16)(cfgPropsAll[ePropMain_ApiVersion_Minor].Data.U16); - versionRequested = (mfxU32)ver.Version; - } - - if (versionRequested) { - if (libImplDesc->ApiVersion.Version < versionRequested) - isCompatible = false; - } + // check API version in calling function since major and minor may be passed + // in separate cfg objects if (libImplDesc->AccelerationModeDescription.NumAccelerationModes > 0) { if (cfgPropsAll[ePropMain_AccelerationMode].Type != MFX_VARIANT_TYPE_UNSET) { @@ -698,13 +727,21 @@ mfxStatus ConfigCtxVPL::CheckPropsGeneral(mfxVariant cfgPropsAll[], isCompatible = false; } + if (cfgPropsAll[ePropDevice_DeviceIDStr].Type != MFX_VARIANT_TYPE_UNSET) { + // since API 2.4 - pass DeviceID as string (do string match) + std::string filtDeviceID = *(std::string *)(cfgPropsAll[ePropDevice_DeviceIDStr].Data.Ptr); + std::string implDeviceID = libImplDesc->Dev.DeviceID; + if (filtDeviceID != implDeviceID) + isCompatible = false; + } + if (isCompatible == true) return MFX_ERR_NONE; return MFX_ERR_UNSUPPORTED; } -mfxStatus ConfigCtxVPL::CheckPropsDec(mfxVariant cfgPropsAll[], +mfxStatus ConfigCtxVPL::CheckPropsDec(const mfxVariant cfgPropsAll[], std::list decConfigList) { auto it = decConfigList.begin(); while (it != decConfigList.end()) { @@ -729,7 +766,8 @@ mfxStatus ConfigCtxVPL::CheckPropsDec(mfxVariant cfgPropsAll[], (width.Step < dc.Width.Step)) isCompatible = false; } - else if (cfgPropsAll[ePropDec_Height].Type != MFX_VARIANT_TYPE_UNSET) { + + if (cfgPropsAll[ePropDec_Height].Type != MFX_VARIANT_TYPE_UNSET) { mfxRange32U height = {}; if (cfgPropsAll[ePropDec_Height].Data.Ptr) height = *((mfxRange32U *)(cfgPropsAll[ePropDec_Height].Data.Ptr)); @@ -748,7 +786,7 @@ mfxStatus ConfigCtxVPL::CheckPropsDec(mfxVariant cfgPropsAll[], return MFX_ERR_UNSUPPORTED; } -mfxStatus ConfigCtxVPL::CheckPropsEnc(mfxVariant cfgPropsAll[], +mfxStatus ConfigCtxVPL::CheckPropsEnc(const mfxVariant cfgPropsAll[], std::list encConfigList) { auto it = encConfigList.begin(); while (it != encConfigList.end()) { @@ -774,7 +812,8 @@ mfxStatus ConfigCtxVPL::CheckPropsEnc(mfxVariant cfgPropsAll[], (width.Step < ec.Width.Step)) isCompatible = false; } - else if (cfgPropsAll[ePropEnc_Height].Type != MFX_VARIANT_TYPE_UNSET) { + + if (cfgPropsAll[ePropEnc_Height].Type != MFX_VARIANT_TYPE_UNSET) { mfxRange32U height = {}; if (cfgPropsAll[ePropEnc_Height].Data.Ptr) height = *((mfxRange32U *)(cfgPropsAll[ePropEnc_Height].Data.Ptr)); @@ -793,7 +832,7 @@ mfxStatus ConfigCtxVPL::CheckPropsEnc(mfxVariant cfgPropsAll[], return MFX_ERR_UNSUPPORTED; } -mfxStatus ConfigCtxVPL::CheckPropsVPP(mfxVariant cfgPropsAll[], +mfxStatus ConfigCtxVPL::CheckPropsVPP(const mfxVariant cfgPropsAll[], std::list vppConfigList) { auto it = vppConfigList.begin(); while (it != vppConfigList.end()) { @@ -803,7 +842,7 @@ mfxStatus ConfigCtxVPL::CheckPropsVPP(mfxVariant cfgPropsAll[], // check if this filter description includes // all of the required VPP properties CHECK_PROP(ePropVPP_FilterFourCC, U32, vc.FilterFourCC); - CHECK_PROP(ePropVPP_MaxDelayInFrames, U32, vc.MaxDelayInFrames); + CHECK_PROP(ePropVPP_MaxDelayInFrames, U16, vc.MaxDelayInFrames); CHECK_PROP(ePropVPP_MemHandleType, U32, vc.MemHandleType); CHECK_PROP(ePropVPP_InFormat, U32, vc.InFormat); CHECK_PROP(ePropVPP_OutFormat, U32, vc.OutFormat); @@ -818,7 +857,8 @@ mfxStatus ConfigCtxVPL::CheckPropsVPP(mfxVariant cfgPropsAll[], (width.Step < vc.Width.Step)) isCompatible = false; } - else if (cfgPropsAll[ePropVPP_Height].Type != MFX_VARIANT_TYPE_UNSET) { + + if (cfgPropsAll[ePropVPP_Height].Type != MFX_VARIANT_TYPE_UNSET) { mfxRange32U height = {}; if (cfgPropsAll[ePropVPP_Height].Data.Ptr) height = *((mfxRange32U *)(cfgPropsAll[ePropVPP_Height].Data.Ptr)); @@ -840,7 +880,7 @@ mfxStatus ConfigCtxVPL::CheckPropsVPP(mfxVariant cfgPropsAll[], // implString = string from implDesc - one or more comma-separated tokens // filtString = string user is looking for - one or more comma-separated tokens // we parse filtString into tokens, then check if all of them are present in implString -mfxStatus ConfigCtxVPL::CheckPropString(mfxChar *implString, std::string filtString) { +mfxStatus ConfigCtxVPL::CheckPropString(const mfxChar *implString, const std::string filtString) { std::list tokenString; std::string s; @@ -861,17 +901,18 @@ mfxStatus ConfigCtxVPL::CheckPropString(mfxChar *implString, std::string filtStr return MFX_ERR_NONE; } -mfxStatus ConfigCtxVPL::ValidateConfig(mfxImplDescription *libImplDesc, - mfxImplementedFunctions *libImplFuncs, +mfxStatus ConfigCtxVPL::ValidateConfig(const mfxImplDescription *libImplDesc, + const mfxImplementedFunctions *libImplFuncs, std::list configCtxList, LibType libType, SpecialConfig *specialConfig) { mfxU32 idx; - mfxStatus sts = MFX_ERR_NONE; bool decRequested = false; bool encRequested = false; bool vppRequested = false; + bool bImplValid = true; + if (!libImplDesc) return MFX_ERR_NULL_PTR; @@ -879,59 +920,134 @@ mfxStatus ConfigCtxVPL::ValidateConfig(mfxImplDescription *libImplDesc, std::list encConfigList; std::list vppConfigList; + // generate "flat" descriptions of each combination + // (e.g. multiple profiles from the same codec) + GetFlatDescriptionsDec(libImplDesc, decConfigList); + GetFlatDescriptionsEnc(libImplDesc, encConfigList); + GetFlatDescriptionsVPP(libImplDesc, vppConfigList); + // list of functions required to be implemented std::list implFunctionList; implFunctionList.clear(); - // save list when multiple filters apply to the the same property - // (e.g two mfxConfig objects with different values for CodecID) - std::list configCtxListDups; - - // initially all properties are unset - mfxVariant cfgPropsAll[eProp_TotalProps] = {}; - for (idx = 0; idx < eProp_TotalProps; idx++) { - cfgPropsAll[idx].Type = MFX_VARIANT_TYPE_UNSET; - } + // check requested API version + mfxVersion reqVersion = {}; + bool bVerSetMajor = false; + bool bVerSetMinor = false; // iterate through all filters and populate cfgPropsAll - std::list::iterator it = configCtxList.begin(); + auto it = configCtxList.begin(); + while (it != configCtxList.end()) { ConfigCtxVPL *config = (*it); - - idx = config->m_propIdx; it++; - //if index is invalid continue to the next filter - if (idx >= eProp_TotalProps) - continue; + // initially all properties are unset + mfxVariant cfgPropsAll[eProp_TotalProps] = {}; + for (idx = 0; idx < eProp_TotalProps; idx++) { + cfgPropsAll[idx].Type = MFX_VARIANT_TYPE_UNSET; + } + + for (idx = 0; idx < eProp_TotalProps; idx++) { + // ignore unset properties + if (config->m_propVar[idx].Type == MFX_VARIANT_TYPE_UNSET) + continue; - // if property is required function, add to list which will be checked below - if (idx == ePropFunc_FunctionName) { - implFunctionList.push_back(config->m_implFunctionName); - continue; + // if property is required function, add to list which will be checked below + if (idx == ePropFunc_FunctionName) { + implFunctionList.push_back(config->m_implFunctionName); + continue; + } + + cfgPropsAll[idx].Type = config->m_propVar[idx].Type; + cfgPropsAll[idx].Data = config->m_propVar[idx].Data; + + if (idx >= ePropDec_CodecID && idx <= ePropDec_ColorFormats) + decRequested = true; + else if (idx >= ePropEnc_CodecID && idx <= ePropEnc_ColorFormats) + encRequested = true; + else if (idx >= ePropVPP_FilterFourCC && idx <= ePropVPP_OutFormat) + vppRequested = true; + } + + // if already marked invalid, no need to check props again + // however we still need to iterate over all of the config objects + // to get any non-filtering properties (returned in SpecialConfig) + if (bImplValid == true) { + if (CheckPropsGeneral(cfgPropsAll, libImplDesc)) + bImplValid = false; + + // MSDK RT compatibility mode (1.x) does not provide Dec/Enc/VPP caps + // ignore these filters if set (do not use them to _exclude_ the library) + if (libType != LibTypeMSDK) { + if (decRequested && CheckPropsDec(cfgPropsAll, decConfigList)) + bImplValid = false; + + if (encRequested && CheckPropsEnc(cfgPropsAll, encConfigList)) + bImplValid = false; + + if (vppRequested && CheckPropsVPP(cfgPropsAll, vppConfigList)) + bImplValid = false; + } + } + + // update any special (including non-filtering) properties, for use by caller + // if multiple cfg objects set the same non-filtering property, the last (most recent) one is used + if (cfgPropsAll[ePropSpecial_HandleType].Type != MFX_VARIANT_TYPE_UNSET) { + specialConfig->deviceHandleType = + (mfxHandleType)cfgPropsAll[ePropSpecial_HandleType].Data.U32; + specialConfig->bIsSet_deviceHandleType = true; + } + + if (cfgPropsAll[ePropSpecial_Handle].Type != MFX_VARIANT_TYPE_UNSET) { + specialConfig->deviceHandle = (mfxHDL)cfgPropsAll[ePropSpecial_Handle].Data.Ptr; + specialConfig->bIsSet_deviceHandle = true; } - // ignore config objects that were never assigned a property - if (config->m_propValue.Type == MFX_VARIANT_TYPE_UNSET) - continue; + if (cfgPropsAll[ePropSpecial_DXGIAdapterIndex].Type != MFX_VARIANT_TYPE_UNSET) { + specialConfig->dxgiAdapterIdx = + (mfxU32)cfgPropsAll[ePropSpecial_DXGIAdapterIndex].Data.U32; + specialConfig->bIsSet_dxgiAdapterIdx = true; + } + + if (cfgPropsAll[ePropMain_AccelerationMode].Type != MFX_VARIANT_TYPE_UNSET) { + specialConfig->accelerationMode = + (mfxAccelerationMode)cfgPropsAll[ePropMain_AccelerationMode].Data.U32; + specialConfig->bIsSet_accelerationMode = true; + } + + // special handling for API version which may be passed either as single U32 (Version) + // or two U16 (Major, Minor) which could come in separate cfg objects + if (cfgPropsAll[ePropMain_ApiVersion].Type != MFX_VARIANT_TYPE_UNSET) { + reqVersion.Version = (mfxU32)cfgPropsAll[ePropMain_ApiVersion].Data.U32; + bVerSetMajor = true; + bVerSetMinor = true; + } + else { + if (cfgPropsAll[ePropMain_ApiVersion_Major].Type != MFX_VARIANT_TYPE_UNSET) { + reqVersion.Major = (mfxU32)cfgPropsAll[ePropMain_ApiVersion_Major].Data.U16; + bVerSetMajor = true; + } - // save duplicates for check in second pass (prop has already been set) - if (cfgPropsAll[idx].Type != MFX_VARIANT_TYPE_UNSET) { - configCtxListDups.push_back(config); - continue; + if (cfgPropsAll[ePropMain_ApiVersion_Minor].Type != MFX_VARIANT_TYPE_UNSET) { + reqVersion.Minor = (mfxU32)cfgPropsAll[ePropMain_ApiVersion_Minor].Data.U16; + bVerSetMinor = true; + } } + } - cfgPropsAll[idx].Type = config->m_propValue.Type; - cfgPropsAll[idx].Data = config->m_propValue.Data; + if (bVerSetMajor && bVerSetMinor) { + // require both Major and Minor to be set if filtering this way + if (libImplDesc->ApiVersion.Version < reqVersion.Version) + bImplValid = false; - if (idx >= ePropDec_CodecID && idx <= ePropDec_ColorFormats) - decRequested = true; - else if (idx >= ePropEnc_CodecID && idx <= ePropEnc_ColorFormats) - encRequested = true; - else if (idx >= ePropVPP_FilterFourCC && idx <= ePropVPP_OutFormat) - vppRequested = true; + specialConfig->ApiVersion.Version = reqVersion.Version; + specialConfig->bIsSet_ApiVersion = true; } + if (bImplValid == false) + return MFX_ERR_UNSUPPORTED; + // check whether required functions are implemented if (!implFunctionList.empty()) { if (!libImplFuncs) { @@ -955,98 +1071,55 @@ mfxStatus ConfigCtxVPL::ValidateConfig(mfxImplDescription *libImplDesc, } } - // update any special (including non-filtering) properties, for use by caller - if (cfgPropsAll[ePropSpecial_HandleType].Type != MFX_VARIANT_TYPE_UNSET) - specialConfig->deviceHandleType = - (mfxHandleType)cfgPropsAll[ePropSpecial_HandleType].Data.U32; + return MFX_ERR_NONE; +} + +bool ConfigCtxVPL::ParseDeviceIDx86(mfxChar *cDeviceID, mfxU32 &deviceID, mfxU32 &adapterIdx) { + std::string strDevID(cDeviceID); + std::regex reDevIDAll("[0-9a-fA-F]+/[0-9]+"); + std::regex reDevIDMin("[0-9a-fA-F]+"); - if (cfgPropsAll[ePropSpecial_Handle].Type != MFX_VARIANT_TYPE_UNSET) - specialConfig->deviceHandle = (mfxHDL)cfgPropsAll[ePropSpecial_Handle].Data.Ptr; + deviceID = DEVICE_ID_UNKNOWN; + adapterIdx = ADAPTER_IDX_UNKNOWN; - if (cfgPropsAll[ePropMain_ApiVersion].Type != MFX_VARIANT_TYPE_UNSET) { - specialConfig->ApiVersion.Version = (mfxU32)cfgPropsAll[ePropMain_ApiVersion].Data.U32; + bool bHasAdapterIdx = false; + if (std::regex_match(strDevID, reDevIDAll)) { + // check for DeviceID in format "devID/adapterIdx" + // devID = hex value + // adapterIdx = decimal integer + bHasAdapterIdx = true; } - else if (cfgPropsAll[ePropMain_ApiVersion_Major].Type != MFX_VARIANT_TYPE_UNSET && - cfgPropsAll[ePropMain_ApiVersion_Minor].Type != MFX_VARIANT_TYPE_UNSET) { - specialConfig->ApiVersion.Major = cfgPropsAll[ePropMain_ApiVersion_Major].Data.U16; - specialConfig->ApiVersion.Minor = cfgPropsAll[ePropMain_ApiVersion_Minor].Data.U16; + else if (std::regex_match(strDevID, reDevIDMin)) { + // check for DeviceID in format "devID" + // (no adpaterIdx) + bHasAdapterIdx = false; } - - if (cfgPropsAll[ePropMain_AccelerationMode].Type != MFX_VARIANT_TYPE_UNSET) - specialConfig->accelerationMode = - (mfxAccelerationMode)cfgPropsAll[ePropMain_AccelerationMode].Data.U32; - - // generate "flat" descriptions of each combination - // (e.g. multiple profiles from the same codec) - GetFlatDescriptionsDec(libImplDesc, decConfigList); - GetFlatDescriptionsEnc(libImplDesc, encConfigList); - GetFlatDescriptionsVPP(libImplDesc, vppConfigList); - - sts = CheckPropsGeneral(cfgPropsAll, libImplDesc); - if (sts) - return sts; - - // early exit - MSDK RT compatibility mode (1.x) does not provide Dec/Enc/VPP caps - // ignore these filters if set (do not use them to _exclude_ the library) - if (libType == LibTypeMSDK) - return MFX_ERR_NONE; - - if (decRequested) { - sts = CheckPropsDec(cfgPropsAll, decConfigList); - if (sts) - return sts; + else { + // invalid format + return false; } - if (encRequested) { - sts = CheckPropsEnc(cfgPropsAll, encConfigList); - if (sts) - return sts; + // get deviceID (value before the slash, if present) + try { + deviceID = std::stoi(strDevID, 0, 16); } - - if (vppRequested) { - sts = CheckPropsVPP(cfgPropsAll, vppConfigList); - if (sts) - return sts; + catch (...) { + return false; } - // second pass - if multiple filters were set with the same property, - // confirm that implementation supports all of them - // - // NOTE: the order of calling MFXSetConfigFilterProperty() can affect - // the logic here if user does something unusual such as setting - // two CodecId's AND two Profiles - how do we know which profile - // is associated with which codec? (it is just some integer) - // Probably need to add more information to the spec to clarify - // allowable combinations of filter properties. - std::list::iterator it2 = configCtxListDups.begin(); - while (it2 != configCtxListDups.end()) { - ConfigCtxVPL *config = (*it2); - - idx = config->m_propIdx; - sts = MFX_ERR_NONE; - it2++; - - //if index is invalid continue to the next filter - if (idx >= eProp_TotalProps) - continue; - - cfgPropsAll[idx].Type = config->m_propValue.Type; - cfgPropsAll[idx].Data = config->m_propValue.Data; + if (bHasAdapterIdx) { + // get adapter index (value after the slash) + size_t idx = strDevID.rfind('/'); + if (idx == std::string::npos) + return false; - // re-test based on the type of parameter (e.g. a second decoder - // type just requires checking the decoder configurations) - // no need to test general (top-level) properties, as they can - // only have a single value - if (idx >= ePropDec_CodecID && idx <= ePropDec_ColorFormats) - sts = CheckPropsDec(cfgPropsAll, decConfigList); - else if (idx >= ePropEnc_CodecID && idx <= ePropEnc_ColorFormats) - sts = CheckPropsEnc(cfgPropsAll, encConfigList); - else if (idx >= ePropVPP_FilterFourCC && idx <= ePropVPP_OutFormat) - sts = CheckPropsVPP(cfgPropsAll, vppConfigList); - - if (sts) - return sts; + try { + adapterIdx = std::stoi(strDevID.substr(idx + 1)); + } + catch (...) { + return false; + } } - return MFX_ERR_NONE; + return true; } diff --git a/dispatcher/vpl/mfx_dispatcher_vpl_loader.cpp b/dispatcher/vpl/mfx_dispatcher_vpl_loader.cpp index 18e41ed3..4c7e98b7 100644 --- a/dispatcher/vpl/mfx_dispatcher_vpl_loader.cpp +++ b/dispatcher/vpl/mfx_dispatcher_vpl_loader.cpp @@ -20,13 +20,13 @@ static const VPLFunctionDesc FunctionDesc2[NumVPLFunctions] = { { "MFXMemory_GetSurfaceForDecode", { { 0, 2 } } }, { "MFXInitialize", { { 0, 2 } } }, - { "MFXMemory_GetSurfaceForVPPOut", { { 1, 2 } } }, - { "MFXVideoDECODE_VPP_Init", { { 1, 2 } } }, - { "MFXVideoDECODE_VPP_DecodeFrameAsync", { { 1, 2 } } }, - { "MFXVideoDECODE_VPP_Reset", { { 1, 2 } } }, - { "MFXVideoDECODE_VPP_GetChannelParam", { { 1, 2 } } }, - { "MFXVideoDECODE_VPP_Close", { { 1, 2 } } }, - { "MFXVideoVPP_ProcessFrameAsync", { { 1, 2 } } }, + { "MFXMemory_GetSurfaceForVPPOut", { { 1, 2 } } }, + { "MFXVideoDECODE_VPP_Init", { { 1, 2 } } }, + { "MFXVideoDECODE_VPP_DecodeFrameAsync", { { 1, 2 } } }, + { "MFXVideoDECODE_VPP_Reset", { { 1, 2 } } }, + { "MFXVideoDECODE_VPP_GetChannelParam", { { 1, 2 } } }, + { "MFXVideoDECODE_VPP_Close", { { 1, 2 } } }, + { "MFXVideoVPP_ProcessFrameAsync", { { 1, 2 } } }, }; static const VPLFunctionDesc MSDKCompatFunctions[NumMSDKFunctions] = { @@ -44,15 +44,19 @@ LoaderCtxVPL::LoaderCtxVPL() : m_libInfoList(), m_implInfoList(), m_configCtxList(), - m_userSearchDirs(), - m_packageSearchDirs(), - m_pathSearchDirs(), - m_legacySearchDirs(), - m_vplPackageDir(), - m_driverStoreDir(), m_specialConfig(), m_implIdxNext(0), - m_bKeepCapsUntilUnload(true) { + m_bKeepCapsUntilUnload(true), + m_envVar(), + m_dispLog() { + // allow loader to distinguish between property value of 0 + // and property not set + m_specialConfig.bIsSet_deviceHandleType = false; + m_specialConfig.bIsSet_deviceHandle = false; + m_specialConfig.bIsSet_accelerationMode = false; + m_specialConfig.bIsSet_ApiVersion = false; + m_specialConfig.bIsSet_dxgiAdapterIdx = false; + return; } @@ -67,13 +71,14 @@ mfxU32 LoaderCtxVPL::ParseEnvSearchPaths(const CHAR_TYPE* envVarName, #if defined(_WIN32) || defined(_WIN64) DWORD err; - CHAR_TYPE envVar[MAX_VPL_SEARCH_PATH] = { L"" }; - err = GetEnvironmentVariableW(envVarName, envVar, MAX_VPL_SEARCH_PATH); - if (!err) - return 0; // environment variable not defined + m_envVar[0] = 0; + + err = GetEnvironmentVariableW(envVarName, m_envVar, MAX_ENV_VAR_LEN); + if (err == 0 || err >= MAX_ENV_VAR_LEN) + return 0; // environment variable not defined or string too long // parse env variable into individual directories - std::wstringstream envPath((CHAR_TYPE*)envVar); + std::wstringstream envPath((CHAR_TYPE*)m_envVar); STRING_TYPE s; while (std::getline(envPath, s, L';')) { searchDirs.push_back(s); @@ -124,7 +129,8 @@ mfxStatus LoaderCtxVPL::SearchDirForLibs(STRING_TYPE searchDir, // special case: do not include dispatcher itself (libmfx.dll, libvpl.dll) if (wcsstr(testFileData.cFileName, L"libmfx.dll") || - wcsstr(testFileData.cFileName, L"libvpl.dll")) + wcsstr(testFileData.cFileName, L"libvpl.dll") || + wcsstr(testFileData.cFileName, L"libvpld.dll")) continue; err = GetFullPathNameW(testFileData.cFileName, @@ -205,8 +211,10 @@ mfxStatus LoaderCtxVPL::SearchDirForLibs(STRING_TYPE searchDir, std::find_if(libInfoList.begin(), libInfoList.end(), [&](LibInfo* li) { return (li->libNameFull == fullPath); }); - if (libFound != libInfoList.end()) + if (libFound != libInfoList.end()) { + free(fullPath); continue; + } LibInfo* libInfo = new LibInfo; if (!libInfo) @@ -227,19 +235,98 @@ mfxStatus LoaderCtxVPL::SearchDirForLibs(STRING_TYPE searchDir, return MFX_ERR_NONE; } +mfxU32 LoaderCtxVPL::GetSearchPathsDriverStore(std::list& searchDirs) { + searchDirs.clear(); + +#if defined(_WIN32) || defined(_WIN64) + mfxStatus sts = MFX_ERR_UNSUPPORTED; + STRING_TYPE vplPath; + + mfxU32 numAdaptersD3D9 = 0; + mfxU32 numAdaptersDXGI1 = 0; + mfxU32 numAdaptersMax = 0; + + // query for number of D3D9 and D3D11 adapters on system + // conservatively check driver store from 0 to sum of adapters + // (though in practice D3D9 will usually be a subset of D3D11) + sts = MFX::GetNumDXGIAdapters(numAdaptersD3D9, numAdaptersDXGI1); + if (sts == MFX_ERR_NONE) + numAdaptersMax = numAdaptersD3D9 + numAdaptersDXGI1; + + if (numAdaptersMax == 0) + numAdaptersMax = MAX_WINDOWS_ADAPTER_ID + 1; + + // get path to Windows driver store + for (mfxU32 adapterID = 0; adapterID < numAdaptersMax; adapterID++) { + vplPath.clear(); + sts = MFX::MFXLibraryIterator::GetDriverStoreDir(vplPath, + MAX_VPL_SEARCH_PATH, + adapterID, + MFX::MFX_DRIVER_STORE_ONEVPL); + if (sts == MFX_ERR_NONE) + searchDirs.push_back(vplPath); + } +#endif + + return (mfxU32)searchDirs.size(); +} + +mfxU32 LoaderCtxVPL::GetSearchPathsCurrentExe(std::list& searchDirs) { + searchDirs.clear(); + +#if defined(_WIN32) || defined(_WIN64) + // get path to location of current executable + wchar_t implPath[MFX::msdk_disp_path_len]; + MFX::GetImplPath(MFX::MFX_APP_FOLDER, implPath); + STRING_TYPE exePath = implPath; + + // strip trailing backslach + size_t exePathLen = exePath.find_last_of(L"\\"); + if (exePathLen > 0) + exePath.erase(exePathLen); + + if (!exePath.empty()) + searchDirs.push_back(exePath); + +#endif + + return (mfxU32)searchDirs.size(); +} + +mfxU32 LoaderCtxVPL::GetSearchPathsCurrentDir(std::list& searchDirs) { + searchDirs.clear(); + +#if defined(_WIN32) || defined(_WIN64) + CHAR_TYPE currDir[MAX_VPL_SEARCH_PATH] = L""; + if (GetCurrentDirectoryW(MAX_VPL_SEARCH_PATH, currDir)) { + searchDirs.push_back(currDir); + } +#else + CHAR_TYPE currDir[MAX_VPL_SEARCH_PATH] = ""; + if (getcwd(currDir, MAX_VPL_SEARCH_PATH)) { + searchDirs.push_back(currDir); + } +#endif + + return (mfxU32)searchDirs.size(); +} + // get legacy MSDK dispatcher search paths // see "oneVPL Session" section in spec -mfxU32 LoaderCtxVPL::ParseLegacySearchPaths(std::list& searchDirs) { +mfxU32 LoaderCtxVPL::GetSearchPathsLegacy(std::list& searchDirs) { searchDirs.clear(); #if defined(_WIN32) || defined(_WIN64) mfxStatus sts = MFX_ERR_UNSUPPORTED; STRING_TYPE msdkPath; - // get path to Windows driver store + // get path to Windows driver store (MSDK) for (mfxU32 adapterID = 0; adapterID <= MAX_WINDOWS_ADAPTER_ID; adapterID++) { msdkPath.clear(); - sts = MFX::MFXLibraryIterator::GetDriverStoreDir(msdkPath, MAX_VPL_SEARCH_PATH, adapterID); + sts = MFX::MFXLibraryIterator::GetDriverStoreDir(msdkPath, + MAX_VPL_SEARCH_PATH, + adapterID, + MFX::MFX_DRIVER_STORE); if (sts == MFX_ERR_NONE) searchDirs.push_back(msdkPath); } @@ -248,7 +335,7 @@ mfxU32 LoaderCtxVPL::ParseLegacySearchPaths(std::list& searchDirs) msdkPath.clear(); sts = MFX::MFXLibraryIterator::GetRegkeyDir(msdkPath, MAX_VPL_SEARCH_PATH, - MFX::MFX_CURRENT_USER_KEY_ONEVPL); + MFX::MFX_CURRENT_USER_KEY); if (sts == MFX_ERR_NONE) searchDirs.push_back(msdkPath); @@ -256,29 +343,40 @@ mfxU32 LoaderCtxVPL::ParseLegacySearchPaths(std::list& searchDirs) msdkPath.clear(); sts = MFX::MFXLibraryIterator::GetRegkeyDir(msdkPath, MAX_VPL_SEARCH_PATH, - MFX::MFX_LOCAL_MACHINE_KEY_ONEVPL); + MFX::MFX_LOCAL_MACHINE_KEY); if (sts == MFX_ERR_NONE) searchDirs.push_back(msdkPath); - // get path to location of current executable - wchar_t implPath[MFX::msdk_disp_path_len]; - MFX::GetImplPath(MFX::MFX_APP_FOLDER, implPath); - STRING_TYPE exePath = implPath; + // get path to %windir%\system32 and %windir%\syswow64 + std::list winSysDir; + ParseEnvSearchPaths(L"windir", winSysDir); - // strip trailing backslach - size_t exePathLen = exePath.find_last_of(L"\\"); - if (exePathLen > 0) - exePath.erase(exePathLen); + // should resolve to a single directory, otherwise something went wrong + if (winSysDir.size() == 1) { + msdkPath = winSysDir.front() + L"\\system32"; + searchDirs.push_back(msdkPath); - if (!exePath.empty()) - searchDirs.push_back(exePath); + msdkPath = winSysDir.front() + L"\\syswow64"; + searchDirs.push_back(msdkPath); + } #else - // Linux + // MSDK open-source installation directories + searchDirs.push_back("/opt/intel/mediasdk/lib"); + searchDirs.push_back("/opt/intel/mediasdk/lib64"); +#endif + + return (mfxU32)searchDirs.size(); +} + +mfxU32 LoaderCtxVPL::GetSearchPathsSystemDefault(std::list& searchDirs) { + searchDirs.clear(); + +#ifdef __linux__ // Add the standard path for libmfx1 install in Ubuntu searchDirs.push_back("/usr/lib/x86_64-linux-gnu"); - // Add other legacy MSDK paths + // Add other default paths searchDirs.push_back("/lib"); searchDirs.push_back("/usr/lib"); searchDirs.push_back("/lib64"); @@ -291,56 +389,135 @@ mfxU32 LoaderCtxVPL::ParseLegacySearchPaths(std::list& searchDirs) // search for implementations of oneAPI Video Processing Library (oneVPL) // according to the rules in the spec mfxStatus LoaderCtxVPL::BuildListOfCandidateLibs() { + DISP_LOG_FUNCTION(&m_dispLog); + mfxStatus sts = MFX_ERR_NONE; STRING_TYPE emptyPath; // default construction = empty + std::list searchDirList; std::list::iterator it; - // first priority: user-defined directories in environment variable - ParseEnvSearchPaths(ENV_ONEVPL_SEARCH_PATH, m_userSearchDirs); - it = m_userSearchDirs.begin(); - while (it != m_userSearchDirs.end()) { +#if defined(_WIN32) || defined(_WIN64) + // first priority: Windows driver store + searchDirList.clear(); + GetSearchPathsDriverStore(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { STRING_TYPE nextDir = (*it); - sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_USER_DEFINED); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_01); it++; } - // second priority: oneVPL package - ParseEnvSearchPaths(ENV_ONEVPL_PACKAGE_PATH, m_packageSearchDirs); - it = m_packageSearchDirs.begin(); - while (it != m_packageSearchDirs.end()) { + // second priority: path to current executable + searchDirList.clear(); + GetSearchPathsCurrentExe(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { STRING_TYPE nextDir = (*it); - sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_VPL_PACKAGE); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_02); it++; } - // third priority: OS-specific PATH / LD_LIBRARY_PATH - ParseEnvSearchPaths(ENV_OS_PATH, m_pathSearchDirs); - it = m_pathSearchDirs.begin(); - while (it != m_pathSearchDirs.end()) { + // third priority: current working directory + searchDirList.clear(); + GetSearchPathsCurrentDir(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { STRING_TYPE nextDir = (*it); - sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_OS_PATH); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_03); it++; } - // fourth priority: default system folders (current location for now) - m_vplPackageDir = MAKE_STRING("./"); - sts = SearchDirForLibs(m_vplPackageDir, m_libInfoList, LIB_PRIORITY_SYS_DEFAULT); + // fourth priority: PATH environment variable + searchDirList.clear(); + ParseEnvSearchPaths(L"PATH", searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_04); + it++; + } - // fifth priority: standalone MSDK/driver installation - ParseLegacySearchPaths(m_legacySearchDirs); - it = m_legacySearchDirs.begin(); - while (it != m_legacySearchDirs.end()) { + // fifth priority: ONEVPL_SEARCH_PATH environment variable + searchDirList.clear(); + ParseEnvSearchPaths(L"ONEVPL_SEARCH_PATH", searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { STRING_TYPE nextDir = (*it); - sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_MSDK_PACKAGE); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_05); it++; } + // lowest priority: legacy MSDK installation + searchDirList.clear(); + GetSearchPathsLegacy(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_LEGACY); + it++; + } +#else + // first priority: LD_LIBRARY_PATH environment variable + searchDirList.clear(); + ParseEnvSearchPaths("LD_LIBRARY_PATH", searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_01); + it++; + } + + // second priority: Linux default paths + searchDirList.clear(); + GetSearchPathsSystemDefault(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_03); + it++; + } + + // third priority: current working directory + searchDirList.clear(); + GetSearchPathsCurrentDir(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_04); + it++; + } + + // fourth priority: ONEVPL_SEARCH_PATH environment variable + searchDirList.clear(); + ParseEnvSearchPaths("ONEVPL_SEARCH_PATH", searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_05); + it++; + } + + // lowest priority: legacy MSDK installation + searchDirList.clear(); + GetSearchPathsLegacy(searchDirList); + it = searchDirList.begin(); + while (it != searchDirList.end()) { + STRING_TYPE nextDir = (*it); + sts = SearchDirForLibs(nextDir, m_libInfoList, LIB_PRIORITY_LEGACY); + it++; + } +#endif + return sts; } // return number of valid libraries found mfxU32 LoaderCtxVPL::CheckValidLibraries() { + DISP_LOG_FUNCTION(&m_dispLog); + + LibInfo* msdkLibBest = nullptr; + // load all libraries std::list::iterator it = m_libInfoList.begin(); while (it != m_libInfoList.end()) { @@ -365,7 +542,8 @@ mfxU32 LoaderCtxVPL::CheckValidLibraries() { // validation of additional functions vs. API version takes place // during UpdateValidImplList() since the minimum API version requested // by application is not known yet (use SetConfigFilterProperty) - if (libInfo->vplFuncTable[IdxMFXInitialize]) { + if (libInfo->vplFuncTable[IdxMFXInitialize] && + libInfo->libPriority != LIB_PRIORITY_LEGACY) { libInfo->libType = LibTypeVPL; it++; continue; @@ -385,10 +563,20 @@ mfxU32 LoaderCtxVPL::CheckValidLibraries() { } // check if all of the required MSDK functions were found + // and this is valid library (can create session, query version) if (i == NumMSDKFunctions) { - libInfo->libType = LibTypeMSDK; - it++; - continue; + sts = LoaderCtxMSDK::QueryAPIVersion(libInfo->libNameFull, &(libInfo->msdkVersion)); + + if (sts == MFX_ERR_NONE) { + libInfo->libType = LibTypeMSDK; + if (msdkLibBest == nullptr || + (libInfo->msdkVersion.Version > msdkLibBest->msdkVersion.Version)) { + msdkLibBest = libInfo; + } + + it++; + continue; + } } // required functions missing from DLL, or DLL failed to load @@ -397,6 +585,20 @@ mfxU32 LoaderCtxVPL::CheckValidLibraries() { it = m_libInfoList.erase(it); } + // prune duplicate MSDK libraries (only keep one with highest API version) + it = m_libInfoList.begin(); + while (it != m_libInfoList.end()) { + LibInfo* libInfo = (*it); + + if (libInfo->libType == LibTypeMSDK && libInfo != msdkLibBest) { + UnloadSingleLibrary(libInfo); + it = m_libInfoList.erase(it); + } + else { + it++; + } + } + // number of valid oneVPL libs return (mfxU32)m_libInfoList.size(); } @@ -434,12 +636,14 @@ mfxStatus LoaderCtxVPL::LoadSingleLibrary(LibInfo* libInfo) { // unload single runtime mfxStatus LoaderCtxVPL::UnloadSingleLibrary(LibInfo* libInfo) { - if (libInfo && libInfo->hModuleVPL) { + if (libInfo) { + if (libInfo->hModuleVPL) { #if defined(_WIN32) || defined(_WIN64) - MFX::mfx_dll_free(libInfo->hModuleVPL); + MFX::mfx_dll_free(libInfo->hModuleVPL); #else - dlclose(libInfo->hModuleVPL); + dlclose(libInfo->hModuleVPL); #endif + } delete libInfo; return MFX_ERR_NONE; } @@ -451,6 +655,8 @@ mfxStatus LoaderCtxVPL::UnloadSingleLibrary(LibInfo* libInfo) { // iterate over all implementation runtimes // unload DLL's and free memory mfxStatus LoaderCtxVPL::UnloadAllLibraries() { + DISP_LOG_FUNCTION(&m_dispLog); + std::list::iterator it2 = m_implInfoList.begin(); while (it2 != m_implInfoList.end()) { ImplInfo* implInfo = (*it2); @@ -498,6 +704,8 @@ mfxStatus LoaderCtxVPL::UnloadSingleImplementation(ImplInfo* implInfo) { (*(mfxStatus(MFX_CDECL*)(mfxHDL))pFunc)(implInfo->implFuncs); implInfo->implFuncs = nullptr; } + + // nothing to do if (capsFormat == MFX_IMPLCAPS_IMPLPATH) since no new memory was allocated } delete implInfo; return MFX_ERR_NONE; @@ -518,11 +726,48 @@ mfxStatus LoaderCtxVPL::ValidateAPIExports(VPLFunctionPtr* vplFuncTable, return MFX_ERR_NONE; } +// convert full path into char* for MFX_IMPLCAPS_IMPLPATH query +mfxStatus LoaderCtxVPL::UpdateImplPath(LibInfo* libInfo) { +#if defined(_WIN32) || defined(_WIN64) + // Windows - strings are 16-bit + size_t nCvt = 0; + if (wcstombs_s(&nCvt, + libInfo->implCapsPath, + sizeof(libInfo->implCapsPath), + libInfo->libNameFull.c_str(), + _TRUNCATE)) { + // unknown error - set to empty string + libInfo->implCapsPath[0] = 0; + return MFX_ERR_UNSUPPORTED; + } +#else + // Linux - strings are 8-bit + strncpy(libInfo->implCapsPath, libInfo->libNameFull.c_str(), sizeof(libInfo->implCapsPath) - 1); +#endif + + return MFX_ERR_NONE; +} + +bool LoaderCtxVPL::IsValidX86GPU(ImplInfo* implInfo, mfxU32& deviceID, mfxU32& adapterIdx) { + mfxImplDescription* implDesc = (mfxImplDescription*)(implInfo->implDesc); + + if (implInfo->validImplIdx >= 0 && implDesc->VendorID == 0x8086 && + implDesc->Impl == MFX_IMPL_TYPE_HARDWARE) { + // verify that DeviceID is a valid format for x86 GPU + // either "DeviceID" (hex) or "DeviceID/AdapterIdx" (hex/dec) + return ConfigCtxVPL::ParseDeviceIDx86(implDesc->Dev.DeviceID, deviceID, adapterIdx); + } + + return false; +} + // query capabilities of all valid libraries // and add to list for future calls to EnumImplementations() // as well as filtering by functionality // assume MFX_IMPLCAPS_IMPLDESCSTRUCTURE is the only format supported mfxStatus LoaderCtxVPL::QueryLibraryCaps() { + DISP_LOG_FUNCTION(&m_dispLog); + mfxStatus sts = MFX_ERR_NONE; std::list::iterator it = m_libInfoList.begin(); @@ -539,7 +784,21 @@ mfxStatus LoaderCtxVPL::QueryLibraryCaps() { hImpl = (*(mfxHDL * (MFX_CDECL*)(mfxImplCapsDeliveryFormat, mfxU32*)) pFunc)(MFX_IMPLCAPS_IMPLDESCSTRUCTURE, &numImpls); + // validate description pointer for each implementation + bool b_isValidDesc = true; if (!hImpl) { + b_isValidDesc = false; + } + else { + for (mfxU32 i = 0; i < numImpls; i++) { + if (!hImpl[i]) { + b_isValidDesc = false; + break; + } + } + } + + if (!b_isValidDesc) { // the required function is implemented incorrectly // remove this library from the list of valid libraries UnloadSingleLibrary(libInfo); @@ -555,6 +814,9 @@ mfxStatus LoaderCtxVPL::QueryLibraryCaps() { hImplFuncs = (*(mfxHDL * (MFX_CDECL*)(mfxImplCapsDeliveryFormat, mfxU32*)) pFunc)(MFX_IMPLCAPS_IMPLEMENTEDFUNCTIONS, &numImplsFuncs); + // save user-friendly path for MFX_IMPLCAPS_IMPLPATH query (API >= 2.4) + UpdateImplPath(libInfo); + for (mfxU32 i = 0; i < numImpls; i++) { ImplInfo* implInfo = new ImplInfo; if (!implInfo) @@ -604,59 +866,76 @@ mfxStatus LoaderCtxVPL::QueryLibraryCaps() { } } else if (libInfo->libType == LibTypeMSDK) { - mfxImplDescription* implDesc = nullptr; - mfxImplementedFunctions* implFuncs = nullptr; + // save user-friendly path for MFX_IMPLCAPS_IMPLPATH query (API >= 2.4) + UpdateImplPath(libInfo); - libInfo->msdkCtx = new LoaderCtxMSDK; - if (!libInfo->msdkCtx) - return MFX_ERR_MEMORY_ALLOC; + mfxU32 numImplMSDK = 0; + for (mfxU32 i = 0; i < MAX_NUM_IMPL_MSDK; i++) { + mfxImplDescription* implDesc = nullptr; + mfxImplementedFunctions* implFuncs = nullptr; - sts = libInfo->msdkCtx->QueryMSDKCaps(libInfo->libNameFull, - &implDesc, - &implFuncs, - &libInfo->msdkCtx->msdkAdapter); + LoaderCtxMSDK* msdkCtx = &(libInfo->msdkCtx[i]); - if (sts || !implDesc || !implFuncs) { - // error loading MSDK library in compatibility mode - remove from list - UnloadSingleLibrary(libInfo); - it = m_libInfoList.erase(it); - continue; - } + sts = msdkCtx->QueryMSDKCaps(libInfo->libNameFull, &implDesc, &implFuncs, i); + + if (sts || !implDesc || !implFuncs) { + // this adapter (i) is not supported + continue; + } + + ImplInfo* implInfo = new ImplInfo; + if (!implInfo) + return MFX_ERR_MEMORY_ALLOC; + + // library which contains this implementation + implInfo->libInfo = libInfo; + + // implementation descriptor returned from runtime + implInfo->implDesc = implDesc; - ImplInfo* implInfo = new ImplInfo; - if (!implInfo) - return MFX_ERR_MEMORY_ALLOC; + // implemented function description, if available + implInfo->implFuncs = implFuncs; + + // fill out mfxInitializationParam for use in CreateSession (MFXInitialize path) + memset(&(implInfo->vplParam), 0, sizeof(mfxInitializationParam)); - // library which contains this implementation - implInfo->libInfo = libInfo; + // default mode for this impl + // this may be changed later by MFXSetConfigFilterProperty(AccelerationMode) + implInfo->vplParam.AccelerationMode = implDesc->AccelerationMode; - // implementation descriptor returned from runtime - implInfo->implDesc = implDesc; + implInfo->version = implDesc->ApiVersion; - // implemented function description, if available - implInfo->implFuncs = implFuncs; + // adapter number + implInfo->msdkImplIdx = i; - // fill out mfxInitializationParam for use in CreateSession (MFXInitialize path) - memset(&(implInfo->vplParam), 0, sizeof(mfxInitializationParam)); + // save local index for this library + implInfo->libImplIdx = 0; - // default mode for this impl - // this may be changed later by MFXSetConfigFilterProperty(AccelerationMode) - implInfo->vplParam.AccelerationMode = implDesc->AccelerationMode; + // initially all libraries have a valid, sequential value (>= 0) + // list of valid libraries is updated with every call to MFXSetConfigFilterProperty() + // (see UpdateValidImplList) + // libraries that do not support all the required props get a value of -1, and + // indexing of the valid libs is recalculated from 0,1,... + implInfo->validImplIdx = m_implIdxNext++; - implInfo->version = implDesc->ApiVersion; + // add implementation to overall list + m_implInfoList.push_back(implInfo); - // save local index for this library - implInfo->libImplIdx = 0; + // update number of valid MSDK adapters + numImplMSDK++; - // initially all libraries have a valid, sequential value (>= 0) - // list of valid libraries is updated with every call to MFXSetConfigFilterProperty() - // (see UpdateValidImplList) - // libraries that do not support all the required props get a value of -1, and - // indexing of the valid libs is recalculated from 0,1,... - implInfo->validImplIdx = m_implIdxNext++; +#ifdef __linux__ + // currently only one adapter on Linux (avoid multiple copies) + break; +#endif + } - // add implementation to overall list - m_implInfoList.push_back(implInfo); + if (numImplMSDK == 0) { + // error loading MSDK library in compatibility mode - remove from list + UnloadSingleLibrary(libInfo); + it = m_libInfoList.erase(it); + continue; + } } it++; } @@ -666,6 +945,13 @@ mfxStatus LoaderCtxVPL::QueryLibraryCaps() { while (it2 != m_implInfoList.end()) { ImplInfo* implInfo = (*it2); + mfxU32 deviceID = 0; + mfxU32 adapterIdx = 0; + if (IsValidX86GPU(implInfo, deviceID, adapterIdx)) { + // save the adapterIdx for any x86 GPU devices (may be used later for filtering) + implInfo->adapterIdx = adapterIdx; + } + // per spec: if both VPL (HW) and MSDK are installed on the same system, only load // the VPL library (mark MSDK as invalid) if (implInfo->libInfo->libType == LibTypeMSDK) { @@ -696,6 +982,8 @@ mfxStatus LoaderCtxVPL::QueryLibraryCaps() { // query implementation i mfxStatus LoaderCtxVPL::QueryImpl(mfxU32 idx, mfxImplCapsDeliveryFormat format, mfxHDL* idesc) { + DISP_LOG_FUNCTION(&m_dispLog); + *idesc = nullptr; std::list::iterator it = m_implInfoList.begin(); @@ -708,6 +996,9 @@ mfxStatus LoaderCtxVPL::QueryImpl(mfxU32 idx, mfxImplCapsDeliveryFormat format, else if (format == MFX_IMPLCAPS_IMPLEMENTEDFUNCTIONS) { *idesc = implInfo->implFuncs; } + else if (format == MFX_IMPLCAPS_IMPLPATH) { + *idesc = implInfo->libInfo->implCapsPath; + } // implementation found, but requested query format is not supported if (*idesc == nullptr) @@ -723,6 +1014,8 @@ mfxStatus LoaderCtxVPL::QueryImpl(mfxU32 idx, mfxImplCapsDeliveryFormat format, } mfxStatus LoaderCtxVPL::ReleaseImpl(mfxHDL idesc) { + DISP_LOG_FUNCTION(&m_dispLog); + mfxStatus sts = MFX_ERR_NONE; if (idesc == nullptr) @@ -744,6 +1037,9 @@ mfxStatus LoaderCtxVPL::ReleaseImpl(mfxHDL idesc) { else if (implInfo->implFuncs == idesc) { capsFormat = MFX_IMPLCAPS_IMPLEMENTEDFUNCTIONS; } + else if (implInfo->libInfo->implCapsPath == idesc) { + capsFormat = MFX_IMPLCAPS_IMPLPATH; + } else { // no match - try next implementation it++; @@ -770,6 +1066,8 @@ mfxStatus LoaderCtxVPL::ReleaseImpl(mfxHDL idesc) { sts = (*(mfxStatus(MFX_CDECL*)(mfxHDL))pFunc)(implInfo->implFuncs); implInfo->implFuncs = nullptr; } + + // nothing to do if (capsFormat == MFX_IMPLCAPS_IMPLPATH) since no new memory was allocated } return sts; @@ -780,6 +1078,8 @@ mfxStatus LoaderCtxVPL::ReleaseImpl(mfxHDL idesc) { } mfxStatus LoaderCtxVPL::UpdateValidImplList(void) { + DISP_LOG_FUNCTION(&m_dispLog); + mfxStatus sts = MFX_ERR_NONE; mfxI32 validImplIdx = 0; @@ -803,6 +1103,12 @@ mfxStatus LoaderCtxVPL::UpdateValidImplList(void) { implInfo->libInfo->libType, &m_specialConfig); + // check special filter properties which are not part of mfxImplDescription + if (m_specialConfig.bIsSet_dxgiAdapterIdx && + (m_specialConfig.dxgiAdapterIdx != implInfo->adapterIdx)) { + sts = MFX_ERR_UNSUPPORTED; + } + if (sts == MFX_ERR_NONE) { // library supports all required properties implInfo->validImplIdx = validImplIdx++; @@ -828,9 +1134,18 @@ mfxStatus LoaderCtxVPL::UpdateValidImplList(void) { // 1) Hardware implementation has priority over software implementation. // 2) General hardware implementation has priority over VSI hardware implementation. // 3) Highest API version has higher priority over lower API version. +// 4) Search path priority: lower values = higher priority mfxStatus LoaderCtxVPL::PrioritizeImplList(void) { + DISP_LOG_FUNCTION(&m_dispLog); + // stable sort - work from lowest to highest priority conditions + // 4 - sort by search path priority + m_implInfoList.sort([](const ImplInfo* impl1, const ImplInfo* impl2) { + // prioritize lowest value for libPriority (1 = highest priority) + return (impl1->libInfo->libPriority < impl2->libInfo->libPriority); + }); + // 3 - sort by API version m_implInfoList.sort([](const ImplInfo* impl1, const ImplInfo* impl2) { mfxImplDescription* implDesc1 = (mfxImplDescription*)(impl1->implDesc); @@ -876,6 +1191,8 @@ mfxStatus LoaderCtxVPL::PrioritizeImplList(void) { } mfxStatus LoaderCtxVPL::CreateSession(mfxU32 idx, mfxSession* session) { + DISP_LOG_FUNCTION(&m_dispLog); + mfxStatus sts = MFX_ERR_NONE; // find library with given implementation index @@ -901,22 +1218,31 @@ mfxStatus LoaderCtxVPL::CreateSession(mfxU32 idx, mfxSession* session) { implInfo->vplParam.VendorImplID = implDesc->VendorImplID; // set any special parameters passed in via SetConfigProperty - if (m_specialConfig.accelerationMode) + // if application did not specify accelerationMode, use default + if (m_specialConfig.bIsSet_accelerationMode) implInfo->vplParam.AccelerationMode = m_specialConfig.accelerationMode; + mfxIMPL msdkImpl = 0; + if (libInfo->libType == LibTypeMSDK) { + if (implInfo->vplParam.AccelerationMode == MFX_ACCEL_MODE_VIA_D3D9) + msdkImpl = libInfo->msdkCtx[implInfo->msdkImplIdx].m_msdkAdapterD3D9; + else + msdkImpl = libInfo->msdkCtx[implInfo->msdkImplIdx].m_msdkAdapter; + } + // initialize this library via MFXInitialize or else fail // (specify full path to library) - sts = MFXInitEx2( - implInfo->version, - implInfo->vplParam, - (libInfo->libType == LibTypeMSDK ? libInfo->msdkCtx->msdkAdapter : 0), - session, - &deviceID, - (CHAR_TYPE*)libInfo->libNameFull.c_str()); + sts = MFXInitEx2(implInfo->version, + implInfo->vplParam, + msdkImpl, + session, + &deviceID, + (CHAR_TYPE*)libInfo->libNameFull.c_str()); } // optionally call MFXSetHandle() if present via SetConfigProperty - if (sts == MFX_ERR_NONE && m_specialConfig.deviceHandleType && + if (sts == MFX_ERR_NONE && m_specialConfig.bIsSet_deviceHandleType && + m_specialConfig.bIsSet_deviceHandle && m_specialConfig.deviceHandleType && m_specialConfig.deviceHandle) { sts = MFXVideoCORE_SetHandle(*session, m_specialConfig.deviceHandleType, @@ -933,6 +1259,8 @@ mfxStatus LoaderCtxVPL::CreateSession(mfxU32 idx, mfxSession* session) { } ConfigCtxVPL* LoaderCtxVPL::AddConfigFilter() { + DISP_LOG_FUNCTION(&m_dispLog); + // create new config filter context and add // to list associated with this loader std::unique_ptr configCtx; @@ -952,6 +1280,8 @@ ConfigCtxVPL* LoaderCtxVPL::AddConfigFilter() { } mfxStatus LoaderCtxVPL::FreeConfigFilters() { + DISP_LOG_FUNCTION(&m_dispLog); + std::list::iterator it = m_configCtxList.begin(); while (it != m_configCtxList.end()) { @@ -963,3 +1293,51 @@ mfxStatus LoaderCtxVPL::FreeConfigFilters() { return MFX_ERR_NONE; } + +mfxStatus LoaderCtxVPL::InitDispatcherLog() { + std::string strLogEnabled, strLogFile; + +#if defined(_WIN32) || defined(_WIN64) + DWORD err; + + char logEnabled[MAX_VPL_SEARCH_PATH] = ""; + err = GetEnvironmentVariable("ONEVPL_DISPATCHER_LOG", logEnabled, MAX_VPL_SEARCH_PATH); + if (err == 0 || err >= MAX_VPL_SEARCH_PATH) + return MFX_ERR_UNSUPPORTED; // environment variable not defined or string too long + + strLogEnabled = logEnabled; + + char logFile[MAX_VPL_SEARCH_PATH] = ""; + err = GetEnvironmentVariable("ONEVPL_DISPATCHER_LOG_FILE", logFile, MAX_VPL_SEARCH_PATH); + if (err == 0 || err >= MAX_VPL_SEARCH_PATH) { + // nothing to do - strLogFile is an empty string + } + else { + strLogFile = logFile; + } + +#else + const char* logEnabled = std::getenv("ONEVPL_DISPATCHER_LOG"); + if (!logEnabled) + return MFX_ERR_UNSUPPORTED; + + strLogEnabled = logEnabled; + + const char* logFile = std::getenv("ONEVPL_DISPATCHER_LOG_FILE"); + if (logFile) + strLogFile = logFile; +#endif + + if (strLogEnabled != "ON") + return MFX_ERR_UNSUPPORTED; + + // currently logLevel is either 0 or non-zero + // additional levels will be added with future API updates + return m_dispLog.Init(1, strLogFile); +} + +// public function to return logger object +// allows logging from C API functions outside of loaderCtx +DispatcherLogVPL* LoaderCtxVPL::GetLogger() { + return &m_dispLog; +} diff --git a/dispatcher/vpl/mfx_dispatcher_vpl_log.cpp b/dispatcher/vpl/mfx_dispatcher_vpl_log.cpp new file mode 100644 index 00000000..1337724e --- /dev/null +++ b/dispatcher/vpl/mfx_dispatcher_vpl_log.cpp @@ -0,0 +1,63 @@ +/*############################################################################ + # Copyright (C) Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#include "vpl/mfx_dispatcher_vpl_log.h" + +DispatcherLogVPL::DispatcherLogVPL() : m_logLevel(0), m_logFileName(), m_logFile(nullptr) {} + +DispatcherLogVPL::~DispatcherLogVPL() { + if (!m_logFileName.empty() && m_logFile) + fclose(m_logFile); + m_logFile = nullptr; +} + +mfxStatus DispatcherLogVPL::Init(mfxU32 logLevel, const std::string &logFileName) { + // avoid leaking file handle if Init is accidentally called more than once + if (m_logFile) + return MFX_ERR_UNSUPPORTED; + + m_logLevel = logLevel; + m_logFileName = logFileName; + + // append to file if it already exists, otherwise create a new one + // m_logFile will be closed in dtor + if (m_logLevel) { + if (m_logFileName.empty()) { + m_logFile = stdout; + } + else { +#if defined(_WIN32) || defined(_WIN64) + fopen_s(&m_logFile, m_logFileName.c_str(), "a"); +#else + m_logFile = fopen(m_logFileName.c_str(), "a"); +#endif + if (!m_logFile) { + m_logFile = stdout; + fprintf(m_logFile, + "Warning - unable to create logfile %s\n", + m_logFileName.c_str()); + fprintf(m_logFile, "Log output will be sent to stdout\n"); + m_logFileName.clear(); + } + } + } + + return MFX_ERR_NONE; +} + +mfxStatus DispatcherLogVPL::LogMessage(const char *msg, ...) { + if (!m_logLevel || !m_logFile) + return MFX_ERR_NONE; + + va_list args; + va_start(args, msg); + vfprintf(m_logFile, msg, args); + va_end(args); + + fprintf(m_logFile, "\n"); + + return MFX_ERR_NONE; +} diff --git a/dispatcher/vpl/mfx_dispatcher_vpl_log.h b/dispatcher/vpl/mfx_dispatcher_vpl_log.h new file mode 100644 index 00000000..2037e6da --- /dev/null +++ b/dispatcher/vpl/mfx_dispatcher_vpl_log.h @@ -0,0 +1,75 @@ +/*############################################################################ + # Copyright (C) Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef DISPATCHER_VPL_MFX_DISPATCHER_VPL_LOG_H_ +#define DISPATCHER_VPL_MFX_DISPATCHER_VPL_LOG_H_ + +/* oneVPL Dispatcher Debug Log + * The debug output of the dispatcher is controlled with the ONEVPL_DISPATCHER_LOG environment variable. + * To enable log output, set the ONEVPL_DISPATCHER_LOG environment variable value equals to "ON". + * + * By default, oneVPL dispatcher prints all log messages to the console. + * To redirect log output to the desired file, set the ONEVPL_DISPATCHER_LOG_FILE environmental + * variable with the file name of the log file. + */ + +#include +#include + +#include + +#include "vpl/mfxdispatcher.h" +#include "vpl/mfxvideo.h" + +#ifndef __FUNC_NAME__ + #if defined(_WIN32) || defined(_WIN64) + #define __FUNC_NAME__ __FUNCTION__ + #else + #define __FUNC_NAME__ __PRETTY_FUNCTION__ + #endif +#endif + +class DispatcherLogVPL { +public: + DispatcherLogVPL(); + ~DispatcherLogVPL(); + + mfxStatus Init(mfxU32 logLevel, const std::string &logFileName); + mfxStatus LogMessage(const char *msdk, ...); + + mfxU32 m_logLevel; + +private: + std::string m_logFileName; + FILE *m_logFile; +}; + +class DispatcherLogVPLFunction { +public: + DispatcherLogVPLFunction(DispatcherLogVPL *dispLog, const char *fnName) + : m_dispLog(), + m_fnName() { + m_dispLog = dispLog; + + if (m_dispLog && m_dispLog->m_logLevel) { + m_fnName = fnName; + m_dispLog->LogMessage("function: %s (enter)", m_fnName.c_str()); + } + } + + ~DispatcherLogVPLFunction() { + if (m_dispLog && m_dispLog->m_logLevel) + m_dispLog->LogMessage("function: %s (return)", m_fnName.c_str()); + } + +private: + DispatcherLogVPL *m_dispLog; + std::string m_fnName; +}; + +#define DISP_LOG_FUNCTION(dispLog) DispatcherLogVPLFunction _dispLogFn(dispLog, __FUNC_NAME__); + +#endif // DISPATCHER_VPL_MFX_DISPATCHER_VPL_LOG_H_ diff --git a/dispatcher/vpl/mfx_dispatcher_vpl_msdk.cpp b/dispatcher/vpl/mfx_dispatcher_vpl_msdk.cpp index 5d622d8c..f0fc0302 100644 --- a/dispatcher/vpl/mfx_dispatcher_vpl_msdk.cpp +++ b/dispatcher/vpl/mfx_dispatcher_vpl_msdk.cpp @@ -14,8 +14,8 @@ // leave table formatting alone // clang-format off -static const mfxChar strImplName[MFX_IMPL_NAME_LEN] = "MSDK RT (compatibility mode)"; -static const mfxChar strLicense[MFX_STRFIELD_LEN] = "MIT"; +static const mfxChar strImplName[MFX_IMPL_NAME_LEN] = "mfxhw64"; +static const mfxChar strLicense[MFX_STRFIELD_LEN] = ""; #if defined _M_IX86 static const mfxChar strKeywords[MFX_STRFIELD_LEN] = "MSDK,x86"; @@ -23,11 +23,17 @@ static const mfxChar strKeywords[MFX_STRFIELD_LEN] = "MSDK,x86"; static const mfxChar strKeywords[MFX_STRFIELD_LEN] = "MSDK,x64"; #endif +static const mfxIMPL msdkImplTab[MAX_NUM_IMPL_MSDK] = { + MFX_IMPL_HARDWARE, + MFX_IMPL_HARDWARE2, + MFX_IMPL_HARDWARE3, + MFX_IMPL_HARDWARE4, +}; + static const mfxAccelerationMode MSDKAccelModes[] = { #ifdef __linux__ MFX_ACCEL_MODE_VIA_VAAPI, #else - MFX_ACCEL_MODE_VIA_D3D9, MFX_ACCEL_MODE_VIA_D3D11, #endif }; @@ -86,15 +92,9 @@ static const mfxImplementedFunctions msdkImplFuncs = { // end table formatting // clang-format on -static const mfxIMPL hwImplTypes[] = { - MFX_IMPL_HARDWARE, - MFX_IMPL_HARDWARE2, - MFX_IMPL_HARDWARE3, - MFX_IMPL_HARDWARE4, -}; - LoaderCtxMSDK::LoaderCtxMSDK() - : msdkAdapter(), + : m_msdkAdapter(), + m_msdkAdapterD3D9(), m_libNameFull(), m_id(), m_accelMode(), @@ -147,19 +147,21 @@ mfxAccelerationMode LoaderCtxMSDK::CvtAccelType(mfxIMPL implType, mfxIMPL implMe return MFX_ACCEL_MODE_NA; } -mfxStatus LoaderCtxMSDK::GetDefaultAccelType(mfxU32 adapterID, mfxIMPL* implDefault) { +mfxStatus LoaderCtxMSDK::GetDefaultAccelType(mfxU32 adapterID, mfxIMPL* implDefault, mfxU64* luid) { #ifdef __linux__ // VAAPI only *implDefault = MFX_IMPL_VIA_VAAPI; + *luid = 0; return MFX_ERR_NONE; #else - // get default acceleration modes + // Windows - D3D11 only mfxU32 VendorID = 0, DeviceID = 0; mfxIMPL implTest; mfxStatus sts; - implTest = MFX_IMPL_VIA_ANY; - sts = MFX::SelectImplementationType(adapterID, &implTest, &VendorID, &DeviceID); + // check whether adapterID supports D3D11 and has correct VendorID + implTest = MFX_IMPL_VIA_D3D11; + sts = MFX::SelectImplementationType(adapterID, &implTest, &VendorID, &DeviceID, luid); if (sts != MFX_ERR_NONE || VendorID != 0x8086) { implTest = MFX_IMPL_UNSUPPORTED; @@ -172,39 +174,66 @@ mfxStatus LoaderCtxMSDK::GetDefaultAccelType(mfxU32 adapterID, mfxIMPL* implDefa #endif } -mfxStatus LoaderCtxMSDK::CheckAccelType(mfxU32 adapterID, mfxIMPL implTest) { -#ifdef __linux__ - // VAAPI only - if (implTest != MFX_IMPL_VIA_VAAPI) - return MFX_ERR_UNSUPPORTED; - - return MFX_ERR_NONE; -#else - // get default acceleration modes - mfxU32 VendorID = 0, DeviceID = 0; +mfxStatus LoaderCtxMSDK::QueryAPIVersion(STRING_TYPE libNameFull, mfxVersion* msdkVersion) { mfxStatus sts; + mfxSession session = nullptr; - sts = MFX::SelectImplementationType(adapterID, &implTest, &VendorID, &DeviceID); + mfxVersion reqVersion; + reqVersion.Major = MSDK_MIN_VERSION_MAJOR; + reqVersion.Minor = MSDK_MIN_VERSION_MINOR; - if (sts != MFX_ERR_NONE || VendorID != 0x8086) - return MFX_ERR_UNSUPPORTED; + // try creating a session with each adapter in order to get MSDK API version + // stop with first successful session creation + for (mfxU32 adapterID = 0; adapterID < MAX_NUM_IMPL_MSDK; adapterID++) { + // try HW session, default acceleration mode + mfxIMPL hwImpl = msdkImplTab[adapterID]; + mfxIMPL implDefault = MFX_IMPL_UNSUPPORTED; + mfxU64 luid; - return MFX_ERR_NONE; -#endif + // if not a valid HW device, try next adapter + sts = GetDefaultAccelType(adapterID, &implDefault, &luid); + if (sts != MFX_ERR_NONE) + continue; + + // set acceleration mode - will be mapped to 1.x API + mfxInitializationParam vplParam = {}; + vplParam.AccelerationMode = + (mfxAccelerationMode)CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00); + + mfxU16 deviceID; + sts = MFXInitEx2(reqVersion, + vplParam, + hwImpl, + &session, + &deviceID, + (CHAR_TYPE*)libNameFull.c_str()); + + if (sts == MFX_ERR_NONE) { + sts = MFXQueryVersion(session, msdkVersion); + MFXClose(session); + + if (sts == MFX_ERR_NONE) + return sts; + } + } + + return MFX_ERR_UNSUPPORTED; } mfxStatus LoaderCtxMSDK::QueryMSDKCaps(STRING_TYPE libNameFull, mfxImplDescription** implDesc, mfxImplementedFunctions** implFuncs, - mfxIMPL* msdkAdapter) { + mfxU32 adapterID) { +#ifdef DISABLE_MSDK_COMPAT + // disable support for legacy MSDK + return MFX_ERR_UNSUPPORTED; +#endif + mfxStatus sts; - mfxSession session; + mfxSession session = nullptr; m_libNameFull = libNameFull; - mfxIMPL msdkImplType = MFX_IMPL_UNSUPPORTED; - *msdkAdapter = MFX_IMPL_UNSUPPORTED; - #ifdef __linux__ // require pthreads to be linked in for MSDK RT to load pthread_key_t pkey; @@ -213,48 +242,23 @@ mfxStatus LoaderCtxMSDK::QueryMSDKCaps(STRING_TYPE libNameFull, } #endif - // try HW session, default acceleration mode, search for first supported device - mfxIMPL hwImpl = MFX_IMPL_AUTO; + // try HW session, default acceleration mode + mfxIMPL hwImpl = msdkImplTab[adapterID]; mfxIMPL implDefault = MFX_IMPL_UNSUPPORTED; - for (mfxU32 i = 0; i < TAB_SIZE(mfxIMPL, hwImplTypes); i++) { - hwImpl = hwImplTypes[i]; - - sts = GetDefaultAccelType(i, &implDefault); - if (sts != MFX_ERR_NONE) { - // unsupported - continue; - } - - sts = - OpenSession(&session, - m_libNameFull, - (mfxAccelerationMode)CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00), - hwImpl); - - if (sts == MFX_ERR_NONE) { - // hwImpl now indicates which adapter succeeded - msdkImplType = MFX_IMPL_HARDWARE; - break; - } - } + mfxU64 luid = 0; -#ifdef ENABLE_MSDK_SW_FALLBACK - // if HW failed, try SW session - if (msdkImplType == MFX_IMPL_UNSUPPORTED) { - sts = OpenSession(&session, m_libNameFull, MFX_ACCEL_MODE_NA, MFX_IMPL_SOFTWARE); - if (sts == MFX_ERR_NONE) { - msdkImplType = MFX_IMPL_SOFTWARE; - } - } -#endif - - // failed to initialize with any impl type - if (msdkImplType == MFX_IMPL_UNSUPPORTED) + sts = GetDefaultAccelType(adapterID, &implDefault, &luid); + if (sts != MFX_ERR_NONE) return MFX_ERR_UNSUPPORTED; - // failed to initialize with any impl type + sts = OpenSession(&session, + m_libNameFull, + (mfxAccelerationMode)CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00), + hwImpl); + + // adapter unsupported if (sts != MFX_ERR_NONE) - return sts; + return MFX_ERR_UNSUPPORTED; // return list of implemented functions *implFuncs = (mfxImplementedFunctions*)(&msdkImplFuncs); @@ -265,90 +269,45 @@ mfxStatus LoaderCtxMSDK::QueryMSDKCaps(STRING_TYPE libNameFull, // fill in top-level capabilities m_id.Version.Version = MFX_IMPLDESCRIPTION_VERSION; + m_id.Impl = MFX_IMPL_TYPE_HARDWARE; // query API version sts = MFXQueryVersion(session, &m_id.ApiVersion); - if (sts != MFX_ERR_NONE) + if (sts != MFX_ERR_NONE) { + CloseSession(&session); return sts; + } + + // set default acceleration mode + m_id.AccelerationMode = CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00); // fill in acceleration description struct mfxAccelerationModeDescription* accelDesc = &(m_id.AccelerationModeDescription); accelDesc->Version.Version = MFX_ACCELERATIONMODESCRIPTION_VERSION; - accelDesc->NumAccelerationModes = 0; - accelDesc->Mode = m_accelMode; - - if (msdkImplType == MFX_IMPL_HARDWARE) { - // query actual implementation for this session - mfxIMPL actualImpl = {}; - sts = MFXQueryIMPL(session, &actualImpl); - if (sts != MFX_ERR_NONE) - return sts; - - // return HW accelerator - required by MFXCreateSession - *msdkAdapter = hwImpl; - - // map MFX HW number to VendorImplID - m_id.VendorImplID = 0; - switch (hwImpl) { - case MFX_IMPL_HARDWARE: - m_id.VendorImplID = 0; - break; - case MFX_IMPL_HARDWARE2: - m_id.VendorImplID = 1; - break; - case MFX_IMPL_HARDWARE3: - m_id.VendorImplID = 2; - break; - case MFX_IMPL_HARDWARE4: - m_id.VendorImplID = 3; - break; - } - - // set default acceleration mode - m_id.AccelerationMode = CvtAccelType(MFX_IMPL_HARDWARE, implDefault & 0xFF00); - - CloseSession(&session); - - // hardware - test for all supported acceleration modes - m_id.Impl = MFX_IMPL_TYPE_HARDWARE; - for (mfxU32 i = 0; i < TAB_SIZE(mfxAccelerationMode, MSDKAccelModes); i++) { - // check if this accelerator type is supported - if (CheckAccelType(m_id.VendorImplID, MSDKAccelModes[i]) != MFX_ERR_NONE) - continue; - sts = OpenSession(&session, m_libNameFull, MSDKAccelModes[i], hwImpl); + // fill in mode description with just the single (default) mode + accelDesc->NumAccelerationModes = 1; + accelDesc->Mode = m_accelMode; + accelDesc->Mode[0] = m_id.AccelerationMode; - if (sts == MFX_ERR_NONE) { - mfxU16 m = accelDesc->NumAccelerationModes; + // return HW accelerator - required by MFXCreateSession + m_msdkAdapter = hwImpl; - accelDesc->Mode[m] = MSDKAccelModes[i]; - accelDesc->NumAccelerationModes++; - - CloseSession(&session); - } - } - - // at least one acceleration mode must be supported - if (accelDesc->NumAccelerationModes == 0) - return MFX_ERR_UNSUPPORTED; - - // if QueryIMPL did not set VIA flag, set default to first supported mode - if (!m_id.AccelerationMode) - m_id.AccelerationMode = accelDesc->Mode[0]; - - // reopen session with default mode - sts = OpenSession(&session, m_libNameFull, m_id.AccelerationMode, hwImpl); - if (sts != MFX_ERR_NONE) - return sts; - } - else { - // software - set default accel mode - m_id.Impl = MFX_IMPL_TYPE_SOFTWARE; - m_id.AccelerationMode = MFX_ACCEL_MODE_NA; - m_id.VendorImplID = 0; - - accelDesc->NumAccelerationModes = 1; - accelDesc->Mode[0] = MFX_ACCEL_MODE_NA; + // map MFX HW number to VendorImplID + m_id.VendorImplID = 0; + switch (hwImpl) { + case MFX_IMPL_HARDWARE: + m_id.VendorImplID = 0; + break; + case MFX_IMPL_HARDWARE2: + m_id.VendorImplID = 1; + break; + case MFX_IMPL_HARDWARE3: + m_id.VendorImplID = 2; + break; + case MFX_IMPL_HARDWARE4: + m_id.VendorImplID = 3; + break; } // fill in strings @@ -378,11 +337,75 @@ mfxStatus LoaderCtxMSDK::QueryMSDKCaps(STRING_TYPE libNameFull, if (deviceID == 0) deviceID = m_loaderDeviceID; + // store DeviceID as "DevID" (hex) / "AdapterIdx" (dec) to match GPU RT Dev->Version.Version = MFX_DEVICEDESCRIPTION_VERSION; - snprintf(Dev->DeviceID, sizeof(Dev->DeviceID), "%04x", deviceID); + snprintf(Dev->DeviceID, sizeof(Dev->DeviceID), "%x/%d", deviceID, m_id.VendorImplID); Dev->NumSubDevices = 0; CloseSession(&session); +#if defined(_WIN32) || defined(_WIN64) + mfxIMPL implD3D9; + m_msdkAdapterD3D9 = MFX_IMPL_UNSUPPORTED; + + sts = CheckD3D9Support(luid, libNameFull, &implD3D9); + if (sts == MFX_ERR_NONE) { + m_msdkAdapterD3D9 = implD3D9; + + accelDesc->Mode[accelDesc->NumAccelerationModes] = MFX_ACCEL_MODE_VIA_D3D9; + accelDesc->NumAccelerationModes++; + } +#endif + return MFX_ERR_NONE; } + +mfxStatus LoaderCtxMSDK::CheckD3D9Support(mfxU64 luid, STRING_TYPE libNameFull, mfxIMPL* implD3D9) { +#if defined(_WIN32) || defined(_WIN64) + mfxU32 VendorID = 0, DeviceID = 0; + mfxIMPL implTest = MFX_IMPL_VIA_D3D9; + + mfxStatus sts; + mfxSession session = nullptr; + + mfxVersion reqVersion; + reqVersion.Major = MSDK_MIN_VERSION_MAJOR; + reqVersion.Minor = MSDK_MIN_VERSION_MINOR; + + *implD3D9 = MFX_IMPL_UNSUPPORTED; + + mfxU32 idx; + for (idx = 0; idx < MAX_NUM_IMPL_MSDK; idx++) { + mfxU64 luidD3D9 = 0; + sts = MFX::SelectImplementationType(idx, &implTest, &VendorID, &DeviceID, &luidD3D9); + + if (sts != MFX_ERR_NONE || VendorID != 0x8086 || luid != luidD3D9) + continue; + + // matching LUID - try creating a D3D9 session + mfxInitializationParam vplParam = {}; + vplParam.AccelerationMode = MFX_ACCEL_MODE_VIA_D3D9; + + mfxU16 deviceID; + sts = MFXInitEx2(reqVersion, + vplParam, + msdkImplTab[idx], + &session, + &deviceID, + (CHAR_TYPE*)libNameFull.c_str()); + + if (sts == MFX_ERR_NONE) { + *implD3D9 = msdkImplTab[idx]; + MFXClose(session); + return MFX_ERR_NONE; + } + + break; // D3D9 not supported + } + + // this adapter (input luid) does not support D3D9 + return MFX_ERR_UNSUPPORTED; +#else + return MFX_ERR_UNSUPPORTED; +#endif +} diff --git a/dispatcher/windows/main.cpp b/dispatcher/windows/main.cpp index da2d7fd3..3f062200 100644 --- a/dispatcher/windows/main.cpp +++ b/dispatcher/windows/main.cpp @@ -556,8 +556,9 @@ mfxStatus MFXInitEx2(mfxVersion version, vplParam); } // unload the failed DLL - if ((MFX_ERR_NONE != mfxRes) && (MFX_WRN_PARTIAL_ACCELERATION != mfxRes)) { + if (MFX_ERR_NONE != mfxRes) { pHandle->Close(); + delete pHandle; return MFX_ERR_UNSUPPORTED; } else { diff --git a/dispatcher/windows/mfx_dxva2_device.cpp b/dispatcher/windows/mfx_dxva2_device.cpp index 2a940784..fa913468 100644 --- a/dispatcher/windows/mfx_dxva2_device.cpp +++ b/dispatcher/windows/mfx_dxva2_device.cpp @@ -326,6 +326,8 @@ bool DXGI1Device::Init(const mfxU32 adapterNum) { } while (SUCCEEDED(hRes)); maxAdapters = curAdapter; + m_numAdapters = maxAdapters; + // there is no required adapter if (adapterNum >= maxAdapters) { return false; @@ -354,6 +356,8 @@ DXVA2Device::DXVA2Device(void) { m_deviceID = 0; m_driverVersion = 0; + + m_luid = 0; } // DXVA2Device::DXVA2Device(void) DXVA2Device::~DXVA2Device(void) { @@ -396,6 +400,7 @@ bool DXVA2Device::InitD3D9(const mfxU32 adapterNum) { m_vendorID = d3d9Device.GetVendorID(); m_deviceID = d3d9Device.GetDeviceID(); m_driverVersion = d3d9Device.GetDriverVersion(); + m_luid = d3d9Device.GetLUID(); } // ... say goodbye @@ -425,6 +430,7 @@ bool DXVA2Device::InitDXGI1(const mfxU32 adapterNum) { m_vendorID = dxgi1Device.GetVendorID(); m_deviceID = dxgi1Device.GetDeviceID(); m_numAdapters = dxgi1Device.GetAdapterCount(); + m_luid = dxgi1Device.GetLUID(); // ... say goodbye return true; @@ -457,6 +463,7 @@ void DXVA2Device::UseAlternativeWay(const D3D9Device *pD3D9Device) { m_vendorID = dxgi1Device.GetVendorID(); m_deviceID = dxgi1Device.GetDeviceID(); m_driverVersion = dxgi1Device.GetDriverVersion(); + m_luid = dxgi1Device.GetLUID(); return; } @@ -489,3 +496,7 @@ mfxU32 DXVA2Device::GetAdapterCount(void) const { return m_numAdapters; } // mfxU32 DXVA2Device::GetAdapterCount(void) const + +mfxU64 DXVA2Device::GetLUID(void) const { + return m_luid; +} // mfxU64 DXVA2Device::GetLUID(void) const diff --git a/dispatcher/windows/mfx_dxva2_device.h b/dispatcher/windows/mfx_dxva2_device.h index 279c45f3..f341e82e 100644 --- a/dispatcher/windows/mfx_dxva2_device.h +++ b/dispatcher/windows/mfx_dxva2_device.h @@ -149,6 +149,7 @@ class DXVA2Device { mfxU32 GetVendorID(void) const; mfxU32 GetDeviceID(void) const; mfxU64 GetDriverVersion(void) const; + mfxU64 GetLUID(void) const; // Provide the number of available adapters mfxU32 GetAdapterCount(void) const; @@ -169,6 +170,8 @@ class DXVA2Device { mfxU32 m_deviceID; //x.x.x.x mfxU64 m_driverVersion; + // LUID + mfxU64 m_luid; private: // unimplemented by intent to make this class non-copyable diff --git a/dispatcher/windows/mfx_library_iterator.cpp b/dispatcher/windows/mfx_library_iterator.cpp index e802f7d4..15f540a6 100644 --- a/dispatcher/windows/mfx_library_iterator.cpp +++ b/dispatcher/windows/mfx_library_iterator.cpp @@ -35,7 +35,8 @@ const wchar_t apiVersionName[] = L"APIVersion"; mfxStatus SelectImplementationType(const mfxU32 adapterNum, mfxIMPL *pImplInterface, mfxU32 *pVendorID, - mfxU32 *pDeviceID) { + mfxU32 *pDeviceID, + mfxU64 *pLUID) { if (NULL == pImplInterface) { return MFX_ERR_NULL_PTR; } @@ -81,6 +82,33 @@ mfxStatus SelectImplementationType(const mfxU32 adapterNum, *pDeviceID = dxvaDevice.GetDeviceID(); } + if (pLUID) { + *pLUID = dxvaDevice.GetLUID(); + } + + return MFX_ERR_NONE; +} + +mfxStatus SelectImplementationType(const mfxU32 adapterNum, + mfxIMPL *pImplInterface, + mfxU32 *pVendorID, + mfxU32 *pDeviceID) { + // do not return LUID + return SelectImplementationType(adapterNum, pImplInterface, pVendorID, pDeviceID, nullptr); +} + +mfxStatus GetNumDXGIAdapters(mfxU32 &numAdaptersD3D9, mfxU32 &numAdaptersDXGI1) { + numAdaptersD3D9 = 0; + numAdaptersDXGI1 = 0; + + DXVA2Device dxvaDevice9; + if (dxvaDevice9.InitD3D9(0)) + numAdaptersD3D9 = dxvaDevice9.GetAdapterCount(); + + DXVA2Device dxvaDevice11; + if (dxvaDevice11.InitDXGI1(0)) + numAdaptersDXGI1 = dxvaDevice11.GetAdapterCount(); + return MFX_ERR_NONE; } @@ -211,11 +239,10 @@ mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, #endif #endif - wchar_t sMediaSDKPath[msdk_disp_path_len] = {}; - if (storageID == MFX_DRIVER_STORE) { - if (!m_driverStoreLoader.GetDriverStorePath(sMediaSDKPath, - sizeof(sMediaSDKPath), + m_driverStoreDir[0] = 0; + if (!m_driverStoreLoader.GetDriverStorePath(m_driverStoreDir, + sizeof(m_driverStoreDir), m_deviceID, L"DriverStorePathForMediaSDK")) { return MFX_ERR_UNSUPPORTED; @@ -231,7 +258,7 @@ mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, return MFX_ERR_UNSUPPORTED; } } - else if (!GetImplPath(storageID, sMediaSDKPath)) { + else if (!GetImplPath(storageID, m_driverStoreDir)) { return MFX_ERR_UNSUPPORTED; } @@ -241,7 +268,7 @@ mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, return MFX_ERR_NONE; } - return InitFolder(implType, sMediaSDKPath, storageID); + return InitFolder(implType, m_driverStoreDir, storageID); } // mfxStatus MFXLibraryIterator::Init(eMfxImplType implType, const mfxU32 adapterNum, int storageID) @@ -570,12 +597,13 @@ bool MFXLibraryIterator::GetSubKeyName(wchar_t *subKeyName, size_t length) const // static functions - create their own MFXLibraryIterator, get paths, then release object mfxStatus MFXLibraryIterator::GetDriverStoreDir(std::wstring &driverStoreDir, size_t length, - mfxU32 adapterID) { + mfxU32 adapterID, + int storageID) { mfxStatus sts = MFX_ERR_UNSUPPORTED; MFX::MFXLibraryIterator libIterator; driverStoreDir.clear(); - sts = libIterator.Init(MFX_LIB_HARDWARE, 0, adapterID, MFX::MFX_DRIVER_STORE_ONEVPL); + sts = libIterator.Init(MFX_LIB_HARDWARE, 0, adapterID, storageID); if (sts) return MFX_ERR_UNSUPPORTED; diff --git a/dispatcher/windows/mfx_library_iterator.h b/dispatcher/windows/mfx_library_iterator.h index e7b5df0c..3938d6c9 100644 --- a/dispatcher/windows/mfx_library_iterator.h +++ b/dispatcher/windows/mfx_library_iterator.h @@ -48,12 +48,20 @@ enum { }; // Try to initialize using given implementation type. Select appropriate type automatically in case of MFX_IMPL_VIA_ANY. -// Params: adapterNum - in, pImplInterface - in/out, pVendorID - out, pDeviceID - out +// Params: adapterNum - in, pImplInterface - in/out, pVendorID - out, pDeviceID - out, pLUID - out (optional) mfxStatus SelectImplementationType(const mfxU32 adapterNum, mfxIMPL *pImplInterface, mfxU32 *pVendorID, mfxU32 *pDeviceID); +mfxStatus SelectImplementationType(const mfxU32 adapterNum, + mfxIMPL *pImplInterface, + mfxU32 *pVendorID, + mfxU32 *pDeviceID, + mfxU64 *pLUID); + +mfxStatus GetNumDXGIAdapters(mfxU32 &numAdaptersD3D9, mfxU32 &numAdaptersDXGI1); + bool GetImplPath(int storageID, wchar_t *sImplPath); const mfxU32 msdk_disp_path_len = 1024; @@ -89,7 +97,8 @@ class MFXLibraryIterator { static mfxStatus GetDriverStoreDir(std::wstring &driverStoreDir, size_t length, - mfxU32 adapterID); + mfxU32 adapterID, + int storageID); static mfxStatus GetRegkeyDir(std::wstring ®Dir, size_t length, int storageID); protected: diff --git a/docker/Dockerfile-centos-7 b/docker/Dockerfile-centos-7 index 236dfd30..d9d23d22 100644 --- a/docker/Dockerfile-centos-7 +++ b/docker/Dockerfile-centos-7 @@ -10,7 +10,7 @@ ARG DOCKER_REGISTRY # Stage 1 FROM ${DOCKER_REGISTRY}centos:centos7 AS vpl_base ENV TZ=Europe/Moscow -RUN yum check-update && yum install -y centos-release-scl && \ +RUN yum update -y && yum install -y centos-release-scl && \ yum-config-manager --enable rhel-server-rhscl-7-rpms && \ yum install -y git libtool make pkgconfig devtoolset-7 @@ -28,6 +28,7 @@ FROM vpl_base AS vpl_build ARG VPL_INSTALL_PREFIX COPY . /oneVPL RUN cd /oneVPL && \ + rm -rf _build && \ mkdir _build && \ cd _build && \ source /opt/rh/devtoolset-7/enable && \ diff --git a/docker/Dockerfile-centos-8 b/docker/Dockerfile-centos-8 index 25b9507e..6c135ab0 100644 --- a/docker/Dockerfile-centos-8 +++ b/docker/Dockerfile-centos-8 @@ -10,7 +10,7 @@ ARG DOCKER_REGISTRY # Stage 1 FROM ${DOCKER_REGISTRY}centos:centos8 AS vpl_base ENV TZ=Europe/Moscow -RUN yum install -y cmake gcc gcc-c++ git libtool make pkgconfig +RUN yum install -y cmake gcc gcc-c++ git libtool make pkgconfig libarchive # Stage 2 @@ -18,6 +18,7 @@ FROM vpl_base AS vpl_build ARG VPL_INSTALL_PREFIX COPY . /oneVPL RUN cd /oneVPL && \ + rm -rf _build && \ mkdir _build && \ cd _build && \ cmake -DCMAKE_INSTALL_PREFIX=${VPL_INSTALL_PREFIX} .. && \ diff --git a/docker/Dockerfile-rhel-8 b/docker/Dockerfile-rhel-8 index 69ed3739..18d04d63 100644 --- a/docker/Dockerfile-rhel-8 +++ b/docker/Dockerfile-rhel-8 @@ -9,9 +9,9 @@ ARG VPL_INSTALL_PREFIX=/opt/intel/onevpl ARG DOCKER_REGISTRY # Stage 1 -FROM ${DOCKER_REGISTRY}ubi:8.1 AS vpl_base +FROM ${DOCKER_REGISTRY}ubi AS vpl_base ENV TZ=Europe/Moscow -RUN yum install -y cmake gcc gcc-c++ git libtool make pkgconfig +RUN yum install -y cmake gcc gcc-c++ git libtool make pkgconfig libarchive # Stage 2 @@ -19,6 +19,7 @@ FROM vpl_base AS vpl_build ARG VPL_INSTALL_PREFIX COPY . /oneVPL RUN cd /oneVPL && \ + rm -rf _build && \ mkdir _build && \ cd _build && \ cmake -DCMAKE_INSTALL_PREFIX=${VPL_INSTALL_PREFIX} .. && \ @@ -27,8 +28,8 @@ RUN cd /oneVPL && \ # Runtime image build -FROM registry.access.redhat.com/ubi8/ubi:8.1 -LABEL Description="This is the RHEL 8.1 base image for the oneAPI Video Processing Library API" +FROM registry.access.redhat.com/ubi8/ubi +LABEL Description="This is the RHEL 8.x base image for the oneAPI Video Processing Library API" LABEL Vendor="Intel Corporation" ARG VPL_INSTALL_PREFIX ENV LD_LIBRARY_PATH=${VPL_INSTALL_PREFIX}/lib diff --git a/docker/Dockerfile-ubuntu-18.04 b/docker/Dockerfile-ubuntu-18.04 index 3cd0bbb7..8aca6178 100644 --- a/docker/Dockerfile-ubuntu-18.04 +++ b/docker/Dockerfile-ubuntu-18.04 @@ -34,6 +34,7 @@ FROM vpl_base AS vpl_build ARG VPL_INSTALL_PREFIX COPY . /oneVPL RUN cd /oneVPL && \ + rm -rf _build && \ mkdir _build && \ cd _build && \ cmake -DCMAKE_INSTALL_PREFIX=${VPL_INSTALL_PREFIX} .. && \ diff --git a/docker/Dockerfile-ubuntu-19.10 b/docker/Dockerfile-ubuntu-19.10 deleted file mode 100644 index a5343087..00000000 --- a/docker/Dockerfile-ubuntu-19.10 +++ /dev/null @@ -1,52 +0,0 @@ -# ============================================================================== -# Copyright (C) Intel Corporation -# -# SPDX-License-Identifier: MIT -# ============================================================================== - -ARG VPL_INSTALL_PREFIX=/opt/intel/onevpl -ARG DOCKER_REGISTRY - -# Stage 1 -FROM ${DOCKER_REGISTRY}ubuntu:19.10 AS vpl_base -ARG DEBIAN_FRONTEND=noninteractive -ENV TZ=Europe/Moscow -RUN apt-get update && apt-get install -y --no-install-recommends \ - build-essential \ - git \ - pkg-config \ - ca-certificates \ - dh-autoreconf \ - libdrm-dev \ - cmake && \ - rm -rf /var/lib/apt/lists/* - -RUN git clone https://github.com/intel/libva.git && \ - cd libva && \ - git fetch --tags && \ - git checkout $(git describe --tags `git rev-list --tags --max-count=1`) && \ - ./autogen.sh && \ - make -j $(nproc --all) && \ - make install - -# Stage 2 -FROM vpl_base AS vpl_build -ARG VPL_INSTALL_PREFIX -COPY . /oneVPL -RUN cd /oneVPL && \ - mkdir _build && \ - cd _build && \ - cmake -DCMAKE_INSTALL_PREFIX=${VPL_INSTALL_PREFIX} .. && \ - make -j $(nproc --all) && \ - make install - - -# Runtime image build -FROM ${DOCKER_REGISTRY}ubuntu:19.10 -LABEL Description="This is the Ubuntu 19.10 base image for the oneAPI Video Processing Library API" -LABEL Vendor="Intel Corporation" -ARG VPL_INSTALL_PREFIX -ENV LD_LIBRARY_PATH=${VPL_INSTALL_PREFIX}/lib -ENV PKG_CONFIG_PATH=${VPL_INSTALL_PREFIX}/pkgconfig -ENV PATH="${PATH}:/${VPL_INSTALL_PREFIX}/bin" -COPY --from=vpl_build ${VPL_INSTALL_PREFIX} ${VPL_INSTALL_PREFIX} diff --git a/docker/Dockerfile-ubuntu-20.04 b/docker/Dockerfile-ubuntu-20.04 index 4faeda70..41dd0e53 100644 --- a/docker/Dockerfile-ubuntu-20.04 +++ b/docker/Dockerfile-ubuntu-20.04 @@ -34,6 +34,7 @@ FROM vpl_base AS vpl_build ARG VPL_INSTALL_PREFIX COPY . /oneVPL RUN cd /oneVPL && \ + rm -rf _build && \ mkdir _build && \ cd _build && \ cmake -DCMAKE_INSTALL_PREFIX=${VPL_INSTALL_PREFIX} .. && \ diff --git a/docker/README.md b/docker/README.md index fab8a3b6..a38e03b4 100644 --- a/docker/README.md +++ b/docker/README.md @@ -9,3 +9,29 @@ The following command will build all of the supported docker container images: ```bash $ ./build_docker_images.sh ``` + + +**LEGAL NOTICE: By downloading and using any scripts (the ā€œSoftware Packageā€) and the included software or software made available for download, you agree to the terms and conditions of the software license agreements for the Software Package, which may also include notices, disclaimers, or license terms for third party software (together, the ā€œAgreementsā€) included in this README file. +If the Software Package is installed through a silent install, your download and use of the Software Package indicates your acceptance of the Agreements.** + +Docker files will also pull in the following: +* [git](https://git-scm.com) +* [build-essential](https://packages.debian.org/sid/build-essential) +* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) +* [ca-certificates](https://packages.ubuntu.com/source/hirsute/ca-certificates) +* [dh-autoeconf](https://salsa.debian.org/debian/dh-autoreconf) +* [libdrm-dev](https://cgit.freedesktop.org/mesa/drm/) +* [cmake](https://cmake.org/) +* [libtool](https://www.gnu.org/software/libtool/) +* [make](https://www.gnu.org/software/make/) +* [pkgconfig](https://github.com/matze/pkgconfig) +* [devtoolset-7](https://www.softwarecollections.org/en/scls/rhscl/devtoolset-7/) +* [gcc](https://gcc.gnu.org/) +* [gcc-c++](https://gcc.gnu.org/) +* [libarchive](https://www.libarchive.org/) +* [CentOS 7](https://hub.docker.com/layers/centos/library/centos/7/images/sha256-b79613a1c63084399b6c21c97ab4e2816ef5e9c513842c1bd4dca46bdd921b31?context=explore) +* [CentOS 8](https://hub.docker.com/layers/centos/library/centos/centos8/images/sha256-7723d6b5d15b1c64d0a82ee6298c66cf8c27179e1c8a458e719041ffd08cd091?context=explore) +* [RedHat 8](https://catalog.redhat.com/software/containers/ubi8/ubi/5c359854d70cc534b3a3784e?tag=8.4&push_date=1622575047000&container-tabs=gti) +* [Ubuntu 18.04](https://hub.docker.com/layers/ubuntu/library/ubuntu/18.04/images/sha256-dce82ba9ee1bc3a515212bb17fa21c134102bffafb5234a25ac10747df25816b?context=explore) +* [Ubuntu 20.04](https://hub.docker.com/layers/ubuntu/library/ubuntu/20.04/images/sha256-42d5c74d24685935e6167271ebb74c5898c5adf273dae80a82f9e39e8ae0dab4?context=explore) +* [Libva](https://github.com/intel/libva.git) \ No newline at end of file diff --git a/docker/build_docker_images.sh b/docker/build_docker_images.sh index bb13b780..eed55668 100755 --- a/docker/build_docker_images.sh +++ b/docker/build_docker_images.sh @@ -1,15 +1,19 @@ #!/bin/bash # ============================================================================== -# Copyright (C) 2018-2020 Intel Corporation +# Copyright (C) Intel Corporation # # SPDX-License-Identifier: MIT # ============================================================================== set -e BASEDIR=$(dirname "$0") +echo "Building RHEL 8 Image" docker build -f ${BASEDIR}/Dockerfile-rhel-8 -t vpl:rhel8 --build-arg DOCKER_REGISTRY=${1:-"registry.access.redhat.com/ubi8/"} ${BASEDIR}/.. +echo "Building CentOS 7 Image" docker build -f ${BASEDIR}/Dockerfile-centos-7 -t vpl:centos7 --build-arg DOCKER_REGISTRY=$1 ${BASEDIR}/.. +echo "Building CentOS 8 Image" docker build -f ${BASEDIR}/Dockerfile-centos-8 -t vpl:centos8 --build-arg DOCKER_REGISTRY=$1 ${BASEDIR}/.. +echo "Building Ubuntu 18.04 Image" docker build -f ${BASEDIR}/Dockerfile-ubuntu-18.04 -t vpl:ubuntu18.04 --build-arg DOCKER_REGISTRY=$1 ${BASEDIR}/.. -docker build -f ${BASEDIR}/Dockerfile-ubuntu-19.10 -t vpl:ubuntu19.10 --build-arg DOCKER_REGISTRY=$1 ${BASEDIR}/.. +echo "Building Ubuntu 20.04 Image" docker build -f ${BASEDIR}/Dockerfile-ubuntu-20.04 -t vpl:ubuntu20.04 --build-arg DOCKER_REGISTRY=$1 ${BASEDIR}/.. diff --git a/docker/tutorial/Dockerfile b/docker/tutorial/Dockerfile deleted file mode 100644 index 4e4739ab..00000000 --- a/docker/tutorial/Dockerfile +++ /dev/null @@ -1,35 +0,0 @@ -FROM ubuntu:20.04 -ENV DEBIAN_FRONTEND=noninteractive - -# Install a few minimal prerequisites -RUN apt update && apt install -y --no-install-recommends \ - software-properties-common ca-certificates gnupg wget apt-utils \ - libva-drm2 vainfo lsb-release \ - libva-dev libdrm2 libdrm-dev libpciaccess0 pciutils \ - build-essential cmake pkg-config strace - - -# Enable Agama package repository for Ubuntu 20.04 -RUN wget -qO - https://repositories.intel.com/graphics/intel-graphics.key | apt-key add - && \ - echo "deb [arch=amd64] https://repositories.intel.com/graphics/ubuntu focal main" > /etc/apt/sources.list.d/intel-graphics.list - -# Enable oneAPI package repository for Ubuntu 20.04 -RUN wget -qO - https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB | apt-key add - && \ - add-apt-repository "deb https://apt.repos.intel.com/oneapi all main" - -# Install MSDK GPU media accelerator runtime -RUN apt-get update && apt-get install -y --no-install-recommends \ - intel-media-va-driver-non-free \ - libmfx1 && \ - echo 'LIBVA_DRIVERS_PATH=/usr/lib/x86_64-linux-gnu/dri' >> /etc/environment && \ - echo 'LIBVA_DRIVER_NAME=iHD' >> /etc/environment && \ - ldconfig - -# Install MSDK Developer Package -RUN apt-get update && apt-get install -y --no-install-recommends \ - libmfx-tools \ - libmfx-dev - -# Install oneVPL Developer Package -RUN apt-get update && apt-get install -y --no-install-recommends \ - intel-oneapi-onevpl-devel diff --git a/docker/tutorial/README.md b/docker/tutorial/README.md deleted file mode 100644 index bf1ebca4..00000000 --- a/docker/tutorial/README.md +++ /dev/null @@ -1,155 +0,0 @@ -# Tutorial: Transition from Intel(R) Media SDK to Intel(R) oneAPI Video Processing Library (oneVPL) - -This tutorial shows the first steps to upgrade Intel(R) Media SDK code to Intel(R) oneAPI Video Processing Library. - -**Note**: This tutorial is based on Docker and assumes that you have already set up and configured Docker for your environment. - -**Contents:** -- [Create an image for the tutorial](#create-an-image-for-the-tutorial) -- [Build examples using the same source for both toolkits](#build-examples-using-the-same-source-for-both-toolkits) -- [Run examples with Intel(R) Media SDK](#run-examples-with-intelr-media-sdk) -- [Run examples with oneVPL](#run-examples-with-onevpl) - -## Create an image for the tutorial -To create an image with all prerequisites and start a container, run the `run.sh` script: - -```bash -./run.sh -``` - -This image is based on Ubuntu 20.04. - -Among other prerequisites for GPU use, this image installs: -* the MSDK developer package from Agama -* the oneVPL developer package from the Intel oneAPI program - -## Build example - -The example illustrated here shows the small changes needed to upgrade. - -Review legacy-createsession code to see initialization changes: - -Media SDK initialization: -``` - sts = MFXInit(cliParams.impl, &version, &session); - VERIFY(MFX_ERR_NONE == sts, "Not able to create VPL session"); -``` - -oneVPL initialization: -``` - mfxConfig cfg = NULL; - mfxLoader loader = NULL; - - loader = MFXLoad(); - VERIFY(NULL != loader, "MFXLoad failed -- is implementation in path?"); - - cfg = MFXCreateConfig(loader); - VERIFY(NULL != cfg, "MFXCreateConfig failed") - - sts = MFXSetConfigFilterProperty( - cfg, - reinterpret_cast(const_cast("mfxImplDescription.Impl")), - cliParams.implValue); - VERIFY(MFX_ERR_NONE == sts, "MFXSetConfigFilterProperty failed"); - - sts = MFXCreateSession(loader, 0, &session); - VERIFY(MFX_ERR_NONE == sts, "Not able to create VPL session"); -``` - -Build the example with Intel(R) Media SDK: - -```bash -cd preview/legacy-createsession/src -g++ legacy-createsession.cpp -o hello_mediasdk -I/usr/include/mfx -I../../../util -lmfx -lva -lva-drm -lpthread -DUSE_MEDIASDK1 -``` - -Build the example with oneVPL: - -```bash -source /opt/intel/oneapi/vpl/latest/env/vars.sh -g++ legacy-createsession.cpp -o hello_onevpl -I/opt/intel/oneapi/vpl/latest/include/vpl -I../../../util -lmfx -lva -lva-drm -lpthread -``` - -**Note**: The oneVPL dispatcher library name was recently updated to `vpl`. Change `-lmfx` to `-lvpl` when compiling -after this `intel-oneapi-onevpl` change has propagated. - -Other than API upgrades, the oneVPL repository adds the convention of adding the `vpl` directory name before include files. -I420 is added as a more recognizable name for the industry standard planar YUV 4:2:0. - -These minor differences are shown at the top of `util.h`: - -```c++ -#ifdef USE_MEDIASDK1 - #include "mfxvideo.h" - enum { - MFX_FOURCC_I420 = MFX_FOURCC_IYUV /*!< Alias for the IYUV color format. */ - }; -#else - #include "vpl/mfxvideo.h" - #include "vpl/mfxjpeg.h" -#endif -``` - -## Run examples with Intel(R) Media SDK - -Run the example code as compiled with Intel(R) Media SDK: - -```bash -./hello_mediasdk -hw -``` - -**Expected output:** - -```bash -Implementation info - version = 1.34 - impl = Hardware:VAAPI -``` - -Check that the legacy Intel(R) Media SDK dispatcher was used: - -```bash -strace ./hello_mediasdk 2>&1 | grep 'libmfx' -``` - -**Expected output:** - -```bash -openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libmfx.so.1", O_RDONLY|O_CLOEXEC) = 3 -openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libmfxhw64.so.1", O_RDONLY|O_CLOEXEC) = 3 -``` - -`libmfx.so.1` is the 1.x legacy Intel(R) Media SDK dispatcher. - - -## Run examples with oneVPL - -Run the example code as compiled with oneVPL: - -```bash -./hello_onevpl -hw -``` - -**Expected output:** - -```bash -Implementation info - version = 1.34 - impl = Hardware:VAAPI -``` - -Check that the oneVPL dispatcher was used: - -```bash -strace ./hello_onevpl 2>&1 | grep 'libmfx' -``` - -**Expected output:** - -```bash -openat(AT_FDCWD, "/opt/intel/oneapi/vpl/2021.1.1/lib/libmfx.so.2", O_RDONLY|O_CLOEXEC) = 3 -openat(AT_FDCWD, "/opt/intel/oneapi/vpl/2021.1.1/lib/libmfxhw64.so.1", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) -openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libmfxhw64.so.1", O_RDONLY|O_CLOEXEC) = 3 -``` - -`libmfx.so.2` is the 2.x oneVPL dispatcher. diff --git a/docker/tutorial/run.sh b/docker/tutorial/run.sh deleted file mode 100755 index 6c03b7df..00000000 --- a/docker/tutorial/run.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -docker build -t onevpl_tutorial . -docker run -it --rm --privileged -v `pwd`/../../examples:/examples -w /examples onevpl_tutorial:latest - diff --git a/doxygen/Doxyfile b/doxygen/Doxyfile new file mode 100644 index 00000000..5311ab07 --- /dev/null +++ b/doxygen/Doxyfile @@ -0,0 +1,2663 @@ +# Doxyfile 1.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = oneVPL++ + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = "C++ API Prototype for oneVPL" + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = ../api/vpl \ + mainpage.md + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.idl \ + *.ddl \ + *.odl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.cs \ + *.d \ + *.php \ + *.php4 \ + *.php5 \ + *.phtml \ + *.inc \ + *.m \ + *.markdown \ + *.md \ + *.mm \ + *.dox \ + *.doc \ + *.txt \ + *.py \ + *.pyw \ + *.f90 \ + *.f95 \ + *.f03 \ + *.f08 \ + *.f \ + *.for \ + *.tcl \ + *.vhd \ + *.vhdl \ + *.ucf \ + *.qsf \ + *.ice + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = mainpage.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: +# http://clang.llvm.org/) for more accurate parsing at the cost of reduced +# performance. This can be particularly helpful with template rich C++ code for +# which doxygen's built-in parser lacks the necessary type information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled and the CLANG_ADD_INC_PATHS tag is set to +# YES then doxygen will add the directory of each input to the include path. +# The default value is: YES. + +CLANG_ADD_INC_PATHS = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the directory containing a file called compile_commands.json. This +# file is the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) containing the +# options used when the source files were built. This is equivalent to +# specifying the -p option to a clang tool, such as clang-check. These options +# will then be passed to the parser. Any options specified with CLANG_OPTIONS +# will be added as well. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = header.html + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = footer.html + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /