diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3f06a76c6..fffe5a2e8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -8,6 +8,7 @@ on: pull_request: branches: - master + workflow_dispatch: concurrency: group: build-${{ github.ref }} diff --git a/.gitignore b/.gitignore index a04bcb2bb..4946e7325 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ *pro.user - +.qtcreator/ **/.vs/ .vscode/ @@ -7,3 +7,26 @@ build/ libs/ config.tests/*/.qmake.stash config.tests/*/Makefile + +third-party/** +!third-party/ + +# Submodules +!third-party/AMF/ +!third-party/DirectX-Headers/ +!third-party/FidelityFX-FSR/ +!third-party/NVIDIAImageScaling/ +!third-party/libvpl/ + +# Bundled SDKs +!third-party/DirectXShaderCompiler/ +!third-party/DirectXShaderCompiler/** +!third-party/RTX_Video_SDK/ +!third-party/RTX_Video_SDK/** +!third-party/IntelVPL/ +!third-party/IntelVPL/**/ +!third-party/IntelVPL/*/lib/** +!third-party/IntelVPL/*/include/** +!third-party/IntelVPL/*/bin/libvpl.dll +!third-party/stb_image/ +!third-party/stb_image/** diff --git a/.gitmodules b/.gitmodules index 2eeecaf9d..7f009eed4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,9 +1,32 @@ [submodule "moonlight-common-c/moonlight-common-c"] path = moonlight-common-c/moonlight-common-c url = https://github.com/moonlight-stream/moonlight-common-c.git + ignore = dirty [submodule "qmdnsengine/qmdnsengine"] path = qmdnsengine/qmdnsengine url = https://github.com/cgutman/qmdnsengine.git + ignore = dirty [submodule "app/SDL_GameControllerDB"] path = app/SDL_GameControllerDB url = https://github.com/gabomdq/SDL_GameControllerDB.git + ignore = dirty +[submodule "third-party/AMF"] + path = third-party/AMF + url = https://github.com/GPUOpen-LibrariesAndSDKs/AMF.git + ignore = dirty +[submodule "third-party/FidelityFX-FSR"] + path = third-party/FidelityFX-FSR + url = https://github.com/GPUOpen-Effects/FidelityFX-FSR.git + ignore = dirty +[submodule "third-party/NVIDIAImageScaling"] + path = third-party/NVIDIAImageScaling + url = https://github.com/NVIDIAGameWorks/NVIDIAImageScaling.git + ignore = dirty +[submodule "third-party/DirectX-Headers"] + path = third-party/DirectX-Headers + url = https://github.com/microsoft/DirectX-Headers.git + ignore = dirty +[submodule "third-party/libvpl"] + path = third-party/libvpl + url = https://github.com/intel/libvpl.git + ignore = dirty diff --git a/app/app.pro b/app/app.pro index 1c0661b30..46c8127a9 100644 --- a/app/app.pro +++ b/app/app.pro @@ -1,4 +1,4 @@ -QT += core quick network quickcontrols2 svg +QT += core quick network quickcontrols2 svg concurrent CONFIG += c++17 unix:!macx { @@ -149,7 +149,7 @@ unix:if(!macx|disable-prebuilts) { } } win32 { - LIBS += -llibssl -llibcrypto -lSDL2 -lSDL2_ttf -lavcodec -lavutil -lswscale -lopus -ldxgi -ld3d11 -llibplacebo + LIBS += -llibssl -llibcrypto -lSDL2 -lSDL2_ttf -lavcodec -lavutil -lswscale -lopus -ldxgi -ld3d11 -ld3d12 -ldxguid -llibplacebo -ld3dcompiler -ldxcompiler CONFIG += ffmpeg libplacebo } win32:!winrt { @@ -161,7 +161,7 @@ macx { CONFIG += discord-rpc libplacebo } - LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreVideo -framework CoreGraphics -framework CoreMedia -framework AppKit -framework Metal -framework QuartzCore + LIBS += -lobjc -framework VideoToolbox -framework AVFoundation -framework CoreVideo -framework CoreGraphics -framework CoreMedia -framework AppKit -framework Metal -framework MetalFx -framework MetalPerformanceShaders -framework QuartzCore CONFIG += ffmpeg } @@ -204,6 +204,7 @@ SOURCES += \ gui/sdlgamepadkeynavigation.cpp \ streaming/video/overlaymanager.cpp \ backend/systemproperties.cpp \ + streaming/video/videoenhancement.cpp \ wm.cpp HEADERS += \ @@ -241,7 +242,8 @@ HEADERS += \ settings/mappingmanager.h \ gui/sdlgamepadkeynavigation.h \ streaming/video/overlaymanager.h \ - backend/systemproperties.h + backend/systemproperties.h \ + streaming/video/videoenhancement.h # Platform-specific renderers and decoders ffmpeg { @@ -391,18 +393,148 @@ config_SL { win32 { HEADERS += streaming/video/ffmpeg-renderers/dxutil.h } + +win32:!winrt { + message(NVIDIA VSR and TrueHDR technologies) + + # Required by NVIDIA RTX Video SDK; compilation fails without these linker flags + # as the SDK is compiled to work with Visual Studio initially + # Note: '/guard:ehcont,no' disables some EH checks + # For a standalone application without external modules, this poses virtually no risk + QMAKE_LFLAGS += /guard:ehcont,no + + LIBS += -ladvapi32 + + OS_ARCHI = x64 + contains(QT_ARCH, arm64) { + OS_ARCHI = arm64 + } + + NGX_DLL_PATH_VSR = "$$PWD/../third-party/RTX_Video_SDK/bin/Windows/$${OS_ARCHI}/rel/nvngx_vsr.dll" + NGX_DLL_PATH_HDR = "$$PWD/../third-party/RTX_Video_SDK/bin/Windows/$${OS_ARCHI}/rel/nvngx_truehdr.dll" + + CONFIG(debug, debug|release) { + # Debug + copy_vsr.commands = $$quote(copy /Y $$shell_path($$NGX_DLL_PATH_VSR) $$shell_path("$$OUT_PWD/debug")) + copy_hdr.commands = $$quote(copy /Y $$shell_path($$NGX_DLL_PATH_HDR) $$shell_path("$$OUT_PWD/debug")) + LIBS += -L$$PWD/../third-party/RTX_Video_SDK/lib/Windows/$${OS_ARCHI} -lnvsdk_ngx_d_dbg + } + + CONFIG(release, debug|release) { + # Release + copy_vsr.commands = $$quote(copy /Y $$shell_path($$NGX_DLL_PATH_VSR) $$shell_path("$$OUT_PWD/release")) + copy_hdr.commands = $$quote(copy /Y $$shell_path($$NGX_DLL_PATH_HDR) $$shell_path("$$OUT_PWD/release")) + LIBS += -L$$PWD/../third-party/RTX_Video_SDK/lib/Windows/$${OS_ARCHI} -lnvsdk_ngx_d + } + + QMAKE_POST_LINK += $$copy_vsr.commands & $$copy_hdr.commands + + INCLUDEPATH += $$PWD/../third-party/RTX_Video_SDK/include +} + +win32:!winrt { + message(AMD Upscaling technologies) + + SOURCES += \ + ../third-party/AMF/amf/public/common/AMFFactory.cpp \ + ../third-party/AMF/amf/public/common/AMFSTL.cpp \ + ../third-party/AMF/amf/public/common/Thread.cpp \ + ../third-party/AMF/amf/public/common/TraceAdapter.cpp \ + ../third-party/AMF/amf/public/common/Windows/ThreadWindows.cpp + + INCLUDEPATH += \ + $$PWD/../third-party/AMF/amf \ + $$PWD/shaders/enhancer/AMD +} + win32:!winrt { - message(DXVA2 and D3D11VA renderers selected) + message(Intel VPL Upscaling technologies) + + # IntelVPL already exists and is compiled for x64 architecture. + # Uncomment if you need to rebuild IntelVPL locally. + # Important: MSVC Build Tools for ARM64 and WinGet (https://github.com/microsoft/winget-cli/releases) are required, + + # # Compile x64 architecture + # vpl_build_x64.commands = \ + # cd $$shell_path($$PWD/../third-party/libvpl) && \ + # script\\bootstrap.bat && \ + # cmake -B _build_x64 -DCMAKE_INSTALL_PREFIX="$$PWD/../third-party/IntelVPL/x64" && \ + # cmake --build _build_x64 --config Release && \ + # cmake --install _build_x64 --config Release + # vpl_build_x64.CONFIG += no_link + # QMAKE_EXTRA_TARGETS += vpl_build_x64 + # PRE_TARGETDEPS += vpl_build_x64 + + # # Compile arm64 architecture + # # Note: Intel does not provide a arm64 version of its library, + # # but we need to compile it to avoid a build error, even if it is not used + # vpl_build_arm64.commands = \ + # cd $$shell_path($$PWD/../third-party/libvpl) && \ + # script\\bootstrap.bat && \ + # cmake -B _build_arm64 -A ARM64 -T host=x64 -DCMAKE_INSTALL_PREFIX="$$PWD/../third-party/IntelVPL/arm64" && \ + # cmake --build _build_arm64 --config Release && \ + # cmake --install _build_arm64 --config Release + # vpl_build_arm64.CONFIG += no_link + # QMAKE_EXTRA_TARGETS += vpl_build_arm64 + # PRE_TARGETDEPS += vpl_build_arm64 + + OS_ARCHI = x64 + contains(QT_ARCH, arm64) { + OS_ARCHI = arm64 + } + + INCLUDEPATH += $$PWD/../third-party/IntelVPL/$${OS_ARCHI}/include + LIBS += -L$$PWD/../third-party/IntelVPL/$${OS_ARCHI}/lib -lvpl + + VPL_DLL_PATH = "$$PWD/../third-party/IntelVPL/$${OS_ARCHI}/bin/libvpl.dll" + + CONFIG(debug, debug|release) { + # Debug + copy_vpl.commands = $$quote(copy /Y $$shell_path($$VPL_DLL_PATH) $$shell_path("$$OUT_PWD/debug")) + } + + CONFIG(release, debug|release) { + # Release + copy_vpl.commands = $$quote(copy /Y $$shell_path($$VPL_DLL_PATH) $$shell_path("$$OUT_PWD/release")) + } + + QMAKE_POST_LINK += & $$copy_vpl.commands + + # IntelVPL is only available for the architecture x64 + contains(QT_ARCH, x86_64) { + DEFINES += HAVE_INTEL_VPL + } +} +win32:!winrt { + message(NVIDIA Image Scaling) + + INCLUDEPATH += $$PWD/../third-party/NVIDIAImageScaling/NIS +} +win32:!winrt { + message(Direct3D 12 headers) + + INCLUDEPATH += $$PWD/../third-party/DirectX-Headers/include +} +win32:!winrt { + message("DXVA2, D3D11renderers and D3D12renderers selected") SOURCES += \ streaming/video/ffmpeg-renderers/dxva2.cpp \ streaming/video/ffmpeg-renderers/d3d11va.cpp \ + streaming/video/ffmpeg-renderers/d3d12va.cpp \ + streaming/video/ffmpeg-renderers/d3d12va_shaders.cpp \ streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.cpp HEADERS += \ streaming/video/ffmpeg-renderers/dxva2.h \ streaming/video/ffmpeg-renderers/d3d11va.h \ + streaming/video/ffmpeg-renderers/d3d12va.h \ + streaming/video/ffmpeg-renderers/d3d12va_shaders.h \ streaming/video/ffmpeg-renderers/pacer/dxvsyncsource.h + + CONFIG(debug, debug|release) { + INCLUDEPATH += $$PWD/../third-party/stb_image + } } macx { message(VideoToolbox renderer selected) diff --git a/app/backend/systemproperties.cpp b/app/backend/systemproperties.cpp index ef79097a2..e541d4b45 100644 --- a/app/backend/systemproperties.cpp +++ b/app/backend/systemproperties.cpp @@ -6,6 +6,7 @@ #include "streaming/session.h" #include "streaming/streamutils.h" +#include "streaming/video/videoenhancement.h" #ifdef Q_OS_WIN32 #define WIN32_LEAN_AND_MEAN @@ -277,3 +278,38 @@ void SystemProperties::refreshDisplays() SDL_QuitSubSystem(SDL_INIT_VIDEO); } + +/** + * \brief Inform if the menu is selectable (DEBUG mode) + * + * For Debugging purpose only, we allow the dropdown menu visible to test other algorithms + * + * \return bool Returns true if in debug mode + */ +bool SystemProperties::isVideoEnhancementSwitchable() +{ +#if defined(QT_DEBUG) && defined(Q_OS_WIN) + return true; +#else + return false; +#endif +} + +/** + * \brief Inform if the GPU is capable of Video enhancement + * + * Check if either Video Super-Resolution features can be used by the GPU. + * + * isAvailable() only reflects that FFmpeg advertises a hwaccel able to carry the + * feature, which stays true on systems where the D3D12 device cannot actually be + * created. On Windows the upscaler lives in the D3D12 renderer (the Vulkan/FSR1 + * path is not user-selectable there), so a D3D12 failure means the feature is out + * of reach and the setting must be greyed out. + * + * \return bool Returns true if the GPU is capable + */ +bool SystemProperties::isVideoEnhancementAvailable() +{ + return VideoEnhancement::getInstance().isAvailable() && + VideoEnhancement::getInstance().isD3D12Available(); +} diff --git a/app/backend/systemproperties.h b/app/backend/systemproperties.h index 8e5b5742c..65ae08bf5 100644 --- a/app/backend/systemproperties.h +++ b/app/backend/systemproperties.h @@ -38,6 +38,8 @@ class SystemProperties : public QObject Q_INVOKABLE QRect getNativeResolution(int displayIndex); Q_INVOKABLE QRect getSafeAreaResolution(int displayIndex); Q_INVOKABLE int getRefreshRate(int displayIndex); + Q_INVOKABLE bool isVideoEnhancementSwitchable(); + Q_INVOKABLE bool isVideoEnhancementAvailable(); Q_INVOKABLE void startAsyncLoad(); Q_INVOKABLE void waitForAsyncLoad(); diff --git a/app/cli/commandlineparser.cpp b/app/cli/commandlineparser.cpp index 2acac458a..b16e6d872 100644 --- a/app/cli/commandlineparser.cpp +++ b/app/cli/commandlineparser.cpp @@ -305,6 +305,16 @@ StreamCommandLineParser::StreamCommandLineParser() {"5.1-surround", StreamingPreferences::AC_51_SURROUND}, {"7.1-surround", StreamingPreferences::AC_71_SURROUND}, }; + m_SuperResolutionModeMap = { + {"auto", StreamingPreferences::SRM_00}, + {"driver", StreamingPreferences::SRM_01}, + {"video-processor", StreamingPreferences::SRM_02}, + {"fsr1-upscaler", StreamingPreferences::SRM_03}, + {"nis-upscaler", StreamingPreferences::SRM_04}, + {"sgsr1-upscaler", StreamingPreferences::SRM_05}, + {"rcas-sharpener", StreamingPreferences::SRM_06}, + {"nis-sharpener", StreamingPreferences::SRM_07}, + }; m_VideoCodecMap = { {"auto", StreamingPreferences::VCC_AUTO}, {"H.264", StreamingPreferences::VCC_FORCE_H264}, @@ -352,6 +362,7 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference parser.addValueOption("packet-size", "video packet size"); parser.addChoiceOption("display-mode", "display mode", m_WindowModeMap.keys()); parser.addChoiceOption("audio-config", "audio config", m_AudioConfigMap.keys()); + parser.addChoiceOption("super-resolution-mode", "super resolution mode", m_SuperResolutionModeMap.keys()); parser.addToggleOption("multi-controller", "multiple controller support"); parser.addToggleOption("quit-after", "quit app after session"); parser.addToggleOption("absolute-mouse", "remote desktop optimized mouse control"); @@ -360,6 +371,7 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference parser.addToggleOption("game-optimization", "game optimizations"); parser.addToggleOption("audio-on-host", "audio on host PC"); parser.addToggleOption("frame-pacing", "frame pacing"); + parser.addToggleOption("video-enhancement", "Enhance video with AI"); parser.addToggleOption("mute-on-focus-loss", "mute audio when Moonlight window loses focus"); parser.addToggleOption("background-gamepad", "background gamepad input"); parser.addToggleOption("reverse-scroll-direction", "inverted scroll direction"); @@ -443,6 +455,11 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference preferences->audioConfig = mapValue(m_AudioConfigMap, parser.getChoiceOptionValue("audio-config")); } + // Resolve --super-resolution-config option + if (parser.isSet("super-resolution-mode")) { + preferences->superResolutionMode = mapValue(m_SuperResolutionModeMap, parser.getChoiceOptionValue("super-resolution-mode")); + } + // Resolve --multi-controller and --no-multi-controller options preferences->multiController = parser.getToggleOptionValue("multi-controller", preferences->multiController); @@ -467,6 +484,9 @@ void StreamCommandLineParser::parse(const QStringList &args, StreamingPreference // Resolve --frame-pacing and --no-frame-pacing options preferences->framePacing = parser.getToggleOptionValue("frame-pacing", preferences->framePacing); + // Resolve --video-enhancement and --no-video-enhancement options + preferences->videoEnhancing = parser.getToggleOptionValue("video-enhancement", preferences->videoEnhancing); + // Resolve --mute-on-focus-loss and --no-mute-on-focus-loss options preferences->muteOnFocusLoss = parser.getToggleOptionValue("mute-on-focus-loss", preferences->muteOnFocusLoss); diff --git a/app/cli/commandlineparser.h b/app/cli/commandlineparser.h index 0f68599fc..39722a064 100644 --- a/app/cli/commandlineparser.h +++ b/app/cli/commandlineparser.h @@ -69,6 +69,7 @@ class StreamCommandLineParser QString m_AppName; QMap m_WindowModeMap; QMap m_AudioConfigMap; + QMap m_SuperResolutionModeMap; QMap m_VideoCodecMap; QMap m_VideoDecoderMap; QMap m_CaptureSysKeysModeMap; diff --git a/app/gui/SettingsView.qml b/app/gui/SettingsView.qml index c119d1556..2c35c87ac 100644 --- a/app/gui/SettingsView.qml +++ b/app/gui/SettingsView.qml @@ -871,6 +871,133 @@ Flickable { : qsTr("HDR streaming is not supported on this PC.") } + + CheckBox { + id: videoEnhancementCheck + width: parent.width + hoverEnabled: true + text: qsTr("Video Super Resolution") + font.pointSize: 12 + enabled: SystemProperties.isVideoEnhancementAvailable() + checked: { + return SystemProperties.isVideoEnhancementAvailable() && StreamingPreferences.videoEnhancing + } + property bool keepValue: checked; + + function changeCheck() { + // We disable Software rendering + if(decoderListModel.get(decoderComboBox.currentIndex).val === StreamingPreferences.VDS_FORCE_SOFTWARE){ + enabled = false; + keepValue = checked; + checked = false; + } else { + enabled = true; + checked = keepValue; + } + } + + onCheckedChanged: { + StreamingPreferences.videoEnhancing = checked + } + ToolTip.delay: 1000 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + ToolTip.text: + qsTr("Leverages hardware acceleration to improve picture clarity by upscaling when stream resolution is below your display resolution.") + + Component.onCompleted: { + if (!SystemProperties.isVideoEnhancementAvailable()){ + text = qsTr("Video Super Resolution (unavailable on this system)") + enabled = false; + checked = false; + } + } + } + + // Note: Do not make the algorythm selector available to the final user + Label { + visible: SystemProperties.isVideoEnhancementSwitchable() + width: parent.width + id: resSuperResolutionModeTitle + enabled: SystemProperties.isVideoEnhancementAvailable() + text: SystemProperties.isVideoEnhancementAvailable() ? + qsTr("Video Super Resolution Mode
(Dropdown available only in Debug mode)
") + : + qsTr("Video Super Resolution Mode (unavailable on this system)") + font.pointSize: 12 + wrapMode: Text.Wrap + } + + // Note: Do not make the algorythm selector available to the final user + AutoResizingComboBox { + + visible: SystemProperties.isVideoEnhancementSwitchable() + enabled: SystemProperties.isVideoEnhancementAvailable() + + ToolTip.delay: 1000 + ToolTip.timeout: 5000 + ToolTip.visible: hovered + ToolTip.text: + qsTr("This dropdown is available only in Debug mode for development and testing purposes.") + + qsTr("\nIn Release mode, it defaults to \"Auto Selection\".") + + // Ignore setting the index at first, and actually set it when the component is loaded + Component.onCompleted: { + var saved_super_resolution = StreamingPreferences.superResolutionMode + currentIndex = 0 + for (var i = 0; i < superResolutionModeListModel.count; i++) { + var el_super_resolution = superResolutionModeListModel.get(i).val; + if (saved_super_resolution === el_super_resolution) { + currentIndex = i + break + } + } + activated(currentIndex) + } + + id: superResolutionModeComboBox + textRole: "text" + model: ListModel { + id: superResolutionModeListModel + + ListElement { + text: qsTr("Auto Selection") + val: StreamingPreferences.SRM_00 + } + ListElement { + text: qsTr("Vendor Driver Upscaler") + val: StreamingPreferences.SRM_01 + } + ListElement { + text: qsTr("Video Processor Upscaler") + val: StreamingPreferences.SRM_02 + } + ListElement { + text: qsTr("FSR1 Upscaler") + val: StreamingPreferences.SRM_03 + } + ListElement { + text: qsTr("NIS Upscaler") + val: StreamingPreferences.SRM_04 + } + ListElement { + text: qsTr("SGSR1 Upscaler") + val: StreamingPreferences.SRM_05 + } + ListElement { + text: qsTr("RCAS Sharpener") + val: StreamingPreferences.SRM_06 + } + ListElement { + text: qsTr("NIS Sharpener") + val: StreamingPreferences.SRM_07 + } + } + // ::onActivated must be used, as it only listens for when the index is changed by a human + onActivated : { + StreamingPreferences.superResolutionMode = superResolutionModeListModel.get(currentIndex).val + } + } } } @@ -1597,6 +1724,9 @@ Flickable { StreamingPreferences.videoDecoderSelection = decoderListModel.get(currentIndex).val } } + onCurrentIndexChanged: { + videoEnhancementCheck.changeCheck() + } } Label { diff --git a/app/main.cpp b/app/main.cpp index c0be000c7..d3292c82b 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef Q_OS_UNIX #include @@ -814,6 +815,13 @@ int main(int argc, char *argv[]) break; } + // Log the OS we're running on. + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Running on %s (%s %s)", + QSysInfo::prettyProductName().toUtf8().constData(), + QSysInfo::kernelType().toUtf8().constData(), + QSysInfo::kernelVersion().toUtf8().constData()); + SDL_version compileVersion; SDL_VERSION(&compileVersion); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, diff --git a/app/resources.qrc b/app/resources.qrc index 04b71edc3..c180cf1f3 100644 --- a/app/resources.qrc +++ b/app/resources.qrc @@ -93,4 +93,19 @@ shaders/d3d11_y410_pixel.fxc shaders/vt_renderer.metal + + shaders/enhancer/copy_cs.hlsl + shaders/enhancer/overlay_ps.hlsl + shaders/enhancer/overlay_vs.hlsl + shaders/enhancer/yuv_to_rgb_ps.hlsl + shaders/enhancer/NVIDIA/NIS_Main.hlsl + shaders/enhancer/NVIDIA/NIS_Scaler.h + shaders/enhancer/AMD/FSR_Pass.hlsl + shaders/enhancer/AMD/ffx_a.h + shaders/enhancer/AMD/ffx_fsr1.h + shaders/enhancer/AMD/FSR1.glsl + shaders/enhancer/AMD/FSR1_HDR.glsl + shaders/enhancer/QUALCOMM/sgsr1_shader.hlsl + shaders/enhancer/QUALCOMM/sgsr1.h + diff --git a/app/settings/streamingpreferences.cpp b/app/settings/streamingpreferences.cpp index 0c2a6c985..f4ac9e379 100644 --- a/app/settings/streamingpreferences.cpp +++ b/app/settings/streamingpreferences.cpp @@ -23,6 +23,7 @@ #define SER_HOSTAUDIO "hostaudio" #define SER_MULTICONT "multicontroller" #define SER_AUDIOCFG "audiocfg" +#define SER_SUPERRESOLUTIONMODE "superresolutionmode" #define SER_VIDEOCFG "videocfg" #define SER_HDR "hdr" #define SER_YUV444 "yuv444" @@ -34,6 +35,7 @@ #define SER_ABSTOUCHMODE "abstouchmode" #define SER_STARTWINDOWED "startwindowed" #define SER_FRAMEPACING "framepacing" +#define SER_VIDEOENHANCING "videoenhancing" #define SER_CONNWARNINGS "connwarnings" #define SER_CONFWARNINGS "confwarnings" #define SER_UIDISPLAYMODE "uidisplaymode" @@ -138,6 +140,7 @@ void StreamingPreferences::reload() absoluteMouseMode = settings.value(SER_ABSMOUSEMODE, false).toBool(); absoluteTouchMode = settings.value(SER_ABSTOUCHMODE, true).toBool(); framePacing = settings.value(SER_FRAMEPACING, false).toBool(); + videoEnhancing = settings.value(SER_VIDEOENHANCING, false).toBool(); connectionWarnings = settings.value(SER_CONNWARNINGS, true).toBool(); configurationWarnings = settings.value(SER_CONFWARNINGS, true).toBool(); richPresence = settings.value(SER_RICHPRESENCE, true).toBool(); @@ -156,6 +159,13 @@ void StreamingPreferences::reload() static_cast(CaptureSysKeysMode::CSK_OFF)).toInt()); audioConfig = static_cast(settings.value(SER_AUDIOCFG, static_cast(AudioConfig::AC_STEREO)).toInt()); +#ifdef QT_DEBUG + superResolutionMode = static_cast(settings.value(SER_SUPERRESOLUTIONMODE, + static_cast(SuperResolutionMode::SRM_00)).toInt()); +#else + // For Release mode, we default to "Auto Selection" + superResolutionMode = SuperResolutionMode::SRM_00; +#endif videoCodecConfig = static_cast(settings.value(SER_VIDEOCFG, static_cast(VideoCodecConfig::VCC_AUTO)).toInt()); videoDecoderSelection = static_cast(settings.value(SER_VIDEODEC, @@ -338,6 +348,7 @@ void StreamingPreferences::save() settings.setValue(SER_ABSMOUSEMODE, absoluteMouseMode); settings.setValue(SER_ABSTOUCHMODE, absoluteTouchMode); settings.setValue(SER_FRAMEPACING, framePacing); + settings.setValue(SER_VIDEOENHANCING, videoEnhancing); settings.setValue(SER_CONNWARNINGS, connectionWarnings); settings.setValue(SER_CONFWARNINGS, configurationWarnings); settings.setValue(SER_RICHPRESENCE, richPresence); @@ -346,6 +357,7 @@ void StreamingPreferences::save() settings.setValue(SER_DETECTNETBLOCKING, detectNetworkBlocking); settings.setValue(SER_SHOWPERFOVERLAY, showPerformanceOverlay); settings.setValue(SER_AUDIOCFG, static_cast(audioConfig)); + settings.setValue(SER_SUPERRESOLUTIONMODE, static_cast(superResolutionMode)); settings.setValue(SER_HDR, enableHdr); settings.setValue(SER_YUV444, enableYUV444); settings.setValue(SER_VIDEOCFG, static_cast(videoCodecConfig)); diff --git a/app/settings/streamingpreferences.h b/app/settings/streamingpreferences.h index ad611f6a2..d4bf91d94 100644 --- a/app/settings/streamingpreferences.h +++ b/app/settings/streamingpreferences.h @@ -26,6 +26,19 @@ class StreamingPreferences : public QObject }; Q_ENUM(AudioConfig) + enum SuperResolutionMode + { + SRM_00, + SRM_01, + SRM_02, + SRM_03, + SRM_04, + SRM_05, + SRM_06, + SRM_07 + }; + Q_ENUM(SuperResolutionMode) + enum VideoCodecConfig { VCC_AUTO, @@ -134,6 +147,7 @@ class StreamingPreferences : public QObject Q_PROPERTY(bool absoluteMouseMode MEMBER absoluteMouseMode NOTIFY absoluteMouseModeChanged) Q_PROPERTY(bool absoluteTouchMode MEMBER absoluteTouchMode NOTIFY absoluteTouchModeChanged) Q_PROPERTY(bool framePacing MEMBER framePacing NOTIFY framePacingChanged) + Q_PROPERTY(bool videoEnhancing MEMBER videoEnhancing NOTIFY videoEnhancingChanged) Q_PROPERTY(bool connectionWarnings MEMBER connectionWarnings NOTIFY connectionWarningsChanged) Q_PROPERTY(bool configurationWarnings MEMBER configurationWarnings NOTIFY configurationWarningsChanged) Q_PROPERTY(bool richPresence MEMBER richPresence NOTIFY richPresenceChanged) @@ -141,6 +155,7 @@ class StreamingPreferences : public QObject Q_PROPERTY(bool detectNetworkBlocking MEMBER detectNetworkBlocking NOTIFY detectNetworkBlockingChanged) Q_PROPERTY(bool showPerformanceOverlay MEMBER showPerformanceOverlay NOTIFY showPerformanceOverlayChanged) Q_PROPERTY(AudioConfig audioConfig MEMBER audioConfig NOTIFY audioConfigChanged) + Q_PROPERTY(SuperResolutionMode superResolutionMode MEMBER superResolutionMode NOTIFY superResolutionModeChanged) Q_PROPERTY(VideoCodecConfig videoCodecConfig MEMBER videoCodecConfig NOTIFY videoCodecConfigChanged) Q_PROPERTY(bool enableHdr MEMBER enableHdr NOTIFY enableHdrChanged) Q_PROPERTY(bool enableYUV444 MEMBER enableYUV444 NOTIFY enableYUV444Changed) @@ -176,6 +191,7 @@ class StreamingPreferences : public QObject bool absoluteMouseMode; bool absoluteTouchMode; bool framePacing; + bool videoEnhancing; bool connectionWarnings; bool configurationWarnings; bool richPresence; @@ -190,6 +206,7 @@ class StreamingPreferences : public QObject bool keepAwake; int packetSize; AudioConfig audioConfig; + SuperResolutionMode superResolutionMode; VideoCodecConfig videoCodecConfig; bool enableHdr; bool enableYUV444; @@ -216,6 +233,7 @@ class StreamingPreferences : public QObject void absoluteMouseModeChanged(); void absoluteTouchModeChanged(); void audioConfigChanged(); + void superResolutionModeChanged(); void videoCodecConfigChanged(); void enableHdrChanged(); void enableYUV444Changed(); @@ -223,6 +241,7 @@ class StreamingPreferences : public QObject void uiDisplayModeChanged(); void windowModeChanged(); void framePacingChanged(); + void videoEnhancingChanged(); void connectionWarningsChanged(); void configurationWarningsChanged(); void richPresenceChanged(); diff --git a/app/shaders/enhancer/AMD/FSR1.glsl b/app/shaders/enhancer/AMD/FSR1.glsl new file mode 100644 index 000000000..51a02a28c --- /dev/null +++ b/app/shaders/enhancer/AMD/FSR1.glsl @@ -0,0 +1,457 @@ +// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// FidelityFX FSR v1.0.2 by AMD +// ported to mpv by agyild +// https://gist.github.com/agyild + +// Changelog +// Made it compatible with pre-OpenGL 4.0 renderers +// Made it directly operate on LUMA plane, since the original shader was operating on LUMA by deriving it from RGB. This should cause a major increase in performance, especially on OpenGL 4.0+ renderers (4+2 texture lookups vs. 12+5) +// Removed transparency preservation mechanism since the alpha channel is a separate source plane than LUMA +// Added optional performance-saving lossy optimizations to EASU (Credit: atyuwen, https://atyuwen.github.io/posts/optimizing-fsr/) +// +// Notes +// Per AMD's guidelines only upscales content up to 4x (e.g., 1080p -> 2160p, 720p -> 1440p etc.) and everything else in between, +// that means FSR will scale up to 4x at maximum, and any further scaling will be processed by mpv's scalers + +//!HOOK LUMA +//!BIND HOOKED +//!SAVE EASUTEX +//!DESC FidelityFX Super Resolution v1.0.2 (EASU) +//!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 > +//!WIDTH OUTPUT.w OUTPUT.w LUMA.w 2 * < * LUMA.w 2 * OUTPUT.w LUMA.w 2 * > * + OUTPUT.w OUTPUT.w LUMA.w 2 * = * + +//!HEIGHT OUTPUT.h OUTPUT.h LUMA.h 2 * < * LUMA.h 2 * OUTPUT.h LUMA.h 2 * > * + OUTPUT.h OUTPUT.h LUMA.h 2 * = * + +//!COMPONENTS 1 + +// User variables - EASU +#define FSR_PQ 0 // Whether the source content has PQ gamma or not. Needs to be set to the same value for both passes. 0 or 1. +#define FSR_EASU_DERING 1 // If set to 0, disables deringing for a small increase in performance. 0 or 1. +#define FSR_EASU_SIMPLE_ANALYSIS 0 // If set to 1, uses a simpler single-pass direction and length analysis for an increase in performance. 0 or 1. +#define FSR_EASU_QUIT_EARLY 0 // If set to 1, uses bilinear filtering for non-edge pixels and skips EASU on those regions for an increase in performance. 0 or 1. + +// Shader code + +#ifndef FSR_EASU_DIR_THRESHOLD + #if (FSR_EASU_QUIT_EARLY == 1) + #define FSR_EASU_DIR_THRESHOLD 64.0 + #elif (FSR_EASU_QUIT_EARLY == 0) + #define FSR_EASU_DIR_THRESHOLD 32768.0 + #endif +#endif + +float APrxLoRcpF1(float a) { + return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a)); +} + +float APrxLoRsqF1(float a) { + return uintBitsToFloat(uint(0x5f347d74) - (floatBitsToUint(a) >> uint(1))); +} + +float AMin3F1(float x, float y, float z) { + return min(x, min(y, z)); +} + +float AMax3F1(float x, float y, float z) { + return max(x, max(y, z)); +} + +#if (FSR_PQ == 1) + +float ToGamma2(float a) { + return pow(a, 4.0); +} + +#endif + + // Filtering for a given tap for the scalar. + void FsrEasuTap( + inout float aC, // Accumulated color, with negative lobe. + inout float aW, // Accumulated weight. + vec2 off, // Pixel offset from resolve position to tap. + vec2 dir, // Gradient direction. + vec2 len, // Length. + float lob, // Negative lobe strength. + float clp, // Clipping point. + float c){ // Tap color. + // Rotate offset by direction. + vec2 v; + v.x = (off.x * ( dir.x)) + (off.y * dir.y); + v.y = (off.x * (-dir.y)) + (off.y * dir.x); + // Anisotropy. + v *= len; + // Compute distance^2. + float d2 = v.x * v.x + v.y * v.y; + // Limit to the window as at corner, 2 taps can easily be outside. + d2 = min(d2, clp); + // Approximation of lancos2 without sin() or rcp(), or sqrt() to get x. + // (25/16 * (2/5 * x^2 - 1)^2 - (25/16 - 1)) * (1/4 * x^2 - 1)^2 + // |_______________________________________| |_______________| + // base window + // The general form of the 'base' is, + // (a*(b*x^2-1)^2-(a-1)) + // Where 'a=1/(2*b-b^2)' and 'b' moves around the negative lobe. + float wB = float(2.0 / 5.0) * d2 + -1.0; + float wA = lob * d2 + -1.0; + wB *= wB; + wA *= wA; + wB = float(25.0 / 16.0) * wB + float(-(25.0 / 16.0 - 1.0)); + float w = wB * wA; + // Do weighted average. + aC += c * w; + aW += w; +} + +// Accumulate direction and length. +void FsrEasuSet( + inout vec2 dir, + inout float len, + vec2 pp, +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + float b, float c, + float i, float j, float f, float e, + float k, float l, float h, float g, + float o, float n +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + bool biS, bool biT, bool biU, bool biV, + float lA, float lB, float lC, float lD, float lE +#endif + ){ + // Compute bilinear weight, branches factor out as predicates are compiler time immediates. + // s t + // u v +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + vec4 w = vec4(0.0); + w.x = (1.0 - pp.x) * (1.0 - pp.y); + w.y = pp.x * (1.0 - pp.y); + w.z = (1.0 - pp.x) * pp.y; + w.w = pp.x * pp.y; + + float lA = dot(w, vec4(b, c, f, g)); + float lB = dot(w, vec4(e, f, i, j)); + float lC = dot(w, vec4(f, g, j, k)); + float lD = dot(w, vec4(g, h, k, l)); + float lE = dot(w, vec4(j, k, n, o)); +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + float w = 0.0; + if (biS) + w = (1.0 - pp.x) * (1.0 - pp.y); + if (biT) + w = pp.x * (1.0 - pp.y); + if (biU) + w = (1.0 - pp.x) * pp.y; + if (biV) + w = pp.x * pp.y; +#endif + // Direction is the '+' diff. + // a + // b c d + // e + // Then takes magnitude from abs average of both sides of 'c'. + // Length converts gradient reversal to 0, smoothly to non-reversal at 1, shaped, then adding horz and vert terms. + float dc = lD - lC; + float cb = lC - lB; + float lenX = max(abs(dc), abs(cb)); + lenX = APrxLoRcpF1(lenX); + float dirX = lD - lB; + lenX = clamp(abs(dirX) * lenX, 0.0, 1.0); + lenX *= lenX; + // Repeat for the y axis. + float ec = lE - lC; + float ca = lC - lA; + float lenY = max(abs(ec), abs(ca)); + lenY = APrxLoRcpF1(lenY); + float dirY = lE - lA; + lenY = clamp(abs(dirY) * lenY, 0.0, 1.0); + lenY *= lenY; +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + len = lenX + lenY; + dir = vec2(dirX, dirY); +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + dir += vec2(dirX, dirY) * w; + len += dot(vec2(w), vec2(lenX, lenY)); +#endif +} + +vec4 hook() { + // Result + vec4 pix = vec4(0.0, 0.0, 0.0, 1.0); + + //------------------------------------------------------------------------------------------------------------------------------ + // +---+---+ + // | | | + // +--(0)--+ + // | b | c | + // +---F---+---+---+ + // | e | f | g | h | + // +--(1)--+--(2)--+ + // | i | j | k | l | + // +---+---+---+---+ + // | n | o | + // +--(3)--+ + // | | | + // +---+---+ + // Get position of 'F'. + vec2 pp = HOOKED_pos * HOOKED_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + //------------------------------------------------------------------------------------------------------------------------------ + // 12-tap kernel. + // b c + // e f g h + // i j k l + // n o + // Gather 4 ordering. + // a b + // r g + // Allowing dead-code removal to remove the 'z's. +#if (defined(HOOKED_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310))) + vec4 bczzL = HOOKED_gather(vec2((fp + vec2(1.0, -1.0)) * HOOKED_pt), 0); + vec4 ijfeL = HOOKED_gather(vec2((fp + vec2(0.0, 1.0)) * HOOKED_pt), 0); + vec4 klhgL = HOOKED_gather(vec2((fp + vec2(2.0, 1.0)) * HOOKED_pt), 0); + vec4 zzonL = HOOKED_gather(vec2((fp + vec2(1.0, 3.0)) * HOOKED_pt), 0); +#else + // pre-OpenGL 4.0 compatibility + float b = HOOKED_tex(vec2((fp + vec2(0.5, -0.5)) * HOOKED_pt)).r; + float c = HOOKED_tex(vec2((fp + vec2(1.5, -0.5)) * HOOKED_pt)).r; + + float e = HOOKED_tex(vec2((fp + vec2(-0.5, 0.5)) * HOOKED_pt)).r; + float f = HOOKED_tex(vec2((fp + vec2( 0.5, 0.5)) * HOOKED_pt)).r; + float g = HOOKED_tex(vec2((fp + vec2( 1.5, 0.5)) * HOOKED_pt)).r; + float h = HOOKED_tex(vec2((fp + vec2( 2.5, 0.5)) * HOOKED_pt)).r; + + float i = HOOKED_tex(vec2((fp + vec2(-0.5, 1.5)) * HOOKED_pt)).r; + float j = HOOKED_tex(vec2((fp + vec2( 0.5, 1.5)) * HOOKED_pt)).r; + float k = HOOKED_tex(vec2((fp + vec2( 1.5, 1.5)) * HOOKED_pt)).r; + float l = HOOKED_tex(vec2((fp + vec2( 2.5, 1.5)) * HOOKED_pt)).r; + + float n = HOOKED_tex(vec2((fp + vec2(0.5, 2.5) ) * HOOKED_pt)).r; + float o = HOOKED_tex(vec2((fp + vec2(1.5, 2.5) ) * HOOKED_pt)).r; + + vec4 bczzL = vec4(b, c, 0.0, 0.0); + vec4 ijfeL = vec4(i, j, f, e); + vec4 klhgL = vec4(k, l, h, g); + vec4 zzonL = vec4(0.0, 0.0, o, n); +#endif + //------------------------------------------------------------------------------------------------------------------------------ + // Rename. + float bL = bczzL.x; + float cL = bczzL.y; + float iL = ijfeL.x; + float jL = ijfeL.y; + float fL = ijfeL.z; + float eL = ijfeL.w; + float kL = klhgL.x; + float lL = klhgL.y; + float hL = klhgL.z; + float gL = klhgL.w; + float oL = zzonL.z; + float nL = zzonL.w; + +#if (FSR_PQ == 1) + // Not the most performance-friendly solution, but should work until mpv adds proper gamma transformation functions for shaders + bL = ToGamma2(bL); + cL = ToGamma2(cL); + iL = ToGamma2(iL); + jL = ToGamma2(jL); + fL = ToGamma2(fL); + eL = ToGamma2(eL); + kL = ToGamma2(kL); + lL = ToGamma2(lL); + hL = ToGamma2(hL); + gL = ToGamma2(gL); + oL = ToGamma2(oL); + nL = ToGamma2(nL); +#endif + + // Accumulate for bilinear interpolation. + vec2 dir = vec2(0.0); + float len = 0.0; +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + FsrEasuSet(dir, len, pp, bL, cL, iL, jL, fL, eL, kL, lL, hL, gL, oL, nL); +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + FsrEasuSet(dir, len, pp, true, false, false, false, bL, eL, fL, gL, jL); + FsrEasuSet(dir, len, pp, false, true, false, false, cL, fL, gL, hL, kL); + FsrEasuSet(dir, len, pp, false, false, true, false, fL, iL, jL, kL, nL); + FsrEasuSet(dir, len, pp, false, false, false, true, gL, jL, kL, lL, oL); +#endif + //------------------------------------------------------------------------------------------------------------------------------ + // Normalize with approximation, and cleanup close to zero. + vec2 dir2 = dir * dir; + float dirR = dir2.x + dir2.y; + bool zro = dirR < float(1.0 / FSR_EASU_DIR_THRESHOLD); + dirR = APrxLoRsqF1(dirR); +#if (FSR_EASU_QUIT_EARLY == 1) + if (zro) { + vec4 w = vec4(0.0); + w.x = (1.0 - pp.x) * (1.0 - pp.y); + w.y = pp.x * (1.0 - pp.y); + w.z = (1.0 - pp.x) * pp.y; + w.w = pp.x * pp.y; + + pix.r = clamp(dot(w, vec4(fL, gL, jL, kL)), 0.0, 1.0); + return pix; + } +#elif (FSR_EASU_QUIT_EARLY == 0) + dirR = zro ? 1.0 : dirR; + dir.x = zro ? 1.0 : dir.x; +#endif + dir *= vec2(dirR); + // Transform from {0 to 2} to {0 to 1} range, and shape with square. + len = len * 0.5; + len *= len; + // Stretch kernel {1.0 vert|horz, to sqrt(2.0) on diagonal}. + float stretch = (dir.x * dir.x + dir.y * dir.y) * APrxLoRcpF1(max(abs(dir.x), abs(dir.y))); + // Anisotropic length after rotation, + // x := 1.0 lerp to 'stretch' on edges + // y := 1.0 lerp to 2x on edges + vec2 len2 = vec2(1.0 + (stretch - 1.0) * len, 1.0 + -0.5 * len); + // Based on the amount of 'edge', + // the window shifts from +/-{sqrt(2.0) to slightly beyond 2.0}. + float lob = 0.5 + float((1.0 / 4.0 - 0.04) - 0.5) * len; + // Set distance^2 clipping point to the end of the adjustable window. + float clp = APrxLoRcpF1(lob); + //------------------------------------------------------------------------------------------------------------------------------ + // Accumulation + // b c + // e f g h + // i j k l + // n o + float aC = 0.0; + float aW = 0.0; + FsrEasuTap(aC, aW, vec2( 0.0,-1.0) - pp, dir, len2, lob, clp, bL); // b + FsrEasuTap(aC, aW, vec2( 1.0,-1.0) - pp, dir, len2, lob, clp, cL); // c + FsrEasuTap(aC, aW, vec2(-1.0, 1.0) - pp, dir, len2, lob, clp, iL); // i + FsrEasuTap(aC, aW, vec2( 0.0, 1.0) - pp, dir, len2, lob, clp, jL); // j + FsrEasuTap(aC, aW, vec2( 0.0, 0.0) - pp, dir, len2, lob, clp, fL); // f + FsrEasuTap(aC, aW, vec2(-1.0, 0.0) - pp, dir, len2, lob, clp, eL); // e + FsrEasuTap(aC, aW, vec2( 1.0, 1.0) - pp, dir, len2, lob, clp, kL); // k + FsrEasuTap(aC, aW, vec2( 2.0, 1.0) - pp, dir, len2, lob, clp, lL); // l + FsrEasuTap(aC, aW, vec2( 2.0, 0.0) - pp, dir, len2, lob, clp, hL); // h + FsrEasuTap(aC, aW, vec2( 1.0, 0.0) - pp, dir, len2, lob, clp, gL); // g + FsrEasuTap(aC, aW, vec2( 1.0, 2.0) - pp, dir, len2, lob, clp, oL); // o + FsrEasuTap(aC, aW, vec2( 0.0, 2.0) - pp, dir, len2, lob, clp, nL); // n + //------------------------------------------------------------------------------------------------------------------------------ + // Normalize and dering. + pix.r = aC / aW; +#if (FSR_EASU_DERING == 1) + float min1 = min(AMin3F1(fL, gL, jL), kL); + float max1 = max(AMax3F1(fL, gL, jL), kL); + pix.r = clamp(pix.r, min1, max1); +#endif + pix.r = clamp(pix.r, 0.0, 1.0); + + return pix; +} + +//!HOOK LUMA +//!BIND EASUTEX +//!DESC FidelityFX Super Resolution v1.0.2 (RCAS) +//!WIDTH EASUTEX.w +//!HEIGHT EASUTEX.h +//!COMPONENTS 1 + +// User variables - RCAS +// #define SHARPNESS 0.2 // Controls the amount of sharpening. The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}. 0.0 to 2.0. +#define FSR_RCAS_DENOISE 1 // If set to 1, lessens the sharpening on noisy areas. Can be disabled for better performance. 0 or 1. +#define FSR_PQ 0 // Whether the source content has PQ gamma or not. Needs to be set to the same value for both passes. 0 or 1. + +// Custom +#define SHARPNESS 0.75 + +// Shader code + +#define FSR_RCAS_LIMIT (0.25 - (1.0 / 16.0)) // This is set at the limit of providing unnatural results for sharpening. + +float APrxMedRcpF1(float a) { + float b = uintBitsToFloat(uint(0x7ef19fff) - floatBitsToUint(a)); + return b * (-b * a + 2.0); +} + +float AMax3F1(float x, float y, float z) { + return max(x, max(y, z)); +} + +float AMin3F1(float x, float y, float z) { + return min(x, min(y, z)); +} + +#if (FSR_PQ == 1) + +float FromGamma2(float a) { + return sqrt(sqrt(a)); +} + +#endif + +vec4 hook() { + // Algorithm uses minimal 3x3 pixel neighborhood. + // b + // d e f + // h +#if (defined(EASUTEX_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310))) + vec3 bde = EASUTEX_gather(EASUTEX_pos + EASUTEX_pt * vec2(-0.5), 0).xyz; + float b = bde.z; + float d = bde.x; + float e = bde.y; + + vec2 fh = EASUTEX_gather(EASUTEX_pos + EASUTEX_pt * vec2(0.5), 0).zx; + float f = fh.x; + float h = fh.y; +#else + float b = EASUTEX_texOff(vec2( 0.0, -1.0)).r; + float d = EASUTEX_texOff(vec2(-1.0, 0.0)).r; + float e = EASUTEX_tex(EASUTEX_pos).r; + float f = EASUTEX_texOff(vec2(1.0, 0.0)).r; + float h = EASUTEX_texOff(vec2(0.0, 1.0)).r; +#endif + + // Min and max of ring. + float mn1L = min(AMin3F1(b, d, f), h); + float mx1L = max(AMax3F1(b, d, f), h); + + // Immediate constants for peak range. + vec2 peakC = vec2(1.0, -1.0 * 4.0); + + // Limiters, these need to be high precision RCPs. + float hitMinL = min(mn1L, e) / (4.0 * mx1L); + float hitMaxL = (peakC.x - max(mx1L, e)) / (4.0 * mn1L + peakC.y); + float lobeL = max(-hitMinL, hitMaxL); + float lobe = max(float(-FSR_RCAS_LIMIT), min(lobeL, 0.0)) * exp2(-clamp(float(SHARPNESS), 0.0, 2.0)); + + // Apply noise removal. +#if (FSR_RCAS_DENOISE == 1) + // Noise detection. + float nz = 0.25 * b + 0.25 * d + 0.25 * f + 0.25 * h - e; + nz = clamp(abs(nz) * APrxMedRcpF1(AMax3F1(AMax3F1(b, d, e), f, h) - AMin3F1(AMin3F1(b, d, e), f, h)), 0.0, 1.0); + nz = -0.5 * nz + 1.0; + lobe *= nz; +#endif + + // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes. + float rcpL = APrxMedRcpF1(4.0 * lobe + 1.0); + vec4 pix = vec4(0.0, 0.0, 0.0, 1.0); + pix.r = float((lobe * b + lobe * d + lobe * h + lobe * f + e) * rcpL); +#if (FSR_PQ == 1) + pix.r = FromGamma2(pix.r); +#endif + + return pix; +} \ No newline at end of file diff --git a/app/shaders/enhancer/AMD/FSR1_HDR.glsl b/app/shaders/enhancer/AMD/FSR1_HDR.glsl new file mode 100644 index 000000000..d3db9e6d4 --- /dev/null +++ b/app/shaders/enhancer/AMD/FSR1_HDR.glsl @@ -0,0 +1,461 @@ +// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +// FidelityFX FSR v1.0.2 by AMD +// ported to mpv by agyild +// https://gist.github.com/agyild + +// Changelog +// Made it compatible with pre-OpenGL 4.0 renderers +// Made it directly operate on LUMA plane, since the original shader was operating on LUMA by deriving it from RGB. This should cause a major increase in performance, especially on OpenGL 4.0+ renderers (4+2 texture lookups vs. 12+5) +// Removed transparency preservation mechanism since the alpha channel is a separate source plane than LUMA +// Added optional performance-saving lossy optimizations to EASU (Credit: atyuwen, https://atyuwen.github.io/posts/optimizing-fsr/) +// +// Notes +// Per AMD's guidelines only upscales content up to 4x (e.g., 1080p -> 2160p, 720p -> 1440p etc.) and everything else in between, +// that means FSR will scale up to 4x at maximum, and any further scaling will be processed by mpv's scalers + +//!HOOK LUMA +//!BIND HOOKED +//!SAVE EASUTEX +//!DESC FidelityFX Super Resolution v1.0.2 (EASU) +//!WHEN OUTPUT.w OUTPUT.h * LUMA.w LUMA.h * / 1.0 > +//!WIDTH OUTPUT.w OUTPUT.w LUMA.w 2 * < * LUMA.w 2 * OUTPUT.w LUMA.w 2 * > * + OUTPUT.w OUTPUT.w LUMA.w 2 * = * + +//!HEIGHT OUTPUT.h OUTPUT.h LUMA.h 2 * < * LUMA.h 2 * OUTPUT.h LUMA.h 2 * > * + OUTPUT.h OUTPUT.h LUMA.h 2 * = * + +//!COMPONENTS 1 + +// User variables - EASU +#define FSR_PQ 0 // Whether the source content has PQ gamma or not. Needs to be set to the same value for both passes. 0 or 1. +#define FSR_EASU_DERING 1 // If set to 0, disables deringing for a small increase in performance. 0 or 1. +#define FSR_EASU_SIMPLE_ANALYSIS 0 // If set to 1, uses a simpler single-pass direction and length analysis for an increase in performance. 0 or 1. +#define FSR_EASU_QUIT_EARLY 0 // If set to 1, uses bilinear filtering for non-edge pixels and skips EASU on those regions for an increase in performance. 0 or 1. + +// Custom +#define FSR_PQ 1 + +// Shader code + +#ifndef FSR_EASU_DIR_THRESHOLD + #if (FSR_EASU_QUIT_EARLY == 1) + #define FSR_EASU_DIR_THRESHOLD 64.0 + #elif (FSR_EASU_QUIT_EARLY == 0) + #define FSR_EASU_DIR_THRESHOLD 32768.0 + #endif +#endif + +float APrxLoRcpF1(float a) { + return uintBitsToFloat(uint(0x7ef07ebb) - floatBitsToUint(a)); +} + +float APrxLoRsqF1(float a) { + return uintBitsToFloat(uint(0x5f347d74) - (floatBitsToUint(a) >> uint(1))); +} + +float AMin3F1(float x, float y, float z) { + return min(x, min(y, z)); +} + +float AMax3F1(float x, float y, float z) { + return max(x, max(y, z)); +} + +#if (FSR_PQ == 1) + +float ToGamma2(float a) { + return pow(a, 4.0); +} + +#endif + + // Filtering for a given tap for the scalar. + void FsrEasuTap( + inout float aC, // Accumulated color, with negative lobe. + inout float aW, // Accumulated weight. + vec2 off, // Pixel offset from resolve position to tap. + vec2 dir, // Gradient direction. + vec2 len, // Length. + float lob, // Negative lobe strength. + float clp, // Clipping point. + float c){ // Tap color. + // Rotate offset by direction. + vec2 v; + v.x = (off.x * ( dir.x)) + (off.y * dir.y); + v.y = (off.x * (-dir.y)) + (off.y * dir.x); + // Anisotropy. + v *= len; + // Compute distance^2. + float d2 = v.x * v.x + v.y * v.y; + // Limit to the window as at corner, 2 taps can easily be outside. + d2 = min(d2, clp); + // Approximation of lancos2 without sin() or rcp(), or sqrt() to get x. + // (25/16 * (2/5 * x^2 - 1)^2 - (25/16 - 1)) * (1/4 * x^2 - 1)^2 + // |_______________________________________| |_______________| + // base window + // The general form of the 'base' is, + // (a*(b*x^2-1)^2-(a-1)) + // Where 'a=1/(2*b-b^2)' and 'b' moves around the negative lobe. + float wB = float(2.0 / 5.0) * d2 + -1.0; + float wA = lob * d2 + -1.0; + wB *= wB; + wA *= wA; + wB = float(25.0 / 16.0) * wB + float(-(25.0 / 16.0 - 1.0)); + float w = wB * wA; + // Do weighted average. + aC += c * w; + aW += w; +} + +// Accumulate direction and length. +void FsrEasuSet( + inout vec2 dir, + inout float len, + vec2 pp, +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + float b, float c, + float i, float j, float f, float e, + float k, float l, float h, float g, + float o, float n +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + bool biS, bool biT, bool biU, bool biV, + float lA, float lB, float lC, float lD, float lE +#endif + ){ + // Compute bilinear weight, branches factor out as predicates are compiler time immediates. + // s t + // u v +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + vec4 w = vec4(0.0); + w.x = (1.0 - pp.x) * (1.0 - pp.y); + w.y = pp.x * (1.0 - pp.y); + w.z = (1.0 - pp.x) * pp.y; + w.w = pp.x * pp.y; + + float lA = dot(w, vec4(b, c, f, g)); + float lB = dot(w, vec4(e, f, i, j)); + float lC = dot(w, vec4(f, g, j, k)); + float lD = dot(w, vec4(g, h, k, l)); + float lE = dot(w, vec4(j, k, n, o)); +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + float w = 0.0; + if (biS) + w = (1.0 - pp.x) * (1.0 - pp.y); + if (biT) + w = pp.x * (1.0 - pp.y); + if (biU) + w = (1.0 - pp.x) * pp.y; + if (biV) + w = pp.x * pp.y; +#endif + // Direction is the '+' diff. + // a + // b c d + // e + // Then takes magnitude from abs average of both sides of 'c'. + // Length converts gradient reversal to 0, smoothly to non-reversal at 1, shaped, then adding horz and vert terms. + float dc = lD - lC; + float cb = lC - lB; + float lenX = max(abs(dc), abs(cb)); + lenX = APrxLoRcpF1(lenX); + float dirX = lD - lB; + lenX = clamp(abs(dirX) * lenX, 0.0, 1.0); + lenX *= lenX; + // Repeat for the y axis. + float ec = lE - lC; + float ca = lC - lA; + float lenY = max(abs(ec), abs(ca)); + lenY = APrxLoRcpF1(lenY); + float dirY = lE - lA; + lenY = clamp(abs(dirY) * lenY, 0.0, 1.0); + lenY *= lenY; +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + len = lenX + lenY; + dir = vec2(dirX, dirY); +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + dir += vec2(dirX, dirY) * w; + len += dot(vec2(w), vec2(lenX, lenY)); +#endif +} + +vec4 hook() { + // Result + vec4 pix = vec4(0.0, 0.0, 0.0, 1.0); + + //------------------------------------------------------------------------------------------------------------------------------ + // +---+---+ + // | | | + // +--(0)--+ + // | b | c | + // +---F---+---+---+ + // | e | f | g | h | + // +--(1)--+--(2)--+ + // | i | j | k | l | + // +---+---+---+---+ + // | n | o | + // +--(3)--+ + // | | | + // +---+---+ + // Get position of 'F'. + vec2 pp = HOOKED_pos * HOOKED_size - vec2(0.5); + vec2 fp = floor(pp); + pp -= fp; + //------------------------------------------------------------------------------------------------------------------------------ + // 12-tap kernel. + // b c + // e f g h + // i j k l + // n o + // Gather 4 ordering. + // a b + // r g + // Allowing dead-code removal to remove the 'z's. +#if (defined(HOOKED_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310))) + vec4 bczzL = HOOKED_gather(vec2((fp + vec2(1.0, -1.0)) * HOOKED_pt), 0); + vec4 ijfeL = HOOKED_gather(vec2((fp + vec2(0.0, 1.0)) * HOOKED_pt), 0); + vec4 klhgL = HOOKED_gather(vec2((fp + vec2(2.0, 1.0)) * HOOKED_pt), 0); + vec4 zzonL = HOOKED_gather(vec2((fp + vec2(1.0, 3.0)) * HOOKED_pt), 0); +#else + // pre-OpenGL 4.0 compatibility + float b = HOOKED_tex(vec2((fp + vec2(0.5, -0.5)) * HOOKED_pt)).r; + float c = HOOKED_tex(vec2((fp + vec2(1.5, -0.5)) * HOOKED_pt)).r; + + float e = HOOKED_tex(vec2((fp + vec2(-0.5, 0.5)) * HOOKED_pt)).r; + float f = HOOKED_tex(vec2((fp + vec2( 0.5, 0.5)) * HOOKED_pt)).r; + float g = HOOKED_tex(vec2((fp + vec2( 1.5, 0.5)) * HOOKED_pt)).r; + float h = HOOKED_tex(vec2((fp + vec2( 2.5, 0.5)) * HOOKED_pt)).r; + + float i = HOOKED_tex(vec2((fp + vec2(-0.5, 1.5)) * HOOKED_pt)).r; + float j = HOOKED_tex(vec2((fp + vec2( 0.5, 1.5)) * HOOKED_pt)).r; + float k = HOOKED_tex(vec2((fp + vec2( 1.5, 1.5)) * HOOKED_pt)).r; + float l = HOOKED_tex(vec2((fp + vec2( 2.5, 1.5)) * HOOKED_pt)).r; + + float n = HOOKED_tex(vec2((fp + vec2(0.5, 2.5) ) * HOOKED_pt)).r; + float o = HOOKED_tex(vec2((fp + vec2(1.5, 2.5) ) * HOOKED_pt)).r; + + vec4 bczzL = vec4(b, c, 0.0, 0.0); + vec4 ijfeL = vec4(i, j, f, e); + vec4 klhgL = vec4(k, l, h, g); + vec4 zzonL = vec4(0.0, 0.0, o, n); +#endif + //------------------------------------------------------------------------------------------------------------------------------ + // Rename. + float bL = bczzL.x; + float cL = bczzL.y; + float iL = ijfeL.x; + float jL = ijfeL.y; + float fL = ijfeL.z; + float eL = ijfeL.w; + float kL = klhgL.x; + float lL = klhgL.y; + float hL = klhgL.z; + float gL = klhgL.w; + float oL = zzonL.z; + float nL = zzonL.w; + +#if (FSR_PQ == 1) + // Not the most performance-friendly solution, but should work until mpv adds proper gamma transformation functions for shaders + bL = ToGamma2(bL); + cL = ToGamma2(cL); + iL = ToGamma2(iL); + jL = ToGamma2(jL); + fL = ToGamma2(fL); + eL = ToGamma2(eL); + kL = ToGamma2(kL); + lL = ToGamma2(lL); + hL = ToGamma2(hL); + gL = ToGamma2(gL); + oL = ToGamma2(oL); + nL = ToGamma2(nL); +#endif + + // Accumulate for bilinear interpolation. + vec2 dir = vec2(0.0); + float len = 0.0; +#if (FSR_EASU_SIMPLE_ANALYSIS == 1) + FsrEasuSet(dir, len, pp, bL, cL, iL, jL, fL, eL, kL, lL, hL, gL, oL, nL); +#elif (FSR_EASU_SIMPLE_ANALYSIS == 0) + FsrEasuSet(dir, len, pp, true, false, false, false, bL, eL, fL, gL, jL); + FsrEasuSet(dir, len, pp, false, true, false, false, cL, fL, gL, hL, kL); + FsrEasuSet(dir, len, pp, false, false, true, false, fL, iL, jL, kL, nL); + FsrEasuSet(dir, len, pp, false, false, false, true, gL, jL, kL, lL, oL); +#endif + //------------------------------------------------------------------------------------------------------------------------------ + // Normalize with approximation, and cleanup close to zero. + vec2 dir2 = dir * dir; + float dirR = dir2.x + dir2.y; + bool zro = dirR < float(1.0 / FSR_EASU_DIR_THRESHOLD); + dirR = APrxLoRsqF1(dirR); +#if (FSR_EASU_QUIT_EARLY == 1) + if (zro) { + vec4 w = vec4(0.0); + w.x = (1.0 - pp.x) * (1.0 - pp.y); + w.y = pp.x * (1.0 - pp.y); + w.z = (1.0 - pp.x) * pp.y; + w.w = pp.x * pp.y; + + pix.r = clamp(dot(w, vec4(fL, gL, jL, kL)), 0.0, 1.0); + return pix; + } +#elif (FSR_EASU_QUIT_EARLY == 0) + dirR = zro ? 1.0 : dirR; + dir.x = zro ? 1.0 : dir.x; +#endif + dir *= vec2(dirR); + // Transform from {0 to 2} to {0 to 1} range, and shape with square. + len = len * 0.5; + len *= len; + // Stretch kernel {1.0 vert|horz, to sqrt(2.0) on diagonal}. + float stretch = (dir.x * dir.x + dir.y * dir.y) * APrxLoRcpF1(max(abs(dir.x), abs(dir.y))); + // Anisotropic length after rotation, + // x := 1.0 lerp to 'stretch' on edges + // y := 1.0 lerp to 2x on edges + vec2 len2 = vec2(1.0 + (stretch - 1.0) * len, 1.0 + -0.5 * len); + // Based on the amount of 'edge', + // the window shifts from +/-{sqrt(2.0) to slightly beyond 2.0}. + float lob = 0.5 + float((1.0 / 4.0 - 0.04) - 0.5) * len; + // Set distance^2 clipping point to the end of the adjustable window. + float clp = APrxLoRcpF1(lob); + //------------------------------------------------------------------------------------------------------------------------------ + // Accumulation + // b c + // e f g h + // i j k l + // n o + float aC = 0.0; + float aW = 0.0; + FsrEasuTap(aC, aW, vec2( 0.0,-1.0) - pp, dir, len2, lob, clp, bL); // b + FsrEasuTap(aC, aW, vec2( 1.0,-1.0) - pp, dir, len2, lob, clp, cL); // c + FsrEasuTap(aC, aW, vec2(-1.0, 1.0) - pp, dir, len2, lob, clp, iL); // i + FsrEasuTap(aC, aW, vec2( 0.0, 1.0) - pp, dir, len2, lob, clp, jL); // j + FsrEasuTap(aC, aW, vec2( 0.0, 0.0) - pp, dir, len2, lob, clp, fL); // f + FsrEasuTap(aC, aW, vec2(-1.0, 0.0) - pp, dir, len2, lob, clp, eL); // e + FsrEasuTap(aC, aW, vec2( 1.0, 1.0) - pp, dir, len2, lob, clp, kL); // k + FsrEasuTap(aC, aW, vec2( 2.0, 1.0) - pp, dir, len2, lob, clp, lL); // l + FsrEasuTap(aC, aW, vec2( 2.0, 0.0) - pp, dir, len2, lob, clp, hL); // h + FsrEasuTap(aC, aW, vec2( 1.0, 0.0) - pp, dir, len2, lob, clp, gL); // g + FsrEasuTap(aC, aW, vec2( 1.0, 2.0) - pp, dir, len2, lob, clp, oL); // o + FsrEasuTap(aC, aW, vec2( 0.0, 2.0) - pp, dir, len2, lob, clp, nL); // n + //------------------------------------------------------------------------------------------------------------------------------ + // Normalize and dering. + pix.r = aC / aW; +#if (FSR_EASU_DERING == 1) + float min1 = min(AMin3F1(fL, gL, jL), kL); + float max1 = max(AMax3F1(fL, gL, jL), kL); + pix.r = clamp(pix.r, min1, max1); +#endif + pix.r = clamp(pix.r, 0.0, 1.0); + + return pix; +} + +//!HOOK LUMA +//!BIND EASUTEX +//!DESC FidelityFX Super Resolution v1.0.2 (RCAS) +//!WIDTH EASUTEX.w +//!HEIGHT EASUTEX.h +//!COMPONENTS 1 + +// User variables - RCAS +// #define SHARPNESS 0.2 // Controls the amount of sharpening. The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}. 0.0 to 2.0. +#define FSR_RCAS_DENOISE 1 // If set to 1, lessens the sharpening on noisy areas. Can be disabled for better performance. 0 or 1. +// #define FSR_PQ 0 // Whether the source content has PQ gamma or not. Needs to be set to the same value for both passes. 0 or 1. + +// Custom +#define SHARPNESS 0.75 +#define FSR_PQ 1 + +// Shader code + +#define FSR_RCAS_LIMIT (0.25 - (1.0 / 16.0)) // This is set at the limit of providing unnatural results for sharpening. + +float APrxMedRcpF1(float a) { + float b = uintBitsToFloat(uint(0x7ef19fff) - floatBitsToUint(a)); + return b * (-b * a + 2.0); +} + +float AMax3F1(float x, float y, float z) { + return max(x, max(y, z)); +} + +float AMin3F1(float x, float y, float z) { + return min(x, min(y, z)); +} + +#if (FSR_PQ == 1) + +float FromGamma2(float a) { + return sqrt(sqrt(a)); +} + +#endif + +vec4 hook() { + // Algorithm uses minimal 3x3 pixel neighborhood. + // b + // d e f + // h +#if (defined(EASUTEX_gather) && (__VERSION__ >= 400 || (GL_ES && __VERSION__ >= 310))) + vec3 bde = EASUTEX_gather(EASUTEX_pos + EASUTEX_pt * vec2(-0.5), 0).xyz; + float b = bde.z; + float d = bde.x; + float e = bde.y; + + vec2 fh = EASUTEX_gather(EASUTEX_pos + EASUTEX_pt * vec2(0.5), 0).zx; + float f = fh.x; + float h = fh.y; +#else + float b = EASUTEX_texOff(vec2( 0.0, -1.0)).r; + float d = EASUTEX_texOff(vec2(-1.0, 0.0)).r; + float e = EASUTEX_tex(EASUTEX_pos).r; + float f = EASUTEX_texOff(vec2(1.0, 0.0)).r; + float h = EASUTEX_texOff(vec2(0.0, 1.0)).r; +#endif + + // Min and max of ring. + float mn1L = min(AMin3F1(b, d, f), h); + float mx1L = max(AMax3F1(b, d, f), h); + + // Immediate constants for peak range. + vec2 peakC = vec2(1.0, -1.0 * 4.0); + + // Limiters, these need to be high precision RCPs. + float hitMinL = min(mn1L, e) / (4.0 * mx1L); + float hitMaxL = (peakC.x - max(mx1L, e)) / (4.0 * mn1L + peakC.y); + float lobeL = max(-hitMinL, hitMaxL); + float lobe = max(float(-FSR_RCAS_LIMIT), min(lobeL, 0.0)) * exp2(-clamp(float(SHARPNESS), 0.0, 2.0)); + + // Apply noise removal. +#if (FSR_RCAS_DENOISE == 1) + // Noise detection. + float nz = 0.25 * b + 0.25 * d + 0.25 * f + 0.25 * h - e; + nz = clamp(abs(nz) * APrxMedRcpF1(AMax3F1(AMax3F1(b, d, e), f, h) - AMin3F1(AMin3F1(b, d, e), f, h)), 0.0, 1.0); + nz = -0.5 * nz + 1.0; + lobe *= nz; +#endif + + // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes. + float rcpL = APrxMedRcpF1(4.0 * lobe + 1.0); + vec4 pix = vec4(0.0, 0.0, 0.0, 1.0); + pix.r = float((lobe * b + lobe * d + lobe * h + lobe * f + e) * rcpL); +#if (FSR_PQ == 1) + pix.r = FromGamma2(pix.r); +#endif + + return pix; +} \ No newline at end of file diff --git a/app/shaders/enhancer/AMD/FSR_Pass.hlsl b/app/shaders/enhancer/AMD/FSR_Pass.hlsl new file mode 100644 index 000000000..85f1a8253 --- /dev/null +++ b/app/shaders/enhancer/AMD/FSR_Pass.hlsl @@ -0,0 +1,107 @@ +// FidelityFX Super Resolution Sample +// +// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +cbuffer cb : register(b0) +{ + uint4 Const0; + uint4 Const1; + uint4 Const2; + uint4 Const3; +}; + +#define A_GPU 1 +#define A_HLSL 1 +#define A_HLSL_6_2 1 + +SamplerState samLinearClamp : register(s0); + +#if ADVANCED_SHADER + #define A_HALF + #include "ffx_a.h" + Texture2D InputTexture : register(t0); + RWTexture2D OutputTexture : register(u0); + #if APPLY_EASU + #define FSR_EASU_H 1 + AH4 FsrEasuRH(AF2 p) { AH4 res = InputTexture.GatherRed(samLinearClamp, p, int2(0, 0)); return res; } + AH4 FsrEasuGH(AF2 p) { AH4 res = InputTexture.GatherGreen(samLinearClamp, p, int2(0, 0)); return res; } + AH4 FsrEasuBH(AF2 p) { AH4 res = InputTexture.GatherBlue(samLinearClamp, p, int2(0, 0)); return res; } + #endif + #if APPLY_RCAS + #define FSR_RCAS_H + AH4 FsrRcasLoadH(ASW2 p) { return InputTexture.Load(ASW3(ASW2(p), 0)); } + void FsrRcasInputH(inout AH1 r,inout AH1 g,inout AH1 b){} + #endif +#else + #include "ffx_a.h" + Texture2D InputTexture : register(t0); + RWTexture2D OutputTexture : register(u0); + #if APPLY_EASU + #define FSR_EASU_F 1 + AF4 FsrEasuRF(AF2 p) { AF4 res = InputTexture.GatherRed(samLinearClamp, p, int2(0, 0)); return res; } + AF4 FsrEasuGF(AF2 p) { AF4 res = InputTexture.GatherGreen(samLinearClamp, p, int2(0, 0)); return res; } + AF4 FsrEasuBF(AF2 p) { AF4 res = InputTexture.GatherBlue(samLinearClamp, p, int2(0, 0)); return res; } + #endif + #if APPLY_RCAS + #define FSR_RCAS_F + AF4 FsrRcasLoadF(ASU2 p) { return InputTexture.Load(int3(ASU2(p), 0)); } + void FsrRcasInputF(inout AF1 r, inout AF1 g, inout AF1 b) {} + #endif +#endif + +#include "ffx_fsr1.h" + +void CurrFilter(int2 pos) +{ +#if APPLY_EASU + #if ADVANCED_SHADER + AH3 c; + FsrEasuH(c, pos, Const0, Const1, Const2, Const3); + OutputTexture[pos] = AH4(c, 1); + #else + AF3 c; + FsrEasuF(c, pos, Const0, Const1, Const2, Const3); + OutputTexture[pos] = float4(c, 1); + #endif +#endif +#if APPLY_RCAS + #if ADVANCED_SHADER + AH3 c; + FsrRcasH(c.r, c.g, c.b, pos, Const0); + OutputTexture[pos] = AH4(c, 1); + #else + AF3 c; + FsrRcasF(c.r, c.g, c.b, pos, Const0); + OutputTexture[pos] = float4(c, 1); + #endif +#endif +} + +[numthreads(64, 1, 1)] +void mainCS(uint3 LocalThreadId : SV_GroupThreadID, uint3 WorkGroupId : SV_GroupID, uint3 Dtid : SV_DispatchThreadID) +{ + // Do remapping of local xy in workgroup for a more PS-like swizzle pattern. + AU2 gxy = ARmp8x8(LocalThreadId.x) + AU2(WorkGroupId.x << 4u, WorkGroupId.y << 4u); + CurrFilter(gxy); + gxy.x += 8u; + CurrFilter(gxy); + gxy.y += 8u; + CurrFilter(gxy); + gxy.x -= 8u; + CurrFilter(gxy); +} + diff --git a/app/shaders/enhancer/AMD/ffx_a.h b/app/shaders/enhancer/AMD/ffx_a.h new file mode 100644 index 000000000..d04bff55c --- /dev/null +++ b/app/shaders/enhancer/AMD/ffx_a.h @@ -0,0 +1,2656 @@ +//============================================================================================================================== +// +// [A] SHADER PORTABILITY 1.20210629 +// +//============================================================================================================================== +// FidelityFX Super Resolution Sample +// +// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +//------------------------------------------------------------------------------------------------------------------------------ +// MIT LICENSE +// =========== +// Copyright (c) 2014 Michal Drobot (for concepts used in "FLOAT APPROXIMATIONS"). +// ----------- +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, +// modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// ----------- +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +// Software. +// ----------- +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +//------------------------------------------------------------------------------------------------------------------------------ +// ABOUT +// ===== +// Common central point for high-level shading language and C portability for various shader headers. +//------------------------------------------------------------------------------------------------------------------------------ +// DEFINES +// ======= +// A_CPU ..... Include the CPU related code. +// A_GPU ..... Include the GPU related code. +// A_GLSL .... Using GLSL. +// A_HLSL .... Using HLSL. +// A_HLSL_6_2 Using HLSL 6.2 with new 'uint16_t' and related types (requires '-enable-16bit-types'). +// A_NO_16_BIT_CAST Don't use instructions that are not availabe in SPIR-V (needed for running A_HLSL_6_2 on Vulkan) +// A_GCC ..... Using a GCC compatible compiler (else assume MSVC compatible compiler by default). +// ======= +// A_BYTE .... Support 8-bit integer. +// A_HALF .... Support 16-bit integer and floating point. +// A_LONG .... Support 64-bit integer. +// A_DUBL .... Support 64-bit floating point. +// ======= +// A_WAVE .... Support wave-wide operations. +//------------------------------------------------------------------------------------------------------------------------------ +// To get #include "ffx_a.h" working in GLSL use '#extension GL_GOOGLE_include_directive:require'. +//------------------------------------------------------------------------------------------------------------------------------ +// SIMPLIFIED TYPE SYSTEM +// ====================== +// - All ints will be unsigned with exception of when signed is required. +// - Type naming simplified and shortened "A<#components>", +// - H = 16-bit float (half) +// - F = 32-bit float (float) +// - D = 64-bit float (double) +// - P = 1-bit integer (predicate, not using bool because 'B' is used for byte) +// - B = 8-bit integer (byte) +// - W = 16-bit integer (word) +// - U = 32-bit integer (unsigned) +// - L = 64-bit integer (long) +// - Using "AS<#components>" for signed when required. +//------------------------------------------------------------------------------------------------------------------------------ +// TODO +// ==== +// - Make sure 'ALerp*(a,b,m)' does 'b*m+(-a*m+a)' (2 ops). +//------------------------------------------------------------------------------------------------------------------------------ +// CHANGE LOG +// ========== +// 20200914 - Expanded wave ops and prx code. +// 20200713 - Added [ZOL] section, fixed serious bugs in sRGB and Rec.709 color conversion code, etc. +//============================================================================================================================== +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// COMMON +//============================================================================================================================== +#define A_2PI 6.28318530718 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// +// CPU +// +// +//============================================================================================================================== +#ifdef A_CPU + // Supporting user defined overrides. + #ifndef A_RESTRICT + #define A_RESTRICT __restrict + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifndef A_STATIC + #define A_STATIC static + #endif +//------------------------------------------------------------------------------------------------------------------------------ + // Same types across CPU and GPU. + // Predicate uses 32-bit integer (C friendly bool). + typedef uint32_t AP1; + typedef float AF1; + typedef double AD1; + typedef uint8_t AB1; + typedef uint16_t AW1; + typedef uint32_t AU1; + typedef uint64_t AL1; + typedef int8_t ASB1; + typedef int16_t ASW1; + typedef int32_t ASU1; + typedef int64_t ASL1; +//------------------------------------------------------------------------------------------------------------------------------ + #define AD1_(a) ((AD1)(a)) + #define AF1_(a) ((AF1)(a)) + #define AL1_(a) ((AL1)(a)) + #define AU1_(a) ((AU1)(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define ASL1_(a) ((ASL1)(a)) + #define ASU1_(a) ((ASU1)(a)) +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AU1 AU1_AF1(AF1 a){union{AF1 f;AU1 u;}bits;bits.f=a;return bits.u;} +//------------------------------------------------------------------------------------------------------------------------------ + #define A_TRUE 1 + #define A_FALSE 0 +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// CPU/GPU PORTING +// +//------------------------------------------------------------------------------------------------------------------------------ +// Get CPU and GPU to share all setup code, without duplicate code paths. +// This uses a lower-case prefix for special vector constructs. +// - In C restrict pointers are used. +// - In the shading language, in/inout/out arguments are used. +// This depends on the ability to access a vector value in both languages via array syntax (aka color[2]). +//============================================================================================================================== +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// VECTOR ARGUMENT/RETURN/INITIALIZATION PORTABILITY +//============================================================================================================================== + #define retAD2 AD1 *A_RESTRICT + #define retAD3 AD1 *A_RESTRICT + #define retAD4 AD1 *A_RESTRICT + #define retAF2 AF1 *A_RESTRICT + #define retAF3 AF1 *A_RESTRICT + #define retAF4 AF1 *A_RESTRICT + #define retAL2 AL1 *A_RESTRICT + #define retAL3 AL1 *A_RESTRICT + #define retAL4 AL1 *A_RESTRICT + #define retAU2 AU1 *A_RESTRICT + #define retAU3 AU1 *A_RESTRICT + #define retAU4 AU1 *A_RESTRICT +//------------------------------------------------------------------------------------------------------------------------------ + #define inAD2 AD1 *A_RESTRICT + #define inAD3 AD1 *A_RESTRICT + #define inAD4 AD1 *A_RESTRICT + #define inAF2 AF1 *A_RESTRICT + #define inAF3 AF1 *A_RESTRICT + #define inAF4 AF1 *A_RESTRICT + #define inAL2 AL1 *A_RESTRICT + #define inAL3 AL1 *A_RESTRICT + #define inAL4 AL1 *A_RESTRICT + #define inAU2 AU1 *A_RESTRICT + #define inAU3 AU1 *A_RESTRICT + #define inAU4 AU1 *A_RESTRICT +//------------------------------------------------------------------------------------------------------------------------------ + #define inoutAD2 AD1 *A_RESTRICT + #define inoutAD3 AD1 *A_RESTRICT + #define inoutAD4 AD1 *A_RESTRICT + #define inoutAF2 AF1 *A_RESTRICT + #define inoutAF3 AF1 *A_RESTRICT + #define inoutAF4 AF1 *A_RESTRICT + #define inoutAL2 AL1 *A_RESTRICT + #define inoutAL3 AL1 *A_RESTRICT + #define inoutAL4 AL1 *A_RESTRICT + #define inoutAU2 AU1 *A_RESTRICT + #define inoutAU3 AU1 *A_RESTRICT + #define inoutAU4 AU1 *A_RESTRICT +//------------------------------------------------------------------------------------------------------------------------------ + #define outAD2 AD1 *A_RESTRICT + #define outAD3 AD1 *A_RESTRICT + #define outAD4 AD1 *A_RESTRICT + #define outAF2 AF1 *A_RESTRICT + #define outAF3 AF1 *A_RESTRICT + #define outAF4 AF1 *A_RESTRICT + #define outAL2 AL1 *A_RESTRICT + #define outAL3 AL1 *A_RESTRICT + #define outAL4 AL1 *A_RESTRICT + #define outAU2 AU1 *A_RESTRICT + #define outAU3 AU1 *A_RESTRICT + #define outAU4 AU1 *A_RESTRICT +//------------------------------------------------------------------------------------------------------------------------------ + #define varAD2(x) AD1 x[2] + #define varAD3(x) AD1 x[3] + #define varAD4(x) AD1 x[4] + #define varAF2(x) AF1 x[2] + #define varAF3(x) AF1 x[3] + #define varAF4(x) AF1 x[4] + #define varAL2(x) AL1 x[2] + #define varAL3(x) AL1 x[3] + #define varAL4(x) AL1 x[4] + #define varAU2(x) AU1 x[2] + #define varAU3(x) AU1 x[3] + #define varAU4(x) AU1 x[4] +//------------------------------------------------------------------------------------------------------------------------------ + #define initAD2(x,y) {x,y} + #define initAD3(x,y,z) {x,y,z} + #define initAD4(x,y,z,w) {x,y,z,w} + #define initAF2(x,y) {x,y} + #define initAF3(x,y,z) {x,y,z} + #define initAF4(x,y,z,w) {x,y,z,w} + #define initAL2(x,y) {x,y} + #define initAL3(x,y,z) {x,y,z} + #define initAL4(x,y,z,w) {x,y,z,w} + #define initAU2(x,y) {x,y} + #define initAU3(x,y,z) {x,y,z} + #define initAU4(x,y,z,w) {x,y,z,w} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// SCALAR RETURN OPS +//------------------------------------------------------------------------------------------------------------------------------ +// TODO +// ==== +// - Replace transcendentals with manual versions. +//============================================================================================================================== + #ifdef A_GCC + A_STATIC AD1 AAbsD1(AD1 a){return __builtin_fabs(a);} + A_STATIC AF1 AAbsF1(AF1 a){return __builtin_fabsf(a);} + A_STATIC AU1 AAbsSU1(AU1 a){return AU1_(__builtin_abs(ASU1_(a)));} + A_STATIC AL1 AAbsSL1(AL1 a){return AL1_(__builtin_llabs(ASL1_(a)));} + #else + A_STATIC AD1 AAbsD1(AD1 a){return fabs(a);} + A_STATIC AF1 AAbsF1(AF1 a){return fabsf(a);} + A_STATIC AU1 AAbsSU1(AU1 a){return AU1_(abs(ASU1_(a)));} + A_STATIC AL1 AAbsSL1(AL1 a){return AL1_(labs((long)ASL1_(a)));} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_GCC + A_STATIC AD1 ACosD1(AD1 a){return __builtin_cos(a);} + A_STATIC AF1 ACosF1(AF1 a){return __builtin_cosf(a);} + #else + A_STATIC AD1 ACosD1(AD1 a){return cos(a);} + A_STATIC AF1 ACosF1(AF1 a){return cosf(a);} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 ADotD2(inAD2 a,inAD2 b){return a[0]*b[0]+a[1]*b[1];} + A_STATIC AD1 ADotD3(inAD3 a,inAD3 b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];} + A_STATIC AD1 ADotD4(inAD4 a,inAD4 b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3];} + A_STATIC AF1 ADotF2(inAF2 a,inAF2 b){return a[0]*b[0]+a[1]*b[1];} + A_STATIC AF1 ADotF3(inAF3 a,inAF3 b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2];} + A_STATIC AF1 ADotF4(inAF4 a,inAF4 b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3];} +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_GCC + A_STATIC AD1 AExp2D1(AD1 a){return __builtin_exp2(a);} + A_STATIC AF1 AExp2F1(AF1 a){return __builtin_exp2f(a);} + #else + A_STATIC AD1 AExp2D1(AD1 a){return exp2(a);} + A_STATIC AF1 AExp2F1(AF1 a){return exp2f(a);} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_GCC + A_STATIC AD1 AFloorD1(AD1 a){return __builtin_floor(a);} + A_STATIC AF1 AFloorF1(AF1 a){return __builtin_floorf(a);} + #else + A_STATIC AD1 AFloorD1(AD1 a){return floor(a);} + A_STATIC AF1 AFloorF1(AF1 a){return floorf(a);} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 ALerpD1(AD1 a,AD1 b,AD1 c){return b*c+(-a*c+a);} + A_STATIC AF1 ALerpF1(AF1 a,AF1 b,AF1 c){return b*c+(-a*c+a);} +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_GCC + A_STATIC AD1 ALog2D1(AD1 a){return __builtin_log2(a);} + A_STATIC AF1 ALog2F1(AF1 a){return __builtin_log2f(a);} + #else + A_STATIC AD1 ALog2D1(AD1 a){return log2(a);} + A_STATIC AF1 ALog2F1(AF1 a){return log2f(a);} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 AMaxD1(AD1 a,AD1 b){return a>b?a:b;} + A_STATIC AF1 AMaxF1(AF1 a,AF1 b){return a>b?a:b;} + A_STATIC AL1 AMaxL1(AL1 a,AL1 b){return a>b?a:b;} + A_STATIC AU1 AMaxU1(AU1 a,AU1 b){return a>b?a:b;} +//------------------------------------------------------------------------------------------------------------------------------ + // These follow the convention that A integer types don't have signage, until they are operated on. + A_STATIC AL1 AMaxSL1(AL1 a,AL1 b){return (ASL1_(a)>ASL1_(b))?a:b;} + A_STATIC AU1 AMaxSU1(AU1 a,AU1 b){return (ASU1_(a)>ASU1_(b))?a:b;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 AMinD1(AD1 a,AD1 b){return a>ASL1_(b));} + A_STATIC AU1 AShrSU1(AU1 a,AU1 b){return AU1_(ASU1_(a)>>ASU1_(b));} +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_GCC + A_STATIC AD1 ASinD1(AD1 a){return __builtin_sin(a);} + A_STATIC AF1 ASinF1(AF1 a){return __builtin_sinf(a);} + #else + A_STATIC AD1 ASinD1(AD1 a){return sin(a);} + A_STATIC AF1 ASinF1(AF1 a){return sinf(a);} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_GCC + A_STATIC AD1 ASqrtD1(AD1 a){return __builtin_sqrt(a);} + A_STATIC AF1 ASqrtF1(AF1 a){return __builtin_sqrtf(a);} + #else + A_STATIC AD1 ASqrtD1(AD1 a){return sqrt(a);} + A_STATIC AF1 ASqrtF1(AF1 a){return sqrtf(a);} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// SCALAR RETURN OPS - DEPENDENT +//============================================================================================================================== + A_STATIC AD1 AClampD1(AD1 x,AD1 n,AD1 m){return AMaxD1(n,AMinD1(x,m));} + A_STATIC AF1 AClampF1(AF1 x,AF1 n,AF1 m){return AMaxF1(n,AMinF1(x,m));} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 AFractD1(AD1 a){return a-AFloorD1(a);} + A_STATIC AF1 AFractF1(AF1 a){return a-AFloorF1(a);} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 APowD1(AD1 a,AD1 b){return AExp2D1(b*ALog2D1(a));} + A_STATIC AF1 APowF1(AF1 a,AF1 b){return AExp2F1(b*ALog2F1(a));} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 ARsqD1(AD1 a){return ARcpD1(ASqrtD1(a));} + A_STATIC AF1 ARsqF1(AF1 a){return ARcpF1(ASqrtF1(a));} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC AD1 ASatD1(AD1 a){return AMinD1(1.0,AMaxD1(0.0,a));} + A_STATIC AF1 ASatF1(AF1 a){return AMinF1(1.0f,AMaxF1(0.0f,a));} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// VECTOR OPS +//------------------------------------------------------------------------------------------------------------------------------ +// These are added as needed for production or prototyping, so not necessarily a complete set. +// They follow a convention of taking in a destination and also returning the destination value to increase utility. +//============================================================================================================================== + A_STATIC retAD2 opAAbsD2(outAD2 d,inAD2 a){d[0]=AAbsD1(a[0]);d[1]=AAbsD1(a[1]);return d;} + A_STATIC retAD3 opAAbsD3(outAD3 d,inAD3 a){d[0]=AAbsD1(a[0]);d[1]=AAbsD1(a[1]);d[2]=AAbsD1(a[2]);return d;} + A_STATIC retAD4 opAAbsD4(outAD4 d,inAD4 a){d[0]=AAbsD1(a[0]);d[1]=AAbsD1(a[1]);d[2]=AAbsD1(a[2]);d[3]=AAbsD1(a[3]);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAAbsF2(outAF2 d,inAF2 a){d[0]=AAbsF1(a[0]);d[1]=AAbsF1(a[1]);return d;} + A_STATIC retAF3 opAAbsF3(outAF3 d,inAF3 a){d[0]=AAbsF1(a[0]);d[1]=AAbsF1(a[1]);d[2]=AAbsF1(a[2]);return d;} + A_STATIC retAF4 opAAbsF4(outAF4 d,inAF4 a){d[0]=AAbsF1(a[0]);d[1]=AAbsF1(a[1]);d[2]=AAbsF1(a[2]);d[3]=AAbsF1(a[3]);return d;} +//============================================================================================================================== + A_STATIC retAD2 opAAddD2(outAD2 d,inAD2 a,inAD2 b){d[0]=a[0]+b[0];d[1]=a[1]+b[1];return d;} + A_STATIC retAD3 opAAddD3(outAD3 d,inAD3 a,inAD3 b){d[0]=a[0]+b[0];d[1]=a[1]+b[1];d[2]=a[2]+b[2];return d;} + A_STATIC retAD4 opAAddD4(outAD4 d,inAD4 a,inAD4 b){d[0]=a[0]+b[0];d[1]=a[1]+b[1];d[2]=a[2]+b[2];d[3]=a[3]+b[3];return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAAddF2(outAF2 d,inAF2 a,inAF2 b){d[0]=a[0]+b[0];d[1]=a[1]+b[1];return d;} + A_STATIC retAF3 opAAddF3(outAF3 d,inAF3 a,inAF3 b){d[0]=a[0]+b[0];d[1]=a[1]+b[1];d[2]=a[2]+b[2];return d;} + A_STATIC retAF4 opAAddF4(outAF4 d,inAF4 a,inAF4 b){d[0]=a[0]+b[0];d[1]=a[1]+b[1];d[2]=a[2]+b[2];d[3]=a[3]+b[3];return d;} +//============================================================================================================================== + A_STATIC retAD2 opAAddOneD2(outAD2 d,inAD2 a,AD1 b){d[0]=a[0]+b;d[1]=a[1]+b;return d;} + A_STATIC retAD3 opAAddOneD3(outAD3 d,inAD3 a,AD1 b){d[0]=a[0]+b;d[1]=a[1]+b;d[2]=a[2]+b;return d;} + A_STATIC retAD4 opAAddOneD4(outAD4 d,inAD4 a,AD1 b){d[0]=a[0]+b;d[1]=a[1]+b;d[2]=a[2]+b;d[3]=a[3]+b;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAAddOneF2(outAF2 d,inAF2 a,AF1 b){d[0]=a[0]+b;d[1]=a[1]+b;return d;} + A_STATIC retAF3 opAAddOneF3(outAF3 d,inAF3 a,AF1 b){d[0]=a[0]+b;d[1]=a[1]+b;d[2]=a[2]+b;return d;} + A_STATIC retAF4 opAAddOneF4(outAF4 d,inAF4 a,AF1 b){d[0]=a[0]+b;d[1]=a[1]+b;d[2]=a[2]+b;d[3]=a[3]+b;return d;} +//============================================================================================================================== + A_STATIC retAD2 opACpyD2(outAD2 d,inAD2 a){d[0]=a[0];d[1]=a[1];return d;} + A_STATIC retAD3 opACpyD3(outAD3 d,inAD3 a){d[0]=a[0];d[1]=a[1];d[2]=a[2];return d;} + A_STATIC retAD4 opACpyD4(outAD4 d,inAD4 a){d[0]=a[0];d[1]=a[1];d[2]=a[2];d[3]=a[3];return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opACpyF2(outAF2 d,inAF2 a){d[0]=a[0];d[1]=a[1];return d;} + A_STATIC retAF3 opACpyF3(outAF3 d,inAF3 a){d[0]=a[0];d[1]=a[1];d[2]=a[2];return d;} + A_STATIC retAF4 opACpyF4(outAF4 d,inAF4 a){d[0]=a[0];d[1]=a[1];d[2]=a[2];d[3]=a[3];return d;} +//============================================================================================================================== + A_STATIC retAD2 opALerpD2(outAD2 d,inAD2 a,inAD2 b,inAD2 c){d[0]=ALerpD1(a[0],b[0],c[0]);d[1]=ALerpD1(a[1],b[1],c[1]);return d;} + A_STATIC retAD3 opALerpD3(outAD3 d,inAD3 a,inAD3 b,inAD3 c){d[0]=ALerpD1(a[0],b[0],c[0]);d[1]=ALerpD1(a[1],b[1],c[1]);d[2]=ALerpD1(a[2],b[2],c[2]);return d;} + A_STATIC retAD4 opALerpD4(outAD4 d,inAD4 a,inAD4 b,inAD4 c){d[0]=ALerpD1(a[0],b[0],c[0]);d[1]=ALerpD1(a[1],b[1],c[1]);d[2]=ALerpD1(a[2],b[2],c[2]);d[3]=ALerpD1(a[3],b[3],c[3]);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opALerpF2(outAF2 d,inAF2 a,inAF2 b,inAF2 c){d[0]=ALerpF1(a[0],b[0],c[0]);d[1]=ALerpF1(a[1],b[1],c[1]);return d;} + A_STATIC retAF3 opALerpF3(outAF3 d,inAF3 a,inAF3 b,inAF3 c){d[0]=ALerpF1(a[0],b[0],c[0]);d[1]=ALerpF1(a[1],b[1],c[1]);d[2]=ALerpF1(a[2],b[2],c[2]);return d;} + A_STATIC retAF4 opALerpF4(outAF4 d,inAF4 a,inAF4 b,inAF4 c){d[0]=ALerpF1(a[0],b[0],c[0]);d[1]=ALerpF1(a[1],b[1],c[1]);d[2]=ALerpF1(a[2],b[2],c[2]);d[3]=ALerpF1(a[3],b[3],c[3]);return d;} +//============================================================================================================================== + A_STATIC retAD2 opALerpOneD2(outAD2 d,inAD2 a,inAD2 b,AD1 c){d[0]=ALerpD1(a[0],b[0],c);d[1]=ALerpD1(a[1],b[1],c);return d;} + A_STATIC retAD3 opALerpOneD3(outAD3 d,inAD3 a,inAD3 b,AD1 c){d[0]=ALerpD1(a[0],b[0],c);d[1]=ALerpD1(a[1],b[1],c);d[2]=ALerpD1(a[2],b[2],c);return d;} + A_STATIC retAD4 opALerpOneD4(outAD4 d,inAD4 a,inAD4 b,AD1 c){d[0]=ALerpD1(a[0],b[0],c);d[1]=ALerpD1(a[1],b[1],c);d[2]=ALerpD1(a[2],b[2],c);d[3]=ALerpD1(a[3],b[3],c);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opALerpOneF2(outAF2 d,inAF2 a,inAF2 b,AF1 c){d[0]=ALerpF1(a[0],b[0],c);d[1]=ALerpF1(a[1],b[1],c);return d;} + A_STATIC retAF3 opALerpOneF3(outAF3 d,inAF3 a,inAF3 b,AF1 c){d[0]=ALerpF1(a[0],b[0],c);d[1]=ALerpF1(a[1],b[1],c);d[2]=ALerpF1(a[2],b[2],c);return d;} + A_STATIC retAF4 opALerpOneF4(outAF4 d,inAF4 a,inAF4 b,AF1 c){d[0]=ALerpF1(a[0],b[0],c);d[1]=ALerpF1(a[1],b[1],c);d[2]=ALerpF1(a[2],b[2],c);d[3]=ALerpF1(a[3],b[3],c);return d;} +//============================================================================================================================== + A_STATIC retAD2 opAMaxD2(outAD2 d,inAD2 a,inAD2 b){d[0]=AMaxD1(a[0],b[0]);d[1]=AMaxD1(a[1],b[1]);return d;} + A_STATIC retAD3 opAMaxD3(outAD3 d,inAD3 a,inAD3 b){d[0]=AMaxD1(a[0],b[0]);d[1]=AMaxD1(a[1],b[1]);d[2]=AMaxD1(a[2],b[2]);return d;} + A_STATIC retAD4 opAMaxD4(outAD4 d,inAD4 a,inAD4 b){d[0]=AMaxD1(a[0],b[0]);d[1]=AMaxD1(a[1],b[1]);d[2]=AMaxD1(a[2],b[2]);d[3]=AMaxD1(a[3],b[3]);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAMaxF2(outAF2 d,inAF2 a,inAF2 b){d[0]=AMaxF1(a[0],b[0]);d[1]=AMaxF1(a[1],b[1]);return d;} + A_STATIC retAF3 opAMaxF3(outAF3 d,inAF3 a,inAF3 b){d[0]=AMaxF1(a[0],b[0]);d[1]=AMaxF1(a[1],b[1]);d[2]=AMaxF1(a[2],b[2]);return d;} + A_STATIC retAF4 opAMaxF4(outAF4 d,inAF4 a,inAF4 b){d[0]=AMaxF1(a[0],b[0]);d[1]=AMaxF1(a[1],b[1]);d[2]=AMaxF1(a[2],b[2]);d[3]=AMaxF1(a[3],b[3]);return d;} +//============================================================================================================================== + A_STATIC retAD2 opAMinD2(outAD2 d,inAD2 a,inAD2 b){d[0]=AMinD1(a[0],b[0]);d[1]=AMinD1(a[1],b[1]);return d;} + A_STATIC retAD3 opAMinD3(outAD3 d,inAD3 a,inAD3 b){d[0]=AMinD1(a[0],b[0]);d[1]=AMinD1(a[1],b[1]);d[2]=AMinD1(a[2],b[2]);return d;} + A_STATIC retAD4 opAMinD4(outAD4 d,inAD4 a,inAD4 b){d[0]=AMinD1(a[0],b[0]);d[1]=AMinD1(a[1],b[1]);d[2]=AMinD1(a[2],b[2]);d[3]=AMinD1(a[3],b[3]);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAMinF2(outAF2 d,inAF2 a,inAF2 b){d[0]=AMinF1(a[0],b[0]);d[1]=AMinF1(a[1],b[1]);return d;} + A_STATIC retAF3 opAMinF3(outAF3 d,inAF3 a,inAF3 b){d[0]=AMinF1(a[0],b[0]);d[1]=AMinF1(a[1],b[1]);d[2]=AMinF1(a[2],b[2]);return d;} + A_STATIC retAF4 opAMinF4(outAF4 d,inAF4 a,inAF4 b){d[0]=AMinF1(a[0],b[0]);d[1]=AMinF1(a[1],b[1]);d[2]=AMinF1(a[2],b[2]);d[3]=AMinF1(a[3],b[3]);return d;} +//============================================================================================================================== + A_STATIC retAD2 opAMulD2(outAD2 d,inAD2 a,inAD2 b){d[0]=a[0]*b[0];d[1]=a[1]*b[1];return d;} + A_STATIC retAD3 opAMulD3(outAD3 d,inAD3 a,inAD3 b){d[0]=a[0]*b[0];d[1]=a[1]*b[1];d[2]=a[2]*b[2];return d;} + A_STATIC retAD4 opAMulD4(outAD4 d,inAD4 a,inAD4 b){d[0]=a[0]*b[0];d[1]=a[1]*b[1];d[2]=a[2]*b[2];d[3]=a[3]*b[3];return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAMulF2(outAF2 d,inAF2 a,inAF2 b){d[0]=a[0]*b[0];d[1]=a[1]*b[1];return d;} + A_STATIC retAF3 opAMulF3(outAF3 d,inAF3 a,inAF3 b){d[0]=a[0]*b[0];d[1]=a[1]*b[1];d[2]=a[2]*b[2];return d;} + A_STATIC retAF4 opAMulF4(outAF4 d,inAF4 a,inAF4 b){d[0]=a[0]*b[0];d[1]=a[1]*b[1];d[2]=a[2]*b[2];d[3]=a[3]*b[3];return d;} +//============================================================================================================================== + A_STATIC retAD2 opAMulOneD2(outAD2 d,inAD2 a,AD1 b){d[0]=a[0]*b;d[1]=a[1]*b;return d;} + A_STATIC retAD3 opAMulOneD3(outAD3 d,inAD3 a,AD1 b){d[0]=a[0]*b;d[1]=a[1]*b;d[2]=a[2]*b;return d;} + A_STATIC retAD4 opAMulOneD4(outAD4 d,inAD4 a,AD1 b){d[0]=a[0]*b;d[1]=a[1]*b;d[2]=a[2]*b;d[3]=a[3]*b;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opAMulOneF2(outAF2 d,inAF2 a,AF1 b){d[0]=a[0]*b;d[1]=a[1]*b;return d;} + A_STATIC retAF3 opAMulOneF3(outAF3 d,inAF3 a,AF1 b){d[0]=a[0]*b;d[1]=a[1]*b;d[2]=a[2]*b;return d;} + A_STATIC retAF4 opAMulOneF4(outAF4 d,inAF4 a,AF1 b){d[0]=a[0]*b;d[1]=a[1]*b;d[2]=a[2]*b;d[3]=a[3]*b;return d;} +//============================================================================================================================== + A_STATIC retAD2 opANegD2(outAD2 d,inAD2 a){d[0]=-a[0];d[1]=-a[1];return d;} + A_STATIC retAD3 opANegD3(outAD3 d,inAD3 a){d[0]=-a[0];d[1]=-a[1];d[2]=-a[2];return d;} + A_STATIC retAD4 opANegD4(outAD4 d,inAD4 a){d[0]=-a[0];d[1]=-a[1];d[2]=-a[2];d[3]=-a[3];return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opANegF2(outAF2 d,inAF2 a){d[0]=-a[0];d[1]=-a[1];return d;} + A_STATIC retAF3 opANegF3(outAF3 d,inAF3 a){d[0]=-a[0];d[1]=-a[1];d[2]=-a[2];return d;} + A_STATIC retAF4 opANegF4(outAF4 d,inAF4 a){d[0]=-a[0];d[1]=-a[1];d[2]=-a[2];d[3]=-a[3];return d;} +//============================================================================================================================== + A_STATIC retAD2 opARcpD2(outAD2 d,inAD2 a){d[0]=ARcpD1(a[0]);d[1]=ARcpD1(a[1]);return d;} + A_STATIC retAD3 opARcpD3(outAD3 d,inAD3 a){d[0]=ARcpD1(a[0]);d[1]=ARcpD1(a[1]);d[2]=ARcpD1(a[2]);return d;} + A_STATIC retAD4 opARcpD4(outAD4 d,inAD4 a){d[0]=ARcpD1(a[0]);d[1]=ARcpD1(a[1]);d[2]=ARcpD1(a[2]);d[3]=ARcpD1(a[3]);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + A_STATIC retAF2 opARcpF2(outAF2 d,inAF2 a){d[0]=ARcpF1(a[0]);d[1]=ARcpF1(a[1]);return d;} + A_STATIC retAF3 opARcpF3(outAF3 d,inAF3 a){d[0]=ARcpF1(a[0]);d[1]=ARcpF1(a[1]);d[2]=ARcpF1(a[2]);return d;} + A_STATIC retAF4 opARcpF4(outAF4 d,inAF4 a){d[0]=ARcpF1(a[0]);d[1]=ARcpF1(a[1]);d[2]=ARcpF1(a[2]);d[3]=ARcpF1(a[3]);return d;} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// HALF FLOAT PACKING +//============================================================================================================================== + // Convert float to half (in lower 16-bits of output). + // Same fast technique as documented here: ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf + // Supports denormals. + // Conversion rules are to make computations possibly "safer" on the GPU, + // -INF & -NaN -> -65504 + // +INF & +NaN -> +65504 + A_STATIC AU1 AU1_AH1_AF1(AF1 f){ + static AW1 base[512]={ + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,0x0100, + 0x0200,0x0400,0x0800,0x0c00,0x1000,0x1400,0x1800,0x1c00,0x2000,0x2400,0x2800,0x2c00,0x3000,0x3400,0x3800,0x3c00, + 0x4000,0x4400,0x4800,0x4c00,0x5000,0x5400,0x5800,0x5c00,0x6000,0x6400,0x6800,0x6c00,0x7000,0x7400,0x7800,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff,0x7bff, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000, + 0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8000,0x8001,0x8002,0x8004,0x8008,0x8010,0x8020,0x8040,0x8080,0x8100, + 0x8200,0x8400,0x8800,0x8c00,0x9000,0x9400,0x9800,0x9c00,0xa000,0xa400,0xa800,0xac00,0xb000,0xb400,0xb800,0xbc00, + 0xc000,0xc400,0xc800,0xcc00,0xd000,0xd400,0xd800,0xdc00,0xe000,0xe400,0xe800,0xec00,0xf000,0xf400,0xf800,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff, + 0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff,0xfbff}; + static AB1 shift[512]={ + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f, + 0x0e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d, + 0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f, + 0x0e,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d, + 0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x0d,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, + 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}; + union{AF1 f;AU1 u;}bits;bits.f=f;AU1 u=bits.u;AU1 i=u>>23;return (AU1)(base[i])+((u&0x7fffff)>>shift[i]);} +//------------------------------------------------------------------------------------------------------------------------------ + // Used to output packed constant. + A_STATIC AU1 AU1_AH2_AF2(inAF2 a){return AU1_AH1_AF1(a[0])+(AU1_AH1_AF1(a[1])<<16);} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// +// GLSL +// +// +//============================================================================================================================== +#if defined(A_GLSL) && defined(A_GPU) + #ifndef A_SKIP_EXT + #ifdef A_HALF + #extension GL_EXT_shader_16bit_storage:require + #extension GL_EXT_shader_explicit_arithmetic_types:require + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_LONG + #extension GL_ARB_gpu_shader_int64:require + #extension GL_NV_shader_atomic_int64:require + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_WAVE + #extension GL_KHR_shader_subgroup_arithmetic:require + #extension GL_KHR_shader_subgroup_ballot:require + #extension GL_KHR_shader_subgroup_quad:require + #extension GL_KHR_shader_subgroup_shuffle:require + #endif + #endif +//============================================================================================================================== + #define AP1 bool + #define AP2 bvec2 + #define AP3 bvec3 + #define AP4 bvec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AF1 float + #define AF2 vec2 + #define AF3 vec3 + #define AF4 vec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1 uint + #define AU2 uvec2 + #define AU3 uvec3 + #define AU4 uvec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASU1 int + #define ASU2 ivec2 + #define ASU3 ivec3 + #define ASU4 ivec4 +//============================================================================================================================== + #define AF1_AU1(x) uintBitsToFloat(AU1(x)) + #define AF2_AU2(x) uintBitsToFloat(AU2(x)) + #define AF3_AU3(x) uintBitsToFloat(AU3(x)) + #define AF4_AU4(x) uintBitsToFloat(AU4(x)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1_AF1(x) floatBitsToUint(AF1(x)) + #define AU2_AF2(x) floatBitsToUint(AF2(x)) + #define AU3_AF3(x) floatBitsToUint(AF3(x)) + #define AU4_AF4(x) floatBitsToUint(AF4(x)) +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AU1_AH1_AF1_x(AF1 a){return packHalf2x16(AF2(a,0.0));} + #define AU1_AH1_AF1(a) AU1_AH1_AF1_x(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1_AH2_AF2 packHalf2x16 + #define AU1_AW2Unorm_AF2 packUnorm2x16 + #define AU1_AB4Unorm_AF4 packUnorm4x8 +//------------------------------------------------------------------------------------------------------------------------------ + #define AF2_AH2_AU1 unpackHalf2x16 + #define AF2_AW2Unorm_AU1 unpackUnorm2x16 + #define AF4_AB4Unorm_AU1 unpackUnorm4x8 +//============================================================================================================================== + AF1 AF1_x(AF1 a){return AF1(a);} + AF2 AF2_x(AF1 a){return AF2(a,a);} + AF3 AF3_x(AF1 a){return AF3(a,a,a);} + AF4 AF4_x(AF1 a){return AF4(a,a,a,a);} + #define AF1_(a) AF1_x(AF1(a)) + #define AF2_(a) AF2_x(AF1(a)) + #define AF3_(a) AF3_x(AF1(a)) + #define AF4_(a) AF4_x(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AU1_x(AU1 a){return AU1(a);} + AU2 AU2_x(AU1 a){return AU2(a,a);} + AU3 AU3_x(AU1 a){return AU3(a,a,a);} + AU4 AU4_x(AU1 a){return AU4(a,a,a,a);} + #define AU1_(a) AU1_x(AU1(a)) + #define AU2_(a) AU2_x(AU1(a)) + #define AU3_(a) AU3_x(AU1(a)) + #define AU4_(a) AU4_x(AU1(a)) +//============================================================================================================================== + AU1 AAbsSU1(AU1 a){return AU1(abs(ASU1(a)));} + AU2 AAbsSU2(AU2 a){return AU2(abs(ASU2(a)));} + AU3 AAbsSU3(AU3 a){return AU3(abs(ASU3(a)));} + AU4 AAbsSU4(AU4 a){return AU4(abs(ASU4(a)));} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 ABfe(AU1 src,AU1 off,AU1 bits){return bitfieldExtract(src,ASU1(off),ASU1(bits));} + AU1 ABfi(AU1 src,AU1 ins,AU1 mask){return (ins&mask)|(src&(~mask));} + // Proxy for V_BFI_B32 where the 'mask' is set as 'bits', 'mask=(1<>ASU1(b));} + AU2 AShrSU2(AU2 a,AU2 b){return AU2(ASU2(a)>>ASU2(b));} + AU3 AShrSU3(AU3 a,AU3 b){return AU3(ASU3(a)>>ASU3(b));} + AU4 AShrSU4(AU4 a,AU4 b){return AU4(ASU4(a)>>ASU4(b));} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// GLSL BYTE +//============================================================================================================================== + #ifdef A_BYTE + #define AB1 uint8_t + #define AB2 u8vec2 + #define AB3 u8vec3 + #define AB4 u8vec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASB1 int8_t + #define ASB2 i8vec2 + #define ASB3 i8vec3 + #define ASB4 i8vec4 +//------------------------------------------------------------------------------------------------------------------------------ + AB1 AB1_x(AB1 a){return AB1(a);} + AB2 AB2_x(AB1 a){return AB2(a,a);} + AB3 AB3_x(AB1 a){return AB3(a,a,a);} + AB4 AB4_x(AB1 a){return AB4(a,a,a,a);} + #define AB1_(a) AB1_x(AB1(a)) + #define AB2_(a) AB2_x(AB1(a)) + #define AB3_(a) AB3_x(AB1(a)) + #define AB4_(a) AB4_x(AB1(a)) + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// GLSL HALF +//============================================================================================================================== + #ifdef A_HALF + #define AH1 float16_t + #define AH2 f16vec2 + #define AH3 f16vec3 + #define AH4 f16vec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AW1 uint16_t + #define AW2 u16vec2 + #define AW3 u16vec3 + #define AW4 u16vec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASW1 int16_t + #define ASW2 i16vec2 + #define ASW3 i16vec3 + #define ASW4 i16vec4 +//============================================================================================================================== + #define AH2_AU1(x) unpackFloat2x16(AU1(x)) + AH4 AH4_AU2_x(AU2 x){return AH4(unpackFloat2x16(x.x),unpackFloat2x16(x.y));} + #define AH4_AU2(x) AH4_AU2_x(AU2(x)) + #define AW2_AU1(x) unpackUint2x16(AU1(x)) + #define AW4_AU2(x) unpackUint4x16(pack64(AU2(x))) +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1_AH2(x) packFloat2x16(AH2(x)) + AU2 AU2_AH4_x(AH4 x){return AU2(packFloat2x16(x.xy),packFloat2x16(x.zw));} + #define AU2_AH4(x) AU2_AH4_x(AH4(x)) + #define AU1_AW2(x) packUint2x16(AW2(x)) + #define AU2_AW4(x) unpack32(packUint4x16(AW4(x))) +//============================================================================================================================== + #define AW1_AH1(x) halfBitsToUint16(AH1(x)) + #define AW2_AH2(x) halfBitsToUint16(AH2(x)) + #define AW3_AH3(x) halfBitsToUint16(AH3(x)) + #define AW4_AH4(x) halfBitsToUint16(AH4(x)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AH1_AW1(x) uint16BitsToHalf(AW1(x)) + #define AH2_AW2(x) uint16BitsToHalf(AW2(x)) + #define AH3_AW3(x) uint16BitsToHalf(AW3(x)) + #define AH4_AW4(x) uint16BitsToHalf(AW4(x)) +//============================================================================================================================== + AH1 AH1_x(AH1 a){return AH1(a);} + AH2 AH2_x(AH1 a){return AH2(a,a);} + AH3 AH3_x(AH1 a){return AH3(a,a,a);} + AH4 AH4_x(AH1 a){return AH4(a,a,a,a);} + #define AH1_(a) AH1_x(AH1(a)) + #define AH2_(a) AH2_x(AH1(a)) + #define AH3_(a) AH3_x(AH1(a)) + #define AH4_(a) AH4_x(AH1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AW1_x(AW1 a){return AW1(a);} + AW2 AW2_x(AW1 a){return AW2(a,a);} + AW3 AW3_x(AW1 a){return AW3(a,a,a);} + AW4 AW4_x(AW1 a){return AW4(a,a,a,a);} + #define AW1_(a) AW1_x(AW1(a)) + #define AW2_(a) AW2_x(AW1(a)) + #define AW3_(a) AW3_x(AW1(a)) + #define AW4_(a) AW4_x(AW1(a)) +//============================================================================================================================== + AW1 AAbsSW1(AW1 a){return AW1(abs(ASW1(a)));} + AW2 AAbsSW2(AW2 a){return AW2(abs(ASW2(a)));} + AW3 AAbsSW3(AW3 a){return AW3(abs(ASW3(a)));} + AW4 AAbsSW4(AW4 a){return AW4(abs(ASW4(a)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AClampH1(AH1 x,AH1 n,AH1 m){return clamp(x,n,m);} + AH2 AClampH2(AH2 x,AH2 n,AH2 m){return clamp(x,n,m);} + AH3 AClampH3(AH3 x,AH3 n,AH3 m){return clamp(x,n,m);} + AH4 AClampH4(AH4 x,AH4 n,AH4 m){return clamp(x,n,m);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AFractH1(AH1 x){return fract(x);} + AH2 AFractH2(AH2 x){return fract(x);} + AH3 AFractH3(AH3 x){return fract(x);} + AH4 AFractH4(AH4 x){return fract(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ALerpH1(AH1 x,AH1 y,AH1 a){return mix(x,y,a);} + AH2 ALerpH2(AH2 x,AH2 y,AH2 a){return mix(x,y,a);} + AH3 ALerpH3(AH3 x,AH3 y,AH3 a){return mix(x,y,a);} + AH4 ALerpH4(AH4 x,AH4 y,AH4 a){return mix(x,y,a);} +//------------------------------------------------------------------------------------------------------------------------------ + // No packed version of max3. + AH1 AMax3H1(AH1 x,AH1 y,AH1 z){return max(x,max(y,z));} + AH2 AMax3H2(AH2 x,AH2 y,AH2 z){return max(x,max(y,z));} + AH3 AMax3H3(AH3 x,AH3 y,AH3 z){return max(x,max(y,z));} + AH4 AMax3H4(AH4 x,AH4 y,AH4 z){return max(x,max(y,z));} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AMaxSW1(AW1 a,AW1 b){return AW1(max(ASU1(a),ASU1(b)));} + AW2 AMaxSW2(AW2 a,AW2 b){return AW2(max(ASU2(a),ASU2(b)));} + AW3 AMaxSW3(AW3 a,AW3 b){return AW3(max(ASU3(a),ASU3(b)));} + AW4 AMaxSW4(AW4 a,AW4 b){return AW4(max(ASU4(a),ASU4(b)));} +//------------------------------------------------------------------------------------------------------------------------------ + // No packed version of min3. + AH1 AMin3H1(AH1 x,AH1 y,AH1 z){return min(x,min(y,z));} + AH2 AMin3H2(AH2 x,AH2 y,AH2 z){return min(x,min(y,z));} + AH3 AMin3H3(AH3 x,AH3 y,AH3 z){return min(x,min(y,z));} + AH4 AMin3H4(AH4 x,AH4 y,AH4 z){return min(x,min(y,z));} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AMinSW1(AW1 a,AW1 b){return AW1(min(ASU1(a),ASU1(b)));} + AW2 AMinSW2(AW2 a,AW2 b){return AW2(min(ASU2(a),ASU2(b)));} + AW3 AMinSW3(AW3 a,AW3 b){return AW3(min(ASU3(a),ASU3(b)));} + AW4 AMinSW4(AW4 a,AW4 b){return AW4(min(ASU4(a),ASU4(b)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ARcpH1(AH1 x){return AH1_(1.0)/x;} + AH2 ARcpH2(AH2 x){return AH2_(1.0)/x;} + AH3 ARcpH3(AH3 x){return AH3_(1.0)/x;} + AH4 ARcpH4(AH4 x){return AH4_(1.0)/x;} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ARsqH1(AH1 x){return AH1_(1.0)/sqrt(x);} + AH2 ARsqH2(AH2 x){return AH2_(1.0)/sqrt(x);} + AH3 ARsqH3(AH3 x){return AH3_(1.0)/sqrt(x);} + AH4 ARsqH4(AH4 x){return AH4_(1.0)/sqrt(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ASatH1(AH1 x){return clamp(x,AH1_(0.0),AH1_(1.0));} + AH2 ASatH2(AH2 x){return clamp(x,AH2_(0.0),AH2_(1.0));} + AH3 ASatH3(AH3 x){return clamp(x,AH3_(0.0),AH3_(1.0));} + AH4 ASatH4(AH4 x){return clamp(x,AH4_(0.0),AH4_(1.0));} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AShrSW1(AW1 a,AW1 b){return AW1(ASW1(a)>>ASW1(b));} + AW2 AShrSW2(AW2 a,AW2 b){return AW2(ASW2(a)>>ASW2(b));} + AW3 AShrSW3(AW3 a,AW3 b){return AW3(ASW3(a)>>ASW3(b));} + AW4 AShrSW4(AW4 a,AW4 b){return AW4(ASW4(a)>>ASW4(b));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// GLSL DOUBLE +//============================================================================================================================== + #ifdef A_DUBL + #define AD1 double + #define AD2 dvec2 + #define AD3 dvec3 + #define AD4 dvec4 +//------------------------------------------------------------------------------------------------------------------------------ + AD1 AD1_x(AD1 a){return AD1(a);} + AD2 AD2_x(AD1 a){return AD2(a,a);} + AD3 AD3_x(AD1 a){return AD3(a,a,a);} + AD4 AD4_x(AD1 a){return AD4(a,a,a,a);} + #define AD1_(a) AD1_x(AD1(a)) + #define AD2_(a) AD2_x(AD1(a)) + #define AD3_(a) AD3_x(AD1(a)) + #define AD4_(a) AD4_x(AD1(a)) +//============================================================================================================================== + AD1 AFractD1(AD1 x){return fract(x);} + AD2 AFractD2(AD2 x){return fract(x);} + AD3 AFractD3(AD3 x){return fract(x);} + AD4 AFractD4(AD4 x){return fract(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ALerpD1(AD1 x,AD1 y,AD1 a){return mix(x,y,a);} + AD2 ALerpD2(AD2 x,AD2 y,AD2 a){return mix(x,y,a);} + AD3 ALerpD3(AD3 x,AD3 y,AD3 a){return mix(x,y,a);} + AD4 ALerpD4(AD4 x,AD4 y,AD4 a){return mix(x,y,a);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ARcpD1(AD1 x){return AD1_(1.0)/x;} + AD2 ARcpD2(AD2 x){return AD2_(1.0)/x;} + AD3 ARcpD3(AD3 x){return AD3_(1.0)/x;} + AD4 ARcpD4(AD4 x){return AD4_(1.0)/x;} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ARsqD1(AD1 x){return AD1_(1.0)/sqrt(x);} + AD2 ARsqD2(AD2 x){return AD2_(1.0)/sqrt(x);} + AD3 ARsqD3(AD3 x){return AD3_(1.0)/sqrt(x);} + AD4 ARsqD4(AD4 x){return AD4_(1.0)/sqrt(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ASatD1(AD1 x){return clamp(x,AD1_(0.0),AD1_(1.0));} + AD2 ASatD2(AD2 x){return clamp(x,AD2_(0.0),AD2_(1.0));} + AD3 ASatD3(AD3 x){return clamp(x,AD3_(0.0),AD3_(1.0));} + AD4 ASatD4(AD4 x){return clamp(x,AD4_(0.0),AD4_(1.0));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// GLSL LONG +//============================================================================================================================== + #ifdef A_LONG + #define AL1 uint64_t + #define AL2 u64vec2 + #define AL3 u64vec3 + #define AL4 u64vec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASL1 int64_t + #define ASL2 i64vec2 + #define ASL3 i64vec3 + #define ASL4 i64vec4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AL1_AU2(x) packUint2x32(AU2(x)) + #define AU2_AL1(x) unpackUint2x32(AL1(x)) +//------------------------------------------------------------------------------------------------------------------------------ + AL1 AL1_x(AL1 a){return AL1(a);} + AL2 AL2_x(AL1 a){return AL2(a,a);} + AL3 AL3_x(AL1 a){return AL3(a,a,a);} + AL4 AL4_x(AL1 a){return AL4(a,a,a,a);} + #define AL1_(a) AL1_x(AL1(a)) + #define AL2_(a) AL2_x(AL1(a)) + #define AL3_(a) AL3_x(AL1(a)) + #define AL4_(a) AL4_x(AL1(a)) +//============================================================================================================================== + AL1 AAbsSL1(AL1 a){return AL1(abs(ASL1(a)));} + AL2 AAbsSL2(AL2 a){return AL2(abs(ASL2(a)));} + AL3 AAbsSL3(AL3 a){return AL3(abs(ASL3(a)));} + AL4 AAbsSL4(AL4 a){return AL4(abs(ASL4(a)));} +//------------------------------------------------------------------------------------------------------------------------------ + AL1 AMaxSL1(AL1 a,AL1 b){return AL1(max(ASU1(a),ASU1(b)));} + AL2 AMaxSL2(AL2 a,AL2 b){return AL2(max(ASU2(a),ASU2(b)));} + AL3 AMaxSL3(AL3 a,AL3 b){return AL3(max(ASU3(a),ASU3(b)));} + AL4 AMaxSL4(AL4 a,AL4 b){return AL4(max(ASU4(a),ASU4(b)));} +//------------------------------------------------------------------------------------------------------------------------------ + AL1 AMinSL1(AL1 a,AL1 b){return AL1(min(ASU1(a),ASU1(b)));} + AL2 AMinSL2(AL2 a,AL2 b){return AL2(min(ASU2(a),ASU2(b)));} + AL3 AMinSL3(AL3 a,AL3 b){return AL3(min(ASU3(a),ASU3(b)));} + AL4 AMinSL4(AL4 a,AL4 b){return AL4(min(ASU4(a),ASU4(b)));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// WAVE OPERATIONS +//============================================================================================================================== + #ifdef A_WAVE + // Where 'x' must be a compile time literal. + AF1 AWaveXorF1(AF1 v,AU1 x){return subgroupShuffleXor(v,x);} + AF2 AWaveXorF2(AF2 v,AU1 x){return subgroupShuffleXor(v,x);} + AF3 AWaveXorF3(AF3 v,AU1 x){return subgroupShuffleXor(v,x);} + AF4 AWaveXorF4(AF4 v,AU1 x){return subgroupShuffleXor(v,x);} + AU1 AWaveXorU1(AU1 v,AU1 x){return subgroupShuffleXor(v,x);} + AU2 AWaveXorU2(AU2 v,AU1 x){return subgroupShuffleXor(v,x);} + AU3 AWaveXorU3(AU3 v,AU1 x){return subgroupShuffleXor(v,x);} + AU4 AWaveXorU4(AU4 v,AU1 x){return subgroupShuffleXor(v,x);} +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_HALF + AH2 AWaveXorH2(AH2 v,AU1 x){return AH2_AU1(subgroupShuffleXor(AU1_AH2(v),x));} + AH4 AWaveXorH4(AH4 v,AU1 x){return AH4_AU2(subgroupShuffleXor(AU2_AH4(v),x));} + AW2 AWaveXorW2(AW2 v,AU1 x){return AW2_AU1(subgroupShuffleXor(AU1_AW2(v),x));} + AW4 AWaveXorW4(AW4 v,AU1 x){return AW4_AU2(subgroupShuffleXor(AU2_AW4(v),x));} + #endif + #endif +//============================================================================================================================== +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// +// HLSL +// +// +//============================================================================================================================== +#if defined(A_HLSL) && defined(A_GPU) + #ifdef A_HLSL_6_2 + #define AP1 bool + #define AP2 bool2 + #define AP3 bool3 + #define AP4 bool4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AF1 float32_t + #define AF2 float32_t2 + #define AF3 float32_t3 + #define AF4 float32_t4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1 uint32_t + #define AU2 uint32_t2 + #define AU3 uint32_t3 + #define AU4 uint32_t4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASU1 int32_t + #define ASU2 int32_t2 + #define ASU3 int32_t3 + #define ASU4 int32_t4 + #else + #define AP1 bool + #define AP2 bool2 + #define AP3 bool3 + #define AP4 bool4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AF1 float + #define AF2 float2 + #define AF3 float3 + #define AF4 float4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1 uint + #define AU2 uint2 + #define AU3 uint3 + #define AU4 uint4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASU1 int + #define ASU2 int2 + #define ASU3 int3 + #define ASU4 int4 + #endif +//============================================================================================================================== + #define AF1_AU1(x) asfloat(AU1(x)) + #define AF2_AU2(x) asfloat(AU2(x)) + #define AF3_AU3(x) asfloat(AU3(x)) + #define AF4_AU4(x) asfloat(AU4(x)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AU1_AF1(x) asuint(AF1(x)) + #define AU2_AF2(x) asuint(AF2(x)) + #define AU3_AF3(x) asuint(AF3(x)) + #define AU4_AF4(x) asuint(AF4(x)) +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AU1_AH1_AF1_x(AF1 a){return f32tof16(a);} + #define AU1_AH1_AF1(a) AU1_AH1_AF1_x(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AU1_AH2_AF2_x(AF2 a){return f32tof16(a.x)|(f32tof16(a.y)<<16);} + #define AU1_AH2_AF2(a) AU1_AH2_AF2_x(AF2(a)) + #define AU1_AB4Unorm_AF4(x) D3DCOLORtoUBYTE4(AF4(x)) +//------------------------------------------------------------------------------------------------------------------------------ + AF2 AF2_AH2_AU1_x(AU1 x){return AF2(f16tof32(x&0xFFFF),f16tof32(x>>16));} + #define AF2_AH2_AU1(x) AF2_AH2_AU1_x(AU1(x)) +//============================================================================================================================== + AF1 AF1_x(AF1 a){return AF1(a);} + AF2 AF2_x(AF1 a){return AF2(a,a);} + AF3 AF3_x(AF1 a){return AF3(a,a,a);} + AF4 AF4_x(AF1 a){return AF4(a,a,a,a);} + #define AF1_(a) AF1_x(AF1(a)) + #define AF2_(a) AF2_x(AF1(a)) + #define AF3_(a) AF3_x(AF1(a)) + #define AF4_(a) AF4_x(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AU1_x(AU1 a){return AU1(a);} + AU2 AU2_x(AU1 a){return AU2(a,a);} + AU3 AU3_x(AU1 a){return AU3(a,a,a);} + AU4 AU4_x(AU1 a){return AU4(a,a,a,a);} + #define AU1_(a) AU1_x(AU1(a)) + #define AU2_(a) AU2_x(AU1(a)) + #define AU3_(a) AU3_x(AU1(a)) + #define AU4_(a) AU4_x(AU1(a)) +//============================================================================================================================== + AU1 AAbsSU1(AU1 a){return AU1(abs(ASU1(a)));} + AU2 AAbsSU2(AU2 a){return AU2(abs(ASU2(a)));} + AU3 AAbsSU3(AU3 a){return AU3(abs(ASU3(a)));} + AU4 AAbsSU4(AU4 a){return AU4(abs(ASU4(a)));} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 ABfe(AU1 src,AU1 off,AU1 bits){AU1 mask=(1u<>off)&mask;} + AU1 ABfi(AU1 src,AU1 ins,AU1 mask){return (ins&mask)|(src&(~mask));} + AU1 ABfiM(AU1 src,AU1 ins,AU1 bits){AU1 mask=(1u<>ASU1(b));} + AU2 AShrSU2(AU2 a,AU2 b){return AU2(ASU2(a)>>ASU2(b));} + AU3 AShrSU3(AU3 a,AU3 b){return AU3(ASU3(a)>>ASU3(b));} + AU4 AShrSU4(AU4 a,AU4 b){return AU4(ASU4(a)>>ASU4(b));} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// HLSL BYTE +//============================================================================================================================== + #ifdef A_BYTE + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// HLSL HALF +//============================================================================================================================== + #ifdef A_HALF + #ifdef A_HLSL_6_2 + #define AH1 float16_t + #define AH2 float16_t2 + #define AH3 float16_t3 + #define AH4 float16_t4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AW1 uint16_t + #define AW2 uint16_t2 + #define AW3 uint16_t3 + #define AW4 uint16_t4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASW1 int16_t + #define ASW2 int16_t2 + #define ASW3 int16_t3 + #define ASW4 int16_t4 + #else + #define AH1 min16float + #define AH2 min16float2 + #define AH3 min16float3 + #define AH4 min16float4 +//------------------------------------------------------------------------------------------------------------------------------ + #define AW1 min16uint + #define AW2 min16uint2 + #define AW3 min16uint3 + #define AW4 min16uint4 +//------------------------------------------------------------------------------------------------------------------------------ + #define ASW1 min16int + #define ASW2 min16int2 + #define ASW3 min16int3 + #define ASW4 min16int4 + #endif +//============================================================================================================================== + // Need to use manual unpack to get optimal execution (don't use packed types in buffers directly). + // Unpack requires this pattern: https://gpuopen.com/first-steps-implementing-fp16/ + AH2 AH2_AU1_x(AU1 x){AF2 t=f16tof32(AU2(x&0xFFFF,x>>16));return AH2(t);} + AH4 AH4_AU2_x(AU2 x){return AH4(AH2_AU1_x(x.x),AH2_AU1_x(x.y));} + AW2 AW2_AU1_x(AU1 x){AU2 t=AU2(x&0xFFFF,x>>16);return AW2(t);} + AW4 AW4_AU2_x(AU2 x){return AW4(AW2_AU1_x(x.x),AW2_AU1_x(x.y));} + #define AH2_AU1(x) AH2_AU1_x(AU1(x)) + #define AH4_AU2(x) AH4_AU2_x(AU2(x)) + #define AW2_AU1(x) AW2_AU1_x(AU1(x)) + #define AW4_AU2(x) AW4_AU2_x(AU2(x)) +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AU1_AH2_x(AH2 x){return f32tof16(x.x)+(f32tof16(x.y)<<16);} + AU2 AU2_AH4_x(AH4 x){return AU2(AU1_AH2_x(x.xy),AU1_AH2_x(x.zw));} + AU1 AU1_AW2_x(AW2 x){return AU1(x.x)+(AU1(x.y)<<16);} + AU2 AU2_AW4_x(AW4 x){return AU2(AU1_AW2_x(x.xy),AU1_AW2_x(x.zw));} + #define AU1_AH2(x) AU1_AH2_x(AH2(x)) + #define AU2_AH4(x) AU2_AH4_x(AH4(x)) + #define AU1_AW2(x) AU1_AW2_x(AW2(x)) + #define AU2_AW4(x) AU2_AW4_x(AW4(x)) +//============================================================================================================================== + #if defined(A_HLSL_6_2) && !defined(A_NO_16_BIT_CAST) + #define AW1_AH1(x) asuint16(x) + #define AW2_AH2(x) asuint16(x) + #define AW3_AH3(x) asuint16(x) + #define AW4_AH4(x) asuint16(x) + #else + #define AW1_AH1(a) AW1(f32tof16(AF1(a))) + #define AW2_AH2(a) AW2(AW1_AH1((a).x),AW1_AH1((a).y)) + #define AW3_AH3(a) AW3(AW1_AH1((a).x),AW1_AH1((a).y),AW1_AH1((a).z)) + #define AW4_AH4(a) AW4(AW1_AH1((a).x),AW1_AH1((a).y),AW1_AH1((a).z),AW1_AH1((a).w)) + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #if defined(A_HLSL_6_2) && !defined(A_NO_16_BIT_CAST) + #define AH1_AW1(x) asfloat16(x) + #define AH2_AW2(x) asfloat16(x) + #define AH3_AW3(x) asfloat16(x) + #define AH4_AW4(x) asfloat16(x) + #else + #define AH1_AW1(a) AH1(f16tof32(AU1(a))) + #define AH2_AW2(a) AH2(AH1_AW1((a).x),AH1_AW1((a).y)) + #define AH3_AW3(a) AH3(AH1_AW1((a).x),AH1_AW1((a).y),AH1_AW1((a).z)) + #define AH4_AW4(a) AH4(AH1_AW1((a).x),AH1_AW1((a).y),AH1_AW1((a).z),AH1_AW1((a).w)) + #endif +//============================================================================================================================== + AH1 AH1_x(AH1 a){return AH1(a);} + AH2 AH2_x(AH1 a){return AH2(a,a);} + AH3 AH3_x(AH1 a){return AH3(a,a,a);} + AH4 AH4_x(AH1 a){return AH4(a,a,a,a);} + #define AH1_(a) AH1_x(AH1(a)) + #define AH2_(a) AH2_x(AH1(a)) + #define AH3_(a) AH3_x(AH1(a)) + #define AH4_(a) AH4_x(AH1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AW1_x(AW1 a){return AW1(a);} + AW2 AW2_x(AW1 a){return AW2(a,a);} + AW3 AW3_x(AW1 a){return AW3(a,a,a);} + AW4 AW4_x(AW1 a){return AW4(a,a,a,a);} + #define AW1_(a) AW1_x(AW1(a)) + #define AW2_(a) AW2_x(AW1(a)) + #define AW3_(a) AW3_x(AW1(a)) + #define AW4_(a) AW4_x(AW1(a)) +//============================================================================================================================== + AW1 AAbsSW1(AW1 a){return AW1(abs(ASW1(a)));} + AW2 AAbsSW2(AW2 a){return AW2(abs(ASW2(a)));} + AW3 AAbsSW3(AW3 a){return AW3(abs(ASW3(a)));} + AW4 AAbsSW4(AW4 a){return AW4(abs(ASW4(a)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AClampH1(AH1 x,AH1 n,AH1 m){return max(n,min(x,m));} + AH2 AClampH2(AH2 x,AH2 n,AH2 m){return max(n,min(x,m));} + AH3 AClampH3(AH3 x,AH3 n,AH3 m){return max(n,min(x,m));} + AH4 AClampH4(AH4 x,AH4 n,AH4 m){return max(n,min(x,m));} +//------------------------------------------------------------------------------------------------------------------------------ + // V_FRACT_F16 (note DX frac() is different). + AH1 AFractH1(AH1 x){return x-floor(x);} + AH2 AFractH2(AH2 x){return x-floor(x);} + AH3 AFractH3(AH3 x){return x-floor(x);} + AH4 AFractH4(AH4 x){return x-floor(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ALerpH1(AH1 x,AH1 y,AH1 a){return lerp(x,y,a);} + AH2 ALerpH2(AH2 x,AH2 y,AH2 a){return lerp(x,y,a);} + AH3 ALerpH3(AH3 x,AH3 y,AH3 a){return lerp(x,y,a);} + AH4 ALerpH4(AH4 x,AH4 y,AH4 a){return lerp(x,y,a);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AMax3H1(AH1 x,AH1 y,AH1 z){return max(x,max(y,z));} + AH2 AMax3H2(AH2 x,AH2 y,AH2 z){return max(x,max(y,z));} + AH3 AMax3H3(AH3 x,AH3 y,AH3 z){return max(x,max(y,z));} + AH4 AMax3H4(AH4 x,AH4 y,AH4 z){return max(x,max(y,z));} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AMaxSW1(AW1 a,AW1 b){return AW1(max(ASU1(a),ASU1(b)));} + AW2 AMaxSW2(AW2 a,AW2 b){return AW2(max(ASU2(a),ASU2(b)));} + AW3 AMaxSW3(AW3 a,AW3 b){return AW3(max(ASU3(a),ASU3(b)));} + AW4 AMaxSW4(AW4 a,AW4 b){return AW4(max(ASU4(a),ASU4(b)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AMin3H1(AH1 x,AH1 y,AH1 z){return min(x,min(y,z));} + AH2 AMin3H2(AH2 x,AH2 y,AH2 z){return min(x,min(y,z));} + AH3 AMin3H3(AH3 x,AH3 y,AH3 z){return min(x,min(y,z));} + AH4 AMin3H4(AH4 x,AH4 y,AH4 z){return min(x,min(y,z));} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AMinSW1(AW1 a,AW1 b){return AW1(min(ASU1(a),ASU1(b)));} + AW2 AMinSW2(AW2 a,AW2 b){return AW2(min(ASU2(a),ASU2(b)));} + AW3 AMinSW3(AW3 a,AW3 b){return AW3(min(ASU3(a),ASU3(b)));} + AW4 AMinSW4(AW4 a,AW4 b){return AW4(min(ASU4(a),ASU4(b)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ARcpH1(AH1 x){return rcp(x);} + AH2 ARcpH2(AH2 x){return rcp(x);} + AH3 ARcpH3(AH3 x){return rcp(x);} + AH4 ARcpH4(AH4 x){return rcp(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ARsqH1(AH1 x){return rsqrt(x);} + AH2 ARsqH2(AH2 x){return rsqrt(x);} + AH3 ARsqH3(AH3 x){return rsqrt(x);} + AH4 ARsqH4(AH4 x){return rsqrt(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ASatH1(AH1 x){return saturate(x);} + AH2 ASatH2(AH2 x){return saturate(x);} + AH3 ASatH3(AH3 x){return saturate(x);} + AH4 ASatH4(AH4 x){return saturate(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AShrSW1(AW1 a,AW1 b){return AW1(ASW1(a)>>ASW1(b));} + AW2 AShrSW2(AW2 a,AW2 b){return AW2(ASW2(a)>>ASW2(b));} + AW3 AShrSW3(AW3 a,AW3 b){return AW3(ASW3(a)>>ASW3(b));} + AW4 AShrSW4(AW4 a,AW4 b){return AW4(ASW4(a)>>ASW4(b));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// HLSL DOUBLE +//============================================================================================================================== + #ifdef A_DUBL + #ifdef A_HLSL_6_2 + #define AD1 float64_t + #define AD2 float64_t2 + #define AD3 float64_t3 + #define AD4 float64_t4 + #else + #define AD1 double + #define AD2 double2 + #define AD3 double3 + #define AD4 double4 + #endif +//------------------------------------------------------------------------------------------------------------------------------ + AD1 AD1_x(AD1 a){return AD1(a);} + AD2 AD2_x(AD1 a){return AD2(a,a);} + AD3 AD3_x(AD1 a){return AD3(a,a,a);} + AD4 AD4_x(AD1 a){return AD4(a,a,a,a);} + #define AD1_(a) AD1_x(AD1(a)) + #define AD2_(a) AD2_x(AD1(a)) + #define AD3_(a) AD3_x(AD1(a)) + #define AD4_(a) AD4_x(AD1(a)) +//============================================================================================================================== + AD1 AFractD1(AD1 a){return a-floor(a);} + AD2 AFractD2(AD2 a){return a-floor(a);} + AD3 AFractD3(AD3 a){return a-floor(a);} + AD4 AFractD4(AD4 a){return a-floor(a);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ALerpD1(AD1 x,AD1 y,AD1 a){return lerp(x,y,a);} + AD2 ALerpD2(AD2 x,AD2 y,AD2 a){return lerp(x,y,a);} + AD3 ALerpD3(AD3 x,AD3 y,AD3 a){return lerp(x,y,a);} + AD4 ALerpD4(AD4 x,AD4 y,AD4 a){return lerp(x,y,a);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ARcpD1(AD1 x){return rcp(x);} + AD2 ARcpD2(AD2 x){return rcp(x);} + AD3 ARcpD3(AD3 x){return rcp(x);} + AD4 ARcpD4(AD4 x){return rcp(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ARsqD1(AD1 x){return rsqrt(x);} + AD2 ARsqD2(AD2 x){return rsqrt(x);} + AD3 ARsqD3(AD3 x){return rsqrt(x);} + AD4 ARsqD4(AD4 x){return rsqrt(x);} +//------------------------------------------------------------------------------------------------------------------------------ + AD1 ASatD1(AD1 x){return saturate(x);} + AD2 ASatD2(AD2 x){return saturate(x);} + AD3 ASatD3(AD3 x){return saturate(x);} + AD4 ASatD4(AD4 x){return saturate(x);} + #endif +//============================================================================================================================== +// HLSL WAVE +//============================================================================================================================== + #ifdef A_WAVE + // Where 'x' must be a compile time literal. + AF1 AWaveXorF1(AF1 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AF2 AWaveXorF2(AF2 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AF3 AWaveXorF3(AF3 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AF4 AWaveXorF4(AF4 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AU1 AWaveXorU1(AU1 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AU2 AWaveXorU1(AU2 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AU3 AWaveXorU1(AU3 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} + AU4 AWaveXorU1(AU4 v,AU1 x){return WaveReadLaneAt(v,WaveGetLaneIndex()^x);} +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_HALF + AH2 AWaveXorH2(AH2 v,AU1 x){return AH2_AU1(WaveReadLaneAt(AU1_AH2(v),WaveGetLaneIndex()^x));} + AH4 AWaveXorH4(AH4 v,AU1 x){return AH4_AU2(WaveReadLaneAt(AU2_AH4(v),WaveGetLaneIndex()^x));} + AW2 AWaveXorW2(AW2 v,AU1 x){return AW2_AU1(WaveReadLaneAt(AU1_AW2(v),WaveGetLaneIndex()^x));} + AW4 AWaveXorW4(AW4 v,AU1 x){return AW4_AU1(WaveReadLaneAt(AU1_AW4(v),WaveGetLaneIndex()^x));} + #endif + #endif +//============================================================================================================================== +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// +// GPU COMMON +// +// +//============================================================================================================================== +#ifdef A_GPU + // Negative and positive infinity. + #define A_INFP_F AF1_AU1(0x7f800000u) + #define A_INFN_F AF1_AU1(0xff800000u) +//------------------------------------------------------------------------------------------------------------------------------ + // Copy sign from 's' to positive 'd'. + AF1 ACpySgnF1(AF1 d,AF1 s){return AF1_AU1(AU1_AF1(d)|(AU1_AF1(s)&AU1_(0x80000000u)));} + AF2 ACpySgnF2(AF2 d,AF2 s){return AF2_AU2(AU2_AF2(d)|(AU2_AF2(s)&AU2_(0x80000000u)));} + AF3 ACpySgnF3(AF3 d,AF3 s){return AF3_AU3(AU3_AF3(d)|(AU3_AF3(s)&AU3_(0x80000000u)));} + AF4 ACpySgnF4(AF4 d,AF4 s){return AF4_AU4(AU4_AF4(d)|(AU4_AF4(s)&AU4_(0x80000000u)));} +//------------------------------------------------------------------------------------------------------------------------------ + // Single operation to return (useful to create a mask to use in lerp for branch free logic), + // m=NaN := 0 + // m>=0 := 0 + // m<0 := 1 + // Uses the following useful floating point logic, + // saturate(+a*(-INF)==-INF) := 0 + // saturate( 0*(-INF)== NaN) := 0 + // saturate(-a*(-INF)==+INF) := 1 + AF1 ASignedF1(AF1 m){return ASatF1(m*AF1_(A_INFN_F));} + AF2 ASignedF2(AF2 m){return ASatF2(m*AF2_(A_INFN_F));} + AF3 ASignedF3(AF3 m){return ASatF3(m*AF3_(A_INFN_F));} + AF4 ASignedF4(AF4 m){return ASatF4(m*AF4_(A_INFN_F));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AGtZeroF1(AF1 m){return ASatF1(m*AF1_(A_INFP_F));} + AF2 AGtZeroF2(AF2 m){return ASatF2(m*AF2_(A_INFP_F));} + AF3 AGtZeroF3(AF3 m){return ASatF3(m*AF3_(A_INFP_F));} + AF4 AGtZeroF4(AF4 m){return ASatF4(m*AF4_(A_INFP_F));} +//============================================================================================================================== + #ifdef A_HALF + #ifdef A_HLSL_6_2 + #define A_INFP_H AH1_AW1((uint16_t)0x7c00u) + #define A_INFN_H AH1_AW1((uint16_t)0xfc00u) + #else + #define A_INFP_H AH1_AW1(0x7c00u) + #define A_INFN_H AH1_AW1(0xfc00u) + #endif + +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ACpySgnH1(AH1 d,AH1 s){return AH1_AW1(AW1_AH1(d)|(AW1_AH1(s)&AW1_(0x8000u)));} + AH2 ACpySgnH2(AH2 d,AH2 s){return AH2_AW2(AW2_AH2(d)|(AW2_AH2(s)&AW2_(0x8000u)));} + AH3 ACpySgnH3(AH3 d,AH3 s){return AH3_AW3(AW3_AH3(d)|(AW3_AH3(s)&AW3_(0x8000u)));} + AH4 ACpySgnH4(AH4 d,AH4 s){return AH4_AW4(AW4_AH4(d)|(AW4_AH4(s)&AW4_(0x8000u)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ASignedH1(AH1 m){return ASatH1(m*AH1_(A_INFN_H));} + AH2 ASignedH2(AH2 m){return ASatH2(m*AH2_(A_INFN_H));} + AH3 ASignedH3(AH3 m){return ASatH3(m*AH3_(A_INFN_H));} + AH4 ASignedH4(AH4 m){return ASatH4(m*AH4_(A_INFN_H));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AGtZeroH1(AH1 m){return ASatH1(m*AH1_(A_INFP_H));} + AH2 AGtZeroH2(AH2 m){return ASatH2(m*AH2_(A_INFP_H));} + AH3 AGtZeroH3(AH3 m){return ASatH3(m*AH3_(A_INFP_H));} + AH4 AGtZeroH4(AH4 m){return ASatH4(m*AH4_(A_INFP_H));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// [FIS] FLOAT INTEGER SORTABLE +//------------------------------------------------------------------------------------------------------------------------------ +// Float to integer sortable. +// - If sign bit=0, flip the sign bit (positives). +// - If sign bit=1, flip all bits (negatives). +// Integer sortable to float. +// - If sign bit=1, flip the sign bit (positives). +// - If sign bit=0, flip all bits (negatives). +// Has nice side effects. +// - Larger integers are more positive values. +// - Float zero is mapped to center of integers (so clear to integer zero is a nice default for atomic max usage). +// Burns 3 ops for conversion {shift,or,xor}. +//============================================================================================================================== + AU1 AFisToU1(AU1 x){return x^(( AShrSU1(x,AU1_(31)))|AU1_(0x80000000));} + AU1 AFisFromU1(AU1 x){return x^((~AShrSU1(x,AU1_(31)))|AU1_(0x80000000));} +//------------------------------------------------------------------------------------------------------------------------------ + // Just adjust high 16-bit value (useful when upper part of 32-bit word is a 16-bit float value). + AU1 AFisToHiU1(AU1 x){return x^(( AShrSU1(x,AU1_(15)))|AU1_(0x80000000));} + AU1 AFisFromHiU1(AU1 x){return x^((~AShrSU1(x,AU1_(15)))|AU1_(0x80000000));} +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_HALF + AW1 AFisToW1(AW1 x){return x^(( AShrSW1(x,AW1_(15)))|AW1_(0x8000));} + AW1 AFisFromW1(AW1 x){return x^((~AShrSW1(x,AW1_(15)))|AW1_(0x8000));} +//------------------------------------------------------------------------------------------------------------------------------ + AW2 AFisToW2(AW2 x){return x^(( AShrSW2(x,AW2_(15)))|AW2_(0x8000));} + AW2 AFisFromW2(AW2 x){return x^((~AShrSW2(x,AW2_(15)))|AW2_(0x8000));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// [PERM] V_PERM_B32 +//------------------------------------------------------------------------------------------------------------------------------ +// Support for V_PERM_B32 started in the 3rd generation of GCN. +//------------------------------------------------------------------------------------------------------------------------------ +// yyyyxxxx - The 'i' input. +// 76543210 +// ======== +// HGFEDCBA - Naming on permutation. +//------------------------------------------------------------------------------------------------------------------------------ +// TODO +// ==== +// - Make sure compiler optimizes this. +//============================================================================================================================== + #ifdef A_HALF + AU1 APerm0E0A(AU2 i){return((i.x )&0xffu)|((i.y<<16)&0xff0000u);} + AU1 APerm0F0B(AU2 i){return((i.x>> 8)&0xffu)|((i.y<< 8)&0xff0000u);} + AU1 APerm0G0C(AU2 i){return((i.x>>16)&0xffu)|((i.y )&0xff0000u);} + AU1 APerm0H0D(AU2 i){return((i.x>>24)&0xffu)|((i.y>> 8)&0xff0000u);} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 APermHGFA(AU2 i){return((i.x )&0x000000ffu)|(i.y&0xffffff00u);} + AU1 APermHGFC(AU2 i){return((i.x>>16)&0x000000ffu)|(i.y&0xffffff00u);} + AU1 APermHGAE(AU2 i){return((i.x<< 8)&0x0000ff00u)|(i.y&0xffff00ffu);} + AU1 APermHGCE(AU2 i){return((i.x>> 8)&0x0000ff00u)|(i.y&0xffff00ffu);} + AU1 APermHAFE(AU2 i){return((i.x<<16)&0x00ff0000u)|(i.y&0xff00ffffu);} + AU1 APermHCFE(AU2 i){return((i.x )&0x00ff0000u)|(i.y&0xff00ffffu);} + AU1 APermAGFE(AU2 i){return((i.x<<24)&0xff000000u)|(i.y&0x00ffffffu);} + AU1 APermCGFE(AU2 i){return((i.x<< 8)&0xff000000u)|(i.y&0x00ffffffu);} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 APermGCEA(AU2 i){return((i.x)&0x00ff00ffu)|((i.y<<8)&0xff00ff00u);} + AU1 APermGECA(AU2 i){return(((i.x)&0xffu)|((i.x>>8)&0xff00u)|((i.y<<16)&0xff0000u)|((i.y<<8)&0xff000000u));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// [BUC] BYTE UNSIGNED CONVERSION +//------------------------------------------------------------------------------------------------------------------------------ +// Designed to use the optimal conversion, enables the scaling to possibly be factored into other computation. +// Works on a range of {0 to A_BUC_<32,16>}, for <32-bit, and 16-bit> respectively. +//------------------------------------------------------------------------------------------------------------------------------ +// OPCODE NOTES +// ============ +// GCN does not do UNORM or SNORM for bytes in opcodes. +// - V_CVT_F32_UBYTE{0,1,2,3} - Unsigned byte to float. +// - V_CVT_PKACC_U8_F32 - Float to unsigned byte (does bit-field insert into 32-bit integer). +// V_PERM_B32 does byte packing with ability to zero fill bytes as well. +// - Can pull out byte values from two sources, and zero fill upper 8-bits of packed hi and lo. +//------------------------------------------------------------------------------------------------------------------------------ +// BYTE : FLOAT - ABuc{0,1,2,3}{To,From}U1() - Designed for V_CVT_F32_UBYTE* and V_CVT_PKACCUM_U8_F32 ops. +// ==== ===== +// 0 : 0 +// 1 : 1 +// ... +// 255 : 255 +// : 256 (just outside the encoding range) +//------------------------------------------------------------------------------------------------------------------------------ +// BYTE : FLOAT - ABuc{0,1,2,3}{To,From}U2() - Designed for 16-bit denormal tricks and V_PERM_B32. +// ==== ===== +// 0 : 0 +// 1 : 1/512 +// 2 : 1/256 +// ... +// 64 : 1/8 +// 128 : 1/4 +// 255 : 255/512 +// : 1/2 (just outside the encoding range) +//------------------------------------------------------------------------------------------------------------------------------ +// OPTIMAL IMPLEMENTATIONS ON AMD ARCHITECTURES +// ============================================ +// r=ABuc0FromU1(i) +// V_CVT_F32_UBYTE0 r,i +// -------------------------------------------- +// r=ABuc0ToU1(d,i) +// V_CVT_PKACCUM_U8_F32 r,i,0,d +// -------------------------------------------- +// d=ABuc0FromU2(i) +// Where 'k0' is an SGPR with 0x0E0A +// Where 'k1' is an SGPR with {32768.0} packed into the lower 16-bits +// V_PERM_B32 d,i.x,i.y,k0 +// V_PK_FMA_F16 d,d,k1.x,0 +// -------------------------------------------- +// r=ABuc0ToU2(d,i) +// Where 'k0' is an SGPR with {1.0/32768.0} packed into the lower 16-bits +// Where 'k1' is an SGPR with 0x???? +// Where 'k2' is an SGPR with 0x???? +// V_PK_FMA_F16 i,i,k0.x,0 +// V_PERM_B32 r.x,i,i,k1 +// V_PERM_B32 r.y,i,i,k2 +//============================================================================================================================== + // Peak range for 32-bit and 16-bit operations. + #define A_BUC_32 (255.0) + #define A_BUC_16 (255.0/512.0) +//============================================================================================================================== + #if 1 + // Designed to be one V_CVT_PKACCUM_U8_F32. + // The extra min is required to pattern match to V_CVT_PKACCUM_U8_F32. + AU1 ABuc0ToU1(AU1 d,AF1 i){return (d&0xffffff00u)|((min(AU1(i),255u) )&(0x000000ffu));} + AU1 ABuc1ToU1(AU1 d,AF1 i){return (d&0xffff00ffu)|((min(AU1(i),255u)<< 8)&(0x0000ff00u));} + AU1 ABuc2ToU1(AU1 d,AF1 i){return (d&0xff00ffffu)|((min(AU1(i),255u)<<16)&(0x00ff0000u));} + AU1 ABuc3ToU1(AU1 d,AF1 i){return (d&0x00ffffffu)|((min(AU1(i),255u)<<24)&(0xff000000u));} +//------------------------------------------------------------------------------------------------------------------------------ + // Designed to be one V_CVT_F32_UBYTE*. + AF1 ABuc0FromU1(AU1 i){return AF1((i )&255u);} + AF1 ABuc1FromU1(AU1 i){return AF1((i>> 8)&255u);} + AF1 ABuc2FromU1(AU1 i){return AF1((i>>16)&255u);} + AF1 ABuc3FromU1(AU1 i){return AF1((i>>24)&255u);} + #endif +//============================================================================================================================== + #ifdef A_HALF + // Takes {x0,x1} and {y0,y1} and builds {{x0,y0},{x1,y1}}. + AW2 ABuc01ToW2(AH2 x,AH2 y){x*=AH2_(1.0/32768.0);y*=AH2_(1.0/32768.0); + return AW2_AU1(APermGCEA(AU2(AU1_AW2(AW2_AH2(x)),AU1_AW2(AW2_AH2(y)))));} +//------------------------------------------------------------------------------------------------------------------------------ + // Designed for 3 ops to do SOA to AOS and conversion. + AU2 ABuc0ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0))); + return AU2(APermHGFA(AU2(d.x,b)),APermHGFC(AU2(d.y,b)));} + AU2 ABuc1ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0))); + return AU2(APermHGAE(AU2(d.x,b)),APermHGCE(AU2(d.y,b)));} + AU2 ABuc2ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0))); + return AU2(APermHAFE(AU2(d.x,b)),APermHCFE(AU2(d.y,b)));} + AU2 ABuc3ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0))); + return AU2(APermAGFE(AU2(d.x,b)),APermCGFE(AU2(d.y,b)));} +//------------------------------------------------------------------------------------------------------------------------------ + // Designed for 2 ops to do both AOS to SOA, and conversion. + AH2 ABuc0FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0E0A(i)))*AH2_(32768.0);} + AH2 ABuc1FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0F0B(i)))*AH2_(32768.0);} + AH2 ABuc2FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0G0C(i)))*AH2_(32768.0);} + AH2 ABuc3FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0H0D(i)))*AH2_(32768.0);} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// [BSC] BYTE SIGNED CONVERSION +//------------------------------------------------------------------------------------------------------------------------------ +// Similar to [BUC]. +// Works on a range of {-/+ A_BSC_<32,16>}, for <32-bit, and 16-bit> respectively. +//------------------------------------------------------------------------------------------------------------------------------ +// ENCODING (without zero-based encoding) +// ======== +// 0 = unused (can be used to mean something else) +// 1 = lowest value +// 128 = exact zero center (zero based encoding +// 255 = highest value +//------------------------------------------------------------------------------------------------------------------------------ +// Zero-based [Zb] flips the MSB bit of the byte (making 128 "exact zero" actually zero). +// This is useful if there is a desire for cleared values to decode as zero. +//------------------------------------------------------------------------------------------------------------------------------ +// BYTE : FLOAT - ABsc{0,1,2,3}{To,From}U2() - Designed for 16-bit denormal tricks and V_PERM_B32. +// ==== ===== +// 0 : -127/512 (unused) +// 1 : -126/512 +// 2 : -125/512 +// ... +// 128 : 0 +// ... +// 255 : 127/512 +// : 1/4 (just outside the encoding range) +//============================================================================================================================== + // Peak range for 32-bit and 16-bit operations. + #define A_BSC_32 (127.0) + #define A_BSC_16 (127.0/512.0) +//============================================================================================================================== + #if 1 + AU1 ABsc0ToU1(AU1 d,AF1 i){return (d&0xffffff00u)|((min(AU1(i+128.0),255u) )&(0x000000ffu));} + AU1 ABsc1ToU1(AU1 d,AF1 i){return (d&0xffff00ffu)|((min(AU1(i+128.0),255u)<< 8)&(0x0000ff00u));} + AU1 ABsc2ToU1(AU1 d,AF1 i){return (d&0xff00ffffu)|((min(AU1(i+128.0),255u)<<16)&(0x00ff0000u));} + AU1 ABsc3ToU1(AU1 d,AF1 i){return (d&0x00ffffffu)|((min(AU1(i+128.0),255u)<<24)&(0xff000000u));} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 ABsc0ToZbU1(AU1 d,AF1 i){return ((d&0xffffff00u)|((min(AU1(trunc(i)+128.0),255u) )&(0x000000ffu)))^0x00000080u;} + AU1 ABsc1ToZbU1(AU1 d,AF1 i){return ((d&0xffff00ffu)|((min(AU1(trunc(i)+128.0),255u)<< 8)&(0x0000ff00u)))^0x00008000u;} + AU1 ABsc2ToZbU1(AU1 d,AF1 i){return ((d&0xff00ffffu)|((min(AU1(trunc(i)+128.0),255u)<<16)&(0x00ff0000u)))^0x00800000u;} + AU1 ABsc3ToZbU1(AU1 d,AF1 i){return ((d&0x00ffffffu)|((min(AU1(trunc(i)+128.0),255u)<<24)&(0xff000000u)))^0x80000000u;} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 ABsc0FromU1(AU1 i){return AF1((i )&255u)-128.0;} + AF1 ABsc1FromU1(AU1 i){return AF1((i>> 8)&255u)-128.0;} + AF1 ABsc2FromU1(AU1 i){return AF1((i>>16)&255u)-128.0;} + AF1 ABsc3FromU1(AU1 i){return AF1((i>>24)&255u)-128.0;} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 ABsc0FromZbU1(AU1 i){return AF1(((i )&255u)^0x80u)-128.0;} + AF1 ABsc1FromZbU1(AU1 i){return AF1(((i>> 8)&255u)^0x80u)-128.0;} + AF1 ABsc2FromZbU1(AU1 i){return AF1(((i>>16)&255u)^0x80u)-128.0;} + AF1 ABsc3FromZbU1(AU1 i){return AF1(((i>>24)&255u)^0x80u)-128.0;} + #endif +//============================================================================================================================== + #ifdef A_HALF + // Takes {x0,x1} and {y0,y1} and builds {{x0,y0},{x1,y1}}. + AW2 ABsc01ToW2(AH2 x,AH2 y){x=x*AH2_(1.0/32768.0)+AH2_(0.25/32768.0);y=y*AH2_(1.0/32768.0)+AH2_(0.25/32768.0); + return AW2_AU1(APermGCEA(AU2(AU1_AW2(AW2_AH2(x)),AU1_AW2(AW2_AH2(y)))));} +//------------------------------------------------------------------------------------------------------------------------------ + AU2 ABsc0ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0))); + return AU2(APermHGFA(AU2(d.x,b)),APermHGFC(AU2(d.y,b)));} + AU2 ABsc1ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0))); + return AU2(APermHGAE(AU2(d.x,b)),APermHGCE(AU2(d.y,b)));} + AU2 ABsc2ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0))); + return AU2(APermHAFE(AU2(d.x,b)),APermHCFE(AU2(d.y,b)));} + AU2 ABsc3ToU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0))); + return AU2(APermAGFE(AU2(d.x,b)),APermCGFE(AU2(d.y,b)));} +//------------------------------------------------------------------------------------------------------------------------------ + AU2 ABsc0ToZbU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0)))^0x00800080u; + return AU2(APermHGFA(AU2(d.x,b)),APermHGFC(AU2(d.y,b)));} + AU2 ABsc1ToZbU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0)))^0x00800080u; + return AU2(APermHGAE(AU2(d.x,b)),APermHGCE(AU2(d.y,b)));} + AU2 ABsc2ToZbU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0)))^0x00800080u; + return AU2(APermHAFE(AU2(d.x,b)),APermHCFE(AU2(d.y,b)));} + AU2 ABsc3ToZbU2(AU2 d,AH2 i){AU1 b=AU1_AW2(AW2_AH2(i*AH2_(1.0/32768.0)+AH2_(0.25/32768.0)))^0x00800080u; + return AU2(APermAGFE(AU2(d.x,b)),APermCGFE(AU2(d.y,b)));} +//------------------------------------------------------------------------------------------------------------------------------ + AH2 ABsc0FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0E0A(i)))*AH2_(32768.0)-AH2_(0.25);} + AH2 ABsc1FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0F0B(i)))*AH2_(32768.0)-AH2_(0.25);} + AH2 ABsc2FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0G0C(i)))*AH2_(32768.0)-AH2_(0.25);} + AH2 ABsc3FromU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0H0D(i)))*AH2_(32768.0)-AH2_(0.25);} +//------------------------------------------------------------------------------------------------------------------------------ + AH2 ABsc0FromZbU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0E0A(i)^0x00800080u))*AH2_(32768.0)-AH2_(0.25);} + AH2 ABsc1FromZbU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0F0B(i)^0x00800080u))*AH2_(32768.0)-AH2_(0.25);} + AH2 ABsc2FromZbU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0G0C(i)^0x00800080u))*AH2_(32768.0)-AH2_(0.25);} + AH2 ABsc3FromZbU2(AU2 i){return AH2_AW2(AW2_AU1(APerm0H0D(i)^0x00800080u))*AH2_(32768.0)-AH2_(0.25);} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// HALF APPROXIMATIONS +//------------------------------------------------------------------------------------------------------------------------------ +// These support only positive inputs. +// Did not see value yet in specialization for range. +// Using quick testing, ended up mostly getting the same "best" approximation for various ranges. +// With hardware that can co-execute transcendentals, the value in approximations could be less than expected. +// However from a latency perspective, if execution of a transcendental is 4 clk, with no packed support, -> 8 clk total. +// And co-execution would require a compiler interleaving a lot of independent work for packed usage. +//------------------------------------------------------------------------------------------------------------------------------ +// The one Newton Raphson iteration form of rsq() was skipped (requires 6 ops total). +// Same with sqrt(), as this could be x*rsq() (7 ops). +//============================================================================================================================== + #ifdef A_HALF + // Minimize squared error across full positive range, 2 ops. + // The 0x1de2 based approximation maps {0 to 1} input maps to < 1 output. + AH1 APrxLoSqrtH1(AH1 a){return AH1_AW1((AW1_AH1(a)>>AW1_(1))+AW1_(0x1de2));} + AH2 APrxLoSqrtH2(AH2 a){return AH2_AW2((AW2_AH2(a)>>AW2_(1))+AW2_(0x1de2));} + AH3 APrxLoSqrtH3(AH3 a){return AH3_AW3((AW3_AH3(a)>>AW3_(1))+AW3_(0x1de2));} + AH4 APrxLoSqrtH4(AH4 a){return AH4_AW4((AW4_AH4(a)>>AW4_(1))+AW4_(0x1de2));} +//------------------------------------------------------------------------------------------------------------------------------ + // Lower precision estimation, 1 op. + // Minimize squared error across {smallest normal to 16384.0}. + AH1 APrxLoRcpH1(AH1 a){return AH1_AW1(AW1_(0x7784)-AW1_AH1(a));} + AH2 APrxLoRcpH2(AH2 a){return AH2_AW2(AW2_(0x7784)-AW2_AH2(a));} + AH3 APrxLoRcpH3(AH3 a){return AH3_AW3(AW3_(0x7784)-AW3_AH3(a));} + AH4 APrxLoRcpH4(AH4 a){return AH4_AW4(AW4_(0x7784)-AW4_AH4(a));} +//------------------------------------------------------------------------------------------------------------------------------ + // Medium precision estimation, one Newton Raphson iteration, 3 ops. + AH1 APrxMedRcpH1(AH1 a){AH1 b=AH1_AW1(AW1_(0x778d)-AW1_AH1(a));return b*(-b*a+AH1_(2.0));} + AH2 APrxMedRcpH2(AH2 a){AH2 b=AH2_AW2(AW2_(0x778d)-AW2_AH2(a));return b*(-b*a+AH2_(2.0));} + AH3 APrxMedRcpH3(AH3 a){AH3 b=AH3_AW3(AW3_(0x778d)-AW3_AH3(a));return b*(-b*a+AH3_(2.0));} + AH4 APrxMedRcpH4(AH4 a){AH4 b=AH4_AW4(AW4_(0x778d)-AW4_AH4(a));return b*(-b*a+AH4_(2.0));} +//------------------------------------------------------------------------------------------------------------------------------ + // Minimize squared error across {smallest normal to 16384.0}, 2 ops. + AH1 APrxLoRsqH1(AH1 a){return AH1_AW1(AW1_(0x59a3)-(AW1_AH1(a)>>AW1_(1)));} + AH2 APrxLoRsqH2(AH2 a){return AH2_AW2(AW2_(0x59a3)-(AW2_AH2(a)>>AW2_(1)));} + AH3 APrxLoRsqH3(AH3 a){return AH3_AW3(AW3_(0x59a3)-(AW3_AH3(a)>>AW3_(1)));} + AH4 APrxLoRsqH4(AH4 a){return AH4_AW4(AW4_(0x59a3)-(AW4_AH4(a)>>AW4_(1)));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// FLOAT APPROXIMATIONS +//------------------------------------------------------------------------------------------------------------------------------ +// Michal Drobot has an excellent presentation on these: "Low Level Optimizations For GCN", +// - Idea dates back to SGI, then to Quake 3, etc. +// - https://michaldrobot.files.wordpress.com/2014/05/gcn_alu_opt_digitaldragons2014.pdf +// - sqrt(x)=rsqrt(x)*x +// - rcp(x)=rsqrt(x)*rsqrt(x) for positive x +// - https://github.com/michaldrobot/ShaderFastLibs/blob/master/ShaderFastMathLib.h +//------------------------------------------------------------------------------------------------------------------------------ +// These below are from perhaps less complete searching for optimal. +// Used FP16 normal range for testing with +4096 32-bit step size for sampling error. +// So these match up well with the half approximations. +//============================================================================================================================== + AF1 APrxLoSqrtF1(AF1 a){return AF1_AU1((AU1_AF1(a)>>AU1_(1))+AU1_(0x1fbc4639));} + AF1 APrxLoRcpF1(AF1 a){return AF1_AU1(AU1_(0x7ef07ebb)-AU1_AF1(a));} + AF1 APrxMedRcpF1(AF1 a){AF1 b=AF1_AU1(AU1_(0x7ef19fff)-AU1_AF1(a));return b*(-b*a+AF1_(2.0));} + AF1 APrxLoRsqF1(AF1 a){return AF1_AU1(AU1_(0x5f347d74)-(AU1_AF1(a)>>AU1_(1)));} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 APrxLoSqrtF2(AF2 a){return AF2_AU2((AU2_AF2(a)>>AU2_(1))+AU2_(0x1fbc4639));} + AF2 APrxLoRcpF2(AF2 a){return AF2_AU2(AU2_(0x7ef07ebb)-AU2_AF2(a));} + AF2 APrxMedRcpF2(AF2 a){AF2 b=AF2_AU2(AU2_(0x7ef19fff)-AU2_AF2(a));return b*(-b*a+AF2_(2.0));} + AF2 APrxLoRsqF2(AF2 a){return AF2_AU2(AU2_(0x5f347d74)-(AU2_AF2(a)>>AU2_(1)));} +//------------------------------------------------------------------------------------------------------------------------------ + AF3 APrxLoSqrtF3(AF3 a){return AF3_AU3((AU3_AF3(a)>>AU3_(1))+AU3_(0x1fbc4639));} + AF3 APrxLoRcpF3(AF3 a){return AF3_AU3(AU3_(0x7ef07ebb)-AU3_AF3(a));} + AF3 APrxMedRcpF3(AF3 a){AF3 b=AF3_AU3(AU3_(0x7ef19fff)-AU3_AF3(a));return b*(-b*a+AF3_(2.0));} + AF3 APrxLoRsqF3(AF3 a){return AF3_AU3(AU3_(0x5f347d74)-(AU3_AF3(a)>>AU3_(1)));} +//------------------------------------------------------------------------------------------------------------------------------ + AF4 APrxLoSqrtF4(AF4 a){return AF4_AU4((AU4_AF4(a)>>AU4_(1))+AU4_(0x1fbc4639));} + AF4 APrxLoRcpF4(AF4 a){return AF4_AU4(AU4_(0x7ef07ebb)-AU4_AF4(a));} + AF4 APrxMedRcpF4(AF4 a){AF4 b=AF4_AU4(AU4_(0x7ef19fff)-AU4_AF4(a));return b*(-b*a+AF4_(2.0));} + AF4 APrxLoRsqF4(AF4 a){return AF4_AU4(AU4_(0x5f347d74)-(AU4_AF4(a)>>AU4_(1)));} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// PQ APPROXIMATIONS +//------------------------------------------------------------------------------------------------------------------------------ +// PQ is very close to x^(1/8). The functions below Use the fast float approximation method to do +// PQ<~>Gamma2 (4th power and fast 4th root) and PQ<~>Linear (8th power and fast 8th root). Maximum error is ~0.2%. +//============================================================================================================================== +// Helpers + AF1 Quart(AF1 a) { a = a * a; return a * a;} + AF1 Oct(AF1 a) { a = a * a; a = a * a; return a * a; } + AF2 Quart(AF2 a) { a = a * a; return a * a; } + AF2 Oct(AF2 a) { a = a * a; a = a * a; return a * a; } + AF3 Quart(AF3 a) { a = a * a; return a * a; } + AF3 Oct(AF3 a) { a = a * a; a = a * a; return a * a; } + AF4 Quart(AF4 a) { a = a * a; return a * a; } + AF4 Oct(AF4 a) { a = a * a; a = a * a; return a * a; } + //------------------------------------------------------------------------------------------------------------------------------ + AF1 APrxPQToGamma2(AF1 a) { return Quart(a); } + AF1 APrxPQToLinear(AF1 a) { return Oct(a); } + AF1 APrxLoGamma2ToPQ(AF1 a) { return AF1_AU1((AU1_AF1(a) >> AU1_(2)) + AU1_(0x2F9A4E46)); } + AF1 APrxMedGamma2ToPQ(AF1 a) { AF1 b = AF1_AU1((AU1_AF1(a) >> AU1_(2)) + AU1_(0x2F9A4E46)); AF1 b4 = Quart(b); return b - b * (b4 - a) / (AF1_(4.0) * b4); } + AF1 APrxHighGamma2ToPQ(AF1 a) { return sqrt(sqrt(a)); } + AF1 APrxLoLinearToPQ(AF1 a) { return AF1_AU1((AU1_AF1(a) >> AU1_(3)) + AU1_(0x378D8723)); } + AF1 APrxMedLinearToPQ(AF1 a) { AF1 b = AF1_AU1((AU1_AF1(a) >> AU1_(3)) + AU1_(0x378D8723)); AF1 b8 = Oct(b); return b - b * (b8 - a) / (AF1_(8.0) * b8); } + AF1 APrxHighLinearToPQ(AF1 a) { return sqrt(sqrt(sqrt(a))); } + //------------------------------------------------------------------------------------------------------------------------------ + AF2 APrxPQToGamma2(AF2 a) { return Quart(a); } + AF2 APrxPQToLinear(AF2 a) { return Oct(a); } + AF2 APrxLoGamma2ToPQ(AF2 a) { return AF2_AU2((AU2_AF2(a) >> AU2_(2)) + AU2_(0x2F9A4E46)); } + AF2 APrxMedGamma2ToPQ(AF2 a) { AF2 b = AF2_AU2((AU2_AF2(a) >> AU2_(2)) + AU2_(0x2F9A4E46)); AF2 b4 = Quart(b); return b - b * (b4 - a) / (AF1_(4.0) * b4); } + AF2 APrxHighGamma2ToPQ(AF2 a) { return sqrt(sqrt(a)); } + AF2 APrxLoLinearToPQ(AF2 a) { return AF2_AU2((AU2_AF2(a) >> AU2_(3)) + AU2_(0x378D8723)); } + AF2 APrxMedLinearToPQ(AF2 a) { AF2 b = AF2_AU2((AU2_AF2(a) >> AU2_(3)) + AU2_(0x378D8723)); AF2 b8 = Oct(b); return b - b * (b8 - a) / (AF1_(8.0) * b8); } + AF2 APrxHighLinearToPQ(AF2 a) { return sqrt(sqrt(sqrt(a))); } + //------------------------------------------------------------------------------------------------------------------------------ + AF3 APrxPQToGamma2(AF3 a) { return Quart(a); } + AF3 APrxPQToLinear(AF3 a) { return Oct(a); } + AF3 APrxLoGamma2ToPQ(AF3 a) { return AF3_AU3((AU3_AF3(a) >> AU3_(2)) + AU3_(0x2F9A4E46)); } + AF3 APrxMedGamma2ToPQ(AF3 a) { AF3 b = AF3_AU3((AU3_AF3(a) >> AU3_(2)) + AU3_(0x2F9A4E46)); AF3 b4 = Quart(b); return b - b * (b4 - a) / (AF1_(4.0) * b4); } + AF3 APrxHighGamma2ToPQ(AF3 a) { return sqrt(sqrt(a)); } + AF3 APrxLoLinearToPQ(AF3 a) { return AF3_AU3((AU3_AF3(a) >> AU3_(3)) + AU3_(0x378D8723)); } + AF3 APrxMedLinearToPQ(AF3 a) { AF3 b = AF3_AU3((AU3_AF3(a) >> AU3_(3)) + AU3_(0x378D8723)); AF3 b8 = Oct(b); return b - b * (b8 - a) / (AF1_(8.0) * b8); } + AF3 APrxHighLinearToPQ(AF3 a) { return sqrt(sqrt(sqrt(a))); } + //------------------------------------------------------------------------------------------------------------------------------ + AF4 APrxPQToGamma2(AF4 a) { return Quart(a); } + AF4 APrxPQToLinear(AF4 a) { return Oct(a); } + AF4 APrxLoGamma2ToPQ(AF4 a) { return AF4_AU4((AU4_AF4(a) >> AU4_(2)) + AU4_(0x2F9A4E46)); } + AF4 APrxMedGamma2ToPQ(AF4 a) { AF4 b = AF4_AU4((AU4_AF4(a) >> AU4_(2)) + AU4_(0x2F9A4E46)); AF4 b4 = Quart(b); return b - b * (b4 - a) / (AF1_(4.0) * b4); } + AF4 APrxHighGamma2ToPQ(AF4 a) { return sqrt(sqrt(a)); } + AF4 APrxLoLinearToPQ(AF4 a) { return AF4_AU4((AU4_AF4(a) >> AU4_(3)) + AU4_(0x378D8723)); } + AF4 APrxMedLinearToPQ(AF4 a) { AF4 b = AF4_AU4((AU4_AF4(a) >> AU4_(3)) + AU4_(0x378D8723)); AF4 b8 = Oct(b); return b - b * (b8 - a) / (AF1_(8.0) * b8); } + AF4 APrxHighLinearToPQ(AF4 a) { return sqrt(sqrt(sqrt(a))); } +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// PARABOLIC SIN & COS +//------------------------------------------------------------------------------------------------------------------------------ +// Approximate answers to transcendental questions. +//------------------------------------------------------------------------------------------------------------------------------ +//============================================================================================================================== + #if 1 + // Valid input range is {-1 to 1} representing {0 to 2 pi}. + // Output range is {-1/4 to 1/4} representing {-1 to 1}. + AF1 APSinF1(AF1 x){return x*abs(x)-x;} // MAD. + AF2 APSinF2(AF2 x){return x*abs(x)-x;} + AF1 APCosF1(AF1 x){x=AFractF1(x*AF1_(0.5)+AF1_(0.75));x=x*AF1_(2.0)-AF1_(1.0);return APSinF1(x);} // 3x MAD, FRACT + AF2 APCosF2(AF2 x){x=AFractF2(x*AF2_(0.5)+AF2_(0.75));x=x*AF2_(2.0)-AF2_(1.0);return APSinF2(x);} + AF2 APSinCosF1(AF1 x){AF1 y=AFractF1(x*AF1_(0.5)+AF1_(0.75));y=y*AF1_(2.0)-AF1_(1.0);return APSinF2(AF2(x,y));} + #endif +//------------------------------------------------------------------------------------------------------------------------------ + #ifdef A_HALF + // For a packed {sin,cos} pair, + // - Native takes 16 clocks and 4 issue slots (no packed transcendentals). + // - Parabolic takes 8 clocks and 8 issue slots (only fract is non-packed). + AH1 APSinH1(AH1 x){return x*abs(x)-x;} + AH2 APSinH2(AH2 x){return x*abs(x)-x;} // AND,FMA + AH1 APCosH1(AH1 x){x=AFractH1(x*AH1_(0.5)+AH1_(0.75));x=x*AH1_(2.0)-AH1_(1.0);return APSinH1(x);} + AH2 APCosH2(AH2 x){x=AFractH2(x*AH2_(0.5)+AH2_(0.75));x=x*AH2_(2.0)-AH2_(1.0);return APSinH2(x);} // 3x FMA, 2xFRACT, AND + AH2 APSinCosH1(AH1 x){AH1 y=AFractH1(x*AH1_(0.5)+AH1_(0.75));y=y*AH1_(2.0)-AH1_(1.0);return APSinH2(AH2(x,y));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// [ZOL] ZERO ONE LOGIC +//------------------------------------------------------------------------------------------------------------------------------ +// Conditional free logic designed for easy 16-bit packing, and backwards porting to 32-bit. +//------------------------------------------------------------------------------------------------------------------------------ +// 0 := false +// 1 := true +//------------------------------------------------------------------------------------------------------------------------------ +// AndNot(x,y) -> !(x&y) .... One op. +// AndOr(x,y,z) -> (x&y)|z ... One op. +// GtZero(x) -> x>0.0 ..... One op. +// Sel(x,y,z) -> x?y:z ..... Two ops, has no precision loss. +// Signed(x) -> x<0.0 ..... One op. +// ZeroPass(x,y) -> x?0:y ..... Two ops, 'y' is a pass through safe for aliasing as integer. +//------------------------------------------------------------------------------------------------------------------------------ +// OPTIMIZATION NOTES +// ================== +// - On Vega to use 2 constants in a packed op, pass in as one AW2 or one AH2 'k.xy' and use as 'k.xx' and 'k.yy'. +// For example 'a.xy*k.xx+k.yy'. +//============================================================================================================================== + #if 1 + AU1 AZolAndU1(AU1 x,AU1 y){return min(x,y);} + AU2 AZolAndU2(AU2 x,AU2 y){return min(x,y);} + AU3 AZolAndU3(AU3 x,AU3 y){return min(x,y);} + AU4 AZolAndU4(AU4 x,AU4 y){return min(x,y);} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AZolNotU1(AU1 x){return x^AU1_(1);} + AU2 AZolNotU2(AU2 x){return x^AU2_(1);} + AU3 AZolNotU3(AU3 x){return x^AU3_(1);} + AU4 AZolNotU4(AU4 x){return x^AU4_(1);} +//------------------------------------------------------------------------------------------------------------------------------ + AU1 AZolOrU1(AU1 x,AU1 y){return max(x,y);} + AU2 AZolOrU2(AU2 x,AU2 y){return max(x,y);} + AU3 AZolOrU3(AU3 x,AU3 y){return max(x,y);} + AU4 AZolOrU4(AU4 x,AU4 y){return max(x,y);} +//============================================================================================================================== + AU1 AZolF1ToU1(AF1 x){return AU1(x);} + AU2 AZolF2ToU2(AF2 x){return AU2(x);} + AU3 AZolF3ToU3(AF3 x){return AU3(x);} + AU4 AZolF4ToU4(AF4 x){return AU4(x);} +//------------------------------------------------------------------------------------------------------------------------------ + // 2 ops, denormals don't work in 32-bit on PC (and if they are enabled, OMOD is disabled). + AU1 AZolNotF1ToU1(AF1 x){return AU1(AF1_(1.0)-x);} + AU2 AZolNotF2ToU2(AF2 x){return AU2(AF2_(1.0)-x);} + AU3 AZolNotF3ToU3(AF3 x){return AU3(AF3_(1.0)-x);} + AU4 AZolNotF4ToU4(AF4 x){return AU4(AF4_(1.0)-x);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolU1ToF1(AU1 x){return AF1(x);} + AF2 AZolU2ToF2(AU2 x){return AF2(x);} + AF3 AZolU3ToF3(AU3 x){return AF3(x);} + AF4 AZolU4ToF4(AU4 x){return AF4(x);} +//============================================================================================================================== + AF1 AZolAndF1(AF1 x,AF1 y){return min(x,y);} + AF2 AZolAndF2(AF2 x,AF2 y){return min(x,y);} + AF3 AZolAndF3(AF3 x,AF3 y){return min(x,y);} + AF4 AZolAndF4(AF4 x,AF4 y){return min(x,y);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 ASolAndNotF1(AF1 x,AF1 y){return (-x)*y+AF1_(1.0);} + AF2 ASolAndNotF2(AF2 x,AF2 y){return (-x)*y+AF2_(1.0);} + AF3 ASolAndNotF3(AF3 x,AF3 y){return (-x)*y+AF3_(1.0);} + AF4 ASolAndNotF4(AF4 x,AF4 y){return (-x)*y+AF4_(1.0);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolAndOrF1(AF1 x,AF1 y,AF1 z){return ASatF1(x*y+z);} + AF2 AZolAndOrF2(AF2 x,AF2 y,AF2 z){return ASatF2(x*y+z);} + AF3 AZolAndOrF3(AF3 x,AF3 y,AF3 z){return ASatF3(x*y+z);} + AF4 AZolAndOrF4(AF4 x,AF4 y,AF4 z){return ASatF4(x*y+z);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolGtZeroF1(AF1 x){return ASatF1(x*AF1_(A_INFP_F));} + AF2 AZolGtZeroF2(AF2 x){return ASatF2(x*AF2_(A_INFP_F));} + AF3 AZolGtZeroF3(AF3 x){return ASatF3(x*AF3_(A_INFP_F));} + AF4 AZolGtZeroF4(AF4 x){return ASatF4(x*AF4_(A_INFP_F));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolNotF1(AF1 x){return AF1_(1.0)-x;} + AF2 AZolNotF2(AF2 x){return AF2_(1.0)-x;} + AF3 AZolNotF3(AF3 x){return AF3_(1.0)-x;} + AF4 AZolNotF4(AF4 x){return AF4_(1.0)-x;} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolOrF1(AF1 x,AF1 y){return max(x,y);} + AF2 AZolOrF2(AF2 x,AF2 y){return max(x,y);} + AF3 AZolOrF3(AF3 x,AF3 y){return max(x,y);} + AF4 AZolOrF4(AF4 x,AF4 y){return max(x,y);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolSelF1(AF1 x,AF1 y,AF1 z){AF1 r=(-x)*z+z;return x*y+r;} + AF2 AZolSelF2(AF2 x,AF2 y,AF2 z){AF2 r=(-x)*z+z;return x*y+r;} + AF3 AZolSelF3(AF3 x,AF3 y,AF3 z){AF3 r=(-x)*z+z;return x*y+r;} + AF4 AZolSelF4(AF4 x,AF4 y,AF4 z){AF4 r=(-x)*z+z;return x*y+r;} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolSignedF1(AF1 x){return ASatF1(x*AF1_(A_INFN_F));} + AF2 AZolSignedF2(AF2 x){return ASatF2(x*AF2_(A_INFN_F));} + AF3 AZolSignedF3(AF3 x){return ASatF3(x*AF3_(A_INFN_F));} + AF4 AZolSignedF4(AF4 x){return ASatF4(x*AF4_(A_INFN_F));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AZolZeroPassF1(AF1 x,AF1 y){return AF1_AU1((AU1_AF1(x)!=AU1_(0))?AU1_(0):AU1_AF1(y));} + AF2 AZolZeroPassF2(AF2 x,AF2 y){return AF2_AU2((AU2_AF2(x)!=AU2_(0))?AU2_(0):AU2_AF2(y));} + AF3 AZolZeroPassF3(AF3 x,AF3 y){return AF3_AU3((AU3_AF3(x)!=AU3_(0))?AU3_(0):AU3_AF3(y));} + AF4 AZolZeroPassF4(AF4 x,AF4 y){return AF4_AU4((AU4_AF4(x)!=AU4_(0))?AU4_(0):AU4_AF4(y));} + #endif +//============================================================================================================================== + #ifdef A_HALF + AW1 AZolAndW1(AW1 x,AW1 y){return min(x,y);} + AW2 AZolAndW2(AW2 x,AW2 y){return min(x,y);} + AW3 AZolAndW3(AW3 x,AW3 y){return min(x,y);} + AW4 AZolAndW4(AW4 x,AW4 y){return min(x,y);} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AZolNotW1(AW1 x){return x^AW1_(1);} + AW2 AZolNotW2(AW2 x){return x^AW2_(1);} + AW3 AZolNotW3(AW3 x){return x^AW3_(1);} + AW4 AZolNotW4(AW4 x){return x^AW4_(1);} +//------------------------------------------------------------------------------------------------------------------------------ + AW1 AZolOrW1(AW1 x,AW1 y){return max(x,y);} + AW2 AZolOrW2(AW2 x,AW2 y){return max(x,y);} + AW3 AZolOrW3(AW3 x,AW3 y){return max(x,y);} + AW4 AZolOrW4(AW4 x,AW4 y){return max(x,y);} +//============================================================================================================================== + // Uses denormal trick. + AW1 AZolH1ToW1(AH1 x){return AW1_AH1(x*AH1_AW1(AW1_(1)));} + AW2 AZolH2ToW2(AH2 x){return AW2_AH2(x*AH2_AW2(AW2_(1)));} + AW3 AZolH3ToW3(AH3 x){return AW3_AH3(x*AH3_AW3(AW3_(1)));} + AW4 AZolH4ToW4(AH4 x){return AW4_AH4(x*AH4_AW4(AW4_(1)));} +//------------------------------------------------------------------------------------------------------------------------------ + // AMD arch lacks a packed conversion opcode. + AH1 AZolW1ToH1(AW1 x){return AH1_AW1(x*AW1_AH1(AH1_(1.0)));} + AH2 AZolW2ToH2(AW2 x){return AH2_AW2(x*AW2_AH2(AH2_(1.0)));} + AH3 AZolW1ToH3(AW3 x){return AH3_AW3(x*AW3_AH3(AH3_(1.0)));} + AH4 AZolW2ToH4(AW4 x){return AH4_AW4(x*AW4_AH4(AH4_(1.0)));} +//============================================================================================================================== + AH1 AZolAndH1(AH1 x,AH1 y){return min(x,y);} + AH2 AZolAndH2(AH2 x,AH2 y){return min(x,y);} + AH3 AZolAndH3(AH3 x,AH3 y){return min(x,y);} + AH4 AZolAndH4(AH4 x,AH4 y){return min(x,y);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 ASolAndNotH1(AH1 x,AH1 y){return (-x)*y+AH1_(1.0);} + AH2 ASolAndNotH2(AH2 x,AH2 y){return (-x)*y+AH2_(1.0);} + AH3 ASolAndNotH3(AH3 x,AH3 y){return (-x)*y+AH3_(1.0);} + AH4 ASolAndNotH4(AH4 x,AH4 y){return (-x)*y+AH4_(1.0);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AZolAndOrH1(AH1 x,AH1 y,AH1 z){return ASatH1(x*y+z);} + AH2 AZolAndOrH2(AH2 x,AH2 y,AH2 z){return ASatH2(x*y+z);} + AH3 AZolAndOrH3(AH3 x,AH3 y,AH3 z){return ASatH3(x*y+z);} + AH4 AZolAndOrH4(AH4 x,AH4 y,AH4 z){return ASatH4(x*y+z);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AZolGtZeroH1(AH1 x){return ASatH1(x*AH1_(A_INFP_H));} + AH2 AZolGtZeroH2(AH2 x){return ASatH2(x*AH2_(A_INFP_H));} + AH3 AZolGtZeroH3(AH3 x){return ASatH3(x*AH3_(A_INFP_H));} + AH4 AZolGtZeroH4(AH4 x){return ASatH4(x*AH4_(A_INFP_H));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AZolNotH1(AH1 x){return AH1_(1.0)-x;} + AH2 AZolNotH2(AH2 x){return AH2_(1.0)-x;} + AH3 AZolNotH3(AH3 x){return AH3_(1.0)-x;} + AH4 AZolNotH4(AH4 x){return AH4_(1.0)-x;} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AZolOrH1(AH1 x,AH1 y){return max(x,y);} + AH2 AZolOrH2(AH2 x,AH2 y){return max(x,y);} + AH3 AZolOrH3(AH3 x,AH3 y){return max(x,y);} + AH4 AZolOrH4(AH4 x,AH4 y){return max(x,y);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AZolSelH1(AH1 x,AH1 y,AH1 z){AH1 r=(-x)*z+z;return x*y+r;} + AH2 AZolSelH2(AH2 x,AH2 y,AH2 z){AH2 r=(-x)*z+z;return x*y+r;} + AH3 AZolSelH3(AH3 x,AH3 y,AH3 z){AH3 r=(-x)*z+z;return x*y+r;} + AH4 AZolSelH4(AH4 x,AH4 y,AH4 z){AH4 r=(-x)*z+z;return x*y+r;} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AZolSignedH1(AH1 x){return ASatH1(x*AH1_(A_INFN_H));} + AH2 AZolSignedH2(AH2 x){return ASatH2(x*AH2_(A_INFN_H));} + AH3 AZolSignedH3(AH3 x){return ASatH3(x*AH3_(A_INFN_H));} + AH4 AZolSignedH4(AH4 x){return ASatH4(x*AH4_(A_INFN_H));} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// COLOR CONVERSIONS +//------------------------------------------------------------------------------------------------------------------------------ +// These are all linear to/from some other space (where 'linear' has been shortened out of the function name). +// So 'ToGamma' is 'LinearToGamma', and 'FromGamma' is 'LinearFromGamma'. +// These are branch free implementations. +// The AToSrgbF1() function is useful for stores for compute shaders for GPUs without hardware linear->sRGB store conversion. +//------------------------------------------------------------------------------------------------------------------------------ +// TRANSFER FUNCTIONS +// ================== +// 709 ..... Rec709 used for some HDTVs +// Gamma ... Typically 2.2 for some PC displays, or 2.4-2.5 for CRTs, or 2.2 FreeSync2 native +// Pq ...... PQ native for HDR10 +// Srgb .... The sRGB output, typical of PC displays, useful for 10-bit output, or storing to 8-bit UNORM without SRGB type +// Two ..... Gamma 2.0, fastest conversion (useful for intermediate pass approximations) +// Three ... Gamma 3.0, less fast, but good for HDR. +//------------------------------------------------------------------------------------------------------------------------------ +// KEEPING TO SPEC +// =============== +// Both Rec.709 and sRGB have a linear segment which as spec'ed would intersect the curved segment 2 times. +// (a.) For 8-bit sRGB, steps {0 to 10.3} are in the linear region (4% of the encoding range). +// (b.) For 8-bit 709, steps {0 to 20.7} are in the linear region (8% of the encoding range). +// Also there is a slight step in the transition regions. +// Precision of the coefficients in the spec being the likely cause. +// Main usage case of the sRGB code is to do the linear->sRGB converstion in a compute shader before store. +// This is to work around lack of hardware (typically only ROP does the conversion for free). +// To "correct" the linear segment, would be to introduce error, because hardware decode of sRGB->linear is fixed (and free). +// So this header keeps with the spec. +// For linear->sRGB transforms, the linear segment in some respects reduces error, because rounding in that region is linear. +// Rounding in the curved region in hardware (and fast software code) introduces error due to rounding in non-linear. +//------------------------------------------------------------------------------------------------------------------------------ +// FOR PQ +// ====== +// Both input and output is {0.0-1.0}, and where output 1.0 represents 10000.0 cd/m^2. +// All constants are only specified to FP32 precision. +// External PQ source reference, +// - https://github.com/ampas/aces-dev/blob/master/transforms/ctl/utilities/ACESlib.Utilities_Color.a1.0.1.ctl +//------------------------------------------------------------------------------------------------------------------------------ +// PACKED VERSIONS +// =============== +// These are the A*H2() functions. +// There is no PQ functions as FP16 seemed to not have enough precision for the conversion. +// The remaining functions are "good enough" for 8-bit, and maybe 10-bit if not concerned about a few 1-bit errors. +// Precision is lowest in the 709 conversion, higher in sRGB, higher still in Two and Gamma (when using 2.2 at least). +//------------------------------------------------------------------------------------------------------------------------------ +// NOTES +// ===== +// Could be faster for PQ conversions to be in ALU or a texture lookup depending on usage case. +//============================================================================================================================== + #if 1 + AF1 ATo709F1(AF1 c){AF3 j=AF3(0.018*4.5,4.5,0.45);AF2 k=AF2(1.099,-0.099); + return clamp(j.x ,c*j.y ,pow(c,j.z )*k.x +k.y );} + AF2 ATo709F2(AF2 c){AF3 j=AF3(0.018*4.5,4.5,0.45);AF2 k=AF2(1.099,-0.099); + return clamp(j.xx ,c*j.yy ,pow(c,j.zz )*k.xx +k.yy );} + AF3 ATo709F3(AF3 c){AF3 j=AF3(0.018*4.5,4.5,0.45);AF2 k=AF2(1.099,-0.099); + return clamp(j.xxx,c*j.yyy,pow(c,j.zzz)*k.xxx+k.yyy);} +//------------------------------------------------------------------------------------------------------------------------------ + // Note 'rcpX' is '1/x', where the 'x' is what would be used in AFromGamma(). + AF1 AToGammaF1(AF1 c,AF1 rcpX){return pow(c,AF1_(rcpX));} + AF2 AToGammaF2(AF2 c,AF1 rcpX){return pow(c,AF2_(rcpX));} + AF3 AToGammaF3(AF3 c,AF1 rcpX){return pow(c,AF3_(rcpX));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AToPqF1(AF1 x){AF1 p=pow(x,AF1_(0.159302)); + return pow((AF1_(0.835938)+AF1_(18.8516)*p)/(AF1_(1.0)+AF1_(18.6875)*p),AF1_(78.8438));} + AF2 AToPqF1(AF2 x){AF2 p=pow(x,AF2_(0.159302)); + return pow((AF2_(0.835938)+AF2_(18.8516)*p)/(AF2_(1.0)+AF2_(18.6875)*p),AF2_(78.8438));} + AF3 AToPqF1(AF3 x){AF3 p=pow(x,AF3_(0.159302)); + return pow((AF3_(0.835938)+AF3_(18.8516)*p)/(AF3_(1.0)+AF3_(18.6875)*p),AF3_(78.8438));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AToSrgbF1(AF1 c){AF3 j=AF3(0.0031308*12.92,12.92,1.0/2.4);AF2 k=AF2(1.055,-0.055); + return clamp(j.x ,c*j.y ,pow(c,j.z )*k.x +k.y );} + AF2 AToSrgbF2(AF2 c){AF3 j=AF3(0.0031308*12.92,12.92,1.0/2.4);AF2 k=AF2(1.055,-0.055); + return clamp(j.xx ,c*j.yy ,pow(c,j.zz )*k.xx +k.yy );} + AF3 AToSrgbF3(AF3 c){AF3 j=AF3(0.0031308*12.92,12.92,1.0/2.4);AF2 k=AF2(1.055,-0.055); + return clamp(j.xxx,c*j.yyy,pow(c,j.zzz)*k.xxx+k.yyy);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AToTwoF1(AF1 c){return sqrt(c);} + AF2 AToTwoF2(AF2 c){return sqrt(c);} + AF3 AToTwoF3(AF3 c){return sqrt(c);} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AToThreeF1(AF1 c){return pow(c,AF1_(1.0/3.0));} + AF2 AToThreeF2(AF2 c){return pow(c,AF2_(1.0/3.0));} + AF3 AToThreeF3(AF3 c){return pow(c,AF3_(1.0/3.0));} + #endif +//============================================================================================================================== + #if 1 + // Unfortunately median won't work here. + AF1 AFrom709F1(AF1 c){AF3 j=AF3(0.081/4.5,1.0/4.5,1.0/0.45);AF2 k=AF2(1.0/1.099,0.099/1.099); + return AZolSelF1(AZolSignedF1(c-j.x ),c*j.y ,pow(c*k.x +k.y ,j.z ));} + AF2 AFrom709F2(AF2 c){AF3 j=AF3(0.081/4.5,1.0/4.5,1.0/0.45);AF2 k=AF2(1.0/1.099,0.099/1.099); + return AZolSelF2(AZolSignedF2(c-j.xx ),c*j.yy ,pow(c*k.xx +k.yy ,j.zz ));} + AF3 AFrom709F3(AF3 c){AF3 j=AF3(0.081/4.5,1.0/4.5,1.0/0.45);AF2 k=AF2(1.0/1.099,0.099/1.099); + return AZolSelF3(AZolSignedF3(c-j.xxx),c*j.yyy,pow(c*k.xxx+k.yyy,j.zzz));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AFromGammaF1(AF1 c,AF1 x){return pow(c,AF1_(x));} + AF2 AFromGammaF2(AF2 c,AF1 x){return pow(c,AF2_(x));} + AF3 AFromGammaF3(AF3 c,AF1 x){return pow(c,AF3_(x));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AFromPqF1(AF1 x){AF1 p=pow(x,AF1_(0.0126833)); + return pow(ASatF1(p-AF1_(0.835938))/(AF1_(18.8516)-AF1_(18.6875)*p),AF1_(6.27739));} + AF2 AFromPqF1(AF2 x){AF2 p=pow(x,AF2_(0.0126833)); + return pow(ASatF2(p-AF2_(0.835938))/(AF2_(18.8516)-AF2_(18.6875)*p),AF2_(6.27739));} + AF3 AFromPqF1(AF3 x){AF3 p=pow(x,AF3_(0.0126833)); + return pow(ASatF3(p-AF3_(0.835938))/(AF3_(18.8516)-AF3_(18.6875)*p),AF3_(6.27739));} +//------------------------------------------------------------------------------------------------------------------------------ + // Unfortunately median won't work here. + AF1 AFromSrgbF1(AF1 c){AF3 j=AF3(0.04045/12.92,1.0/12.92,2.4);AF2 k=AF2(1.0/1.055,0.055/1.055); + return AZolSelF1(AZolSignedF1(c-j.x ),c*j.y ,pow(c*k.x +k.y ,j.z ));} + AF2 AFromSrgbF2(AF2 c){AF3 j=AF3(0.04045/12.92,1.0/12.92,2.4);AF2 k=AF2(1.0/1.055,0.055/1.055); + return AZolSelF2(AZolSignedF2(c-j.xx ),c*j.yy ,pow(c*k.xx +k.yy ,j.zz ));} + AF3 AFromSrgbF3(AF3 c){AF3 j=AF3(0.04045/12.92,1.0/12.92,2.4);AF2 k=AF2(1.0/1.055,0.055/1.055); + return AZolSelF3(AZolSignedF3(c-j.xxx),c*j.yyy,pow(c*k.xxx+k.yyy,j.zzz));} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AFromTwoF1(AF1 c){return c*c;} + AF2 AFromTwoF2(AF2 c){return c*c;} + AF3 AFromTwoF3(AF3 c){return c*c;} +//------------------------------------------------------------------------------------------------------------------------------ + AF1 AFromThreeF1(AF1 c){return c*c*c;} + AF2 AFromThreeF2(AF2 c){return c*c*c;} + AF3 AFromThreeF3(AF3 c){return c*c*c;} + #endif +//============================================================================================================================== + #ifdef A_HALF + AH1 ATo709H1(AH1 c){AH3 j=AH3(0.018*4.5,4.5,0.45);AH2 k=AH2(1.099,-0.099); + return clamp(j.x ,c*j.y ,pow(c,j.z )*k.x +k.y );} + AH2 ATo709H2(AH2 c){AH3 j=AH3(0.018*4.5,4.5,0.45);AH2 k=AH2(1.099,-0.099); + return clamp(j.xx ,c*j.yy ,pow(c,j.zz )*k.xx +k.yy );} + AH3 ATo709H3(AH3 c){AH3 j=AH3(0.018*4.5,4.5,0.45);AH2 k=AH2(1.099,-0.099); + return clamp(j.xxx,c*j.yyy,pow(c,j.zzz)*k.xxx+k.yyy);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AToGammaH1(AH1 c,AH1 rcpX){return pow(c,AH1_(rcpX));} + AH2 AToGammaH2(AH2 c,AH1 rcpX){return pow(c,AH2_(rcpX));} + AH3 AToGammaH3(AH3 c,AH1 rcpX){return pow(c,AH3_(rcpX));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AToSrgbH1(AH1 c){AH3 j=AH3(0.0031308*12.92,12.92,1.0/2.4);AH2 k=AH2(1.055,-0.055); + return clamp(j.x ,c*j.y ,pow(c,j.z )*k.x +k.y );} + AH2 AToSrgbH2(AH2 c){AH3 j=AH3(0.0031308*12.92,12.92,1.0/2.4);AH2 k=AH2(1.055,-0.055); + return clamp(j.xx ,c*j.yy ,pow(c,j.zz )*k.xx +k.yy );} + AH3 AToSrgbH3(AH3 c){AH3 j=AH3(0.0031308*12.92,12.92,1.0/2.4);AH2 k=AH2(1.055,-0.055); + return clamp(j.xxx,c*j.yyy,pow(c,j.zzz)*k.xxx+k.yyy);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AToTwoH1(AH1 c){return sqrt(c);} + AH2 AToTwoH2(AH2 c){return sqrt(c);} + AH3 AToTwoH3(AH3 c){return sqrt(c);} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AToThreeF1(AH1 c){return pow(c,AH1_(1.0/3.0));} + AH2 AToThreeF2(AH2 c){return pow(c,AH2_(1.0/3.0));} + AH3 AToThreeF3(AH3 c){return pow(c,AH3_(1.0/3.0));} + #endif +//============================================================================================================================== + #ifdef A_HALF + AH1 AFrom709H1(AH1 c){AH3 j=AH3(0.081/4.5,1.0/4.5,1.0/0.45);AH2 k=AH2(1.0/1.099,0.099/1.099); + return AZolSelH1(AZolSignedH1(c-j.x ),c*j.y ,pow(c*k.x +k.y ,j.z ));} + AH2 AFrom709H2(AH2 c){AH3 j=AH3(0.081/4.5,1.0/4.5,1.0/0.45);AH2 k=AH2(1.0/1.099,0.099/1.099); + return AZolSelH2(AZolSignedH2(c-j.xx ),c*j.yy ,pow(c*k.xx +k.yy ,j.zz ));} + AH3 AFrom709H3(AH3 c){AH3 j=AH3(0.081/4.5,1.0/4.5,1.0/0.45);AH2 k=AH2(1.0/1.099,0.099/1.099); + return AZolSelH3(AZolSignedH3(c-j.xxx),c*j.yyy,pow(c*k.xxx+k.yyy,j.zzz));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AFromGammaH1(AH1 c,AH1 x){return pow(c,AH1_(x));} + AH2 AFromGammaH2(AH2 c,AH1 x){return pow(c,AH2_(x));} + AH3 AFromGammaH3(AH3 c,AH1 x){return pow(c,AH3_(x));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AHromSrgbF1(AH1 c){AH3 j=AH3(0.04045/12.92,1.0/12.92,2.4);AH2 k=AH2(1.0/1.055,0.055/1.055); + return AZolSelH1(AZolSignedH1(c-j.x ),c*j.y ,pow(c*k.x +k.y ,j.z ));} + AH2 AHromSrgbF2(AH2 c){AH3 j=AH3(0.04045/12.92,1.0/12.92,2.4);AH2 k=AH2(1.0/1.055,0.055/1.055); + return AZolSelH2(AZolSignedH2(c-j.xx ),c*j.yy ,pow(c*k.xx +k.yy ,j.zz ));} + AH3 AHromSrgbF3(AH3 c){AH3 j=AH3(0.04045/12.92,1.0/12.92,2.4);AH2 k=AH2(1.0/1.055,0.055/1.055); + return AZolSelH3(AZolSignedH3(c-j.xxx),c*j.yyy,pow(c*k.xxx+k.yyy,j.zzz));} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AFromTwoH1(AH1 c){return c*c;} + AH2 AFromTwoH2(AH2 c){return c*c;} + AH3 AFromTwoH3(AH3 c){return c*c;} +//------------------------------------------------------------------------------------------------------------------------------ + AH1 AFromThreeH1(AH1 c){return c*c*c;} + AH2 AFromThreeH2(AH2 c){return c*c*c;} + AH3 AFromThreeH3(AH3 c){return c*c*c;} + #endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// CS REMAP +//============================================================================================================================== + // Simple remap 64x1 to 8x8 with rotated 2x2 pixel quads in quad linear. + // 543210 + // ====== + // ..xxx. + // yy...y + AU2 ARmp8x8(AU1 a){return AU2(ABfe(a,1u,3u),ABfiM(ABfe(a,3u,3u),a,1u));} +//============================================================================================================================== + // More complex remap 64x1 to 8x8 which is necessary for 2D wave reductions. + // 543210 + // ====== + // .xx..x + // y..yy. + // Details, + // LANE TO 8x8 MAPPING + // =================== + // 00 01 08 09 10 11 18 19 + // 02 03 0a 0b 12 13 1a 1b + // 04 05 0c 0d 14 15 1c 1d + // 06 07 0e 0f 16 17 1e 1f + // 20 21 28 29 30 31 38 39 + // 22 23 2a 2b 32 33 3a 3b + // 24 25 2c 2d 34 35 3c 3d + // 26 27 2e 2f 36 37 3e 3f + AU2 ARmpRed8x8(AU1 a){return AU2(ABfiM(ABfe(a,2u,3u),a,1u),ABfiM(ABfe(a,3u,3u),ABfe(a,1u,2u),2u));} +//============================================================================================================================== + #ifdef A_HALF + AW2 ARmp8x8H(AU1 a){return AW2(ABfe(a,1u,3u),ABfiM(ABfe(a,3u,3u),a,1u));} + AW2 ARmpRed8x8H(AU1 a){return AW2(ABfiM(ABfe(a,2u,3u),a,1u),ABfiM(ABfe(a,3u,3u),ABfe(a,1u,2u),2u));} + #endif +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// REFERENCE +// +//------------------------------------------------------------------------------------------------------------------------------ +// IEEE FLOAT RULES +// ================ +// - saturate(NaN)=0, saturate(-INF)=0, saturate(+INF)=1 +// - {+/-}0 * {+/-}INF = NaN +// - -INF + (+INF) = NaN +// - {+/-}0 / {+/-}0 = NaN +// - {+/-}INF / {+/-}INF = NaN +// - a<(-0) := sqrt(a) = NaN (a=-0.0 won't NaN) +// - 0 == -0 +// - 4/0 = +INF +// - 4/-0 = -INF +// - 4+INF = +INF +// - 4-INF = -INF +// - 4*(+INF) = +INF +// - 4*(-INF) = -INF +// - -4*(+INF) = -INF +// - sqrt(+INF) = +INF +//------------------------------------------------------------------------------------------------------------------------------ +// FP16 ENCODING +// ============= +// fedcba9876543210 +// ---------------- +// ......mmmmmmmmmm 10-bit mantissa (encodes 11-bit 0.5 to 1.0 except for denormals) +// .eeeee.......... 5-bit exponent +// .00000.......... denormals +// .00001.......... -14 exponent +// .11110.......... 15 exponent +// .111110000000000 infinity +// .11111nnnnnnnnnn NaN with n!=0 +// s............... sign +//------------------------------------------------------------------------------------------------------------------------------ +// FP16/INT16 ALIASING DENORMAL +// ============================ +// 11-bit unsigned integers alias with half float denormal/normal values, +// 1 = 2^(-24) = 1/16777216 ....................... first denormal value +// 2 = 2^(-23) +// ... +// 1023 = 2^(-14)*(1-2^(-10)) = 2^(-14)*(1-1/1024) ... last denormal value +// 1024 = 2^(-14) = 1/16384 .......................... first normal value that still maps to integers +// 2047 .............................................. last normal value that still maps to integers +// Scaling limits, +// 2^15 = 32768 ...................................... largest power of 2 scaling +// Largest pow2 conversion mapping is at *32768, +// 1 : 2^(-9) = 1/512 +// 2 : 1/256 +// 4 : 1/128 +// 8 : 1/64 +// 16 : 1/32 +// 32 : 1/16 +// 64 : 1/8 +// 128 : 1/4 +// 256 : 1/2 +// 512 : 1 +// 1024 : 2 +// 2047 : a little less than 4 +//============================================================================================================================== +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// +// GPU/CPU PORTABILITY +// +// +//------------------------------------------------------------------------------------------------------------------------------ +// This is the GPU implementation. +// See the CPU implementation for docs. +//============================================================================================================================== +#ifdef A_GPU + #define A_TRUE true + #define A_FALSE false + #define A_STATIC +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// VECTOR ARGUMENT/RETURN/INITIALIZATION PORTABILITY +//============================================================================================================================== + #define retAD2 AD2 + #define retAD3 AD3 + #define retAD4 AD4 + #define retAF2 AF2 + #define retAF3 AF3 + #define retAF4 AF4 + #define retAL2 AL2 + #define retAL3 AL3 + #define retAL4 AL4 + #define retAU2 AU2 + #define retAU3 AU3 + #define retAU4 AU4 +//------------------------------------------------------------------------------------------------------------------------------ + #define inAD2 in AD2 + #define inAD3 in AD3 + #define inAD4 in AD4 + #define inAF2 in AF2 + #define inAF3 in AF3 + #define inAF4 in AF4 + #define inAL2 in AL2 + #define inAL3 in AL3 + #define inAL4 in AL4 + #define inAU2 in AU2 + #define inAU3 in AU3 + #define inAU4 in AU4 +//------------------------------------------------------------------------------------------------------------------------------ + #define inoutAD2 inout AD2 + #define inoutAD3 inout AD3 + #define inoutAD4 inout AD4 + #define inoutAF2 inout AF2 + #define inoutAF3 inout AF3 + #define inoutAF4 inout AF4 + #define inoutAL2 inout AL2 + #define inoutAL3 inout AL3 + #define inoutAL4 inout AL4 + #define inoutAU2 inout AU2 + #define inoutAU3 inout AU3 + #define inoutAU4 inout AU4 +//------------------------------------------------------------------------------------------------------------------------------ + #define outAD2 out AD2 + #define outAD3 out AD3 + #define outAD4 out AD4 + #define outAF2 out AF2 + #define outAF3 out AF3 + #define outAF4 out AF4 + #define outAL2 out AL2 + #define outAL3 out AL3 + #define outAL4 out AL4 + #define outAU2 out AU2 + #define outAU3 out AU3 + #define outAU4 out AU4 +//------------------------------------------------------------------------------------------------------------------------------ + #define varAD2(x) AD2 x + #define varAD3(x) AD3 x + #define varAD4(x) AD4 x + #define varAF2(x) AF2 x + #define varAF3(x) AF3 x + #define varAF4(x) AF4 x + #define varAL2(x) AL2 x + #define varAL3(x) AL3 x + #define varAL4(x) AL4 x + #define varAU2(x) AU2 x + #define varAU3(x) AU3 x + #define varAU4(x) AU4 x +//------------------------------------------------------------------------------------------------------------------------------ + #define initAD2(x,y) AD2(x,y) + #define initAD3(x,y,z) AD3(x,y,z) + #define initAD4(x,y,z,w) AD4(x,y,z,w) + #define initAF2(x,y) AF2(x,y) + #define initAF3(x,y,z) AF3(x,y,z) + #define initAF4(x,y,z,w) AF4(x,y,z,w) + #define initAL2(x,y) AL2(x,y) + #define initAL3(x,y,z) AL3(x,y,z) + #define initAL4(x,y,z,w) AL4(x,y,z,w) + #define initAU2(x,y) AU2(x,y) + #define initAU3(x,y,z) AU3(x,y,z) + #define initAU4(x,y,z,w) AU4(x,y,z,w) +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// SCALAR RETURN OPS +//============================================================================================================================== + #define AAbsD1(a) abs(AD1(a)) + #define AAbsF1(a) abs(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define ACosD1(a) cos(AD1(a)) + #define ACosF1(a) cos(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define ADotD2(a,b) dot(AD2(a),AD2(b)) + #define ADotD3(a,b) dot(AD3(a),AD3(b)) + #define ADotD4(a,b) dot(AD4(a),AD4(b)) + #define ADotF2(a,b) dot(AF2(a),AF2(b)) + #define ADotF3(a,b) dot(AF3(a),AF3(b)) + #define ADotF4(a,b) dot(AF4(a),AF4(b)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AExp2D1(a) exp2(AD1(a)) + #define AExp2F1(a) exp2(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AFloorD1(a) floor(AD1(a)) + #define AFloorF1(a) floor(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define ALog2D1(a) log2(AD1(a)) + #define ALog2F1(a) log2(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define AMaxD1(a,b) max(a,b) + #define AMaxF1(a,b) max(a,b) + #define AMaxL1(a,b) max(a,b) + #define AMaxU1(a,b) max(a,b) +//------------------------------------------------------------------------------------------------------------------------------ + #define AMinD1(a,b) min(a,b) + #define AMinF1(a,b) min(a,b) + #define AMinL1(a,b) min(a,b) + #define AMinU1(a,b) min(a,b) +//------------------------------------------------------------------------------------------------------------------------------ + #define ASinD1(a) sin(AD1(a)) + #define ASinF1(a) sin(AF1(a)) +//------------------------------------------------------------------------------------------------------------------------------ + #define ASqrtD1(a) sqrt(AD1(a)) + #define ASqrtF1(a) sqrt(AF1(a)) +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// SCALAR RETURN OPS - DEPENDENT +//============================================================================================================================== + #define APowD1(a,b) pow(AD1(a),AF1(b)) + #define APowF1(a,b) pow(AF1(a),AF1(b)) +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// VECTOR OPS +//------------------------------------------------------------------------------------------------------------------------------ +// These are added as needed for production or prototyping, so not necessarily a complete set. +// They follow a convention of taking in a destination and also returning the destination value to increase utility. +//============================================================================================================================== + #ifdef A_DUBL + AD2 opAAbsD2(outAD2 d,inAD2 a){d=abs(a);return d;} + AD3 opAAbsD3(outAD3 d,inAD3 a){d=abs(a);return d;} + AD4 opAAbsD4(outAD4 d,inAD4 a){d=abs(a);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opAAddD2(outAD2 d,inAD2 a,inAD2 b){d=a+b;return d;} + AD3 opAAddD3(outAD3 d,inAD3 a,inAD3 b){d=a+b;return d;} + AD4 opAAddD4(outAD4 d,inAD4 a,inAD4 b){d=a+b;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opAAddOneD2(outAD2 d,inAD2 a,AD1 b){d=a+AD2_(b);return d;} + AD3 opAAddOneD3(outAD3 d,inAD3 a,AD1 b){d=a+AD3_(b);return d;} + AD4 opAAddOneD4(outAD4 d,inAD4 a,AD1 b){d=a+AD4_(b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opACpyD2(outAD2 d,inAD2 a){d=a;return d;} + AD3 opACpyD3(outAD3 d,inAD3 a){d=a;return d;} + AD4 opACpyD4(outAD4 d,inAD4 a){d=a;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opALerpD2(outAD2 d,inAD2 a,inAD2 b,inAD2 c){d=ALerpD2(a,b,c);return d;} + AD3 opALerpD3(outAD3 d,inAD3 a,inAD3 b,inAD3 c){d=ALerpD3(a,b,c);return d;} + AD4 opALerpD4(outAD4 d,inAD4 a,inAD4 b,inAD4 c){d=ALerpD4(a,b,c);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opALerpOneD2(outAD2 d,inAD2 a,inAD2 b,AD1 c){d=ALerpD2(a,b,AD2_(c));return d;} + AD3 opALerpOneD3(outAD3 d,inAD3 a,inAD3 b,AD1 c){d=ALerpD3(a,b,AD3_(c));return d;} + AD4 opALerpOneD4(outAD4 d,inAD4 a,inAD4 b,AD1 c){d=ALerpD4(a,b,AD4_(c));return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opAMaxD2(outAD2 d,inAD2 a,inAD2 b){d=max(a,b);return d;} + AD3 opAMaxD3(outAD3 d,inAD3 a,inAD3 b){d=max(a,b);return d;} + AD4 opAMaxD4(outAD4 d,inAD4 a,inAD4 b){d=max(a,b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opAMinD2(outAD2 d,inAD2 a,inAD2 b){d=min(a,b);return d;} + AD3 opAMinD3(outAD3 d,inAD3 a,inAD3 b){d=min(a,b);return d;} + AD4 opAMinD4(outAD4 d,inAD4 a,inAD4 b){d=min(a,b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opAMulD2(outAD2 d,inAD2 a,inAD2 b){d=a*b;return d;} + AD3 opAMulD3(outAD3 d,inAD3 a,inAD3 b){d=a*b;return d;} + AD4 opAMulD4(outAD4 d,inAD4 a,inAD4 b){d=a*b;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opAMulOneD2(outAD2 d,inAD2 a,AD1 b){d=a*AD2_(b);return d;} + AD3 opAMulOneD3(outAD3 d,inAD3 a,AD1 b){d=a*AD3_(b);return d;} + AD4 opAMulOneD4(outAD4 d,inAD4 a,AD1 b){d=a*AD4_(b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opANegD2(outAD2 d,inAD2 a){d=-a;return d;} + AD3 opANegD3(outAD3 d,inAD3 a){d=-a;return d;} + AD4 opANegD4(outAD4 d,inAD4 a){d=-a;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AD2 opARcpD2(outAD2 d,inAD2 a){d=ARcpD2(a);return d;} + AD3 opARcpD3(outAD3 d,inAD3 a){d=ARcpD3(a);return d;} + AD4 opARcpD4(outAD4 d,inAD4 a){d=ARcpD4(a);return d;} + #endif +//============================================================================================================================== + AF2 opAAbsF2(outAF2 d,inAF2 a){d=abs(a);return d;} + AF3 opAAbsF3(outAF3 d,inAF3 a){d=abs(a);return d;} + AF4 opAAbsF4(outAF4 d,inAF4 a){d=abs(a);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opAAddF2(outAF2 d,inAF2 a,inAF2 b){d=a+b;return d;} + AF3 opAAddF3(outAF3 d,inAF3 a,inAF3 b){d=a+b;return d;} + AF4 opAAddF4(outAF4 d,inAF4 a,inAF4 b){d=a+b;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opAAddOneF2(outAF2 d,inAF2 a,AF1 b){d=a+AF2_(b);return d;} + AF3 opAAddOneF3(outAF3 d,inAF3 a,AF1 b){d=a+AF3_(b);return d;} + AF4 opAAddOneF4(outAF4 d,inAF4 a,AF1 b){d=a+AF4_(b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opACpyF2(outAF2 d,inAF2 a){d=a;return d;} + AF3 opACpyF3(outAF3 d,inAF3 a){d=a;return d;} + AF4 opACpyF4(outAF4 d,inAF4 a){d=a;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opALerpF2(outAF2 d,inAF2 a,inAF2 b,inAF2 c){d=ALerpF2(a,b,c);return d;} + AF3 opALerpF3(outAF3 d,inAF3 a,inAF3 b,inAF3 c){d=ALerpF3(a,b,c);return d;} + AF4 opALerpF4(outAF4 d,inAF4 a,inAF4 b,inAF4 c){d=ALerpF4(a,b,c);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opALerpOneF2(outAF2 d,inAF2 a,inAF2 b,AF1 c){d=ALerpF2(a,b,AF2_(c));return d;} + AF3 opALerpOneF3(outAF3 d,inAF3 a,inAF3 b,AF1 c){d=ALerpF3(a,b,AF3_(c));return d;} + AF4 opALerpOneF4(outAF4 d,inAF4 a,inAF4 b,AF1 c){d=ALerpF4(a,b,AF4_(c));return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opAMaxF2(outAF2 d,inAF2 a,inAF2 b){d=max(a,b);return d;} + AF3 opAMaxF3(outAF3 d,inAF3 a,inAF3 b){d=max(a,b);return d;} + AF4 opAMaxF4(outAF4 d,inAF4 a,inAF4 b){d=max(a,b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opAMinF2(outAF2 d,inAF2 a,inAF2 b){d=min(a,b);return d;} + AF3 opAMinF3(outAF3 d,inAF3 a,inAF3 b){d=min(a,b);return d;} + AF4 opAMinF4(outAF4 d,inAF4 a,inAF4 b){d=min(a,b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opAMulF2(outAF2 d,inAF2 a,inAF2 b){d=a*b;return d;} + AF3 opAMulF3(outAF3 d,inAF3 a,inAF3 b){d=a*b;return d;} + AF4 opAMulF4(outAF4 d,inAF4 a,inAF4 b){d=a*b;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opAMulOneF2(outAF2 d,inAF2 a,AF1 b){d=a*AF2_(b);return d;} + AF3 opAMulOneF3(outAF3 d,inAF3 a,AF1 b){d=a*AF3_(b);return d;} + AF4 opAMulOneF4(outAF4 d,inAF4 a,AF1 b){d=a*AF4_(b);return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opANegF2(outAF2 d,inAF2 a){d=-a;return d;} + AF3 opANegF3(outAF3 d,inAF3 a){d=-a;return d;} + AF4 opANegF4(outAF4 d,inAF4 a){d=-a;return d;} +//------------------------------------------------------------------------------------------------------------------------------ + AF2 opARcpF2(outAF2 d,inAF2 a){d=ARcpF2(a);return d;} + AF3 opARcpF3(outAF3 d,inAF3 a){d=ARcpF3(a);return d;} + AF4 opARcpF4(outAF4 d,inAF4 a){d=ARcpF4(a);return d;} +#endif diff --git a/app/shaders/enhancer/AMD/ffx_fsr1.h b/app/shaders/enhancer/AMD/ffx_fsr1.h new file mode 100644 index 000000000..4e0b3d548 --- /dev/null +++ b/app/shaders/enhancer/AMD/ffx_fsr1.h @@ -0,0 +1,1199 @@ +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// +// AMD FidelityFX SUPER RESOLUTION [FSR 1] ::: SPATIAL SCALING & EXTRAS - v1.20210629 +// +// +//------------------------------------------------------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//------------------------------------------------------------------------------------------------------------------------------ +// FidelityFX Super Resolution Sample +// +// Copyright (c) 2021 Advanced Micro Devices, Inc. All rights reserved. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files(the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions : +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +//------------------------------------------------------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//------------------------------------------------------------------------------------------------------------------------------ +// ABOUT +// ===== +// FSR is a collection of algorithms relating to generating a higher resolution image. +// This specific header focuses on single-image non-temporal image scaling, and related tools. +// +// The core functions are EASU and RCAS: +// [EASU] Edge Adaptive Spatial Upsampling ....... 1x to 4x area range spatial scaling, clamped adaptive elliptical filter. +// [RCAS] Robust Contrast Adaptive Sharpening .... A non-scaling variation on CAS. +// RCAS needs to be applied after EASU as a separate pass. +// +// Optional utility functions are: +// [LFGA] Linear Film Grain Applicator ........... Tool to apply film grain after scaling. +// [SRTM] Simple Reversible Tone-Mapper .......... Linear HDR {0 to FP16_MAX} to {0 to 1} and back. +// [TEPD] Temporal Energy Preserving Dither ...... Temporally energy preserving dithered {0 to 1} linear to gamma 2.0 conversion. +// See each individual sub-section for inline documentation. +//------------------------------------------------------------------------------------------------------------------------------ +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//------------------------------------------------------------------------------------------------------------------------------ +// FUNCTION PERMUTATIONS +// ===================== +// *F() ..... Single item computation with 32-bit. +// *H() ..... Single item computation with 16-bit, with packing (aka two 16-bit ops in parallel) when possible. +// *Hx2() ... Processing two items in parallel with 16-bit, easier packing. +// Not all interfaces in this file have a *Hx2() form. +//============================================================================================================================== +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// FSR - [EASU] EDGE ADAPTIVE SPATIAL UPSAMPLING +// +//------------------------------------------------------------------------------------------------------------------------------ +// EASU provides a high quality spatial-only scaling at relatively low cost. +// Meaning EASU is appropiate for laptops and other low-end GPUs. +// Quality from 1x to 4x area scaling is good. +//------------------------------------------------------------------------------------------------------------------------------ +// The scalar uses a modified fast approximation to the standard lanczos(size=2) kernel. +// EASU runs in a single pass, so it applies a directionally and anisotropically adaptive radial lanczos. +// This is also kept as simple as possible to have minimum runtime. +//------------------------------------------------------------------------------------------------------------------------------ +// The lanzcos filter has negative lobes, so by itself it will introduce ringing. +// To remove all ringing, the algorithm uses the nearest 2x2 input texels as a neighborhood, +// and limits output to the minimum and maximum of that neighborhood. +//------------------------------------------------------------------------------------------------------------------------------ +// Input image requirements: +// +// Color needs to be encoded as 3 channel[red, green, blue](e.g.XYZ not supported) +// Each channel needs to be in the range[0, 1] +// Any color primaries are supported +// Display / tonemapping curve needs to be as if presenting to sRGB display or similar(e.g.Gamma 2.0) +// There should be no banding in the input +// There should be no high amplitude noise in the input +// There should be no noise in the input that is not at input pixel granularity +// For performance purposes, use 32bpp formats +//------------------------------------------------------------------------------------------------------------------------------ +// Best to apply EASU at the end of the frame after tonemapping +// but before film grain or composite of the UI. +//------------------------------------------------------------------------------------------------------------------------------ +// Example of including this header for D3D HLSL : +// +// #define A_GPU 1 +// #define A_HLSL 1 +// #define A_HALF 1 +// #include "ffx_a.h" +// #define FSR_EASU_H 1 +// #define FSR_RCAS_H 1 +// //declare input callbacks +// #include "ffx_fsr1.h" +// +// Example of including this header for Vulkan GLSL : +// +// #define A_GPU 1 +// #define A_GLSL 1 +// #define A_HALF 1 +// #include "ffx_a.h" +// #define FSR_EASU_H 1 +// #define FSR_RCAS_H 1 +// //declare input callbacks +// #include "ffx_fsr1.h" +// +// Example of including this header for Vulkan HLSL : +// +// #define A_GPU 1 +// #define A_HLSL 1 +// #define A_HLSL_6_2 1 +// #define A_NO_16_BIT_CAST 1 +// #define A_HALF 1 +// #include "ffx_a.h" +// #define FSR_EASU_H 1 +// #define FSR_RCAS_H 1 +// //declare input callbacks +// #include "ffx_fsr1.h" +// +// Example of declaring the required input callbacks for GLSL : +// The callbacks need to gather4 for each color channel using the specified texture coordinate 'p'. +// EASU uses gather4 to reduce position computation logic and for free Arrays of Structures to Structures of Arrays conversion. +// +// AH4 FsrEasuRH(AF2 p){return AH4(textureGather(sampler2D(tex,sam),p,0));} +// AH4 FsrEasuGH(AF2 p){return AH4(textureGather(sampler2D(tex,sam),p,1));} +// AH4 FsrEasuBH(AF2 p){return AH4(textureGather(sampler2D(tex,sam),p,2));} +// ... +// The FsrEasuCon function needs to be called from the CPU or GPU to set up constants. +// The difference in viewport and input image size is there to support Dynamic Resolution Scaling. +// To use FsrEasuCon() on the CPU, define A_CPU before including ffx_a and ffx_fsr1. +// Including a GPU example here, the 'con0' through 'con3' values would be stored out to a constant buffer. +// AU4 con0,con1,con2,con3; +// FsrEasuCon(con0,con1,con2,con3, +// 1920.0,1080.0, // Viewport size (top left aligned) in the input image which is to be scaled. +// 3840.0,2160.0, // The size of the input image. +// 2560.0,1440.0); // The output resolution. +//============================================================================================================================== +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// CONSTANT SETUP +//============================================================================================================================== +// Call to setup required constant values (works on CPU or GPU). +A_STATIC void FsrEasuCon( +outAU4 con0, +outAU4 con1, +outAU4 con2, +outAU4 con3, +// This the rendered image resolution being upscaled +AF1 inputViewportInPixelsX, +AF1 inputViewportInPixelsY, +// This is the resolution of the resource containing the input image (useful for dynamic resolution) +AF1 inputSizeInPixelsX, +AF1 inputSizeInPixelsY, +// This is the display resolution which the input image gets upscaled to +AF1 outputSizeInPixelsX, +AF1 outputSizeInPixelsY){ + // Output integer position to a pixel position in viewport. + con0[0]=AU1_AF1(inputViewportInPixelsX*ARcpF1(outputSizeInPixelsX)); + con0[1]=AU1_AF1(inputViewportInPixelsY*ARcpF1(outputSizeInPixelsY)); + con0[2]=AU1_AF1(AF1_(0.5)*inputViewportInPixelsX*ARcpF1(outputSizeInPixelsX)-AF1_(0.5)); + con0[3]=AU1_AF1(AF1_(0.5)*inputViewportInPixelsY*ARcpF1(outputSizeInPixelsY)-AF1_(0.5)); + // Viewport pixel position to normalized image space. + // This is used to get upper-left of 'F' tap. + con1[0]=AU1_AF1(ARcpF1(inputSizeInPixelsX)); + con1[1]=AU1_AF1(ARcpF1(inputSizeInPixelsY)); + // Centers of gather4, first offset from upper-left of 'F'. + // +---+---+ + // | | | + // +--(0)--+ + // | b | c | + // +---F---+---+---+ + // | e | f | g | h | + // +--(1)--+--(2)--+ + // | i | j | k | l | + // +---+---+---+---+ + // | n | o | + // +--(3)--+ + // | | | + // +---+---+ + con1[2]=AU1_AF1(AF1_( 1.0)*ARcpF1(inputSizeInPixelsX)); + con1[3]=AU1_AF1(AF1_(-1.0)*ARcpF1(inputSizeInPixelsY)); + // These are from (0) instead of 'F'. + con2[0]=AU1_AF1(AF1_(-1.0)*ARcpF1(inputSizeInPixelsX)); + con2[1]=AU1_AF1(AF1_( 2.0)*ARcpF1(inputSizeInPixelsY)); + con2[2]=AU1_AF1(AF1_( 1.0)*ARcpF1(inputSizeInPixelsX)); + con2[3]=AU1_AF1(AF1_( 2.0)*ARcpF1(inputSizeInPixelsY)); + con3[0]=AU1_AF1(AF1_( 0.0)*ARcpF1(inputSizeInPixelsX)); + con3[1]=AU1_AF1(AF1_( 4.0)*ARcpF1(inputSizeInPixelsY)); + con3[2]=con3[3]=0;} + +//If the an offset into the input image resource +A_STATIC void FsrEasuConOffset( + outAU4 con0, + outAU4 con1, + outAU4 con2, + outAU4 con3, + // This the rendered image resolution being upscaled + AF1 inputViewportInPixelsX, + AF1 inputViewportInPixelsY, + // This is the resolution of the resource containing the input image (useful for dynamic resolution) + AF1 inputSizeInPixelsX, + AF1 inputSizeInPixelsY, + // This is the display resolution which the input image gets upscaled to + AF1 outputSizeInPixelsX, + AF1 outputSizeInPixelsY, + // This is the input image offset into the resource containing it (useful for dynamic resolution) + AF1 inputOffsetInPixelsX, + AF1 inputOffsetInPixelsY) { + FsrEasuCon(con0, con1, con2, con3, inputViewportInPixelsX, inputViewportInPixelsY, inputSizeInPixelsX, inputSizeInPixelsY, outputSizeInPixelsX, outputSizeInPixelsY); + con0[2] = AU1_AF1(AF1_(0.5) * inputViewportInPixelsX * ARcpF1(outputSizeInPixelsX) - AF1_(0.5) + inputOffsetInPixelsX); + con0[3] = AU1_AF1(AF1_(0.5) * inputViewportInPixelsY * ARcpF1(outputSizeInPixelsY) - AF1_(0.5) + inputOffsetInPixelsY); +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// NON-PACKED 32-BIT VERSION +//============================================================================================================================== +#if defined(A_GPU)&&defined(FSR_EASU_F) + // Input callback prototypes, need to be implemented by calling shader + AF4 FsrEasuRF(AF2 p); + AF4 FsrEasuGF(AF2 p); + AF4 FsrEasuBF(AF2 p); +//------------------------------------------------------------------------------------------------------------------------------ + // Filtering for a given tap for the scalar. + void FsrEasuTapF( + inout AF3 aC, // Accumulated color, with negative lobe. + inout AF1 aW, // Accumulated weight. + AF2 off, // Pixel offset from resolve position to tap. + AF2 dir, // Gradient direction. + AF2 len, // Length. + AF1 lob, // Negative lobe strength. + AF1 clp, // Clipping point. + AF3 c){ // Tap color. + // Rotate offset by direction. + AF2 v; + v.x=(off.x*( dir.x))+(off.y*dir.y); + v.y=(off.x*(-dir.y))+(off.y*dir.x); + // Anisotropy. + v*=len; + // Compute distance^2. + AF1 d2=v.x*v.x+v.y*v.y; + // Limit to the window as at corner, 2 taps can easily be outside. + d2=min(d2,clp); + // Approximation of lancos2 without sin() or rcp(), or sqrt() to get x. + // (25/16 * (2/5 * x^2 - 1)^2 - (25/16 - 1)) * (1/4 * x^2 - 1)^2 + // |_______________________________________| |_______________| + // base window + // The general form of the 'base' is, + // (a*(b*x^2-1)^2-(a-1)) + // Where 'a=1/(2*b-b^2)' and 'b' moves around the negative lobe. + AF1 wB=AF1_(2.0/5.0)*d2+AF1_(-1.0); + AF1 wA=lob*d2+AF1_(-1.0); + wB*=wB; + wA*=wA; + wB=AF1_(25.0/16.0)*wB+AF1_(-(25.0/16.0-1.0)); + AF1 w=wB*wA; + // Do weighted average. + aC+=c*w;aW+=w;} +//------------------------------------------------------------------------------------------------------------------------------ + // Accumulate direction and length. + void FsrEasuSetF( + inout AF2 dir, + inout AF1 len, + AF2 pp, + AP1 biS,AP1 biT,AP1 biU,AP1 biV, + AF1 lA,AF1 lB,AF1 lC,AF1 lD,AF1 lE){ + // Compute bilinear weight, branches factor out as predicates are compiler time immediates. + // s t + // u v + AF1 w = AF1_(0.0); + if(biS)w=(AF1_(1.0)-pp.x)*(AF1_(1.0)-pp.y); + if(biT)w= pp.x *(AF1_(1.0)-pp.y); + if(biU)w=(AF1_(1.0)-pp.x)* pp.y ; + if(biV)w= pp.x * pp.y ; + // Direction is the '+' diff. + // a + // b c d + // e + // Then takes magnitude from abs average of both sides of 'c'. + // Length converts gradient reversal to 0, smoothly to non-reversal at 1, shaped, then adding horz and vert terms. + AF1 dc=lD-lC; + AF1 cb=lC-lB; + AF1 lenX=max(abs(dc),abs(cb)); + lenX=APrxLoRcpF1(lenX); + AF1 dirX=lD-lB; + dir.x+=dirX*w; + lenX=ASatF1(abs(dirX)*lenX); + lenX*=lenX; + len+=lenX*w; + // Repeat for the y axis. + AF1 ec=lE-lC; + AF1 ca=lC-lA; + AF1 lenY=max(abs(ec),abs(ca)); + lenY=APrxLoRcpF1(lenY); + AF1 dirY=lE-lA; + dir.y+=dirY*w; + lenY=ASatF1(abs(dirY)*lenY); + lenY*=lenY; + len+=lenY*w;} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrEasuF( + out AF3 pix, + AU2 ip, // Integer pixel position in output. + AU4 con0, // Constants generated by FsrEasuCon(). + AU4 con1, + AU4 con2, + AU4 con3){ +//------------------------------------------------------------------------------------------------------------------------------ + // Get position of 'f'. + AF2 pp=AF2(ip)*AF2_AU2(con0.xy)+AF2_AU2(con0.zw); + AF2 fp=floor(pp); + pp-=fp; +//------------------------------------------------------------------------------------------------------------------------------ + // 12-tap kernel. + // b c + // e f g h + // i j k l + // n o + // Gather 4 ordering. + // a b + // r g + // For packed FP16, need either {rg} or {ab} so using the following setup for gather in all versions, + // a b <- unused (z) + // r g + // a b a b + // r g r g + // a b + // r g <- unused (z) + // Allowing dead-code removal to remove the 'z's. + AF2 p0=fp*AF2_AU2(con1.xy)+AF2_AU2(con1.zw); + // These are from p0 to avoid pulling two constants on pre-Navi hardware. + AF2 p1=p0+AF2_AU2(con2.xy); + AF2 p2=p0+AF2_AU2(con2.zw); + AF2 p3=p0+AF2_AU2(con3.xy); + AF4 bczzR=FsrEasuRF(p0); + AF4 bczzG=FsrEasuGF(p0); + AF4 bczzB=FsrEasuBF(p0); + AF4 ijfeR=FsrEasuRF(p1); + AF4 ijfeG=FsrEasuGF(p1); + AF4 ijfeB=FsrEasuBF(p1); + AF4 klhgR=FsrEasuRF(p2); + AF4 klhgG=FsrEasuGF(p2); + AF4 klhgB=FsrEasuBF(p2); + AF4 zzonR=FsrEasuRF(p3); + AF4 zzonG=FsrEasuGF(p3); + AF4 zzonB=FsrEasuBF(p3); +//------------------------------------------------------------------------------------------------------------------------------ + // Simplest multi-channel approximate luma possible (luma times 2, in 2 FMA/MAD). + AF4 bczzL=bczzB*AF4_(0.5)+(bczzR*AF4_(0.5)+bczzG); + AF4 ijfeL=ijfeB*AF4_(0.5)+(ijfeR*AF4_(0.5)+ijfeG); + AF4 klhgL=klhgB*AF4_(0.5)+(klhgR*AF4_(0.5)+klhgG); + AF4 zzonL=zzonB*AF4_(0.5)+(zzonR*AF4_(0.5)+zzonG); + // Rename. + AF1 bL=bczzL.x; + AF1 cL=bczzL.y; + AF1 iL=ijfeL.x; + AF1 jL=ijfeL.y; + AF1 fL=ijfeL.z; + AF1 eL=ijfeL.w; + AF1 kL=klhgL.x; + AF1 lL=klhgL.y; + AF1 hL=klhgL.z; + AF1 gL=klhgL.w; + AF1 oL=zzonL.z; + AF1 nL=zzonL.w; + // Accumulate for bilinear interpolation. + AF2 dir=AF2_(0.0); + AF1 len=AF1_(0.0); + FsrEasuSetF(dir,len,pp,true, false,false,false,bL,eL,fL,gL,jL); + FsrEasuSetF(dir,len,pp,false,true ,false,false,cL,fL,gL,hL,kL); + FsrEasuSetF(dir,len,pp,false,false,true ,false,fL,iL,jL,kL,nL); + FsrEasuSetF(dir,len,pp,false,false,false,true ,gL,jL,kL,lL,oL); +//------------------------------------------------------------------------------------------------------------------------------ + // Normalize with approximation, and cleanup close to zero. + AF2 dir2=dir*dir; + AF1 dirR=dir2.x+dir2.y; + AP1 zro=dirR w = -m/(n+e+w+s) +// 1 == (w*(n+e+w+s)+m)/(4*w+1) -> w = (1-m)/(n+e+w+s-4*1) +// Then chooses the 'w' which results in no clipping, limits 'w', and multiplies by the 'sharp' amount. +// This solution above has issues with MSAA input as the steps along the gradient cause edge detection issues. +// So RCAS uses 4x the maximum and 4x the minimum (depending on equation)in place of the individual taps. +// As well as switching from 'm' to either the minimum or maximum (depending on side), to help in energy conservation. +// This stabilizes RCAS. +// RCAS does a simple highpass which is normalized against the local contrast then shaped, +// 0.25 +// 0.25 -1 0.25 +// 0.25 +// This is used as a noise detection filter, to reduce the effect of RCAS on grain, and focus on real edges. +// +// GLSL example for the required callbacks : +// +// AH4 FsrRcasLoadH(ASW2 p){return AH4(imageLoad(imgSrc,ASU2(p)));} +// void FsrRcasInputH(inout AH1 r,inout AH1 g,inout AH1 b) +// { +// //do any simple input color conversions here or leave empty if none needed +// } +// +// FsrRcasCon need to be called from the CPU or GPU to set up constants. +// Including a GPU example here, the 'con' value would be stored out to a constant buffer. +// +// AU4 con; +// FsrRcasCon(con, +// 0.0); // The scale is {0.0 := maximum sharpness, to N>0, where N is the number of stops (halving) of the reduction of sharpness}. +// --------------- +// RCAS sharpening supports a CAS-like pass-through alpha via, +// #define FSR_RCAS_PASSTHROUGH_ALPHA 1 +// RCAS also supports a define to enable a more expensive path to avoid some sharpening of noise. +// Would suggest it is better to apply film grain after RCAS sharpening (and after scaling) instead of using this define, +// #define FSR_RCAS_DENOISE 1 +//============================================================================================================================== +// This is set at the limit of providing unnatural results for sharpening. +#define FSR_RCAS_LIMIT (0.25-(1.0/16.0)) +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// CONSTANT SETUP +//============================================================================================================================== +// Call to setup required constant values (works on CPU or GPU). +A_STATIC void FsrRcasCon( +outAU4 con, +// The scale is {0.0 := maximum, to N>0, where N is the number of stops (halving) of the reduction of sharpness}. +AF1 sharpness){ + // Transform from stops to linear value. + sharpness=AExp2F1(-sharpness); + varAF2(hSharp)=initAF2(sharpness,sharpness); + con[0]=AU1_AF1(sharpness); + con[1]=AU1_AH2_AF2(hSharp); + con[2]=0; + con[3]=0;} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// NON-PACKED 32-BIT VERSION +//============================================================================================================================== +#if defined(A_GPU)&&defined(FSR_RCAS_F) + // Input callback prototypes that need to be implemented by calling shader + AF4 FsrRcasLoadF(ASU2 p); + void FsrRcasInputF(inout AF1 r,inout AF1 g,inout AF1 b); +//------------------------------------------------------------------------------------------------------------------------------ + void FsrRcasF( + out AF1 pixR, // Output values, non-vector so port between RcasFilter() and RcasFilterH() is easy. + out AF1 pixG, + out AF1 pixB, + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + out AF1 pixA, + #endif + AU2 ip, // Integer pixel position in output. + AU4 con){ // Constant generated by RcasSetup(). + // Algorithm uses minimal 3x3 pixel neighborhood. + // b + // d e f + // h + ASU2 sp=ASU2(ip); + AF3 b=FsrRcasLoadF(sp+ASU2( 0,-1)).rgb; + AF3 d=FsrRcasLoadF(sp+ASU2(-1, 0)).rgb; + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + AF4 ee=FsrRcasLoadF(sp); + AF3 e=ee.rgb;pixA=ee.a; + #else + AF3 e=FsrRcasLoadF(sp).rgb; + #endif + AF3 f=FsrRcasLoadF(sp+ASU2( 1, 0)).rgb; + AF3 h=FsrRcasLoadF(sp+ASU2( 0, 1)).rgb; + // Rename (32-bit) or regroup (16-bit). + AF1 bR=b.r; + AF1 bG=b.g; + AF1 bB=b.b; + AF1 dR=d.r; + AF1 dG=d.g; + AF1 dB=d.b; + AF1 eR=e.r; + AF1 eG=e.g; + AF1 eB=e.b; + AF1 fR=f.r; + AF1 fG=f.g; + AF1 fB=f.b; + AF1 hR=h.r; + AF1 hG=h.g; + AF1 hB=h.b; + // Run optional input transform. + FsrRcasInputF(bR,bG,bB); + FsrRcasInputF(dR,dG,dB); + FsrRcasInputF(eR,eG,eB); + FsrRcasInputF(fR,fG,fB); + FsrRcasInputF(hR,hG,hB); + // Luma times 2. + AF1 bL=bB*AF1_(0.5)+(bR*AF1_(0.5)+bG); + AF1 dL=dB*AF1_(0.5)+(dR*AF1_(0.5)+dG); + AF1 eL=eB*AF1_(0.5)+(eR*AF1_(0.5)+eG); + AF1 fL=fB*AF1_(0.5)+(fR*AF1_(0.5)+fG); + AF1 hL=hB*AF1_(0.5)+(hR*AF1_(0.5)+hG); + // Noise detection. + AF1 nz=AF1_(0.25)*bL+AF1_(0.25)*dL+AF1_(0.25)*fL+AF1_(0.25)*hL-eL; + nz=ASatF1(abs(nz)*APrxMedRcpF1(AMax3F1(AMax3F1(bL,dL,eL),fL,hL)-AMin3F1(AMin3F1(bL,dL,eL),fL,hL))); + nz=AF1_(-0.5)*nz+AF1_(1.0); + // Min and max of ring. + AF1 mn4R=min(AMin3F1(bR,dR,fR),hR); + AF1 mn4G=min(AMin3F1(bG,dG,fG),hG); + AF1 mn4B=min(AMin3F1(bB,dB,fB),hB); + AF1 mx4R=max(AMax3F1(bR,dR,fR),hR); + AF1 mx4G=max(AMax3F1(bG,dG,fG),hG); + AF1 mx4B=max(AMax3F1(bB,dB,fB),hB); + // Immediate constants for peak range. + AF2 peakC=AF2(1.0,-1.0*4.0); + // Limiters, these need to be high precision RCPs. + AF1 hitMinR=min(mn4R,eR)*ARcpF1(AF1_(4.0)*mx4R); + AF1 hitMinG=min(mn4G,eG)*ARcpF1(AF1_(4.0)*mx4G); + AF1 hitMinB=min(mn4B,eB)*ARcpF1(AF1_(4.0)*mx4B); + AF1 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpF1(AF1_(4.0)*mn4R+peakC.y); + AF1 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpF1(AF1_(4.0)*mn4G+peakC.y); + AF1 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpF1(AF1_(4.0)*mn4B+peakC.y); + AF1 lobeR=max(-hitMinR,hitMaxR); + AF1 lobeG=max(-hitMinG,hitMaxG); + AF1 lobeB=max(-hitMinB,hitMaxB); + AF1 lobe=max(AF1_(-FSR_RCAS_LIMIT),min(AMax3F1(lobeR,lobeG,lobeB),AF1_(0.0)))*AF1_AU1(con.x); + // Apply noise removal. + #ifdef FSR_RCAS_DENOISE + lobe*=nz; + #endif + // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes. + AF1 rcpL=APrxMedRcpF1(AF1_(4.0)*lobe+AF1_(1.0)); + pixR=(lobe*bR+lobe*dR+lobe*hR+lobe*fR+eR)*rcpL; + pixG=(lobe*bG+lobe*dG+lobe*hG+lobe*fG+eG)*rcpL; + pixB=(lobe*bB+lobe*dB+lobe*hB+lobe*fB+eB)*rcpL; + return;} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// NON-PACKED 16-BIT VERSION +//============================================================================================================================== +#if defined(A_GPU)&&defined(A_HALF)&&defined(FSR_RCAS_H) + // Input callback prototypes that need to be implemented by calling shader + AH4 FsrRcasLoadH(ASW2 p); + void FsrRcasInputH(inout AH1 r,inout AH1 g,inout AH1 b); +//------------------------------------------------------------------------------------------------------------------------------ + void FsrRcasH( + out AH1 pixR, // Output values, non-vector so port between RcasFilter() and RcasFilterH() is easy. + out AH1 pixG, + out AH1 pixB, + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + out AH1 pixA, + #endif + AU2 ip, // Integer pixel position in output. + AU4 con){ // Constant generated by RcasSetup(). + // Sharpening algorithm uses minimal 3x3 pixel neighborhood. + // b + // d e f + // h + ASW2 sp=ASW2(ip); + AH3 b=FsrRcasLoadH(sp+ASW2( 0,-1)).rgb; + AH3 d=FsrRcasLoadH(sp+ASW2(-1, 0)).rgb; + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + AH4 ee=FsrRcasLoadH(sp); + AH3 e=ee.rgb;pixA=ee.a; + #else + AH3 e=FsrRcasLoadH(sp).rgb; + #endif + AH3 f=FsrRcasLoadH(sp+ASW2( 1, 0)).rgb; + AH3 h=FsrRcasLoadH(sp+ASW2( 0, 1)).rgb; + // Rename (32-bit) or regroup (16-bit). + AH1 bR=b.r; + AH1 bG=b.g; + AH1 bB=b.b; + AH1 dR=d.r; + AH1 dG=d.g; + AH1 dB=d.b; + AH1 eR=e.r; + AH1 eG=e.g; + AH1 eB=e.b; + AH1 fR=f.r; + AH1 fG=f.g; + AH1 fB=f.b; + AH1 hR=h.r; + AH1 hG=h.g; + AH1 hB=h.b; + // Run optional input transform. + FsrRcasInputH(bR,bG,bB); + FsrRcasInputH(dR,dG,dB); + FsrRcasInputH(eR,eG,eB); + FsrRcasInputH(fR,fG,fB); + FsrRcasInputH(hR,hG,hB); + // Luma times 2. + AH1 bL=bB*AH1_(0.5)+(bR*AH1_(0.5)+bG); + AH1 dL=dB*AH1_(0.5)+(dR*AH1_(0.5)+dG); + AH1 eL=eB*AH1_(0.5)+(eR*AH1_(0.5)+eG); + AH1 fL=fB*AH1_(0.5)+(fR*AH1_(0.5)+fG); + AH1 hL=hB*AH1_(0.5)+(hR*AH1_(0.5)+hG); + // Noise detection. + AH1 nz=AH1_(0.25)*bL+AH1_(0.25)*dL+AH1_(0.25)*fL+AH1_(0.25)*hL-eL; + nz=ASatH1(abs(nz)*APrxMedRcpH1(AMax3H1(AMax3H1(bL,dL,eL),fL,hL)-AMin3H1(AMin3H1(bL,dL,eL),fL,hL))); + nz=AH1_(-0.5)*nz+AH1_(1.0); + // Min and max of ring. + AH1 mn4R=min(AMin3H1(bR,dR,fR),hR); + AH1 mn4G=min(AMin3H1(bG,dG,fG),hG); + AH1 mn4B=min(AMin3H1(bB,dB,fB),hB); + AH1 mx4R=max(AMax3H1(bR,dR,fR),hR); + AH1 mx4G=max(AMax3H1(bG,dG,fG),hG); + AH1 mx4B=max(AMax3H1(bB,dB,fB),hB); + // Immediate constants for peak range. + AH2 peakC=AH2(1.0,-1.0*4.0); + // Limiters, these need to be high precision RCPs. + AH1 hitMinR=min(mn4R,eR)*ARcpH1(AH1_(4.0)*mx4R); + AH1 hitMinG=min(mn4G,eG)*ARcpH1(AH1_(4.0)*mx4G); + AH1 hitMinB=min(mn4B,eB)*ARcpH1(AH1_(4.0)*mx4B); + AH1 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpH1(AH1_(4.0)*mn4R+peakC.y); + AH1 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpH1(AH1_(4.0)*mn4G+peakC.y); + AH1 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpH1(AH1_(4.0)*mn4B+peakC.y); + AH1 lobeR=max(-hitMinR,hitMaxR); + AH1 lobeG=max(-hitMinG,hitMaxG); + AH1 lobeB=max(-hitMinB,hitMaxB); + AH1 lobe=max(AH1_(-FSR_RCAS_LIMIT),min(AMax3H1(lobeR,lobeG,lobeB),AH1_(0.0)))*AH2_AU1(con.y).x; + // Apply noise removal. + #ifdef FSR_RCAS_DENOISE + lobe*=nz; + #endif + // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes. + AH1 rcpL=APrxMedRcpH1(AH1_(4.0)*lobe+AH1_(1.0)); + pixR=(lobe*bR+lobe*dR+lobe*hR+lobe*fR+eR)*rcpL; + pixG=(lobe*bG+lobe*dG+lobe*hG+lobe*fG+eG)*rcpL; + pixB=(lobe*bB+lobe*dB+lobe*hB+lobe*fB+eB)*rcpL;} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// PACKED 16-BIT VERSION +//============================================================================================================================== +#if defined(A_GPU)&&defined(A_HALF)&&defined(FSR_RCAS_HX2) + // Input callback prototypes that need to be implemented by the calling shader + AH4 FsrRcasLoadHx2(ASW2 p); + void FsrRcasInputHx2(inout AH2 r,inout AH2 g,inout AH2 b); +//------------------------------------------------------------------------------------------------------------------------------ + // Can be used to convert from packed Structures of Arrays to Arrays of Structures for store. + void FsrRcasDepackHx2(out AH4 pix0,out AH4 pix1,AH2 pixR,AH2 pixG,AH2 pixB){ + #ifdef A_HLSL + // Invoke a slower path for DX only, since it won't allow uninitialized values. + pix0.a=pix1.a=0.0; + #endif + pix0.rgb=AH3(pixR.x,pixG.x,pixB.x); + pix1.rgb=AH3(pixR.y,pixG.y,pixB.y);} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrRcasHx2( + // Output values are for 2 8x8 tiles in a 16x8 region. + // pix.x = left 8x8 tile + // pix.y = right 8x8 tile + // This enables later processing to easily be packed as well. + out AH2 pixR, + out AH2 pixG, + out AH2 pixB, + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + out AH2 pixA, + #endif + AU2 ip, // Integer pixel position in output. + AU4 con){ // Constant generated by RcasSetup(). + // No scaling algorithm uses minimal 3x3 pixel neighborhood. + ASW2 sp0=ASW2(ip); + AH3 b0=FsrRcasLoadHx2(sp0+ASW2( 0,-1)).rgb; + AH3 d0=FsrRcasLoadHx2(sp0+ASW2(-1, 0)).rgb; + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + AH4 ee0=FsrRcasLoadHx2(sp0); + AH3 e0=ee0.rgb;pixA.r=ee0.a; + #else + AH3 e0=FsrRcasLoadHx2(sp0).rgb; + #endif + AH3 f0=FsrRcasLoadHx2(sp0+ASW2( 1, 0)).rgb; + AH3 h0=FsrRcasLoadHx2(sp0+ASW2( 0, 1)).rgb; + ASW2 sp1=sp0+ASW2(8,0); + AH3 b1=FsrRcasLoadHx2(sp1+ASW2( 0,-1)).rgb; + AH3 d1=FsrRcasLoadHx2(sp1+ASW2(-1, 0)).rgb; + #ifdef FSR_RCAS_PASSTHROUGH_ALPHA + AH4 ee1=FsrRcasLoadHx2(sp1); + AH3 e1=ee1.rgb;pixA.g=ee1.a; + #else + AH3 e1=FsrRcasLoadHx2(sp1).rgb; + #endif + AH3 f1=FsrRcasLoadHx2(sp1+ASW2( 1, 0)).rgb; + AH3 h1=FsrRcasLoadHx2(sp1+ASW2( 0, 1)).rgb; + // Arrays of Structures to Structures of Arrays conversion. + AH2 bR=AH2(b0.r,b1.r); + AH2 bG=AH2(b0.g,b1.g); + AH2 bB=AH2(b0.b,b1.b); + AH2 dR=AH2(d0.r,d1.r); + AH2 dG=AH2(d0.g,d1.g); + AH2 dB=AH2(d0.b,d1.b); + AH2 eR=AH2(e0.r,e1.r); + AH2 eG=AH2(e0.g,e1.g); + AH2 eB=AH2(e0.b,e1.b); + AH2 fR=AH2(f0.r,f1.r); + AH2 fG=AH2(f0.g,f1.g); + AH2 fB=AH2(f0.b,f1.b); + AH2 hR=AH2(h0.r,h1.r); + AH2 hG=AH2(h0.g,h1.g); + AH2 hB=AH2(h0.b,h1.b); + // Run optional input transform. + FsrRcasInputHx2(bR,bG,bB); + FsrRcasInputHx2(dR,dG,dB); + FsrRcasInputHx2(eR,eG,eB); + FsrRcasInputHx2(fR,fG,fB); + FsrRcasInputHx2(hR,hG,hB); + // Luma times 2. + AH2 bL=bB*AH2_(0.5)+(bR*AH2_(0.5)+bG); + AH2 dL=dB*AH2_(0.5)+(dR*AH2_(0.5)+dG); + AH2 eL=eB*AH2_(0.5)+(eR*AH2_(0.5)+eG); + AH2 fL=fB*AH2_(0.5)+(fR*AH2_(0.5)+fG); + AH2 hL=hB*AH2_(0.5)+(hR*AH2_(0.5)+hG); + // Noise detection. + AH2 nz=AH2_(0.25)*bL+AH2_(0.25)*dL+AH2_(0.25)*fL+AH2_(0.25)*hL-eL; + nz=ASatH2(abs(nz)*APrxMedRcpH2(AMax3H2(AMax3H2(bL,dL,eL),fL,hL)-AMin3H2(AMin3H2(bL,dL,eL),fL,hL))); + nz=AH2_(-0.5)*nz+AH2_(1.0); + // Min and max of ring. + AH2 mn4R=min(AMin3H2(bR,dR,fR),hR); + AH2 mn4G=min(AMin3H2(bG,dG,fG),hG); + AH2 mn4B=min(AMin3H2(bB,dB,fB),hB); + AH2 mx4R=max(AMax3H2(bR,dR,fR),hR); + AH2 mx4G=max(AMax3H2(bG,dG,fG),hG); + AH2 mx4B=max(AMax3H2(bB,dB,fB),hB); + // Immediate constants for peak range. + AH2 peakC=AH2(1.0,-1.0*4.0); + // Limiters, these need to be high precision RCPs. + AH2 hitMinR=min(mn4R,eR)*ARcpH2(AH2_(4.0)*mx4R); + AH2 hitMinG=min(mn4G,eG)*ARcpH2(AH2_(4.0)*mx4G); + AH2 hitMinB=min(mn4B,eB)*ARcpH2(AH2_(4.0)*mx4B); + AH2 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpH2(AH2_(4.0)*mn4R+peakC.y); + AH2 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpH2(AH2_(4.0)*mn4G+peakC.y); + AH2 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpH2(AH2_(4.0)*mn4B+peakC.y); + AH2 lobeR=max(-hitMinR,hitMaxR); + AH2 lobeG=max(-hitMinG,hitMaxG); + AH2 lobeB=max(-hitMinB,hitMaxB); + AH2 lobe=max(AH2_(-FSR_RCAS_LIMIT),min(AMax3H2(lobeR,lobeG,lobeB),AH2_(0.0)))*AH2_(AH2_AU1(con.y).x); + // Apply noise removal. + #ifdef FSR_RCAS_DENOISE + lobe*=nz; + #endif + // Resolve, which needs the medium precision rcp approximation to avoid visible tonality changes. + AH2 rcpL=APrxMedRcpH2(AH2_(4.0)*lobe+AH2_(1.0)); + pixR=(lobe*bR+lobe*dR+lobe*hR+lobe*fR+eR)*rcpL; + pixG=(lobe*bG+lobe*dG+lobe*hG+lobe*fG+eG)*rcpL; + pixB=(lobe*bB+lobe*dB+lobe*hB+lobe*fB+eB)*rcpL;} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// FSR - [LFGA] LINEAR FILM GRAIN APPLICATOR +// +//------------------------------------------------------------------------------------------------------------------------------ +// Adding output-resolution film grain after scaling is a good way to mask both rendering and scaling artifacts. +// Suggest using tiled blue noise as film grain input, with peak noise frequency set for a specific look and feel. +// The 'Lfga*()' functions provide a convenient way to introduce grain. +// These functions limit grain based on distance to signal limits. +// This is done so that the grain is temporally energy preserving, and thus won't modify image tonality. +// Grain application should be done in a linear colorspace. +// The grain should be temporally changing, but have a temporal sum per pixel that adds to zero (non-biased). +//------------------------------------------------------------------------------------------------------------------------------ +// Usage, +// FsrLfga*( +// color, // In/out linear colorspace color {0 to 1} ranged. +// grain, // Per pixel grain texture value {-0.5 to 0.5} ranged, input is 3-channel to support colored grain. +// amount); // Amount of grain (0 to 1} ranged. +//------------------------------------------------------------------------------------------------------------------------------ +// Example if grain texture is monochrome: 'FsrLfgaF(color,AF3_(grain),amount)' +//============================================================================================================================== +#if defined(A_GPU) + // Maximum grain is the minimum distance to the signal limit. + void FsrLfgaF(inout AF3 c,AF3 t,AF1 a){c+=(t*AF3_(a))*min(AF3_(1.0)-c,c);} +#endif +//============================================================================================================================== +#if defined(A_GPU)&&defined(A_HALF) + // Half precision version (slower). + void FsrLfgaH(inout AH3 c,AH3 t,AH1 a){c+=(t*AH3_(a))*min(AH3_(1.0)-c,c);} +//------------------------------------------------------------------------------------------------------------------------------ + // Packed half precision version (faster). + void FsrLfgaHx2(inout AH2 cR,inout AH2 cG,inout AH2 cB,AH2 tR,AH2 tG,AH2 tB,AH1 a){ + cR+=(tR*AH2_(a))*min(AH2_(1.0)-cR,cR);cG+=(tG*AH2_(a))*min(AH2_(1.0)-cG,cG);cB+=(tB*AH2_(a))*min(AH2_(1.0)-cB,cB);} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// FSR - [SRTM] SIMPLE REVERSIBLE TONE-MAPPER +// +//------------------------------------------------------------------------------------------------------------------------------ +// This provides a way to take linear HDR color {0 to FP16_MAX} and convert it into a temporary {0 to 1} ranged post-tonemapped linear. +// The tonemapper preserves RGB ratio, which helps maintain HDR color bleed during filtering. +//------------------------------------------------------------------------------------------------------------------------------ +// Reversible tonemapper usage, +// FsrSrtm*(color); // {0 to FP16_MAX} converted to {0 to 1}. +// FsrSrtmInv*(color); // {0 to 1} converted into {0 to 32768, output peak safe for FP16}. +//============================================================================================================================== +#if defined(A_GPU) + void FsrSrtmF(inout AF3 c){c*=AF3_(ARcpF1(AMax3F1(c.r,c.g,c.b)+AF1_(1.0)));} + // The extra max solves the c=1.0 case (which is a /0). + void FsrSrtmInvF(inout AF3 c){c*=AF3_(ARcpF1(max(AF1_(1.0/32768.0),AF1_(1.0)-AMax3F1(c.r,c.g,c.b))));} +#endif +//============================================================================================================================== +#if defined(A_GPU)&&defined(A_HALF) + void FsrSrtmH(inout AH3 c){c*=AH3_(ARcpH1(AMax3H1(c.r,c.g,c.b)+AH1_(1.0)));} + void FsrSrtmInvH(inout AH3 c){c*=AH3_(ARcpH1(max(AH1_(1.0/32768.0),AH1_(1.0)-AMax3H1(c.r,c.g,c.b))));} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrSrtmHx2(inout AH2 cR,inout AH2 cG,inout AH2 cB){ + AH2 rcp=ARcpH2(AMax3H2(cR,cG,cB)+AH2_(1.0));cR*=rcp;cG*=rcp;cB*=rcp;} + void FsrSrtmInvHx2(inout AH2 cR,inout AH2 cG,inout AH2 cB){ + AH2 rcp=ARcpH2(max(AH2_(1.0/32768.0),AH2_(1.0)-AMax3H2(cR,cG,cB)));cR*=rcp;cG*=rcp;cB*=rcp;} +#endif +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//_____________________________________________________________/\_______________________________________________________________ +//============================================================================================================================== +// +// FSR - [TEPD] TEMPORAL ENERGY PRESERVING DITHER +// +//------------------------------------------------------------------------------------------------------------------------------ +// Temporally energy preserving dithered {0 to 1} linear to gamma 2.0 conversion. +// Gamma 2.0 is used so that the conversion back to linear is just to square the color. +// The conversion comes in 8-bit and 10-bit modes, designed for output to 8-bit UNORM or 10:10:10:2 respectively. +// Given good non-biased temporal blue noise as dither input, +// the output dither will temporally conserve energy. +// This is done by choosing the linear nearest step point instead of perceptual nearest. +// See code below for details. +//------------------------------------------------------------------------------------------------------------------------------ +// DX SPEC RULES FOR FLOAT->UNORM 8-BIT CONVERSION +// =============================================== +// - Output is 'uint(floor(saturate(n)*255.0+0.5))'. +// - Thus rounding is to nearest. +// - NaN gets converted to zero. +// - INF is clamped to {0.0 to 1.0}. +//============================================================================================================================== +#if defined(A_GPU) + // Hand tuned integer position to dither value, with more values than simple checkerboard. + // Only 32-bit has enough precision for this compddation. + // Output is {0 to <1}. + AF1 FsrTepdDitF(AU2 p,AU1 f){ + AF1 x=AF1_(p.x+f); + AF1 y=AF1_(p.y); + // The 1.61803 golden ratio. + AF1 a=AF1_((1.0+sqrt(5.0))/2.0); + // Number designed to provide a good visual pattern. + AF1 b=AF1_(1.0/3.69); + x=x*a+(y*b); + return AFractF1(x);} +//------------------------------------------------------------------------------------------------------------------------------ + // This version is 8-bit gamma 2.0. + // The 'c' input is {0 to 1}. + // Output is {0 to 1} ready for image store. + void FsrTepdC8F(inout AF3 c,AF1 dit){ + AF3 n=sqrt(c); + n=floor(n*AF3_(255.0))*AF3_(1.0/255.0); + AF3 a=n*n; + AF3 b=n+AF3_(1.0/255.0);b=b*b; + // Ratio of 'a' to 'b' required to produce 'c'. + // APrxLoRcpF1() won't work here (at least for very high dynamic ranges). + // APrxMedRcpF1() is an IADD,FMA,MUL. + AF3 r=(c-b)*APrxMedRcpF3(a-b); + // Use the ratio as a cutoff to choose 'a' or 'b'. + // AGtZeroF1() is a MUL. + c=ASatF3(n+AGtZeroF3(AF3_(dit)-r)*AF3_(1.0/255.0));} +//------------------------------------------------------------------------------------------------------------------------------ + // This version is 10-bit gamma 2.0. + // The 'c' input is {0 to 1}. + // Output is {0 to 1} ready for image store. + void FsrTepdC10F(inout AF3 c,AF1 dit){ + AF3 n=sqrt(c); + n=floor(n*AF3_(1023.0))*AF3_(1.0/1023.0); + AF3 a=n*n; + AF3 b=n+AF3_(1.0/1023.0);b=b*b; + AF3 r=(c-b)*APrxMedRcpF3(a-b); + c=ASatF3(n+AGtZeroF3(AF3_(dit)-r)*AF3_(1.0/1023.0));} +#endif +//============================================================================================================================== +#if defined(A_GPU)&&defined(A_HALF) + AH1 FsrTepdDitH(AU2 p,AU1 f){ + AF1 x=AF1_(p.x+f); + AF1 y=AF1_(p.y); + AF1 a=AF1_((1.0+sqrt(5.0))/2.0); + AF1 b=AF1_(1.0/3.69); + x=x*a+(y*b); + return AH1(AFractF1(x));} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrTepdC8H(inout AH3 c,AH1 dit){ + AH3 n=sqrt(c); + n=floor(n*AH3_(255.0))*AH3_(1.0/255.0); + AH3 a=n*n; + AH3 b=n+AH3_(1.0/255.0);b=b*b; + AH3 r=(c-b)*APrxMedRcpH3(a-b); + c=ASatH3(n+AGtZeroH3(AH3_(dit)-r)*AH3_(1.0/255.0));} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrTepdC10H(inout AH3 c,AH1 dit){ + AH3 n=sqrt(c); + n=floor(n*AH3_(1023.0))*AH3_(1.0/1023.0); + AH3 a=n*n; + AH3 b=n+AH3_(1.0/1023.0);b=b*b; + AH3 r=(c-b)*APrxMedRcpH3(a-b); + c=ASatH3(n+AGtZeroH3(AH3_(dit)-r)*AH3_(1.0/1023.0));} +//============================================================================================================================== + // This computes dither for positions 'p' and 'p+{8,0}'. + AH2 FsrTepdDitHx2(AU2 p,AU1 f){ + AF2 x; + x.x=AF1_(p.x+f); + x.y=x.x+AF1_(8.0); + AF1 y=AF1_(p.y); + AF1 a=AF1_((1.0+sqrt(5.0))/2.0); + AF1 b=AF1_(1.0/3.69); + x=x*AF2_(a)+AF2_(y*b); + return AH2(AFractF2(x));} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrTepdC8Hx2(inout AH2 cR,inout AH2 cG,inout AH2 cB,AH2 dit){ + AH2 nR=sqrt(cR); + AH2 nG=sqrt(cG); + AH2 nB=sqrt(cB); + nR=floor(nR*AH2_(255.0))*AH2_(1.0/255.0); + nG=floor(nG*AH2_(255.0))*AH2_(1.0/255.0); + nB=floor(nB*AH2_(255.0))*AH2_(1.0/255.0); + AH2 aR=nR*nR; + AH2 aG=nG*nG; + AH2 aB=nB*nB; + AH2 bR=nR+AH2_(1.0/255.0);bR=bR*bR; + AH2 bG=nG+AH2_(1.0/255.0);bG=bG*bG; + AH2 bB=nB+AH2_(1.0/255.0);bB=bB*bB; + AH2 rR=(cR-bR)*APrxMedRcpH2(aR-bR); + AH2 rG=(cG-bG)*APrxMedRcpH2(aG-bG); + AH2 rB=(cB-bB)*APrxMedRcpH2(aB-bB); + cR=ASatH2(nR+AGtZeroH2(dit-rR)*AH2_(1.0/255.0)); + cG=ASatH2(nG+AGtZeroH2(dit-rG)*AH2_(1.0/255.0)); + cB=ASatH2(nB+AGtZeroH2(dit-rB)*AH2_(1.0/255.0));} +//------------------------------------------------------------------------------------------------------------------------------ + void FsrTepdC10Hx2(inout AH2 cR,inout AH2 cG,inout AH2 cB,AH2 dit){ + AH2 nR=sqrt(cR); + AH2 nG=sqrt(cG); + AH2 nB=sqrt(cB); + nR=floor(nR*AH2_(1023.0))*AH2_(1.0/1023.0); + nG=floor(nG*AH2_(1023.0))*AH2_(1.0/1023.0); + nB=floor(nB*AH2_(1023.0))*AH2_(1.0/1023.0); + AH2 aR=nR*nR; + AH2 aG=nG*nG; + AH2 aB=nB*nB; + AH2 bR=nR+AH2_(1.0/1023.0);bR=bR*bR; + AH2 bG=nG+AH2_(1.0/1023.0);bG=bG*bG; + AH2 bB=nB+AH2_(1.0/1023.0);bB=bB*bB; + AH2 rR=(cR-bR)*APrxMedRcpH2(aR-bR); + AH2 rG=(cG-bG)*APrxMedRcpH2(aG-bG); + AH2 rB=(cB-bB)*APrxMedRcpH2(aB-bB); + cR=ASatH2(nR+AGtZeroH2(dit-rR)*AH2_(1.0/1023.0)); + cG=ASatH2(nG+AGtZeroH2(dit-rG)*AH2_(1.0/1023.0)); + cB=ASatH2(nB+AGtZeroH2(dit-rB)*AH2_(1.0/1023.0));} +#endif diff --git a/app/shaders/enhancer/NVIDIA/NIS_Main.hlsl b/app/shaders/enhancer/NVIDIA/NIS_Main.hlsl new file mode 100644 index 000000000..df744eb4b --- /dev/null +++ b/app/shaders/enhancer/NVIDIA/NIS_Main.hlsl @@ -0,0 +1,111 @@ +// The MIT License(MIT) +// +// Copyright(c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files(the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +//--------------------------------------------------------------------------------- +// NVIDIA Image Scaling SDK - v1.0.3 +//--------------------------------------------------------------------------------- +// HLSL main example +//--------------------------------------------------------------------------------- + +#define NIS_HLSL 1 + +#ifndef NIS_SCALER +#define NIS_SCALER 1 +#endif + +#ifndef NIS_DXC +#define NIS_DXC 0 +#endif + +#if NIS_DXC +#define NIS_PUSH_CONSTANT [[vk::push_constant]] +#define NIS_BINDING(bindingIndex) [[vk::binding(bindingIndex, 0)]] +#else +#define NIS_PUSH_CONSTANT +#define NIS_BINDING(bindingIndex) +#endif + + +NIS_BINDING(0) cbuffer cb : register(b0) +{ + float kDetectRatio; + float kDetectThres; + float kMinContrastRatio; + float kRatioNorm; + + float kContrastBoost; + float kEps; + float kSharpStartY; + float kSharpScaleY; + + float kSharpStrengthMin; + float kSharpStrengthScale; + float kSharpLimitMin; + float kSharpLimitScale; + + float kScaleX; + float kScaleY; + + float kDstNormX; + float kDstNormY; + float kSrcNormX; + float kSrcNormY; + + uint kInputViewportOriginX; + uint kInputViewportOriginY; + uint kInputViewportWidth; + uint kInputViewportHeight; + + uint kOutputViewportOriginX; + uint kOutputViewportOriginY; + uint kOutputViewportWidth; + uint kOutputViewportHeight; + + float reserved0; + float reserved1; +}; + +NIS_BINDING(1) SamplerState samplerLinearClamp : register(s0); +#if NIS_NV12_SUPPORT +NIS_BINDING(2) Texture2D in_texture_y : register(t0); +NIS_BINDING(2) Texture2D in_texture_uv : register(t3); +#else +NIS_BINDING(2) Texture2D in_texture : register(t0); +#endif +NIS_BINDING(3) RWTexture2D out_texture : register(u0); +#if NIS_SCALER +NIS_BINDING(4) Texture2D coef_scaler : register(t1); +NIS_BINDING(5) Texture2D coef_usm : register(t2); +#endif + + + +#include "NIS_Scaler.h" + +[numthreads(NIS_THREAD_GROUP_SIZE, 1, 1)] +void main(uint3 blockIdx : SV_GroupID, uint3 threadIdx : SV_GroupThreadID) +{ +#if NIS_SCALER + NVScaler(blockIdx.xy, threadIdx.x); +#else + NVSharpen(blockIdx.xy, threadIdx.x); +#endif +} diff --git a/app/shaders/enhancer/NVIDIA/NIS_Scaler.h b/app/shaders/enhancer/NVIDIA/NIS_Scaler.h new file mode 100644 index 000000000..02f645c2c --- /dev/null +++ b/app/shaders/enhancer/NVIDIA/NIS_Scaler.h @@ -0,0 +1,1020 @@ +// The MIT License(MIT) +// +// Copyright(c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files(the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions : +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +//--------------------------------------------------------------------------------- +// NVIDIA Image Scaling SDK - v1.0.3 +//--------------------------------------------------------------------------------- +// The NVIDIA Image Scaling SDK provides a single spatial scaling and sharpening algorithm +// for cross-platform support. The scaling algorithm uses a 6-tap scaling filter combined +// with 4 directional scaling and adaptive sharpening filters, which creates nice smooth images +// and sharp edges. In addition, the SDK provides a state-of-the-art adaptive directional sharpening algorithm +// for use in applications where no scaling is required. +// +// The directional scaling and sharpening algorithm is named NVScaler while the adaptive-directional-sharpening-only +// algorithm is named NVSharpen. Both algorithms are provided as compute shaders and +// developers are free to integrate them in their applications. Note that if you integrate NVScaler, you +// should NOT integrate NVSharpen, as NVScaler already includes a sharpening pass +// +// Pipeline Placement +// ------------------ +// The call into the NVIDIA Image Scaling shaders must occur during the post-processing phase after tone-mapping. +// Applying the scaling in linear HDR in-game color-space may result in a sharpening effect that is +// either not visible or too strong. Since sharpening algorithms can enhance noisy or grainy regions, it is recommended +// that certain effects such as film grain should occur after NVScaler or NVSharpen. Low-pass filters such as motion blur or +// light bloom are recommended to be applied before NVScaler or NVSharpen to avoid sharpening attenuation. +// +// Color Space and Ranges +// ---------------------- +// NVIDIA Image Scaling shaders can process color textures stored as either LDR or HDR with the following +// restrictions: +// 1) LDR +// - The range of color values must be in the [0, 1] range +// - The input color texture must be in display-referred color-space after tone mapping and OETF (gamma-correction) +// has been applied +// 2) HDR PQ +// - The range of color values must be in the [0, 1] range +// - The input color texture must be in display-referred color-space after tone mapping with Rec.2020 PQ OETF applied +// 3) HDR Linear +// - The recommended range of color values is [0, 12.5], where luminance value (as per BT. 709) of +// 1.0 maps to brightness value of 80nits (sRGB peak) and 12.5 maps to 1000nits +// - The input color texture may have luminance values that are either linear and scene-referred or +// linear and display-referred (after tone mapping) +// +// If the input color texture sent to NVScaler/NVSharpen is in HDR format set NIS_HDR_MODE define to either +// NIS_HDR_MODE_LINEAR (1) or NIS_HDR_MODE_PQ (2). +// +// Supported Texture Formats +// ------------------------- +// Input and output formats: +// Input and output formats are expected to be in the rages defined in previous section and should be +// specified using non-integer data types such as DXGI_FORMAT_R8G8B8A8_UNORM. +// +// Coefficients formats: +// The scaler coefficients and USM coefficients format should be specified using float4 type such as +// DXGI_FORMAT_R32G32B32A32_FLOAT or DXGI_FORMAT_R16G16B16A16_FLOAT. +// +// Resource States, Buffers, and Sampler: +// The game or application calling NVIDIA Image Scaling SDK shaders must ensure that the textures are in +// the correct state. +// - Input color textures must be in pixel shader read state. Shader Resource View (SRV) in DirectX +// - The output texture must be in read/write state. Unordered Access View (UAV) in DirectX +// - The coefficients texture for NVScaler must be in read state. Shader Resource View (SRV) in DirectX +// - The configuration variables must be passed as constant buffer. Constant Buffer View (CBV) in DirectX +// - The sampler for texture pixel sampling. Linear clamp SamplerState in Direct +// +// Adding NVIDIA Image Scaling SDK to a Project +// -------------------------------------------- +// Include NIS_Scaler.h directly in your application or alternative use the provided NIS_Main.hlsl shader file. +// Use NIS_Config.h to get the ideal shader dispatch values for your platform, to configure the algorithm constant +// values (NVScalerUpdateConfig, and NVSharpenUpdateConfig), and to access the algorithm coefficients (coef_scale and coef_USM). +// +// Defines: +// NIS_SCALER: default (1) NVScaler, (0) fast NVSharpen only, no upscaling +// NIS_HDR_MODE: default (0) disabled, (1) Linear, (2) PQ +// NIS_BLOCK_WIDTH: pixels per block width. Use GetOptimalBlockWidth query for your platform +// NIS_BLOCK_HEIGHT: pixels per block height. Use GetOptimalBlockHeight query for your platform +// NIS_THREAD_GROUP_SIZE: number of threads per group. Use GetOptimalThreadGroupSize query for your platform +// NIS_USE_HALF_PRECISION: default (0) disabled, (1) enable half pression computation +// NIS_HLSL: (1) enabled, (0) disabled +// NIS_HLSL_6_2: default (0) HLSL v5, (1) HLSL v6.2 forces NIS_HLSL=1 +// NIS_GLSL: (1) enabled, (0) disabled +// NIS_VIEWPORT_SUPPORT: default(0) disabled, (1) enable input/output viewport support +// NIS_NV12_SUPPORT: default(0) disabled, (1) enable NV12 input +// NIS_CLAMP_OUTPUT: default(0) disabled, (1) enable output clamp +// +// Default NVScaler shader constants: +// [NIS_BLOCK_WIDTH, NIS_BLOCK_HEIGHT, NIS_THREAD_GROUP_SIZE] = [32, 24, 256] +// +// Default NVSharpen shader constants: +// [NIS_BLOCK_WIDTH, NIS_BLOCK_HEIGHT, NIS_THREAD_GROUP_SIZE] = [32, 32, 256] +// +// NIS_UNROLL: default [unroll] +// NIS_UNROLL_INNER: default NIS_UNROLL, define in case of a compiler error for inner nested loops +//--------------------------------------------------------------------------------- + +// NVScaler enable by default. Set to 0 for NVSharpen only +#ifndef NIS_SCALER +#define NIS_SCALER 1 +#endif + +// HDR Modes +#define NIS_HDR_MODE_NONE 0 +#define NIS_HDR_MODE_LINEAR 1 +#define NIS_HDR_MODE_PQ 2 +#ifndef NIS_HDR_MODE +#define NIS_HDR_MODE NIS_HDR_MODE_NONE +#endif +#define kHDRCompressionFactor 0.282842712f + +// Viewport support +#ifndef NIS_VIEWPORT_SUPPORT +#define NIS_VIEWPORT_SUPPORT 0 +#endif + +// HLSL, GLSL +#if NIS_HLSL==0 && !defined(NIS_GLSL) +#define NIS_GLSL 1 +#endif +#if NIS_HLSL_6_2 || (!NIS_GLSL && !NIS_HLSL) +#if defined(NIS_HLSL) +#undef NIS_HLSL +#endif +#define NIS_HLSL 1 +#endif +#if NIS_HLSL && NIS_GLSL +#undef NIS_GLSL +#define NIS_GLSL 0 +#endif + +// Half precision +#ifndef NIS_USE_HALF_PRECISION +#define NIS_USE_HALF_PRECISION 0 +#endif + +#if NIS_HLSL +// Generic type and function aliases for HLSL +#define NVF float +#define NVF2 float2 +#define NVF3 float3 +#define NVF4 float4 +#define NVI int +#define NVI2 int2 +#define NVU uint +#define NVU2 uint2 +#define NVB bool +#if NIS_USE_HALF_PRECISION +#if NIS_HLSL_6_2 +#define NVH float16_t +#define NVH2 float16_t2 +#define NVH3 float16_t3 +#define NVH4 float16_t4 +#else +#define NVH min16float +#define NVH2 min16float2 +#define NVH3 min16float3 +#define NVH4 min16float4 +#endif // NIS_HLSL_6_2 +#else // FP32 types +#define NVH NVF +#define NVH2 NVF2 +#define NVH3 NVF3 +#define NVH4 NVF4 +#endif // NIS_USE_HALF_PRECISION +#define NVSHARED groupshared +#define NVTEX_LOAD(x, pos) x[pos] +#define NVTEX_SAMPLE(x, sampler, pos) x.SampleLevel(sampler, pos, 0) +#define NVTEX_SAMPLE_RED(x, sampler, pos) x.GatherRed(sampler, pos) +#define NVTEX_SAMPLE_GREEN(x, sampler, pos) x.GatherGreen(sampler, pos) +#define NVTEX_SAMPLE_BLUE(x, sampler, pos) x.GatherBlue(sampler, pos) +#define NVTEX_STORE(x, pos, v) x[pos] = v +#ifndef NIS_UNROLL +#define NIS_UNROLL [unroll] +#endif +#endif // NIS_HLSL + +// Generic type and function aliases for GLSL +#if NIS_GLSL +#define NVF float +#define NVF2 vec2 +#define NVF3 vec3 +#define NVF4 vec4 +#define NVI int +#define NVI2 ivec2 +#define NVU uint +#define NVU2 uvec2 +#define NVB bool +#if NIS_USE_HALF_PRECISION +#define NVH float16_t +#define NVH2 f16vec2 +#define NVH3 f16vec3 +#define NVH4 f16vec4 +#else // FP32 types +#define NVH NVF +#define NVH2 NVF2 +#define NVH3 NVF3 +#define NVH4 NVF4 +#endif // NIS_USE_HALF_PRECISION +#define NVSHARED shared +#define NVTEX_LOAD(x, pos) texelFetch(sampler2D(x, samplerLinearClamp), pos, 0) +#define NVTEX_SAMPLE(x, sampler, pos) textureLod(sampler2D(x, sampler), pos, 0) +#define NVTEX_SAMPLE_RED(x, sampler, pos) textureGather(sampler2D(x, sampler), pos, 0) +#define NVTEX_SAMPLE_GREEN(x, sampler, pos) textureGather(sampler2D(x, sampler), pos, 1) +#define NVTEX_SAMPLE_BLUE(x, sampler, pos) textureGather(sampler2D(x, sampler), pos, 2) +#define NVTEX_STORE(x, pos, v) imageStore(x, NVI2(pos), v) +#define saturate(x) clamp(x, 0, 1) +#define lerp(a, b, x) mix(a, b, x) +#define GroupMemoryBarrierWithGroupSync() groupMemoryBarrier(); barrier() +#ifndef NIS_UNROLL +#define NIS_UNROLL +#endif +#endif // NIS_GLSL + +#ifndef NIS_UNROLL_INNER +#define NIS_UNROLL_INNER NIS_UNROLL +#endif + +// Texture gather +#ifndef NIS_TEXTURE_GATHER +#define NIS_TEXTURE_GATHER 0 +#endif + +// NIS Scaling +#define NIS_SCALE_INT 1 +#define NIS_SCALE_FLOAT NVF(1.f) + +// NIS output clamp +#if NIS_CLAMP_OUTPUT +#if NIS_HDR_MODE == NIS_HDR_MODE_LINEAR +#define NVCLAMP(x) ( clamp(x, 0.0f, 12.5f) ) +#else +#define NVCLAMP(x) ( saturate(x) ) +#endif +#else +#define NVCLAMP(x) (x) +#endif + +NVF getY(NVF3 rgba) +{ +#if NIS_HDR_MODE == NIS_HDR_MODE_PQ + return NVF(0.262f) * rgba.x + NVF(0.678f) * rgba.y + NVF(0.0593f) * rgba.z; +#elif NIS_HDR_MODE == NIS_HDR_MODE_LINEAR + return sqrt(NVF(0.2126f) * rgba.x + NVF(0.7152f) * rgba.y + NVF(0.0722f) * rgba.z) * kHDRCompressionFactor; +#else + return NVF(0.2126f) * rgba.x + NVF(0.7152f) * rgba.y + NVF(0.0722f) * rgba.z; +#endif +} + +NVF getYLinear(NVF3 rgba) +{ + return NVF(0.2126f) * rgba.x + NVF(0.7152f) * rgba.y + NVF(0.0722f) * rgba.z; +} + +NVF3 YUVtoRGB(NVF3 yuv) +{ + float y = yuv.x - 16.0f / 255.0f; + float u = yuv.y - 128.0f / 255.0f; + float v = yuv.z - 128.0f / 255.0f; + NVF3 rgb; + rgb.x = saturate(1.164f * y + 1.596f * v); + rgb.y = saturate(1.164f * y - 0.392f * u - 0.813f * v); + rgb.z = saturate(1.164f * y + 2.017f * u); + return rgb; +} + +#if NIS_SCALER +NVF4 GetEdgeMap(NVF p[4][4], NVI i, NVI j) +#else +NVF4 GetEdgeMap(NVF p[5][5], NVI i, NVI j) +#endif +{ + const NVF g_0 = abs(p[0 + i][0 + j] + p[0 + i][1 + j] + p[0 + i][2 + j] - p[2 + i][0 + j] - p[2 + i][1 + j] - p[2 + i][2 + j]); + const NVF g_45 = abs(p[1 + i][0 + j] + p[0 + i][0 + j] + p[0 + i][1 + j] - p[2 + i][1 + j] - p[2 + i][2 + j] - p[1 + i][2 + j]); + const NVF g_90 = abs(p[0 + i][0 + j] + p[1 + i][0 + j] + p[2 + i][0 + j] - p[0 + i][2 + j] - p[1 + i][2 + j] - p[2 + i][2 + j]); + const NVF g_135 = abs(p[1 + i][0 + j] + p[2 + i][0 + j] + p[2 + i][1 + j] - p[0 + i][1 + j] - p[0 + i][2 + j] - p[1 + i][2 + j]); + + const NVF g_0_90_max = max(g_0, g_90); + const NVF g_0_90_min = min(g_0, g_90); + const NVF g_45_135_max = max(g_45, g_135); + const NVF g_45_135_min = min(g_45, g_135); + + NVF e_0_90 = 0; + NVF e_45_135 = 0; + + if (g_0_90_max + g_45_135_max == 0) + { + return NVF4(0, 0, 0, 0); + } + + e_0_90 = min(g_0_90_max / (g_0_90_max + g_45_135_max), 1.0f); + e_45_135 = 1.0f - e_0_90; + + NVB c_0_90 = (g_0_90_max > (g_0_90_min * kDetectRatio)) && (g_0_90_max > kDetectThres) && (g_0_90_max > g_45_135_min); + NVB c_45_135 = (g_45_135_max > (g_45_135_min * kDetectRatio)) && (g_45_135_max > kDetectThres) && (g_45_135_max > g_0_90_min); + NVB c_g_0_90 = g_0_90_max == g_0; + NVB c_g_45_135 = g_45_135_max == g_45; + + NVF f_e_0_90 = (c_0_90 && c_45_135) ? e_0_90 : 1.0f; + NVF f_e_45_135 = (c_0_90 && c_45_135) ? e_45_135 : 1.0f; + + NVF weight_0 = (c_0_90 && c_g_0_90) ? f_e_0_90 : 0.0f; + NVF weight_90 = (c_0_90 && !c_g_0_90) ? f_e_0_90 : 0.0f; + NVF weight_45 = (c_45_135 && c_g_45_135) ? f_e_45_135 : 0.0f; + NVF weight_135 = (c_45_135 && !c_g_45_135) ? f_e_45_135 : 0.0f; + + return NVF4(weight_0, weight_90, weight_45, weight_135); +} + +#if NIS_SCALER + +#ifndef NIS_BLOCK_WIDTH +#define NIS_BLOCK_WIDTH 32 +#endif +#ifndef NIS_BLOCK_HEIGHT +#define NIS_BLOCK_HEIGHT 24 +#endif +#ifndef NIS_THREAD_GROUP_SIZE +#define NIS_THREAD_GROUP_SIZE 256 +#endif +#define kPhaseCount 64 +#define kFilterSize 6 +#define kSupportSize 6 +#define kPadSize kSupportSize +// 'Tile' is the region of source luminance values that we load into shPixelsY. +// It is the area of source pixels covered by the destination 'Block' plus a +// 3 pixel border of support pixels. +#define kTilePitch (NIS_BLOCK_WIDTH + kPadSize) +#define kTileSize (kTilePitch * (NIS_BLOCK_HEIGHT + kPadSize)) +// 'EdgeMap' is the region of source pixels for which edge map vectors are derived. +// It is the area of source pixels covered by the destination 'Block' plus a +// 1 pixel border. +#define kEdgeMapPitch (NIS_BLOCK_WIDTH + 2) +#define kEdgeMapSize (kEdgeMapPitch * (NIS_BLOCK_HEIGHT + 2)) + +NVSHARED NVF shPixelsY[kTileSize]; +NVSHARED NVH shCoefScaler[kPhaseCount][kFilterSize]; +NVSHARED NVH shCoefUSM[kPhaseCount][kFilterSize]; +NVSHARED NVH4 shEdgeMap[kEdgeMapSize]; + +void LoadFilterBanksSh(NVI i0) { + // Load up filter banks to shared memory + // The work is spread over (kPhaseCount * 2) threads + NVI i = i0; +#if( kPhaseCount * 2 > NIS_THREAD_GROUP_SIZE ) + for (; i < kPhaseCount * 2; i += NIS_THREAD_GROUP_SIZE) +#else + if (i < kPhaseCount * 2) +#endif + { + NVI phase = i >> 1; + NVI vIdx = i & 1; + + NVH4 v = NVH4(NVTEX_LOAD(coef_scaler, NVI2(vIdx, phase))); + NVI filterOffset = vIdx * 4; + shCoefScaler[phase][filterOffset + 0] = v.x; + shCoefScaler[phase][filterOffset + 1] = v.y; + if (vIdx == 0) + { + shCoefScaler[phase][2] = v.z; + shCoefScaler[phase][3] = v.w; + } + + v = NVH4(NVTEX_LOAD(coef_usm, NVI2(vIdx, phase))); + shCoefUSM[phase][filterOffset + 0] = v.x; + shCoefUSM[phase][filterOffset + 1] = v.y; + if (vIdx == 0) + { + shCoefUSM[phase][2] = v.z; + shCoefUSM[phase][3] = v.w; + } + } +} + + +NVF CalcLTI(NVF p0, NVF p1, NVF p2, NVF p3, NVF p4, NVF p5, NVI phase_index) +{ + const NVB selector = (phase_index <= kPhaseCount / 2); + NVF sel = selector ? p0 : p3; + const NVF a_min = min(min(p1, p2), sel); + const NVF a_max = max(max(p1, p2), sel); + sel = selector ? p2 : p5; + const NVF b_min = min(min(p3, p4), sel); + const NVF b_max = max(max(p3, p4), sel); + + const NVF a_cont = a_max - a_min; + const NVF b_cont = b_max - b_min; + + const NVF cont_ratio = max(a_cont, b_cont) / (min(a_cont, b_cont) + kEps); + return (1.0f - saturate((cont_ratio - kMinContrastRatio) * kRatioNorm)) * kContrastBoost; +} + +NVF4 GetInterpEdgeMap(const NVF4 edge[2][2], NVF phase_frac_x, NVF phase_frac_y) +{ + NVF4 h0 = lerp(edge[0][0], edge[0][1], phase_frac_x); + NVF4 h1 = lerp(edge[1][0], edge[1][1], phase_frac_x); + return lerp(h0, h1, phase_frac_y); +} + +NVF EvalPoly6(const NVF pxl[6], NVI phase_int) +{ + NVF y = 0.f; + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + y += shCoefScaler[phase_int][i] * pxl[i]; + } + } + NVF y_usm = 0.f; + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + y_usm += shCoefUSM[phase_int][i] * pxl[i]; + } + } + + // let's compute a piece-wise ramp based on luma + const NVF y_scale = 1.0f - saturate((y * (1.0f / NIS_SCALE_FLOAT) - kSharpStartY) * kSharpScaleY); + + // scale the ramp to sharpen as a function of luma + const NVF y_sharpness = y_scale * kSharpStrengthScale + kSharpStrengthMin; + + y_usm *= y_sharpness; + + // scale the ramp to limit USM as a function of luma + const NVF y_sharpness_limit = (y_scale * kSharpLimitScale + kSharpLimitMin) * y; + + y_usm = min(y_sharpness_limit, max(-y_sharpness_limit, y_usm)); + // reduce ringing + y_usm *= CalcLTI(pxl[0], pxl[1], pxl[2], pxl[3], pxl[4], pxl[5], phase_int); + + return y + y_usm; +} + +NVF FilterNormal(const NVF p[6][6], NVI phase_x_frac_int, NVI phase_y_frac_int) +{ + NVF h_acc = 0.0f; + NIS_UNROLL + for (NVI j = 0; j < 6; ++j) + { + NVF v_acc = 0.0f; + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + v_acc += p[i][j] * shCoefScaler[phase_y_frac_int][i]; + } + h_acc += v_acc * shCoefScaler[phase_x_frac_int][j]; + } + + // let's return the sum unpacked -> we can accumulate it later + return h_acc; +} + +NVF AddDirFilters(NVF p[6][6], NVF phase_x_frac, NVF phase_y_frac, NVI phase_x_frac_int, NVI phase_y_frac_int, NVF4 w) +{ + NVF f = 0; + if (w.x > 0.0f) + { + // 0 deg filter + NVF interp0Deg[6]; + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + interp0Deg[i] = lerp(p[i][2], p[i][3], phase_x_frac); + } + } + f += EvalPoly6(interp0Deg, phase_y_frac_int) * w.x; + } + if (w.y > 0.0f) + { + // 90 deg filter + NVF interp90Deg[6]; + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + interp90Deg[i] = lerp(p[2][i], p[3][i], phase_y_frac); + } + } + + f += EvalPoly6(interp90Deg, phase_x_frac_int) * w.y; + } + if (w.z > 0.0f) + { + //45 deg filter + NVF pphase_b45 = 0.5f + 0.5f * (phase_x_frac - phase_y_frac); + + NVF temp_interp45Deg[7]; + temp_interp45Deg[1] = lerp(p[2][1], p[1][2], pphase_b45); + temp_interp45Deg[3] = lerp(p[3][2], p[2][3], pphase_b45); + temp_interp45Deg[5] = lerp(p[4][3], p[3][4], pphase_b45); + { + pphase_b45 = pphase_b45 - 0.5f; + NVF a = (pphase_b45 >= 0.f) ? p[0][2] : p[2][0]; + NVF b = (pphase_b45 >= 0.f) ? p[1][3] : p[3][1]; + NVF c = (pphase_b45 >= 0.f) ? p[2][4] : p[4][2]; + NVF d = (pphase_b45 >= 0.f) ? p[3][5] : p[5][3]; + temp_interp45Deg[0] = lerp(p[1][1], a, abs(pphase_b45)); + temp_interp45Deg[2] = lerp(p[2][2], b, abs(pphase_b45)); + temp_interp45Deg[4] = lerp(p[3][3], c, abs(pphase_b45)); + temp_interp45Deg[6] = lerp(p[4][4], d, abs(pphase_b45)); + } + + NVF interp45Deg[6]; + NVF pphase_p45 = phase_x_frac + phase_y_frac; + if (pphase_p45 >= 1) + { + NIS_UNROLL + for (NVI i = 0; i < 6; i++) + { + interp45Deg[i] = temp_interp45Deg[i + 1]; + } + pphase_p45 = pphase_p45 - 1; + } + else + { + NIS_UNROLL + for (NVI i = 0; i < 6; i++) + { + interp45Deg[i] = temp_interp45Deg[i]; + } + } + + f += EvalPoly6(interp45Deg, NVI(pphase_p45 * 64)) * w.z; + } + if (w.w > 0.0f) + { + //135 deg filter + NVF pphase_b135 = 0.5f * (phase_x_frac + phase_y_frac); + + NVF temp_interp135Deg[7]; + temp_interp135Deg[1] = lerp(p[3][1], p[4][2], pphase_b135); + temp_interp135Deg[3] = lerp(p[2][2], p[3][3], pphase_b135); + temp_interp135Deg[5] = lerp(p[1][3], p[2][4], pphase_b135); + { + pphase_b135 = pphase_b135 - 0.5f; + NVF a = (pphase_b135 >= 0.f) ? p[5][2] : p[3][0]; + NVF b = (pphase_b135 >= 0.f) ? p[4][3] : p[2][1]; + NVF c = (pphase_b135 >= 0.f) ? p[3][4] : p[1][2]; + NVF d = (pphase_b135 >= 0.f) ? p[2][5] : p[0][3]; + temp_interp135Deg[0] = lerp(p[4][1], a, abs(pphase_b135)); + temp_interp135Deg[2] = lerp(p[3][2], b, abs(pphase_b135)); + temp_interp135Deg[4] = lerp(p[2][3], c, abs(pphase_b135)); + temp_interp135Deg[6] = lerp(p[1][4], d, abs(pphase_b135)); + } + + NVF interp135Deg[6]; + NVF pphase_p135 = 1 + (phase_x_frac - phase_y_frac); + if (pphase_p135 >= 1) + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + interp135Deg[i] = temp_interp135Deg[i + 1]; + } + pphase_p135 = pphase_p135 - 1; + } + else + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + interp135Deg[i] = temp_interp135Deg[i]; + } + } + + f += EvalPoly6(interp135Deg, NVI(pphase_p135 * 64)) * w.w; + } + return f; +} + + +//----------------------------------------------------------------------------------------------- +// NVScaler +//----------------------------------------------------------------------------------------------- +void NVScaler(NVU2 blockIdx, NVU threadIdx) +{ + // Figure out the range of pixels from input image that would be needed to be loaded for this thread-block + NVI dstBlockX = NVI(NIS_BLOCK_WIDTH * blockIdx.x); + NVI dstBlockY = NVI(NIS_BLOCK_HEIGHT * blockIdx.y); + + const NVI srcBlockStartX = NVI(floor((dstBlockX + 0.5f) * kScaleX - 0.5f)); + const NVI srcBlockStartY = NVI(floor((dstBlockY + 0.5f) * kScaleY - 0.5f)); + const NVI srcBlockEndX = NVI(ceil((dstBlockX + NIS_BLOCK_WIDTH + 0.5f) * kScaleX - 0.5f)); + const NVI srcBlockEndY = NVI(ceil((dstBlockY + NIS_BLOCK_HEIGHT + 0.5f) * kScaleY - 0.5f)); + + NVI numTilePixelsX = srcBlockEndX - srcBlockStartX + kSupportSize - 1; + NVI numTilePixelsY = srcBlockEndY - srcBlockStartY + kSupportSize - 1; + + // round-up load region to even size since we're loading in 2x2 batches + numTilePixelsX += numTilePixelsX & 0x1; + numTilePixelsY += numTilePixelsY & 0x1; + const NVI numTilePixels = numTilePixelsX * numTilePixelsY; + + // calculate the equivalent values for the edge map + const NVI numEdgeMapPixelsX = numTilePixelsX - kSupportSize + 2; + const NVI numEdgeMapPixelsY = numTilePixelsY - kSupportSize + 2; + const NVI numEdgeMapPixels = numEdgeMapPixelsX * numEdgeMapPixelsY; + + // fill in input luma tile (shPixelsY) in batches of 2x2 pixels + // we use texture gather to get extra support necessary + // to compute 2x2 edge map outputs too + { + for (NVU i = threadIdx * 2; i < NVU(numTilePixels) >> 1; i += NIS_THREAD_GROUP_SIZE * 2) + { + NVU py = (i / numTilePixelsX) * 2; + NVU px = i % numTilePixelsX; + + // 0.5 to be in the center of texel + // - (kSupportSize - 1) / 2 to shift by the kernel support size + NVF kShift = 0.5f - (kSupportSize - 1) / 2; +#if NIS_VIEWPORT_SUPPORT + const NVF tx = (srcBlockStartX + px + kInputViewportOriginX + kShift) * kSrcNormX; + const NVF ty = (srcBlockStartY + py + kInputViewportOriginY + kShift) * kSrcNormY; +#else + const NVF tx = (srcBlockStartX + px + kShift) * kSrcNormX; + const NVF ty = (srcBlockStartY + py + kShift) * kSrcNormY; +#endif + NVF p[2][2]; +#if NIS_TEXTURE_GATHER + { + const NVF4 sr = NVTEX_SAMPLE_RED(in_texture, samplerLinearClamp, NVF2(tx, ty)); + const NVF4 sg = NVTEX_SAMPLE_GREEN(in_texture, samplerLinearClamp, NVF2(tx, ty)); + const NVF4 sb = NVTEX_SAMPLE_BLUE(in_texture, samplerLinearClamp, NVF2(tx, ty)); + + p[0][0] = getY(NVF3(sr.w, sg.w, sb.w)); + p[0][1] = getY(NVF3(sr.z, sg.z, sb.z)); + p[1][0] = getY(NVF3(sr.x, sg.x, sb.x)); + p[1][1] = getY(NVF3(sr.y, sg.y, sb.y)); + } +#else + NIS_UNROLL_INNER + for (NVI j = 0; j < 2; j++) + { + NIS_UNROLL_INNER + for (NVI k = 0; k < 2; k++) + { +#if NIS_NV12_SUPPORT + p[j][k] = NVTEX_SAMPLE(in_texture_y, samplerLinearClamp, NVF2(tx + k * kSrcNormX, ty + j * kSrcNormY)); +#else + const NVF4 px = NVTEX_SAMPLE(in_texture, samplerLinearClamp, NVF2(tx + k * kSrcNormX, ty + j * kSrcNormY)); + p[j][k] = getY(px.xyz); +#endif + } + } +#endif + const NVU idx = py * kTilePitch + px; + shPixelsY[idx] = NVH(p[0][0]); + shPixelsY[idx + 1] = NVH(p[0][1]); + shPixelsY[idx + kTilePitch] = NVH(p[1][0]); + shPixelsY[idx + kTilePitch + 1] = NVH(p[1][1]); + } + } + GroupMemoryBarrierWithGroupSync(); + { + // fill in the edge map of 2x2 pixels + for (NVU i = threadIdx * 2; i < NVU(numEdgeMapPixels) >> 1; i += NIS_THREAD_GROUP_SIZE * 2) + { + NVU py = (i / numEdgeMapPixelsX) * 2; + NVU px = i % numEdgeMapPixelsX; + + const NVU edgeMapIdx = py * kEdgeMapPitch + px; + + NVU tileCornerIdx = (py + 1) * kTilePitch + px + 1; + NVF p[4][4]; + NIS_UNROLL_INNER + for (NVI j = 0; j < 4; j++) + { + NIS_UNROLL_INNER + for (NVI k = 0; k < 4; k++) + { + p[j][k] = shPixelsY[tileCornerIdx + j * kTilePitch + k]; + } + } + + shEdgeMap[edgeMapIdx] = NVH4(GetEdgeMap(p, 0, 0)); + shEdgeMap[edgeMapIdx + 1] = NVH4(GetEdgeMap(p, 0, 1)); + shEdgeMap[edgeMapIdx + kEdgeMapPitch] = NVH4(GetEdgeMap(p, 1, 0)); + shEdgeMap[edgeMapIdx + kEdgeMapPitch + 1] = NVH4(GetEdgeMap(p, 1, 1)); + } + } + LoadFilterBanksSh(NVI(threadIdx)); + GroupMemoryBarrierWithGroupSync(); + + // output coord within a tile + const NVI2 pos = NVI2(NVU(threadIdx) % NVU(NIS_BLOCK_WIDTH), NVU(threadIdx) / NVU(NIS_BLOCK_WIDTH)); + // x coord inside the output image + const NVI dstX = dstBlockX + pos.x; + // x coord inside the input image + const NVF srcX = (0.5f + dstX) * kScaleX - 0.5f; + // nearest integer part + const NVI px = NVI(floor(srcX) - srcBlockStartX); + // fractional part + const NVF fx = srcX - floor(srcX); + // discretized phase + const NVI fx_int = NVI(fx * kPhaseCount); +#if NIS_VIEWPORT_SUPPORT + if (NVU(srcX) > kInputViewportWidth || NVU(dstX) > kOutputViewportWidth) + { + return; + } +#endif + for (NVI k = 0; k < NIS_BLOCK_WIDTH * NIS_BLOCK_HEIGHT / NIS_THREAD_GROUP_SIZE; ++k) + { + // y coord inside the output image + const NVI dstY = dstBlockY + pos.y + k * (NIS_THREAD_GROUP_SIZE / NIS_BLOCK_WIDTH); + // y coord inside the input image + const NVF srcY = (0.5f + dstY) * kScaleY - 0.5f; +#if NIS_VIEWPORT_SUPPORT + if (!(NVU(srcY) > kInputViewportHeight || NVU(dstY) > kOutputViewportHeight)) +#endif + { + // nearest integer part + const NVI py = NVI(floor(srcY) - srcBlockStartY); + // fractional part + const NVF fy = srcY - floor(srcY); + // discretized phase + const NVI fy_int = NVI(fy * kPhaseCount); + + // generate weights for directional filters + const NVI startEdgeMapIdx = py * kEdgeMapPitch + px; + NVF4 edge[2][2]; + NIS_UNROLL + for (NVI i = 0; i < 2; i++) + { + NIS_UNROLL + for (NVI j = 0; j < 2; j++) + { + // need to shift edge map sampling since it's a 2x2 centered inside 6x6 grid + edge[i][j] = shEdgeMap[startEdgeMapIdx + (i * kEdgeMapPitch) + j]; + } + } + const NVF4 w = GetInterpEdgeMap(edge, fx, fy) * NIS_SCALE_INT; + + // load 6x6 support to regs + const NVI startTileIdx = py * kTilePitch + px; + NVF p[6][6]; + { + NIS_UNROLL + for (NVI i = 0; i < 6; ++i) + { + NIS_UNROLL + for (NVI j = 0; j < 6; ++j) + { + p[i][j] = shPixelsY[startTileIdx + i * kTilePitch + j]; + } + } + } + + // weigth for luma + const NVF baseWeight = NIS_SCALE_FLOAT - w.x - w.y - w.z - w.w; + + // final luma is a weighted product of directional & normal filters + NVF opY = 0; + + // get traditional scaler filter output + opY += FilterNormal(p, fx_int, fy_int) * baseWeight; + + // get directional filter bank output + opY += AddDirFilters(p, fx, fy, fx_int, fy_int, w); + +#if NIS_VIEWPORT_SUPPORT + NVF2 coord = NVF2((srcX + kInputViewportOriginX + 0.5f) * kSrcNormX, (srcY + kInputViewportOriginY + 0.5f) * kSrcNormY); + NVF2 dstCoord = NVF2(dstX + kOutputViewportOriginX, dstY + kOutputViewportOriginY); +#else + NVF2 coord = NVF2((srcX + 0.5f) * kSrcNormX, (srcY + 0.5f) * kSrcNormY); + NVF2 dstCoord = NVF2(dstX, dstY); +#endif + // do bilinear tap for chroma upscaling +#if NIS_NV12_SUPPORT + NVF y = NVTEX_SAMPLE(in_texture_y, samplerLinearClamp, coord); + NVF2 uv = NVTEX_SAMPLE(in_texture_uv, samplerLinearClamp, coord); + NVF4 op = NVF4(YUVtoRGB(NVF3(y, uv)), 1.0f); +#else + NVF4 op = NVTEX_SAMPLE(in_texture, samplerLinearClamp, coord); + NVF y = getY(NVF3(op.x, op.y, op.z)); +#endif + +#if NIS_HDR_MODE == NIS_HDR_MODE_LINEAR + const NVF kEps = 1e-4f; + const NVF kNorm = 1.0f / (NIS_SCALE_FLOAT * kHDRCompressionFactor); + const NVF opYN = max(opY, 0.0f) * kNorm; + const NVF corr = (opYN * opYN + kEps) / (max(getYLinear(NVF3(op.x, op.y, op.z)), 0.0f) + kEps); + op.x *= corr; + op.y *= corr; + op.z *= corr; +#else + const NVF corr = opY * (1.0f / NIS_SCALE_FLOAT) - y; + op.x += corr; + op.y += corr; + op.z += corr; +#endif + NVTEX_STORE(out_texture, dstCoord, NVCLAMP(op)); + } + } +} +#else + +#ifndef NIS_BLOCK_WIDTH +#define NIS_BLOCK_WIDTH 32 +#endif +#ifndef NIS_BLOCK_HEIGHT +#define NIS_BLOCK_HEIGHT 32 +#endif +#ifndef NIS_THREAD_GROUP_SIZE +#define NIS_THREAD_GROUP_SIZE 256 +#endif + +#define kSupportSize 5 +#define kNumPixelsX (NIS_BLOCK_WIDTH + kSupportSize + 1) +#define kNumPixelsY (NIS_BLOCK_HEIGHT + kSupportSize + 1) + +NVSHARED NVF shPixelsY[kNumPixelsY][kNumPixelsX]; + +NVF CalcLTIFast(const NVF y[5]) +{ + const NVF a_min = min(min(y[0], y[1]), y[2]); + const NVF a_max = max(max(y[0], y[1]), y[2]); + + const NVF b_min = min(min(y[2], y[3]), y[4]); + const NVF b_max = max(max(y[2], y[3]), y[4]); + + const NVF a_cont = a_max - a_min; + const NVF b_cont = b_max - b_min; + + const NVF cont_ratio = max(a_cont, b_cont) / (min(a_cont, b_cont) + kEps); + return (1.0f - saturate((cont_ratio - kMinContrastRatio) * kRatioNorm)) * kContrastBoost; +} + +NVF EvalUSM(const NVF pxl[5], const NVF sharpnessStrength, const NVF sharpnessLimit) +{ + // USM profile + NVF y_usm = -0.6001f * pxl[1] + 1.2002f * pxl[2] - 0.6001f * pxl[3]; + // boost USM profile + y_usm *= sharpnessStrength; + // clamp to the limit + y_usm = min(sharpnessLimit, max(-sharpnessLimit, y_usm)); + // reduce ringing + y_usm *= CalcLTIFast(pxl); + + return y_usm; +} + +NVF4 GetDirUSM(const NVF p[5][5]) +{ + // sharpness boost & limit are the same for all directions + const NVF scaleY = 1.0f - saturate((p[2][2] - kSharpStartY) * kSharpScaleY); + // scale the ramp to sharpen as a function of luma + const NVF sharpnessStrength = scaleY * kSharpStrengthScale + kSharpStrengthMin; + // scale the ramp to limit USM as a function of luma + const NVF sharpnessLimit = (scaleY * kSharpLimitScale + kSharpLimitMin) * p[2][2]; + + NVF4 rval; + // 0 deg filter + NVF interp0Deg[5]; + { + for (NVI i = 0; i < 5; ++i) + { + interp0Deg[i] = p[i][2]; + } + } + + rval.x = EvalUSM(interp0Deg, sharpnessStrength, sharpnessLimit); + + // 90 deg filter + NVF interp90Deg[5]; + { + for (NVI i = 0; i < 5; ++i) + { + interp90Deg[i] = p[2][i]; + } + } + + rval.y = EvalUSM(interp90Deg, sharpnessStrength, sharpnessLimit); + + //45 deg filter + NVF interp45Deg[5]; + interp45Deg[0] = p[1][1]; + interp45Deg[1] = lerp(p[2][1], p[1][2], 0.5f); + interp45Deg[2] = p[2][2]; + interp45Deg[3] = lerp(p[3][2], p[2][3], 0.5f); + interp45Deg[4] = p[3][3]; + + rval.z = EvalUSM(interp45Deg, sharpnessStrength, sharpnessLimit); + + //135 deg filter + NVF interp135Deg[5]; + interp135Deg[0] = p[3][1]; + interp135Deg[1] = lerp(p[3][2], p[2][1], 0.5f); + interp135Deg[2] = p[2][2]; + interp135Deg[3] = lerp(p[2][3], p[1][2], 0.5f); + interp135Deg[4] = p[1][3]; + + rval.w = EvalUSM(interp135Deg, sharpnessStrength, sharpnessLimit); + return rval; +} + +//----------------------------------------------------------------------------------------------- +// NVSharpen +//----------------------------------------------------------------------------------------------- +void NVSharpen(NVU2 blockIdx, NVU threadIdx) +{ + const NVI dstBlockX = NVI(NIS_BLOCK_WIDTH * blockIdx.x); + const NVI dstBlockY = NVI(NIS_BLOCK_HEIGHT * blockIdx.y); + + // fill in input luma tile in batches of 2x2 pixels + // we use texture gather to get extra support necessary + // to compute 2x2 edge map outputs too + const NVF kShift = 0.5f - kSupportSize / 2; + + for (NVI i = NVI(threadIdx) * 2; i < kNumPixelsX * kNumPixelsY / 2; i += NIS_THREAD_GROUP_SIZE * 2) + { + NVU2 pos = NVU2(NVU(i) % NVU(kNumPixelsX), NVU(i) / NVU(kNumPixelsX) * 2); + NIS_UNROLL + for (NVI dy = 0; dy < 2; dy++) + { + NIS_UNROLL + for (NVI dx = 0; dx < 2; dx++) + { +#if NIS_VIEWPORT_SUPPORT + const NVF tx = (dstBlockX + pos.x + kInputViewportOriginX + dx + kShift) * kSrcNormX; + const NVF ty = (dstBlockY + pos.y + kInputViewportOriginY + dy + kShift) * kSrcNormY; +#else + const NVF tx = (dstBlockX + pos.x + dx + kShift) * kSrcNormX; + const NVF ty = (dstBlockY + pos.y + dy + kShift) * kSrcNormY; +#endif +#if NIS_NV12_SUPPORT + shPixelsY[pos.y + dy][pos.x + dx] = NVTEX_SAMPLE(in_texture_y, samplerLinearClamp, NVF2(tx, ty)); +#else + const NVF4 px = NVTEX_SAMPLE(in_texture, samplerLinearClamp, NVF2(tx, ty)); + shPixelsY[pos.y + dy][pos.x + dx] = getY(px.xyz); +#endif + } + } + } + + GroupMemoryBarrierWithGroupSync(); + + for (NVI k = NVI(threadIdx); k < NIS_BLOCK_WIDTH * NIS_BLOCK_HEIGHT; k += NIS_THREAD_GROUP_SIZE) + { + const NVI2 pos = NVI2(NVU(k) % NVU(NIS_BLOCK_WIDTH), NVU(k) / NVU(NIS_BLOCK_WIDTH)); + + // load 5x5 support to regs + NVF p[5][5]; + NIS_UNROLL + for (NVI i = 0; i < 5; ++i) + { + NIS_UNROLL + for (NVI j = 0; j < 5; ++j) + { + p[i][j] = shPixelsY[pos.y + i][pos.x + j]; + } + } + + // get directional filter bank output + NVF4 dirUSM = GetDirUSM(p); + + // generate weights for directional filters + NVF4 w = GetEdgeMap(p, kSupportSize / 2 - 1, kSupportSize / 2 - 1); + + // final USM is a weighted sum filter outputs + const NVF usmY = (dirUSM.x * w.x + dirUSM.y * w.y + dirUSM.z * w.z + dirUSM.w * w.w); + + // do bilinear tap and correct rgb texel so it produces new sharpened luma + const NVI dstX = dstBlockX + pos.x; + const NVI dstY = dstBlockY + pos.y; + +#if NIS_VIEWPORT_SUPPORT + NVF2 coord = NVF2((dstX + kInputViewportOriginX + 0.5f) * kSrcNormX, (dstY + kInputViewportOriginY + 0.5f) * kSrcNormY); + NVF2 dstCoord = NVF2(dstX + kOutputViewportOriginX, dstY + kOutputViewportOriginY); + if (!(NVU(dstX) > kOutputViewportWidth || NVU(dstY) > kOutputViewportHeight)) +#else + NVF2 coord = NVF2((dstX + 0.5f) * kSrcNormX, (dstY + 0.5f) * kSrcNormY); + NVF2 dstCoord = NVF2(dstX, dstY); +#endif + { +#if NIS_NV12_SUPPORT + NVF y = NVTEX_SAMPLE(in_texture_y, samplerLinearClamp, coord); + NVF2 uv = NVTEX_SAMPLE(in_texture_uv, samplerLinearClamp, coord); + NVF4 op = NVF4(YUVtoRGB(NVF3(y, uv)), 1.0f); +#else + NVF4 op = NVTEX_SAMPLE(in_texture, samplerLinearClamp, coord); +#endif +#if NIS_HDR_MODE == NIS_HDR_MODE_LINEAR + const NVF kEps = 1e-4f * kHDRCompressionFactor * kHDRCompressionFactor; + NVF newY = p[2][2] + usmY; + newY = max(newY, 0.0f); + const NVF oldY = p[2][2]; + const NVF corr = (newY * newY + kEps) / (oldY * oldY + kEps); + op.x *= corr; + op.y *= corr; + op.z *= corr; +#else + op.x += usmY; + op.y += usmY; + op.z += usmY; +#endif + NVTEX_STORE(out_texture, dstCoord, NVCLAMP(op)); + } + } +} +#endif \ No newline at end of file diff --git a/app/shaders/enhancer/QUALCOMM/LICENSE.txt b/app/shaders/enhancer/QUALCOMM/LICENSE.txt new file mode 100644 index 000000000..d9d513c75 --- /dev/null +++ b/app/shaders/enhancer/QUALCOMM/LICENSE.txt @@ -0,0 +1,29 @@ +Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +SPDX-License-Identifier: BSD-3-Clause \ No newline at end of file diff --git a/app/shaders/enhancer/QUALCOMM/sgsr1.h b/app/shaders/enhancer/QUALCOMM/sgsr1.h new file mode 100644 index 000000000..96ea277de --- /dev/null +++ b/app/shaders/enhancer/QUALCOMM/sgsr1.h @@ -0,0 +1,163 @@ +//============================================================================================================ +// +// +// Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// +//============================================================================================================ + +//////////////////////// +// USER CONFIGURATION // +//////////////////////// + +/* +* Operation modes: +* RGBA -> 1 +* RGBY -> 3 +* LERP -> 4 +*/ +#define OperationMode 1 + +/* +* If set, will use edge direction to improve visual quality +* Expect a minimal cost increase +*/ +#define UseEdgeDirection + +#define EdgeThreshold 6.0/255.0 + +#define EdgeSharpness 1.5 + +//////////////////////// +//////////////////////// +//////////////////////// + +// ///////SGSR_GL_Mobile.frag///////////////////////////////////////// +#if defined(SGSR_MOBILE) +half fastLanczos2(half x) +{ + half wA = x- half(4.0); + half wB = x*wA-wA; + wA *= wA; + return wB*wA; +} + +#if defined(UseEdgeDirection) +half2 weightY(half dx, half dy, half c, half3 data) +#else +half2 weightY(half dx, half dy, half c, half data) +#endif +{ +#if defined(UseEdgeDirection) + half std = data.x; + half2 dir = data.yz; + + half edgeDis = ((dx*dir.y)+(dy*dir.x)); + half x = (((dx*dx)+(dy*dy))+((edgeDis*edgeDis)*((clamp(((c*c)*std),0.0,1.0)*0.7)+-1.0))); +#else + half std = data; + half x = ((dx*dx)+(dy* dy))* half(0.5) + clamp(abs(c)*std, 0.0, 1.0); +#endif + + half w = fastLanczos2(x); + return half2(w, w * c); +} + +half2 edgeDirection(half4 left, half4 right) +{ + half2 dir; + half RxLz = (right.x + (-left.z)); + half RwLy = (right.w + (-left.y)); + half2 delta; + delta.x = (RxLz + RwLy); + delta.y = (RxLz + (-RwLy)); + half lengthInv = rsqrt((delta.x * delta.x+ 3.075740e-05) + (delta.y * delta.y)); + dir.x = (delta.x * lengthInv); + dir.y = (delta.y * lengthInv); + return dir; +} + +void SgsrYuvH( + out half4 pix, + float2 uv, + float4 con1) +{ + int mode = OperationMode; + half edgeThreshold = EdgeThreshold; + half edgeSharpness = EdgeSharpness; + if(mode == 1) + pix.xyz = SGSRRGBH(uv).xyz; + else + pix.xyzw = SGSRRGBH(uv).xyzw; + float xCenter; + xCenter = abs(uv.x+-0.5); + float yCenter; + yCenter = abs(uv.y+-0.5); + + //todo: config the SR region based on needs + //if ( mode!=4 && xCenter*xCenter+yCenter*yCenter<=0.4 * 0.4) + if ( mode!=4) + { + float2 imgCoord = ((uv.xy*con1.zw)+ float2(-0.5,0.5)); + float2 imgCoordPixel = floor(imgCoord); + float2 coord = (imgCoordPixel*con1.xy); + half2 pl = (imgCoord+(-imgCoordPixel)); + half4 left = SGSRH(coord, mode); + + half edgeVote = abs(left.z - left.y) + abs(pix[mode] - left.y) + abs(pix[mode] - left.z) ; + if(edgeVote > edgeThreshold) + { + coord.x += con1.x; + + half4 right = SGSRH(coord + float2(con1.x, 0.0), mode); + half4 upDown; + upDown.xy = SGSRH(coord + float2(0.0, -con1.y), mode).wz; + upDown.zw = SGSRH(coord + float2(0.0, con1.y), mode).yx; + + half mean = (left.y+left.z+right.x+right.w)* half(0.25); + left = left - half4(mean,mean,mean,mean); + right = right - half4(mean, mean, mean, mean); + upDown = upDown - half4(mean, mean, mean, mean); + pix.w =pix[mode] - mean; + + half sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w))+(((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w)))+(((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w))); + half sumMean = 1.014185e+01/sum; + half std = (sumMean*sumMean); + +#if defined(UseEdgeDirection) + half3 data = half3(std, edgeDirection(left, right)); +#else + half data = std; +#endif + + half2 aWY = weightY(pl.x, pl.y+1.0, upDown.x,data); + aWY += weightY(pl.x-1.0, pl.y+1.0, upDown.y,data); + aWY += weightY(pl.x-1.0, pl.y-2.0, upDown.z,data); + aWY += weightY(pl.x, pl.y-2.0, upDown.w,data); + aWY += weightY(pl.x+1.0, pl.y-1.0, left.x,data); + aWY += weightY(pl.x, pl.y-1.0, left.y,data); + aWY += weightY(pl.x, pl.y, left.z,data); + aWY += weightY(pl.x+1.0, pl.y, left.w,data); + aWY += weightY(pl.x-1.0, pl.y-1.0, right.x,data); + aWY += weightY(pl.x-2.0, pl.y-1.0, right.y,data); + aWY += weightY(pl.x-2.0, pl.y, right.z,data); + aWY += weightY(pl.x-1.0, pl.y, right.w,data); + + half finalY = aWY.y/aWY.x; + + half max4 = max(max(left.y,left.z),max(right.x,right.w)); + half min4 = min(min(left.y,left.z),min(right.x,right.w)); + finalY = clamp(edgeSharpness*finalY, min4, max4); + + half deltaY = finalY -pix.w; + + pix.x = saturate((pix.x+deltaY)); + pix.y = saturate((pix.y+deltaY)); + pix.z = saturate((pix.z+deltaY)); + } + } + pix.w = 1.0; //assume alpha channel is not used + +} +#endif +//////////////////////////////////////////////////////////////////////// diff --git a/app/shaders/enhancer/QUALCOMM/sgsr1_shader.hlsl b/app/shaders/enhancer/QUALCOMM/sgsr1_shader.hlsl new file mode 100644 index 000000000..745d81c39 --- /dev/null +++ b/app/shaders/enhancer/QUALCOMM/sgsr1_shader.hlsl @@ -0,0 +1,102 @@ +//============================================================================================================ +// +// +// Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// +//============================================================================================================ + +#define SGSR_MOBILE + +cbuffer PerFrameConstants : register (b0) +{ + float4 ViewportInfo; +} + +// ============================================================================ +// VERTEX SHADER OUTPUT STRUCTURE +// ============================================================================ + +struct VS_OUTPUT { + float4 position : SV_POSITION; + float2 texCoord : TEXCOORD0; +}; + +// ============================================================================ +// VERTEX SHADER +// ============================================================================ + +VS_OUTPUT mainVS(uint vertexID : SV_VertexID) +{ + VS_OUTPUT output; + + output.texCoord = float2((vertexID << 1) & 2, vertexID & 2); + output.position = float4(output.texCoord * float2(2, -2) + float2(-1, 1), 0, 1); + + return output; +} + +// ============================================================================ +// PIXEL SHADER (Upscaler) +// ============================================================================ + +SamplerState samLinearClamp : register(s0); // Not set from the code, but default LINEAR + CLAMP is fine. +Texture2D InputTexture : register(t0); +#define SGSR_H 1 + +half4 SGSRRH(float2 p) +{ + half4 res = InputTexture.GatherRed(samLinearClamp, p); + return res; +} +half4 SGSRGH(float2 p) +{ + half4 res = InputTexture.GatherGreen(samLinearClamp, p); + return res; +} +half4 SGSRBH(float2 p) +{ + half4 res = InputTexture.GatherBlue(samLinearClamp, p); + return res; +} +half4 SGSRAH(float2 p) +{ + half4 res = InputTexture.GatherAlpha(samLinearClamp, p); + return res; +} +half4 SGSRRGBH(float2 p) +{ + half4 res = InputTexture.SampleLevel(samLinearClamp, p, 0); + return res; +} + +half4 SGSRH(float2 p, uint channel) +{ + if (channel == 0) + return SGSRRH(p); + if (channel == 1) + return SGSRGH(p); + if (channel == 2) + return SGSRBH(p); + return SGSRAH(p); +} + +#include "sgsr1.h" + +// ===================================================================================== +// +// SNAPDRAGON GAME SUPER RESOLUTION +// +// ===================================================================================== + +half4 SnapdragonGameSuperResolution(float2 uv) +{ + half4 OutColor = half4(0, 0, 0, 1); + SgsrYuvH(OutColor, uv, ViewportInfo); + return OutColor; +} + +half4 mainPS (float4 position : SV_POSITION, float2 uv : TEXCOORD) : SV_TARGET +{ + return SnapdragonGameSuperResolution(uv); +} diff --git a/app/shaders/enhancer/copy_cs.hlsl b/app/shaders/enhancer/copy_cs.hlsl new file mode 100644 index 000000000..28cb713ff --- /dev/null +++ b/app/shaders/enhancer/copy_cs.hlsl @@ -0,0 +1,10 @@ +// Copy RGBA to RGBA + +Texture2D g_Input : register(t0); +RWTexture2D g_Output : register(u0); + +[numthreads(16, 16, 1)] +void mainCS(uint3 DTid : SV_DispatchThreadID) +{ + g_Output[DTid.xy] = g_Input.Load(int3(DTid.xy, 0)); +} diff --git a/app/shaders/enhancer/overlay_ps.hlsl b/app/shaders/enhancer/overlay_ps.hlsl new file mode 100644 index 000000000..ccdbe7bd7 --- /dev/null +++ b/app/shaders/enhancer/overlay_ps.hlsl @@ -0,0 +1,13 @@ +Texture2D tex0 : register(t0); +SamplerState samp0 : register(s0); + +struct PSInput { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 color : COLOR0; +}; + +float4 main(PSInput pin) : SV_TARGET { + float4 texColor = tex0.Sample(samp0, pin.uv); + return lerp(pin.color, texColor, texColor.a); +} diff --git a/app/shaders/enhancer/overlay_vs.hlsl b/app/shaders/enhancer/overlay_vs.hlsl new file mode 100644 index 000000000..21354cc1a --- /dev/null +++ b/app/shaders/enhancer/overlay_vs.hlsl @@ -0,0 +1,19 @@ +struct VSInput { + float2 pos : POSITION0; + float2 uv : TEXCOORD0; + float4 color : COLOR0; +}; + +struct PSInput { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 color : COLOR0; +}; + +PSInput main(VSInput vin) { + PSInput vout; + vout.pos = float4(vin.pos, 0.0f, 1.0f); + vout.uv = vin.uv; + vout.color = vin.color; + return vout; +} diff --git a/app/shaders/enhancer/yuv_to_rgb_ps.hlsl b/app/shaders/enhancer/yuv_to_rgb_ps.hlsl new file mode 100644 index 000000000..7fc15b638 --- /dev/null +++ b/app/shaders/enhancer/yuv_to_rgb_ps.hlsl @@ -0,0 +1,259 @@ +// Pixel Shader +// Convert YUV -> Linear RGB +// Supports NV12, P010, AYUV, Y410 input +// Compile with Shader 6.2 and "-enable-16bit-types" + +// Input format enum +#define FMT_NV12 0 +#define FMT_P010 1 +#define FMT_AYUV 2 +#define FMT_Y410 3 + +// Gamma / color space +#define GC_LINEAR 0 +#define GC_G22 1 +#define GC_G24 2 +#define GC_PQ 3 + +// Output enum +#define OUT_RGBA8 0 +#define OUT_RGB10 1 + +// Color range +#define CR_LIMITED 0 +#define CR_FULL 1 + +// Root constants: small cbuffer (SetGraphicsRoot32BitConstants alternative) +cbuffer RootConsts : register(b0) +{ + // SDR and HDR invert bits + // Block 0 (0->16) + float g_INV_8BIT : packoffset(c0.x); + float g_INV_10BIT : packoffset(c0.y); + + // PQ converter constants + // Block 1 (16->32) + float g_M1Inv : packoffset(c1.x); + float g_M2Inv : packoffset(c1.y); + float g_C1 : packoffset(c1.z); + float g_C2 : packoffset(c1.w); + // Block 2 (32->48) + float g_C3 : packoffset(c2.x); + + // CSC matrix rows + // Block 3 (48->64) + float g_CSC_Row0_x : packoffset(c3.x); + float g_CSC_Row0_y : packoffset(c3.y); + float g_CSC_Row0_z : packoffset(c3.z); + + // Block 4 (64->80) + float g_CSC_Row1_x : packoffset(c4.x); + float g_CSC_Row1_y : packoffset(c4.y); + float g_CSC_Row1_z : packoffset(c4.z); + + // Block 5 (80->96) + float g_CSC_Row2_x : packoffset(c5.x); + float g_CSC_Row2_y : packoffset(c5.y); + float g_CSC_Row2_z : packoffset(c5.z); + + // Color range and YUV Offset + // Block 6 (96->112) + float g_ScaleY : packoffset(c6.x); + float g_OffsetY : packoffset(c6.y); + float g_OffsetU : packoffset(c6.z); + float g_OffsetV : packoffset(c6.w); + + // Texture format In/Out + // Block 7 (112->128) + uint g_InputFormat : packoffset(c7.x); + uint g_OutputFormat : packoffset(c7.y); + uint g_GammaCorrection : packoffset(c7.z); + uint g_Range : packoffset(c7.w); +}; + +// Texture2D Plane Y (luminance) or AYUV/Y410 +Texture2D g_TexY : register(t0); + +// Texture2D Plane UV (chrominance) +Texture2D g_TexUV : register(t1); + +// Sampler Point for perfomance +SamplerState g_SamplerPoint : register(s0); + +// ============================================================================ +// VERTEX SHADER OUTPUT STRUCTURE +// ============================================================================ + +struct VS_OUTPUT { + float4 position : SV_POSITION; + float2 texCoord : TEXCOORD0; +}; + +// ============================================================================ +// VERTEX SHADER +// ============================================================================ + +VS_OUTPUT mainVS(uint vertexID : SV_VertexID) +{ + VS_OUTPUT output; + + output.texCoord = float2((vertexID << 1) & 2, vertexID & 2); + output.position = float4(output.texCoord * float2(2, -2) + float2(-1, 1), 0, 1); + + return output; +} + +// ============================================================================ +// PIXEL SHADER (Convert YUV -> RGB + Gamma -> Linear) +// ============================================================================ + +#if ADVANCED_SHADER + + float4 mainPS(VS_OUTPUT input) : SV_TARGET + { + // Convert to half + float16_t g16_INV_8BIT = (float16_t)g_INV_8BIT; + float16_t g16_INV_10BIT = (float16_t)g_INV_10BIT; + + float16_t g16_M1Inv = (float16_t)g_M1Inv; + float16_t g16_M2Inv = (float16_t)g_M2Inv; + float16_t g16_C1 = (float16_t)g_C1; + float16_t g16_C2 = (float16_t)g_C2; + float16_t g16_C3 = (float16_t)g_C3; + + float16_t g16_CSC_Row0_x = (float16_t)g_CSC_Row0_x; + float16_t g16_CSC_Row0_y = (float16_t)g_CSC_Row0_y; + float16_t g16_CSC_Row0_z = (float16_t)g_CSC_Row0_z; + + float16_t g16_CSC_Row1_x = (float16_t)g_CSC_Row1_x; + float16_t g16_CSC_Row1_y = (float16_t)g_CSC_Row1_y; + float16_t g16_CSC_Row1_z = (float16_t)g_CSC_Row1_z; + + float16_t g16_CSC_Row2_x = (float16_t)g_CSC_Row2_x; + float16_t g16_CSC_Row2_y = (float16_t)g_CSC_Row2_y; + float16_t g16_CSC_Row2_z = (float16_t)g_CSC_Row2_z; + + float16_t g16_ScaleY = (float16_t)g_ScaleY; + float16_t g16_OffsetY = (float16_t)g_OffsetY; + float16_t g16_OffsetU = (float16_t)g_OffsetU; + float16_t g16_OffsetV = (float16_t)g_OffsetV; + + uint16_t g16_InputFormat = (uint16_t)g_InputFormat; + uint16_t g16_OutputFormat = (uint16_t)g_OutputFormat; + uint16_t g16_GammaCorrection = (uint16_t)g_GammaCorrection; + uint16_t g16_Range = (uint16_t)g_Range; + + // sample into float then convert to half (texture fetch typically returns float) + float yf = 0.0f; + float2 uvf = float2(0.0f, 0.0f); + + if (g16_InputFormat == FMT_NV12) + { + yf = g_TexY.Sample(g_SamplerPoint, input.texCoord).r; + uvf = g_TexUV.Sample(g_SamplerPoint, input.texCoord).rg; + } + else if (g_InputFormat == FMT_P010) + { + yf = g_TexY.Sample(g_SamplerPoint, input.texCoord).r; + uvf = g_TexUV.Sample(g_SamplerPoint, input.texCoord).rg; + } + else if (g16_InputFormat == FMT_AYUV) + { + float4 packed = g_TexY.Sample(g_SamplerPoint, input.texCoord); + yf = packed.b; + uvf = packed.gr; + } + else if (g16_InputFormat == FMT_Y410) + { + float4 packed = g_TexY.Sample(g_SamplerPoint, input.texCoord); + yf = packed.g; + uvf = packed.rb; + } + else + { + return float4(0.0f, 1.0f, 0.0f, 1.0f); + } + + // Convert into half domain for processing + float16_t y = float16_t(yf); + float16_t2 uv = float16_t2(uvf); + // Range conversion: limited [16..235] -> [0..1] if required + if (g16_Range == CR_LIMITED) + { + y = y - float16_t(g16_OffsetY); + } + + // Subtract offsets (offsets stored in cbuffer as min16float) + float16_t u = uv.x - float16_t(g16_OffsetU); + float16_t v = uv.y - float16_t(g16_OffsetV); + float16_t3 yuv = float16_t3(y, u, v); + + // Multiply by CSC (Y'CbCr -> R'G'B') + float16_t3 rgbPrime; + rgbPrime.r = dot(yuv, float16_t3(g16_CSC_Row0_x, g16_CSC_Row0_y, g16_CSC_Row0_z)); + rgbPrime.g = dot(yuv, float16_t3(g16_CSC_Row1_x, g16_CSC_Row1_y, g16_CSC_Row1_z)); + rgbPrime.b = dot(yuv, float16_t3(g16_CSC_Row2_x, g16_CSC_Row2_y, g16_CSC_Row2_z)); + + return float4((float16_t3)saturate(rgbPrime), 1.0f); + } + +#else + + float4 mainPS(VS_OUTPUT input) : SV_TARGET + { + float yf = 0.0f; + float2 uvf = float2(0.0f, 0.0f); + + if (g_InputFormat == FMT_NV12) + { + yf = g_TexY.Sample(g_SamplerPoint, input.texCoord).r; + uvf = g_TexUV.Sample(g_SamplerPoint, input.texCoord).rg; + } + else if (g_InputFormat == FMT_P010) + { + yf = g_TexY.Sample(g_SamplerPoint, input.texCoord).r; + uvf = g_TexUV.Sample(g_SamplerPoint, input.texCoord).rg; + } + else if (g_InputFormat == FMT_AYUV) + { + float4 packed = g_TexY.Sample(g_SamplerPoint, input.texCoord); + yf = packed.b; + uvf = packed.gr; + } + else if (g_InputFormat == FMT_Y410) + { + float4 packed = g_TexY.Sample(g_SamplerPoint, input.texCoord); + yf = packed.g; + uvf = packed.rb; + } + else + { + return float4(0.0f, 1.0f, 0.0f, 1.0f); + } + + // Convert into half domain for processing + float y = float(yf); + float2 uv = float2(uvf); + // Range conversion: limited [16..235] -> [0..1] if required + if (g_Range == CR_LIMITED) + { + y = y - float(g_OffsetY); + } + + // Subtract offsets (offsets stored in cbuffer as min16float) + float u = uv.x - float(g_OffsetU); + float v = uv.y - float(g_OffsetV); + float3 yuv = float3(y, u, v); + + // Multiply by CSC (Y'CbCr -> R'G'B') + float3 rgbPrime; + rgbPrime.r = dot(yuv, float3(g_CSC_Row0_x, g_CSC_Row0_y, g_CSC_Row0_z)); + rgbPrime.g = dot(yuv, float3(g_CSC_Row1_x, g_CSC_Row1_y, g_CSC_Row1_z)); + rgbPrime.b = dot(yuv, float3(g_CSC_Row2_x, g_CSC_Row2_y, g_CSC_Row2_z)); + + return float4((float3)saturate(rgbPrime), 1.0f); + } + +#endif + + diff --git a/app/streaming/session.cpp b/app/streaming/session.cpp index 40c1e59c8..1bcbac274 100644 --- a/app/streaming/session.cpp +++ b/app/streaming/session.cpp @@ -278,7 +278,7 @@ void Session::clSetAdaptiveTriggers(uint16_t controllerNumber, uint8_t eventFlag bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, StreamingPreferences::RendererSelection renderer, SDL_Window* window, int videoFormat, int width, int height, - int frameRate, bool enableVsync, bool enableFramePacing, bool testOnly, IVideoDecoder*& chosenDecoder) + int frameRate, bool enableVsync, bool enableFramePacing, bool enableVideoEnhancement, bool testOnly, IVideoDecoder*& chosenDecoder) { DECODER_PARAMETERS params; @@ -294,6 +294,7 @@ bool Session::chooseDecoder(StreamingPreferences::VideoDecoderSelection vds, params.window = window; params.enableVsync = enableVsync; params.enableFramePacing = enableFramePacing; + params.enableVideoEnhancement = enableVideoEnhancement; params.testOnly = testOnly; params.vds = vds; params.renderer = renderer; @@ -400,7 +401,7 @@ void Session::getDecoderInfo(SDL_Window* window, if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_H265_MAIN10, 1920, 1080, 60, - false, false, true, decoder)) { + false, false, StreamingPreferences::get()->videoEnhancing, true, decoder)) { isHardwareAccelerated = decoder->isHardwareAccelerated(); isFullScreenOnly = decoder->isAlwaysFullScreen(); isHdrSupported = decoder->isHdrSupported(); @@ -414,7 +415,7 @@ void Session::getDecoderInfo(SDL_Window* window, if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_AV1_MAIN10, 1920, 1080, 60, - false, false, true, decoder)) { + false, false, StreamingPreferences::get()->videoEnhancing, true, decoder)) { // If we've got a working AV1 Main 10-bit decoder, we'll enable the HDR checkbox // but we will still continue probing to get other attributes for HEVC or H.264 // decoders. See the AV1 comment at the top of the function for more info. @@ -427,11 +428,11 @@ void Session::getDecoderInfo(SDL_Window* window, if (chooseDecoder(StreamingPreferences::VDS_FORCE_SOFTWARE, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_H265_MAIN10, 1920, 1080, 60, - false, false, true, decoder) || + false, false, false, true, decoder) || chooseDecoder(StreamingPreferences::VDS_FORCE_SOFTWARE, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_AV1_MAIN10, 1920, 1080, 60, - false, false, true, decoder)) { + false, false, false, true, decoder)) { isHdrSupported = decoder->isHdrSupported(); delete decoder; } @@ -446,7 +447,7 @@ void Session::getDecoderInfo(SDL_Window* window, if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_H265, 1920, 1080, 60, - false, false, true, decoder)) { + false, false, StreamingPreferences::get()->videoEnhancing, true, decoder)) { isHardwareAccelerated = decoder->isHardwareAccelerated(); isFullScreenOnly = decoder->isAlwaysFullScreen(); maxResolution = decoder->getDecoderMaxResolution(); @@ -460,7 +461,7 @@ void Session::getDecoderInfo(SDL_Window* window, if (chooseDecoder(StreamingPreferences::VDS_FORCE_HARDWARE, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_AV1_MAIN8, 1920, 1080, 60, - false, false, true, decoder)) { + false, false, m_Preferences->videoEnhancing, true, decoder)) { isHardwareAccelerated = decoder->isHardwareAccelerated(); isFullScreenOnly = decoder->isAlwaysFullScreen(); maxResolution = decoder->getDecoderMaxResolution(); @@ -475,7 +476,7 @@ void Session::getDecoderInfo(SDL_Window* window, if (chooseDecoder(StreamingPreferences::VDS_AUTO, StreamingPreferences::RS_PROBE_ONLY, window, VIDEO_FORMAT_H264, 1920, 1080, 60, - false, false, true, decoder)) { + false, false, StreamingPreferences::get()->videoEnhancing, true, decoder)) { isHardwareAccelerated = decoder->isHardwareAccelerated(); isFullScreenOnly = decoder->isAlwaysFullScreen(); maxResolution = decoder->getDecoderMaxResolution(); @@ -498,7 +499,7 @@ Session::getDecoderAvailability(SDL_Window* window, if (!chooseDecoder(vds, StreamingPreferences::RS_PROBE_ONLY, window, videoFormat, width, height, frameRate, - false, false, true, decoder)) { + false, false, StreamingPreferences::get()->videoEnhancing, true, decoder)) { return DecoderAvailability::None; } @@ -524,7 +525,7 @@ bool Session::populateDecoderProperties(SDL_Window* window) m_StreamConfig.width, m_StreamConfig.height, m_StreamConfig.fps, - false, false, true, decoder)) { + false, false, m_Preferences->videoEnhancing, true, decoder)) { return false; } @@ -2214,6 +2215,7 @@ void Session::exec() m_ActiveVideoHeight, m_ActiveVideoFrameRate, enableVsync, enableVsync && m_Preferences->framePacing, + m_Preferences->videoEnhancing, false, s_ActiveSession->m_VideoDecoder)) { SDL_UnlockMutex(m_DecoderLock); diff --git a/app/streaming/session.h b/app/streaming/session.h index 53ac9e06b..8b375bcfe 100644 --- a/app/streaming/session.h +++ b/app/streaming/session.h @@ -187,7 +187,7 @@ class Session : public QObject StreamingPreferences::RendererSelection renderer, SDL_Window* window, int videoFormat, int width, int height, int frameRate, bool enableVsync, bool enableFramePacing, - bool testOnly, + bool enableVideoEnhancement, bool testOnly, IVideoDecoder*& chosenDecoder); static diff --git a/app/streaming/video/decoder.h b/app/streaming/video/decoder.h index 2214850ab..5a75737f3 100644 --- a/app/streaming/video/decoder.h +++ b/app/streaming/video/decoder.h @@ -41,9 +41,12 @@ typedef struct _DECODER_PARAMETERS { int videoFormat; int width; int height; + int textureWidth; + int textureHeight; int frameRate; bool enableVsync; bool enableFramePacing; + bool enableVideoEnhancement; bool testOnly; } DECODER_PARAMETERS, *PDECODER_PARAMETERS; diff --git a/app/streaming/video/ffmpeg-renderers/d3d12va.cpp b/app/streaming/video/ffmpeg-renderers/d3d12va.cpp new file mode 100644 index 000000000..5ee44318f --- /dev/null +++ b/app/streaming/video/ffmpeg-renderers/d3d12va.cpp @@ -0,0 +1,6454 @@ +#include "d3d12va.h" + +// Standard DXVA GUIDs for HEVC RExt profiles (redefined for compatibility with pre-24H2 SDKs) +DEFINE_GUID(k_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN_444, 0x4008018f, 0xf537, 0x4b36, 0x98, 0xcf, 0x61, 0xaf, 0x8a, 0x2c, 0x1a, 0x33); +DEFINE_GUID(k_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10_444, 0x0dabeffa, 0x4458, 0x4602, 0xbc, 0x03, 0x07, 0x95, 0x65, 0x9d, 0x61, 0x7c); + +bool D3D12VARenderer::m_IsFrameHDR = false; +bool D3D12VARenderer::m_IsClientHDR = false; +int D3D12VARenderer::m_VsrQualityLevel = 0; +int D3D12VARenderer::m_VsrQualityCap = 0; + +/** + * \brief Constructor + */ +D3D12VARenderer::D3D12VARenderer(int decoderSelectionPass): + IFFmpegRenderer(RendererType::D3D12VA), + m_SkipFrame(false), + m_VideoEnhancement(&VideoEnhancement::getInstance()), + m_Preferences(StreamingPreferences::get()), + m_OverlayLock(0), + m_HwDeviceContext(nullptr), + m_AmfInitialized(false), + m_IntelInitialized(false), + m_NvidiaInitialized(false), + m_AmfContext(nullptr), + m_AmfData(nullptr), + m_AmfUpscalerYUV(nullptr), + m_AmfVideoConverter(nullptr), + m_AmfUpscalerRGB(nullptr), + m_AmfVideoConverterUpscaled(nullptr), + m_AmfSurfaceYUV(nullptr), + m_AmfSurfaceRGB(nullptr), + m_AmfSurfaceUpscaledYUV(nullptr), + m_AmfSurfaceUpscaledRGB(nullptr), + m_VSRFeature(nullptr), + m_TrueHDRFeature(nullptr), + m_VppSession(nullptr) +{ + Q_UNUSED(decoderSelectionPass); + + m_ContextLock = SDL_CreateMutex(); + + // Give a High CPU priority to this thread + DwmEnableMMCSS(TRUE); + + QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, []() + { + // When the application leave, make sure we reset the Display setting + ChangeDisplaySettingsW(nullptr, 0); + }); +} + +/** + * \brief Destructor + */ +D3D12VARenderer::~D3D12VARenderer() +{ + DwmEnableMMCSS(FALSE); + + // Reset the Display setting + ChangeDisplaySettingsW(nullptr, 0); + + SDL_DestroyMutex(m_ContextLock); + + // Wait for the thread to finish properly + m_cancelHDRUpdate = true; + m_HDRUpdateFuture.waitForFinished(); + waitForVideoProcess(true); + waitForGraphics(true); + waitForOverlay(true); + + if (m_FenceVideoProcessEvent) CloseHandle(m_FenceVideoProcessEvent); + if (m_FenceGraphicsEvent) CloseHandle(m_FenceGraphicsEvent); + if (m_FenceOverlayEvent) CloseHandle(m_FenceOverlayEvent); + if (m_FenceAMFEvent) CloseHandle(m_FenceAMFEvent); + + // Textures + m_D3D11FrameTexture.Reset(); + m_FrameTexture.Reset(); + m_RGBTexture.Reset(); + m_RGBTextureUpscaled.Reset(); + m_YUVTextureUpscaled.Reset(); + m_OutputTexture.Reset(); + m_OutputTexturePrevious.Reset(); + for (auto& item : m_OverlayTextures) { + item.Reset(); + } + for (auto& item : m_BackBuffers) { + item.Reset(); + } + + // Clean Shaders + m_ShaderConverter.reset(); + m_ShaderUpscaler.reset(); + + m_OverlayPSO.Reset(); + m_OverlayRootSignature.Reset(); + m_OverlaySrvHeap.Reset(); + m_RtvHeap.Reset(); + + m_SwapChain.Reset(); + + for (auto& allocator : m_VideoProcessCommandAllocators) allocator.Reset(); + m_VideoProcessAllocatorFence = {}; + m_VideoProcessCommandList.Reset(); + m_VideoProcessCommandQueue.Reset(); + + for (auto& allocator : m_GraphicsCommandAllocators) allocator.Reset(); + m_GraphicsAllocatorFence = {}; + m_TimestampReadbackBuffer.Reset(); + m_TimestampPending = {}; + m_GraphicsCommandList.Reset(); + m_GraphicsCommandQueue.Reset(); + + m_OverlayCommandAllocator.Reset(); + m_OverlayCommandList.Reset(); + m_OverlayCommandQueue.Reset(); + + m_PictureCommandAllocator.Reset(); + m_PictureCommandList.Reset(); + m_PictureCommandQueue.Reset(); + + m_FenceVideoProcess.Reset(); + m_FenceGraphics.Reset(); + m_FenceOverlay.Reset(); + m_FenceAMF.Reset(); + + m_VideoProcessorConvert.Reset(); + m_VideoProcessorUpscaler.Reset(); + m_VideoProcessorUpscalerConvert.Reset(); + m_VideoDevice.Reset(); + + if (m_D3D11DeviceContext) { + m_D3D11DeviceContext->Flush(); + m_D3D11DeviceContext->ClearState(); + } + + if (m_HwDeviceContext) { + av_buffer_unref(&m_HwDeviceContext); + m_HwDeviceContext = nullptr; + } + + // Nvidia VSR and TrueHDR + NVSDK_NGX_D3D12_ReleaseFeature(m_VSRFeature); + m_VSRFeature = nullptr; + NVSDK_NGX_D3D12_ReleaseFeature(m_TrueHDRFeature); + m_TrueHDRFeature = nullptr; + NVSDK_NGX_D3D12_DestroyParameters(m_VSRngxParameters); + NVSDK_NGX_D3D12_DestroyParameters(m_TrueHDRngxParameters); + + // Intel VPL + if(m_VppSession){ + for (;;) { + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + mfxSyncPoint syncp = nullptr; + + mfxStatus sts = MFXVideoVPP_RunFrameVPPAsync( + m_VppSession, + nullptr, // NULL input = drain + nullptr, + nullptr, + &syncp + ); + + if (sts == MFX_ERR_NONE && syncp) { + MFXVideoCORE_SyncOperation(m_VppSession, syncp, INFINITE); + continue; + } + + if (sts == MFX_ERR_MORE_DATA) + break; + + if (sts < 0) + break; + } + MFXVideoVPP_Close(m_VppSession); + MFXClose(m_VppSession); + m_VppSession = nullptr; + } + + for (auto& item : m_VppSurfaceIn) { + item.surface = nullptr; + } + + for (auto& item : m_VppSurfaceOut) { + item.surface = nullptr; + } + + m_D3D11VideoDevice.Reset(); + m_D3D11DeviceContext.Reset(); + m_D3D11Device.Reset(); + + m_Device.Reset(); + m_Adapter.Reset(); + m_Factory.Reset(); + + if(m_DebugLayer && m_DebugVerbose){ + ComPtr dxgiDebug; + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) + { + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_DETAIL); + } + } +} + +/** + * \brief Verify the result and display error logs + * + * Verify if the operation succeed + * Display error log in case of failed + * + * \param HRESULT hr Result of the operation + * \param const char* operation Additional message + * \return bool Return true if succeed + */ +bool D3D12VARenderer::verifyHResult(HRESULT hr, const char* operation) +{ + if (FAILED(hr)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "%s failed with HRESULT: 0x%08X", operation, hr); + + // Convert HRESULT in a readable string + char errorMsg[256]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorMsg, sizeof(errorMsg), nullptr); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error message: %s", errorMsg); + + if (m_Device) { + // If debug layer available, print messages from ID3D12InfoQueue + ComPtr infoQueue; + if (SUCCEEDED(m_Device->QueryInterface(IID_PPV_ARGS(&infoQueue)))) { + UINT64 num = infoQueue->GetNumStoredMessages(); + for (UINT64 i = 0; i < num; ++i) { + SIZE_T msgSize = 0; + infoQueue->GetMessage(i, nullptr, &msgSize); + std::vector buf(msgSize); + D3D12_MESSAGE* msg = reinterpret_cast(buf.data()); + infoQueue->GetMessage(i, msg, &msgSize); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "D3D12Msg %u: %s", (unsigned)i, msg->pDescription); + } + infoQueue->ClearStoredMessages(); + } + + HRESULT removedHr = m_Device->GetDeviceRemovedReason(); + if (removedHr != S_OK) { + char errorMsg[256]; + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM, + nullptr, + removedHr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorMsg, + sizeof(errorMsg), + nullptr + ); + + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Device removed! HRESULT: 0x%08X, Message: %s", + removedHr, errorMsg); + } + } + + return false; + } + return true; +} + +/** + * \brief Check client display HDR + * + * Check if the client display has HDR enabled + * + * \return bool Returns true if success + */ +bool D3D12VARenderer::getDisplayHDRStatus() +{ + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + SDL_GetWindowWMInfo(m_DecoderParams.window, &info); + + POINT windowPoint = {}; + GetClientRect(info.info.win.window, (LPRECT)&windowPoint); + ClientToScreen(info.info.win.window, &windowPoint); + + ComPtr factory; + if (FAILED(CreateDXGIFactory2(0, IID_PPV_ARGS(&factory)))) + return false; + + ComPtr adapter; + for (UINT adapterIndex = 0; + SUCCEEDED(factory->EnumAdapters1(adapterIndex, &adapter)); + ++adapterIndex) + { + ComPtr output; + for (UINT outputIndex = 0; + SUCCEEDED(adapter->EnumOutputs(outputIndex, &output)); + ++outputIndex) + { + ComPtr output6; + if (FAILED(output.As(&output6))) + continue; + + DXGI_OUTPUT_DESC1 desc = {}; + if (FAILED(output6->GetDesc1(&desc))) + continue; + + m_MaxLuminance = desc.MaxLuminance; + + RECT desktopCoordinates = desc.DesktopCoordinates; + if (PtInRect(&desktopCoordinates, windowPoint)) + { + // Returns True if HDR is on + return desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 || + desc.ColorSpace == DXGI_COLOR_SPACE_RGB_STUDIO_G2084_NONE_P2020 || + desc.ColorSpace == DXGI_COLOR_SPACE_RGB_STUDIO_G24_NONE_P2020 || + desc.ColorSpace == DXGI_COLOR_SPACE_RGB_STUDIO_G22_NONE_P2020 || + desc.ColorSpace == DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020; + } + } + } + return false; +} + +/** + * \brief Update the value of HDR status + * + * Update the value of HDR enabler asynchronously to avoid blocking the main renderer. + * This is a Multithread method as it is CPU consuming to not freeze the application. + * + * \params bool isFrameHDR + * \return void + */ +void D3D12VARenderer::updateDisplayHDRStatusAsync(bool isFrameHDR) +{ + // Swapchain ColorSpace can be changed in live + if (isFrameHDR != D3D12VARenderer::m_IsFrameHDR) { + D3D12VARenderer::m_IsFrameHDR = isFrameHDR; + // Updating the swapChain shall be enough as it auto correct the output, + // but we still need to reinitialise the renderer to make the whole chain aligned + m_RGBColorSpace = (D3D12VARenderer::m_IsFrameHDR || m_VendorHDRenabled) ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + m_SwapChain->SetColorSpace1(m_RGBColorSpace); + m_ReloadRenderer = true; + } + + // Check the Client HDR status every 3s + m_CheckHDRCount++; + if (m_CheckHDRCount < 3 * m_DecoderParams.frameRate) { + return; + } + + // Skip if update is already running or paused + if (m_PauseHDRUpdate || m_HDRUpdateFuture.isRunning()) + return; + + m_CheckHDRCount = 0; + m_PauseHDRUpdate = true; + + // Create a safe Qt pointer that tracks object lifetime (QObject-aware) + QPointer self(this); + m_HDRUpdateFuture = QtConcurrent::run([self]() { + + // The thread is all about this line, to not block the rendering thread + // as it takes some time to get the information + bool hdrEnabled = self->getDisplayHDRStatus(); + + // Safely modify QObject from the main thread using queued signal + QMetaObject::invokeMethod(self, [self, hdrEnabled]() { + + if (!self) return; + + // Check if the display HDR setting changed for Host and Client + if (hdrEnabled != D3D12VARenderer::m_IsClientHDR || self->m_ReloadRenderer) { + D3D12VARenderer::m_IsClientHDR = hdrEnabled; + + // Reload the Renderer to set properly Textures format, Color spaces, etc. + SDL_Event event; + event.type = SDL_RENDER_TARGETS_RESET; + SDL_PushEvent(&event); + } + // Reset the pause flag (executed in the main GUI thread) + self->m_PauseHDRUpdate = false; + }, Qt::QueuedConnection); + }); +} + +/** + * \brief Set the most appropriate Enhancement method according to the GPU + * + * Based on multiple performance (latency) and picture quality tests on divers GPU/iGPU, + * the method will setup the most apprioriate setting for enhanced rendering. + * NOTE: Any change to this method needs to be widely tested as each GPU acts differently, regression could be observed. + * Documentation: In comments of the following PR, you will find a schema with the whole pipeline for reference. + * https://github.com/moonlight-stream/moonlight-qt/pull/1557 + * + * \return void + */ +void D3D12VARenderer::enhanceAutoSelection() +{ + // We copy the value to not overwrite the user selection value while testing + StreamingPreferences::SuperResolutionMode superResolutionMode = m_Preferences->superResolutionMode; + + m_VendorVSRenabled = false; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::NONE; + m_InfoUpscaler = "Video Processor"; + m_InfoSharpener = "Video Processor"; + m_InfoAlgo = "Video Processor"; + + // For Test, we default on Auto mode as it is made to work on both, SDR and HDR. + // It avoids a fallback to Vulkan if in Debug mode an specific algorythm is selected which may not work in HDR (like FSR1). + if (m_DecoderParams.testOnly) { + superResolutionMode = StreamingPreferences::SRM_00; + } + + // We first let the application select the estimated best-fit per GPU Vendor. + // This is equivalent to StreamingPreferences::SRM_00 plus some vendor specifications. + + // AMD + if(m_VideoEnhancement->isVendorAMD()){ + m_VendorVSRenabled = true; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_AMF; + m_RenderStep2 = RenderStep::NONE; + m_InfoUpscaler = "AMF FSR EASU"; + m_InfoSharpener = "AMF FSR RCAS"; + m_InfoAlgo = "AMF FSR1"; + } + + // Intel + else if(m_VideoEnhancement->isVendorIntel()){ + if(m_IsIntegratedGPU){ + m_VendorVSRenabled = false; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::NONE; + m_InfoUpscaler = "Video Processor"; + m_InfoSharpener = "None"; + if (m_EdgeEnhancementValue > 0){ + m_InfoSharpener = "Video Processor"; + } + m_InfoAlgo = "Video Processor"; + } else if(m_IsTexture10bits){ + m_VendorVSRenabled = false; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NIS; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "NIS Upscaler"; + m_InfoSharpener = "NIS Sharpener"; + m_InfoAlgo = "Shader NIS"; + } else { + + // IntelVPL is only available for the architecture x64, we fallback to FSR1 only for ARM. +#if defined(HAVE_INTEL_VPL) + // // NOTE: Current version is too slow (20ms per frame) + // m_VendorVSRenabled = true; + // m_VendorHDRenabled = false; + // m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + // m_RenderStep1 = RenderStep::UPSCALE_VPL; + // m_RenderStep2 = RenderStep::CONVERT_SHADER; + // m_InfoUpscaler = "Intel VPL AI Super Resolution"; + // m_InfoSharpener = "Intel VPL"; + // m_InfoAlgo = "Intel VPL"; + + m_VendorVSRenabled = false; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::FSR1; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "FSR1 EASU"; + m_InfoSharpener = "FRS1 RCAS"; + m_InfoAlgo = "Shader FSR1"; +#else + m_VendorVSRenabled = false; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::FSR1; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "FSR1 EASU"; + m_InfoSharpener = "FRS1 RCAS"; + m_InfoAlgo = "Shader FSR1"; +#endif + } + } + + // NVIDIA + else if(m_VideoEnhancement->isVendorNVIDIA()){ + if(isNvidiaVSRSupport()){ + // Nvidia Driver's optimization + m_VendorVSRenabled = true; + m_VendorHDRenabled = false; // It makes some screens darker + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_VSR; + m_InfoUpscaler = "NVIDIA RTX Video Super Resolution"; + m_InfoSharpener = "Video Processor"; + m_InfoAlgo = "NVIDIA RTX Video Super Resolution"; + } else { + // For GPUs which are not supporting VSR capability (like the GTX), + // we switch to NIS. + m_VendorVSRenabled = false; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NIS; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "NIS Upscaler"; + m_InfoSharpener = "NIS Sharpener"; + m_InfoAlgo = "Shader NIS"; + } + } + + // Qualcomm + else if(m_VideoEnhancement->isVendorQualcomm()){ + m_VendorVSRenabled = true; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::SGSR1; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "SGSR1 Upscaler"; + m_InfoSharpener = "SGSR1 Sharpener"; + m_InfoAlgo = "Shader SGSR1"; + } + + // The user can force the algorithm used for Test/Debug purpose only, the production must be set to "auto" + // User Interface: Hidden by default. It is visible only in Debug mode. + // CLI: It is available via the parameter "super-resolution-mode" to force the algorythm to use + + switch (superResolutionMode) { + + case StreamingPreferences::SRM_01: + // DRIVER + m_VendorVSRenabled = true; + m_VendorHDRenabled = true; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::NONE; + if(m_VideoEnhancement->isVendorAMD()){ + m_VendorVSRenabled = true; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_AMF; + m_RenderStep2 = RenderStep::NONE; + } else if(m_VideoEnhancement->isVendorIntel()){ + m_VendorVSRenabled = true; + m_VendorHDRenabled = false; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::UPSCALE_VPL; + m_RenderStep2 = RenderStep::CONVERT_SHADER; + } else if(m_VideoEnhancement->isVendorNVIDIA()){ + m_VendorVSRenabled = true; + m_VendorHDRenabled = true; + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_VSR; + } + m_InfoUpscaler = "Vendor Driver Upscaler"; + m_InfoSharpener = "Vendor Driver Sharpener"; + m_InfoAlgo = "Vendor Driver"; + break; + + case StreamingPreferences::SRM_02: + // VP_ONLY + m_VendorVSRenabled = false; + // m_VendorHDRenabled: Keep default setting + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::NONE; + m_InfoUpscaler = "Video Processor"; + m_InfoSharpener = "None"; + if (m_EdgeEnhancementValue > 0){ + m_InfoSharpener = "Video Processor"; + } + m_InfoAlgo = "Video Processor"; + break; + + case StreamingPreferences::SRM_03: + // FSR1 (Shader version) + m_VendorVSRenabled = false; + // m_VendorHDRenabled: Keep default setting + m_EnhancerType = D3D12VideoShaders::Enhancer::FSR1; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "FSR1 EASU"; + m_InfoSharpener = "FRS1 RCAS"; + m_InfoAlgo = "Shader FSR1"; + break; + + case StreamingPreferences::SRM_04: + // NIS + m_VendorVSRenabled = false; + // m_VendorHDRenabled: Keep default setting + m_EnhancerType = D3D12VideoShaders::Enhancer::NIS; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "NIS Upscaler"; + m_InfoSharpener = "NIS Sharpener"; + m_InfoAlgo = "Shader NIS"; + break; + + case StreamingPreferences::SRM_05: + // SGSR1 + m_VendorVSRenabled = false; + // m_VendorHDRenabled: Keep default setting + m_EnhancerType = D3D12VideoShaders::Enhancer::SGSR1; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "SGSR1 Upscaler"; + m_InfoSharpener = "SGSR1 Sharpener"; + m_InfoAlgo = "Shader SGSR1"; + break; + + + case StreamingPreferences::SRM_06: + // RCAS (Only Sharpener) + m_VendorVSRenabled = false; + // m_VendorHDRenabled: Keep default setting + m_EnhancerType = D3D12VideoShaders::Enhancer::RCAS; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::SHARPEN_SHADER; + m_InfoUpscaler = "Video Processor"; + m_InfoSharpener = "RCAS Sharpener"; + m_InfoAlgo = "Video Processor RCAS"; + break; + + case StreamingPreferences::SRM_07: + // NIS Sharpener + m_VendorVSRenabled = false; + // m_VendorHDRenabled: Keep default setting + m_EnhancerType = D3D12VideoShaders::Enhancer::NIS_SHARPENER; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::SHARPEN_SHADER; + m_InfoUpscaler = "Video Processor"; + m_InfoSharpener = "NIS Sharpener"; + m_InfoAlgo = "Video Processor NIS"; + break; + + default: + break; + } + + // Disable SDR->HDR feature if we receive HDR stream, or if the display is HDR off + if(D3D12VARenderer::m_IsFrameHDR || !D3D12VARenderer::m_IsClientHDR){ + m_VendorHDRenabled = false; + } + + // Disable VSR if we use Shader to upscale + if(D3D12VideoShaders::isUpscaler(m_EnhancerType)){ + m_VendorVSRenabled = false; + } + + // Correct VSR + m_VendorVSRenabled = false; + switch (m_RenderStep1) { + case RenderStep::ALL_AMF: + case RenderStep::CONVERT_AMF: + case RenderStep::UPSCALE_AMF: + case RenderStep::UPSCALE_VSR: + case RenderStep::UPSCALE_VPL: + m_VendorVSRenabled = true; + break; + default: + break; + } + switch (m_RenderStep2) { + case RenderStep::ALL_AMF: + case RenderStep::CONVERT_AMF: + case RenderStep::UPSCALE_AMF: + case RenderStep::UPSCALE_VSR: + case RenderStep::UPSCALE_VPL: + m_VendorVSRenabled = true; + break; + default: + break; + } + + // Test VSR, but do not activate + if(m_VendorVSRenabled){ + if(m_VideoEnhancement->isVendorAMD()){ + m_VideoEnhancement->setVSRcapable(enableAMDVideoSuperResolution(false)); + } else if(m_VideoEnhancement->isVendorIntel()){ + m_VideoEnhancement->setVSRcapable(enableIntelVideoSuperResolution(false)); + } else if(m_VideoEnhancement->isVendorNVIDIA()){ + m_VideoEnhancement->setVSRcapable(enableNvidiaVideoSuperResolution(false)); + } + m_VendorVSRenabled = m_VideoEnhancement->isVSRcapable(); + + // We fallback to VideoProcessor + if(!m_VendorVSRenabled){ + m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + m_RenderStep1 = RenderStep::ALL_VIDEOPROCESSOR; + m_RenderStep2 = RenderStep::NONE; + m_InfoUpscaler = "Video Processor"; + m_InfoSharpener = "None"; + if (m_EdgeEnhancementValue > 0){ + m_InfoSharpener = "Video Processor"; + } + m_InfoAlgo = "Video Processor"; + } + } + + // Test HDR, but do not activate + if(m_VendorHDRenabled){ + if(m_VideoEnhancement->isVendorAMD()){ + m_VideoEnhancement->setHDRcapable(enableAMDHDR(false)); + } else if(m_VideoEnhancement->isVendorIntel()){ + m_VideoEnhancement->setHDRcapable(enableIntelHDR(false)); + } else if(m_VideoEnhancement->isVendorNVIDIA()){ + m_VideoEnhancement->setHDRcapable(enableNvidiaHDR(false)); + } + m_VendorHDRenabled = m_VideoEnhancement->isHDRcapable(); + } + + if(m_RenderStep1 == RenderStep::ALL_VIDEOPROCESSOR && m_EdgeEnhancementValue > 0){ + m_RenderStep2 = RenderStep::NONE; + m_InfoSharpener = "Video Processor"; + m_InfoAlgo = "Video Processor"; + } + + // Note: Currently the YUV->RGB Shader is not accurate (wrong color), so we rely on the Video Processor to convert + if(m_IsTextureYUV444 && m_RenderStep1 == RenderStep::CONVERT_SHADER){ + m_RenderStep1 = RenderStep::CONVERT_VIDEOPROCESSOR; + } + if(m_IsTextureYUV444 && m_RenderStep2 == RenderStep::CONVERT_SHADER){ + m_RenderStep2 = RenderStep::CONVERT_VIDEOPROCESSOR; + } + + // At true, RenderStep2 is not needed + m_SkipRenderStep2 = m_RenderStep2 == RenderStep::NONE; + + // The VideoProcess queue is only fed by the VideoProcessor steps + auto usesVideoProcessor = [](RenderStep step) { + return step == RenderStep::ALL_VIDEOPROCESSOR || + step == RenderStep::CONVERT_VIDEOPROCESSOR || + step == RenderStep::UPSCALE_VIDEOPROCESSOR; + }; + m_UsesVideoProcessQueue = usesVideoProcessor(m_RenderStep1) || usesVideoProcessor(m_RenderStep2); + + // Add statistics information + m_VideoEnhancement->setRatio(static_cast(m_OutputTextureInfo.height) / static_cast(m_DecoderParams.textureHeight)); + if(m_VendorHDRenabled){ + m_InfoAlgo = m_InfoAlgo + " (SDR->HDR)"; + } + m_VideoEnhancement->setAlgo(m_InfoAlgo); + + qInfo() << "Enhancer VSR : " + std::to_string(m_VendorVSRenabled); + qInfo() << "Enhancer SDR->HDR : " + std::to_string(m_VendorHDRenabled); + qInfo() << "Enhancer Upscaling : " + m_InfoUpscaler; + qInfo() << "Enhancer Sharpening: " + m_InfoSharpener; +} + +/** + * \brief Enable Video Super-Resolution for AMD GPU + * + * This feature is available since this drive 22.3.1 (March 2022) + * https://community.amd.com/t5/gaming/amd-software-24-1-1-amd-fluid-motion-frames-an-updated-ui-and/ba-p/656213 + * + * \param bool activate Default is true, at true it enables the use of Video Super-Resolution feature + * \param bool logInfo Default is true, at true is displays the result in the console logs + * \return bool Return true if the capability is available + */ +bool D3D12VARenderer::enableAMDVideoSuperResolution(bool activate, bool logInfo) +{ + // The feature is announced since Jan 23rd, 2024, with the driver 24.1.1 and on series 7000 + // https://community.amd.com/t5/gaming/amd-software-24-1-1-amd-fluid-motion-frames-an-updated-ui-and/ba-p/656213 + // But it is available as SDK since March 2022 (22.3.1) which means it might also work for series 5000 and 6000 (to be tested) + // https://github.com/GPUOpen-LibrariesAndSDKs/AMF/blob/master/amf/doc/AMF_HQ_Scaler_API.md + + if (!m_VendorVSRenabled) + activate = false; + + AMF_RESULT res; + AMFCapsPtr amfCaps; + AMFContextPtr baseContext; + + // We skip if already initialized + if(m_AmfInitialized && activate) + return true; + + AMF_SURFACE_FORMAT SurfaceFormatYUV; + AMF_SURFACE_FORMAT SurfaceFormatRGB; + AMFColor backgroundColor = AMFConstructColor(0, 0, 0, 255); + AMF_COLOR_RANGE_ENUM amfColorRange = AMF_COLOR_RANGE_STUDIO; + + // AMF Context initialization + res = g_AMFFactory.Init(); + if (res != AMF_OK) goto ErrorAMD; + res = g_AMFFactory.GetFactory()->CreateContext(&baseContext); + if (res != AMF_OK) goto ErrorAMD; + res = baseContext->QueryInterface(AMFContext2::IID(), (void**)&m_AmfContext); + if (res != AMF_OK) goto ErrorAMD; + res = g_AMFFactory.GetFactory()->CreateComponent(m_AmfContext, AMFHQScaler, &m_AmfUpscalerRGB); + if (res != AMF_OK) goto ErrorAMD; + res = g_AMFFactory.GetFactory()->CreateComponent(m_AmfContext, AMFHQScaler, &m_AmfUpscalerYUV); + if (res != AMF_OK) goto ErrorAMD; + res = g_AMFFactory.GetFactory()->CreateComponent(m_AmfContext, AMFVideoConverter, &m_AmfVideoConverter); + if (res != AMF_OK) goto ErrorAMD; + res = g_AMFFactory.GetFactory()->CreateComponent(m_AmfContext, AMFVideoConverter, &m_AmfVideoConverterUpscaled); + if (res != AMF_OK) goto ErrorAMD; + + res = m_AmfContext->InitDX12(m_Device.Get()); + if (res != AMF_OK) goto ErrorAMD; + + res = m_AmfContext->GetCompute(AMF_MEMORY_DX12, &m_AmfCompute); + if (res != AMF_OK) goto ErrorAMD; + + // We are getting the command queue to work with fence + m_AmfCommandQueue = static_cast(m_AmfCompute->GetNativeCommandQueue()); + + // AMFHQScaler is the newest feature available (v1.4.33), so at least this one need to be accessible + m_AmfUpscalerYUV->GetCaps(&amfCaps); + if (amfCaps != nullptr && amfCaps->GetAccelerationType() == AMF_ACCEL_NOT_SUPPORTED) { + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "The hardware does not support needed AMD AMF capabilities."); + goto ErrorAMD; + } + + // Format initialization + if(m_IsTextureYUV444){ + SurfaceFormatYUV = m_IsTexture10bits ? AMF_SURFACE_Y410 : AMF_SURFACE_AYUV; + } else { + SurfaceFormatYUV = m_IsTexture10bits ? AMF_SURFACE_P010 : AMF_SURFACE_NV12; + } + + // Format initialization + SurfaceFormatRGB = m_IsTexture10bits ? AMF_SURFACE_R10G10B10A2 : AMF_SURFACE_RGBA; + + if(m_Decoder.ColorRange & COLOR_RANGE_FULL){ + amfColorRange = AMF_COLOR_RANGE_FULL; + } + + // Input YUV Surface initialization + res = m_AmfContext->AllocSurface(AMF_MEMORY_DX12, + SurfaceFormatYUV, + m_DecoderParams.textureWidth, + m_DecoderParams.textureHeight, + &m_AmfSurfaceYUV); + if (res != AMF_OK) goto ErrorAMD; + + // Input/Output Scaled YUV Surface initialization + res = m_AmfContext->AllocSurface(AMF_MEMORY_DX12, + SurfaceFormatYUV, + m_OutputTextureInfo.width, + m_OutputTextureInfo.height, + &m_AmfSurfaceUpscaledYUV); + if (res != AMF_OK) goto ErrorAMD; + + // Input/Output RGB Surface initialization + res = m_AmfContext->AllocSurface(AMF_MEMORY_DX12, + SurfaceFormatRGB, + m_DecoderParams.textureWidth, + m_DecoderParams.textureHeight, + &m_AmfSurfaceRGB); + if (res != AMF_OK) goto ErrorAMD; + + // Output Scaled RGB Surface initialization + res = m_AmfContext->AllocSurface(AMF_MEMORY_DX12, + SurfaceFormatRGB, + m_OutputTextureInfo.width, + m_OutputTextureInfo.height, + &m_AmfSurfaceUpscaledRGB); + if (res != AMF_OK) goto ErrorAMD; + + // RGB Upscale initialization + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_OUTPUT_SIZE, ::AMFConstructSize(m_OutputTextureInfo.width, m_OutputTextureInfo.height)); + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_ENGINE_TYPE, AMF_MEMORY_DX12); + // Do not use AMF_HQ_SCALER_ALGORITHM_VIDEOSR1_1, the picture is blurry, even with a ratio of 2.0 + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_ALGORITHM, AMF_HQ_SCALER_ALGORITHM_VIDEOSR1_0); + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_KEEP_ASPECT_RATIO, true); + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_FILL, true); + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_FILL_COLOR, backgroundColor); + // We only apply sharpening when the picture is scaled (0 = Most sharpened / 2.00 = Not sharpened) + if (m_OutputTextureInfo.width == m_DecoderParams.textureWidth && m_OutputTextureInfo.height == m_DecoderParams.textureHeight){ + m_AmfUpscalerSharpness = false; + } else { + m_AmfUpscalerSharpness = true; + } + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_SHARPNESS, m_AmfUpscalerSharpness ? 0.50 : 2.00); + m_AmfUpscalerRGB->SetProperty(AMF_HQ_SCALER_FRAME_RATE, m_DecoderParams.frameRate); + // Initialize with the size of the texture that will be input + res = m_AmfUpscalerRGB->Init(SurfaceFormatRGB, + m_DecoderParams.textureWidth, + m_DecoderParams.textureHeight); + if (res != AMF_OK) goto ErrorAMD; + m_AmfUpscalerRGB->Optimize(nullptr); + + // YUV Upscale initialization + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_OUTPUT_SIZE, ::AMFConstructSize(m_OutputTextureInfo.width, m_OutputTextureInfo.height)); + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_ENGINE_TYPE, AMF_MEMORY_DX12); + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_ALGORITHM, AMF_HQ_SCALER_ALGORITHM_VIDEOSR1_0); + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_KEEP_ASPECT_RATIO, true); + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_FILL, true); + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_FILL_COLOR, backgroundColor); + // We only apply sharpening when the picture is scaled (0 = Most sharpened / 2.00 = Not sharpened) + if (m_OutputTextureInfo.width == m_DecoderParams.textureWidth && m_OutputTextureInfo.height == m_DecoderParams.textureHeight){ + m_AmfUpscalerSharpness = false; + } else { + m_AmfUpscalerSharpness = true; + } + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_SHARPNESS, m_AmfUpscalerSharpness ? 0.50 : 2.00); + m_AmfUpscalerYUV->SetProperty(AMF_HQ_SCALER_FRAME_RATE, m_DecoderParams.frameRate); + // Initialize with the size of the texture that will be input + res = m_AmfUpscalerYUV->Init(SurfaceFormatYUV, + m_DecoderParams.textureWidth, + m_DecoderParams.textureHeight); + if (res != AMF_OK) goto ErrorAMD; + m_AmfUpscalerYUV->Optimize(nullptr); + + // Convert YUV to RGB + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_MEMORY_TYPE, AMF_MEMORY_DX12); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_FORMAT, SurfaceFormatRGB); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_FILL, true); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_FILL_COLOR, backgroundColor); + // Note: For unknown reason, the HDR rendering is correct while keeping BT709 color space. + // If I use the HDR setting, the coloring is too bright. + if(m_AmfHdrColorSpaceEnabled && D3D12VARenderer::m_IsFrameHDR){ + // Input P010, RGB BT.2020 with PQ (HDR10), limited/full range + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_RANGE, amfColorRange); + // Output R10G10B10A2, RGB BT.2020 with PQ (HDR10), full range + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_RANGE, AMF_COLOR_RANGE_FULL); + } else { + // Input NV12 = YUV BT.709, limited/full range + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_RANGE, amfColorRange); + // Output RGBA = RGB BT.709, full range + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, AMF_VIDEO_CONVERTER_COLOR_PROFILE_709); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_RANGE, AMF_COLOR_RANGE_FULL); + } + // Initialize with the size of the output texture + res = m_AmfVideoConverter->Init(SurfaceFormatYUV, + m_DecoderParams.textureWidth, + m_DecoderParams.textureHeight); + if (res != AMF_OK) goto ErrorAMD; + m_AmfVideoConverter->Optimize(nullptr); + + // Convert Upscaled YUV to RGB + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_MEMORY_TYPE, AMF_MEMORY_DX12); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_FORMAT, SurfaceFormatRGB); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_FILL, true); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_FILL_COLOR, backgroundColor); + if(m_AmfHdrColorSpaceEnabled && D3D12VARenderer::m_IsFrameHDR){ + // Input P010, RGB BT.2020 with PQ (HDR10), limited/full range + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_RANGE, amfColorRange); + // Output R10G10B10A2, RGB BT.2020 with PQ (HDR10), full range + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, AMF_VIDEO_CONVERTER_COLOR_PROFILE_FULL_2020); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_SMPTE2084); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT2020); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_RANGE, AMF_COLOR_RANGE_FULL); + } else { + // Input NV12 = YUV BT.709, limited range + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_COLOR_RANGE, amfColorRange); + // Output RGBA = RGB BT.709, full range + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_COLOR_PROFILE, AMF_VIDEO_CONVERTER_COLOR_PROFILE_709); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_TRANSFER_CHARACTERISTIC, AMF_COLOR_TRANSFER_CHARACTERISTIC_BT709); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_PRIMARIES, AMF_COLOR_PRIMARIES_BT709); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_COLOR_RANGE, AMF_COLOR_RANGE_FULL); + } + // Initialize with the size of the output texture + res = m_AmfVideoConverterUpscaled->Init(SurfaceFormatYUV, + m_OutputTextureInfo.width, + m_OutputTextureInfo.height); + if (res != AMF_OK) goto ErrorAMD; + m_AmfVideoConverterUpscaled->Optimize(nullptr); + + if(!activate){ + // Up Scaler + m_AmfUpscalerRGB->Terminate(); + m_AmfUpscalerRGB = nullptr; + m_AmfUpscalerYUV->Terminate(); + m_AmfUpscalerYUV = nullptr; + // Converter + m_AmfVideoConverter->Terminate(); + m_AmfVideoConverter = nullptr; + m_AmfVideoConverterUpscaled->Terminate(); + m_AmfVideoConverterUpscaled = nullptr; + // Context + m_AmfContext->Terminate(); + m_AmfContext = nullptr; + // Factory + g_AMFFactory.Terminate(); + + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AMD Video Super Resolution disabled"); + } else { + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AMD Video Super Resolution enabled"); + } + + m_AmfInitialized = activate; + return true; + +ErrorAMD: + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AMD Video Super Resolution failed."); + m_AmfInitialized = false; + return false; +} + +/** + * \brief Enable Video Super-Resolution for Intel GPU + * + * The AI Super Resolution is available as an experimental mode, it needs to enable ONEVPL_EXPERIMENTAL. + * https://intel.github.io/libvpl/latest/API_ref/VPL_structs_vpp.html#mfxextvppaisuperresolution + * + * \param bool activate Default is true, at true it enables the use of Video Super-Resolution feature + * \param bool logInfo Default is true, at true is displays the result in the console logs + * \return bool Return true if the capability is available + */ +bool D3D12VARenderer::enableIntelVideoSuperResolution(bool activate, bool logInfo) +{ + // IntelVPL is only available for the architecture x64 +#if !defined(HAVE_INTEL_VPL) + m_VendorVSRenabled = false; +#endif + if (!m_VendorVSRenabled) { + activate = false; + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Intel Video Super Resolution disabled"); + m_IntelInitialized = false; + return false; + } + + // Reset + if (m_VppSession) { + MFXVideoVPP_Close(m_VppSession); + MFXClose(m_VppSession); + m_VppSession = nullptr; + } + + if (!m_D3D11Device) + return false; + + ComPtr pMultithread; + HRESULT hr = m_D3D11Device.As(&pMultithread); + if (SUCCEEDED(hr)) { + pMultithread->SetMultithreadProtected(true); + qInfo() << "VPL: D3D11: Multithread protection enabled."; + } else { + qInfo() << "VPL: D3D11: Failed to enable multithread protection."; + } + + mfxHDL deviceHandle = (mfxHDL)m_D3D11Device.Get(); + + if (!m_VendorVSRenabled) + activate = false; + + // Safe helper : zero frameInfo first + auto zeroFrame = [](mfxFrameInfo &fi){ memset(&fi, 0, sizeof(fi)); }; + + mfxStatus sts; + + uint fourCC = MFX_FOURCC_NV12; + if (m_IsTextureYUV444) { + fourCC = MFX_FOURCC_AYUV; + } + + // VPP Parameters + m_VppParams = {}; + zeroFrame(m_VppParams.vpp.In); + zeroFrame(m_VppParams.vpp.Out); + + m_VppParams.vpp.In.FourCC = fourCC; + m_VppParams.vpp.In.ChromaFormat = m_IsTextureYUV444 ? MFX_CHROMAFORMAT_YUV444 : MFX_CHROMAFORMAT_YUV420; + m_VppParams.vpp.In.FrameRateExtN = m_DecoderParams.frameRate; + m_VppParams.vpp.In.FrameRateExtD = 1; + m_VppParams.vpp.In.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + m_VppParams.vpp.In.CropW = m_DecoderParams.textureWidth; + m_VppParams.vpp.In.CropH = m_DecoderParams.textureHeight; + m_VppParams.vpp.In.CropX = 0; + m_VppParams.vpp.In.CropY = 0; + m_VppParams.vpp.In.Width = ALIGN16(m_VppParams.vpp.In.CropW); + m_VppParams.vpp.In.Height = ALIGN16(m_VppParams.vpp.In.CropH); + + m_VppParams.vpp.Out.FourCC = fourCC; + m_VppParams.vpp.Out.ChromaFormat = m_IsTextureYUV444 ? MFX_CHROMAFORMAT_YUV444 : MFX_CHROMAFORMAT_YUV420; + m_VppParams.vpp.Out.FrameRateExtN = m_DecoderParams.frameRate; + m_VppParams.vpp.Out.FrameRateExtD = 1; + m_VppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; + m_VppParams.vpp.Out.CropW = m_OutputTextureInfo.width; + m_VppParams.vpp.Out.CropH = m_OutputTextureInfo.height; + m_VppParams.vpp.Out.CropX = 0; + m_VppParams.vpp.Out.CropY = 0; + m_VppParams.vpp.Out.Width = ALIGN16(m_VppParams.vpp.Out.CropW); + m_VppParams.vpp.Out.Height = ALIGN16(m_VppParams.vpp.Out.CropH); + + m_VppParams.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY | MFX_IOPATTERN_OUT_VIDEO_MEMORY; + m_VppParams.AsyncDepth = 2; + + m_VppParams.NumExtParam = 0; + m_VppParams.ExtParam = nullptr; + + std::array extParams = {}; + + // AI Super Resolution + // NOTE: Not suitable for real-time streaming. + // It is activated when the scaling is over x1.40. + // Currently too slow on a A380, 20ms (720p to 1440p) with AlGORITHM_1, and 40ms with AlGORITHM_2. + // The picture quality is too flat, it looses details, it's good for Anime but not for games. + mfxExtVPPAISuperResolution aiSuperResolution = {}; + aiSuperResolution.Header.BufferId = MFX_EXTBUFF_VPP_AI_SUPER_RESOLUTION; + aiSuperResolution.Header.BufferSz = sizeof(mfxExtVPPAISuperResolution); + aiSuperResolution.SRMode = MFX_AI_SUPER_RESOLUTION_MODE_DEFAULT; + aiSuperResolution.SRAlgorithm = MFX_AI_SUPER_RESOLUTION_ALGORITHM_DEFAULT; + extParams[m_VppParams.NumExtParam++] = (mfxExtBuffer*)&aiSuperResolution; + + // Fallback to Scaling quality method + // NOTE: Same quality as Video Processor, but slower than Video Processor + mfxExtVPPScaling scaling = {}; + scaling.Header.BufferId = MFX_EXTBUFF_VPP_SCALING; + scaling.Header.BufferSz = sizeof(mfxExtVPPScaling); + scaling.ScalingMode = MFX_SCALING_MODE_QUALITY; + // extParams[m_VppParams.NumExtParam++] = (mfxExtBuffer*)&scaling; + + m_VppParams.ExtParam = extParams.data(); + + mfxConfig mfxCfg[3]; + mfxVariant mfxVar[3]; + + m_VppLoader = MFXLoad(); + if (m_VppLoader == NULL) goto ErrorIntel; + + // Hardware + mfxCfg[0] = MFXCreateConfig(m_VppLoader); + mfxVar[0].Version.Version = MFX_VARIANT_VERSION; + mfxVar[0].Type = MFX_VARIANT_TYPE_U32; + mfxVar[0].Data.U32 = MFX_IMPL_TYPE_HARDWARE; + sts = MFXSetConfigFilterProperty(mfxCfg[0], (mfxU8 *)"mfxImplDescription.Impl", mfxVar[0]); + if (sts != MFX_ERR_NONE) goto ErrorIntel; + + // D3D11 + mfxCfg[1] = MFXCreateConfig(m_VppLoader); + mfxVar[1].Version.Version = MFX_VARIANT_VERSION; + mfxVar[1].Type = MFX_VARIANT_TYPE_U32; + mfxVar[1].Data.U32 = MFX_IMPL_VIA_D3D11; + sts = MFXSetConfigFilterProperty(mfxCfg[1], (mfxU8 *)"mfxImplDescription.AccelerationMode", mfxVar[1]); + if (sts != MFX_ERR_NONE) goto ErrorIntel; + + // Session + sts = MFXCreateSession(m_VppLoader, 0, &m_VppSession); + if (sts != MFX_ERR_NONE) goto ErrorIntel; + + // IntelVPL needs multithreading enabled + MFXVideoCORE_SetHandle(m_VppSession, MFX_HANDLE_D3D11_DEVICE, deviceHandle); + + sts = MFXVideoVPP_Query(m_VppSession, &m_VppParams, &m_VppParams); + if (sts == MFX_ERR_UNSUPPORTED) { + // Fallback to Quality scaling + + if(m_VppSession){ + MFXVideoVPP_Close(m_VppSession); + MFXClose(m_VppSession); + m_VppSession = nullptr; + } + + // Scaling + mfxCfg[2] = MFXCreateConfig(m_VppLoader); + mfxVar[2].Version.Version = MFX_VARIANT_VERSION; + mfxVar[2].Type = MFX_VARIANT_TYPE_U32; + mfxVar[2].Data.U32 = MFX_EXTBUFF_VPP_SCALING; + sts = MFXSetConfigFilterProperty(mfxCfg[2], (mfxU8 *)"mfxImplDescription.mfxVPPDescription.filter.FilterFourCC", mfxVar[2]); + if (sts != MFX_ERR_NONE) goto ErrorIntel; + + extParams[0] = (mfxExtBuffer*)&scaling; + m_VppParams.NumExtParam = 1; + m_VppParams.ExtParam = extParams.data(); + + // Session + sts = MFXCreateSession(m_VppLoader, 0, &m_VppSession); + if (sts != MFX_ERR_NONE) goto ErrorIntel; + + // IntelVPL needs multithreading enabled + MFXVideoCORE_SetHandle(m_VppSession, MFX_HANDLE_D3D11_DEVICE, deviceHandle); + + } else if (sts != MFX_ERR_NONE) { + qInfo() << "MFXVideoVPP_Query failed:" << sts; + goto ErrorIntel; + } + + // VPP Initialization + sts = MFXVideoVPP_Init(m_VppSession, &m_VppParams); + if(MFX_ERR_NONE != sts){ + qInfo() << "VPP Initialization failed:" << sts; + goto ErrorIntel; + } + + MFXVideoVPP_QueryIOSurf(m_VppSession, &m_VppParams, m_VppReq); + + // Memory Interface + MFXGetMemoryInterface(m_VppSession, &m_MemoryInterface); + + MFXUnload(m_VppLoader); + + if (activate) { + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Intel Video Super Resolution enabled"); + } else { + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Intel Video Super Resolution disabled"); + } + + m_IntelInitialized = activate; + + return true; + + +ErrorIntel: + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Intel Video Super Resolution failed."); + m_IntelInitialized = false; + MFXUnload(m_VppLoader); + if (m_VppSession) { + MFXVideoVPP_Close(m_VppSession); + MFXClose(m_VppSession); + m_VppSession = nullptr; + } + return false; +} + +/** + * \brief Enable Video Super-Resolution for NVIDIA + * + * This feature is available starting from series NVIDIA RTX 2000 and GeForce driver 545.84 (Oct 17, 2023) + * https://catalog.ngc.nvidia.com/orgs/nvidia/teams/multimedia/models/dlpp + * + * + * \param bool activate Default is true, at true it enables the use of Video Super-Resolution feature + * \param bool logInfo Default is true, at true is displays the result in the console logs + * \return bool Return true if the capability is available + */ +bool D3D12VARenderer::enableNvidiaVideoSuperResolution(bool activate, bool logInfo) +{ + if (!m_VendorVSRenabled) + activate = false; + + NVSDK_NGX_Result ResultVSR; + + // Reset + NVSDK_NGX_D3D12_ReleaseFeature(m_VSRFeature); + m_VSRFeature = nullptr; + NVSDK_NGX_D3D12_DestroyParameters(m_VSRngxParameters); + m_VSRngxParameters = {}; + + // init NGX SDK + NVSDK_NGX_Result Status = NVSDK_NGX_D3D12_Init(APP_ID, APP_PATH, m_Device.Get()); + if (NVSDK_NGX_FAILED(Status)){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + // Get NGX parameters interface (managed and released by NGX) + Status = NVSDK_NGX_D3D12_GetCapabilityParameters(&m_VSRngxParameters); + if (NVSDK_NGX_FAILED(Status)){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + // Now check if VSR is available on the system + int VSRAvailable = 0; + ResultVSR = m_VSRngxParameters->Get(NVSDK_NGX_Parameter_VSR_Available, &VSRAvailable); + if (!VSRAvailable){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + resetGraphicsCommandList(); + + // Create the VSR feature instance. The quality level has to be part of the + // creation parameters: NGX sizes its internal resources from it, so evaluating + // later with a different level corrupts the feature and hangs the device. + NVSDK_NGX_Parameter_SetUI(m_VSRngxParameters, NVSDK_NGX_Parameter_VSR_QualityLevel, (unsigned int)m_VsrQualityLevel); + NVSDK_NGX_Feature_Create_Params VSRCreateParams = {}; + ResultVSR = NGX_D3D12_CREATE_VSR_EXT(m_GraphicsCommandList.Get(), 1, 1, &m_VSRFeature, m_VSRngxParameters, &VSRCreateParams); + + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForGraphics(); + resetGraphicsCommandList(); + + if (NVSDK_NGX_FAILED(ResultVSR)){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + if (activate) { + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution enabled"); + } else { + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution disabled"); + } + + m_NvidiaInitialized = activate; + return true; +} + +/** + * \brief Enable HDR for AMD GPU + * + * This feature is not available for AMD, and has not yet been announced (by Dec 1st, 2025) + * + * \param bool activate Default is true, at true it enables the use of HDR feature + * \param bool logInfo Default is true, at true is displays the result in the console logs + * \return bool Return true if the capability is available + */ +bool D3D12VARenderer::enableAMDHDR(bool activate, bool logInfo) +{ + if (!m_VendorHDRenabled) + activate = false; + + // [TODO] Feature not yet announced + + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "AMD HDR capability is not yet supported by your client's GPU."); + return false; +} + +/** + * \brief Enable HDR for Intel GPU + * + * This feature is not available for Intel, and has not yet been announced (by Dec 1st, 2025) + * + * \param bool activate Default is true, at true it enables the use of HDR feature + * \param bool logInfo Default is true, at true is displays the result in the console logs + * \return bool Return true if the capability is available + */ +bool D3D12VARenderer::enableIntelHDR(bool activate, bool logInfo) +{ + if (!m_VendorHDRenabled) + activate = false; + + // [TODO] Feature not yet announced + + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Intel HDR capability is not yet supported by your client's GPU."); + return false; +} + +/** + * \brief Enable HDR for NVIDIA + * + * This feature is available starting from series NVIDIA RTX 2000 and GeForce driver 545.84 (Oct 17, 2023) + * + * Values from Chromium source code: + * https://chromium.googlesource.com/chromium/src/+/master/ui/gl/swap_chain_presenter.cc + * + * \param bool activate Default is true, at true it enables the use of HDR feature + * \param bool logInfo Default is true, at true is displays the result in the console logs + * \return bool Return true if the capability is available + */ +bool D3D12VARenderer::enableNvidiaHDR(bool activate, bool logInfo) +{ + if (!m_VendorHDRenabled) + activate = false; + + NVSDK_NGX_Result ResultTrueHDR; + + // Reset + NVSDK_NGX_D3D12_ReleaseFeature(m_TrueHDRFeature); + m_TrueHDRFeature = nullptr; + NVSDK_NGX_D3D12_DestroyParameters(m_TrueHDRngxParameters); + m_TrueHDRngxParameters = {}; + + // init NGX SDK + NVSDK_NGX_Result Status = NVSDK_NGX_D3D12_Init(APP_ID, APP_PATH, m_Device.Get()); + if (NVSDK_NGX_FAILED(Status)){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + // Get NGX parameters interface (managed and released by NGX) + Status = NVSDK_NGX_D3D12_GetCapabilityParameters(&m_TrueHDRngxParameters); + if (NVSDK_NGX_FAILED(Status)){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + // Now check if TrueHDR is available on the system + int TrueHDRAvailable = 0; + ResultTrueHDR = m_TrueHDRngxParameters->Get(NVSDK_NGX_Parameter_TrueHDR_Available, &TrueHDRAvailable); + if (!TrueHDRAvailable){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + resetGraphicsCommandList(); + + // Create the TrueHDR feature instance + NVSDK_NGX_Feature_Create_Params TrueHDRCreateParams = {}; + ResultTrueHDR = NGX_D3D12_CREATE_TRUEHDR_EXT(m_GraphicsCommandList.Get(), 1, 1, &m_TrueHDRFeature, m_TrueHDRngxParameters, &TrueHDRCreateParams); + + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForGraphics(); + resetGraphicsCommandList(); + + if (NVSDK_NGX_FAILED(ResultTrueHDR)){ + if(logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX Video Super Resolution failed."); + return false; + } + + if (activate) { + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX HDR enabled"); + } else { + if (logInfo) SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "NVIDIA RTX HDR disabled"); + } + + return true; +} + +/** + * \brief Find an unlocked surface in the pool + * + * Searches through the surface pool to find the first surface + * that is either uninitialized or not currently locked. + * + * \param std::vector& pool Surface pool to search + * \return VppSurface* Pointer to unlocked surface, or nullptr if none found + */ +D3D12VARenderer::VppSurface* D3D12VARenderer::findUnlockedSurface(std::vector& pool) +{ + for (auto& s : pool) { + if (!s.surface || s.surface->Data.Locked == 0) + return &s; + } + return nullptr; +} + +/** + * \brief Check is the Nvidia GPU is supporting Video Super Resolution + * + * This tells if the GPU is a RTX 2000+, which starts to support Video Super Resolution feature. + * Identification is based on DX12 Mesh Shader feature. + * + * \return bool Return true if the GPU is RTX2000+ + */ +bool D3D12VARenderer::isNvidiaVSRSupport() +{ + if(!m_VideoEnhancement->isVendorNVIDIA()){ + return false; + } + + std::wstring wdesc(m_AdapterDesc.Description); + std::string description(wdesc.begin(), wdesc.end()); + + // Check if the description contains " RTX ", case-insensitive + // This does cover all RTX GPUs + if (std::regex_search(description, std::regex(" RTX ", std::regex_constants::icase))) + return true; + + // Check Mesh Shader support (tier 1 minimum) which starts from RTX 3000+ + // This does cover any future Nvidia GPU which may not contains RTX in its description + D3D12_FEATURE_DATA_D3D12_OPTIONS7 options7 = {}; + if (SUCCEEDED(m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS7, &options7, sizeof(options7)))) + { + if (options7.MeshShaderTier >= D3D12_MESH_SHADER_TIER_1) { + return true; + } + } + + return false; +} + +/** + * \brief Set HDR capabilities + * + * Apply HDR metadata consistently across the processing pipeline to ensure + * the final output is correctly rendered on HDR-capable displays. + * + * \param bool enabled At true it enables the HDR settings + * \return void + */ +void D3D12VARenderer::setHdrMode(bool enabled) +{ + // Prepare HDR Meta Data for Streamed content + bool streamSet = false; + SS_HDR_METADATA hdrMetadata; + if (enabled && LiGetHdrMetadata(&hdrMetadata)) { + m_StreamHDRMetaData = {}; + m_StreamHDRMetaData.RedPrimary[0] = hdrMetadata.displayPrimaries[0].x; + m_StreamHDRMetaData.RedPrimary[1] = hdrMetadata.displayPrimaries[0].y; + m_StreamHDRMetaData.GreenPrimary[0] = hdrMetadata.displayPrimaries[1].x; + m_StreamHDRMetaData.GreenPrimary[1] = hdrMetadata.displayPrimaries[1].y; + m_StreamHDRMetaData.BluePrimary[0] = hdrMetadata.displayPrimaries[2].x; + m_StreamHDRMetaData.BluePrimary[1] = hdrMetadata.displayPrimaries[2].y; + m_StreamHDRMetaData.WhitePoint[0] = hdrMetadata.whitePoint.x; + m_StreamHDRMetaData.WhitePoint[1] = hdrMetadata.whitePoint.y; + m_StreamHDRMetaData.MaxMasteringLuminance = hdrMetadata.maxDisplayLuminance; + m_StreamHDRMetaData.MinMasteringLuminance = hdrMetadata.minDisplayLuminance; + + // As the Content is unknown since it is streamed, MaxCLL and MaxFALL cannot be evaluated from the source on the fly, + // therefore streamed source returns 0 as value for both. We default at 1000/400 (standard); + m_StreamHDRMetaData.MaxContentLightLevel = 1000; + m_StreamHDRMetaData.MaxFrameAverageLightLevel = 4000; + + setAMDHdr(); + + // It seems that there is no effect + m_SwapChain->SetHDRMetaData( + DXGI_HDR_METADATA_TYPE_HDR10, + sizeof(m_StreamHDRMetaData), + &m_StreamHDRMetaData + ); + + streamSet = true; + } + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Set stream HDR mode: %s", streamSet ? "enabled" : "disabled"); +} + +/** + * \brief Apply AMD AMF HDR metadata + * + * Configures and propagates HDR10 static metadata to AMD AMF video converters, + * ensuring correct HDR rendering for PQ (ST 2084) encoded frames. + * + * \return void + */ +void D3D12VARenderer::setAMDHdr() +{ + if(!m_AmfInitialized || !m_AmfHdrColorSpaceEnabled || !D3D12VARenderer::m_IsFrameHDR) + return; + + AMF_RESULT res; + + // HDR Input Metadata + AMFHDRMetadata hdr = {}; + + // Primaires (exemple BT.2020) + hdr.redPrimary[0] = m_StreamHDRMetaData.RedPrimary[0]; + hdr.redPrimary[1] = m_StreamHDRMetaData.RedPrimary[1]; + hdr.greenPrimary[0] = m_StreamHDRMetaData.GreenPrimary[0]; + hdr.greenPrimary[1] = m_StreamHDRMetaData.GreenPrimary[1]; + hdr.bluePrimary[0] = m_StreamHDRMetaData.BluePrimary[0]; + hdr.bluePrimary[1] = m_StreamHDRMetaData.BluePrimary[1]; + + // White point (D65) + hdr.whitePoint[0] = m_StreamHDRMetaData.WhitePoint[0]; + hdr.whitePoint[1] = m_StreamHDRMetaData.WhitePoint[1]; + + // Luminance mastering + hdr.maxMasteringLuminance = 10000 * m_StreamHDRMetaData.MaxMasteringLuminance; + hdr.minMasteringLuminance = m_StreamHDRMetaData.MinMasteringLuminance; + + // Light Levels + hdr.maxContentLightLevel = m_StreamHDRMetaData.MaxContentLightLevel; + hdr.maxFrameAverageLightLevel = m_StreamHDRMetaData.MaxFrameAverageLightLevel; + + res = m_AmfContext->AllocBuffer(AMF_MEMORY_HOST, + sizeof(AMFHDRMetadata), + &m_HdrBuffer); + if (res != AMF_OK) return; + memcpy(m_HdrBuffer->GetNative(), &hdr, sizeof(AMFHDRMetadata)); + + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_INPUT_HDR_METADATA, m_HdrBuffer); + m_AmfVideoConverter->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_HDR_METADATA, m_HdrBuffer); + + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_INPUT_HDR_METADATA, m_HdrBuffer); + m_AmfVideoConverterUpscaled->SetProperty(AMF_VIDEO_CONVERTER_OUTPUT_HDR_METADATA, m_HdrBuffer); +} + +/** + * \brief Set the decoder engine + * + * Set the decoder engine + * + * \param AVCodecContext* context + * \param AVDictionary** options + * \return bool + */ +bool D3D12VARenderer::prepareDecoderContext(AVCodecContext* context, AVDictionary** options) +{ + Q_UNUSED(options); + + context->hw_device_ctx = av_buffer_ref(m_HwDeviceContext); + + if (m_IsFrameD3D11) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Using D3D11VA decoding with D3D12VA accelerated renderer"); + } else { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Using D3D12VA accelerated renderer"); + } + + return true; +} + +/** + * \brief Set the decoder frame format + * + * Set the decoder frame format + * + * \param AVCodecContext* context + * \param AVPixelFormat pixelFormat + * \return bool + */ +bool D3D12VARenderer::prepareDecoderContextInGetFormat(AVCodecContext *context, AVPixelFormat pixelFormat) +{ + int err; + + // Create a new hardware frames context suitable for decoding our specified format + av_buffer_unref(&context->hw_frames_ctx); + err = avcodec_get_hw_frames_parameters(context, m_HwDeviceContext, pixelFormat, &context->hw_frames_ctx); + if (err < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to get hwframes context parameters: %d", + err); + return false; + } + + AVHWFramesContext* framesContext = (AVHWFramesContext*)context->hw_frames_ctx->data; + + // We can have up to 16 reference frames plus a working surface + framesContext->initial_pool_size = DECODER_BUFFER_POOL_SIZE; + + framesContext->sw_format = m_Decoder.AVFormat; + framesContext->width = m_FrameWidth; + framesContext->height = m_FrameHeight; + + if (m_IsFrameD3D11) { + // Use D3D11va to decode + + framesContext->format = AV_PIX_FMT_D3D11; + + AVD3D11VAFramesContext* d3d11vaFramesContext = (AVD3D11VAFramesContext*)framesContext->hwctx; + + d3d11vaFramesContext->BindFlags |= D3D11_BIND_DECODER; + + } else { + // Use D3D12va to decode + + framesContext->format = AV_PIX_FMT_D3D12; + + AVD3D12VAFramesContext* d3d12vaFramesContext = (AVD3D12VAFramesContext*)framesContext->hwctx; + + d3d12vaFramesContext->format = m_Decoder.Format; + } + + err = av_hwframe_ctx_init(context->hw_frames_ctx); + if (err < 0) { + av_buffer_unref(&context->hw_frames_ctx); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed initialize hwframes context: %d", + err); + return false; + } + + return true; +} + +/** + * \brief Notified if the pipeline supports live window changes + * + * Always at false to force the recreation of decoder/renderer + * + * \param PWINDOW_STATE_CHANGE_INFO stateInfo + * \return bool, Always returns false + */ +bool D3D12VARenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO stateInfo) +{ + // We force to recreate the renderer + return !(stateInfo->stateChangeFlags & (WINDOW_STATE_CHANGE_DISPLAY | WINDOW_STATE_CHANGE_SIZE)); +} + +/** + * \brief Get Renderer attributes + * + * Get Renderer attributes activated for the renderer. + * + * \return int, Return Attributes + */ +int D3D12VARenderer::getRendererAttributes() +{ + int attributes = 0; + + // This renderer supports HDR + attributes |= RENDERER_ATTRIBUTE_HDR_SUPPORT; + + // This renderer requires frame pacing to synchronize with VBlank when we're in full-screen. + // In windowed mode, we will render as fast we can and DWM will grab whatever is latest at the + // time unless the user opts for pacing. We will use pacing in full-screen mode and normal DWM + // sequencing in full-screen desktop mode to behave similarly to the DXVA2 renderer. + if ((SDL_GetWindowFlags(m_DecoderParams.window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) { + attributes |= RENDERER_ATTRIBUTE_FORCE_PACING; + } + + return attributes; +} + +/** + * \brief Add capabilities to the decoder + * + * By default we ignore the reference frame for HEVC and AV1 as adding 1 frame equals to high-latency. + * H264 doesn't use reference frame. + * + * \return int, Returns the value as an integer of capabilities added + */ +int D3D12VARenderer::getDecoderCapabilities() +{ + return CAPABILITY_REFERENCE_FRAME_INVALIDATION_HEVC | + CAPABILITY_REFERENCE_FRAME_INVALIDATION_AV1; +} + +/** + * \brief Get decoder color space + * + * Get decoder color space + * + * \return int, Returns the value of the color space + */ +int D3D12VARenderer::getDecoderColorspace() +{ + return D3D12VARenderer::m_IsFrameHDR ? COLORSPACE_REC_2020 : COLORSPACE_REC_709; +} + +/** + * \brief Get decoder color range + * + * Get decoder color space. + * + * \return int, Always returns the value of the color range full + */ +int D3D12VARenderer::getDecoderColorRange() +{ + // Compare to Limited, Full has only a additional bandwidth cost is about 3% for SDR, it avoid banding and have better color accuracy. + return COLOR_RANGE_FULL; +} + +/** + * \brief Lock the rendering context + * + * Inform the decoder FFmpeg that the DeviceContext is in used. + * + * \param void *lock_ctx + * \return void + */ +void D3D12VARenderer::lockContext(void *lock_ctx) +{ + auto me = (D3D12VARenderer*)lock_ctx; + + SDL_LockMutex(me->m_ContextLock); +} + +/** + * \brief Unlock the rendering context + * + * Inform the decoder FFmpeg that the DeviceContext is free. + * + * \param void *lock_ctx + * \return void + */ +void D3D12VARenderer::unlockContext(void *lock_ctx) +{ + auto me = (D3D12VARenderer*)lock_ctx; + + SDL_UnlockMutex(me->m_ContextLock); +} + +/** + * \brief Initialize the information of the best-fit Adapter + * + * In case of multiple GPUs, apply the most appropriate GPU available based on Video Super Resolution capabilities + * and priority of Vendor implementation status (NVIDIA -> AMD -> Intel -> Others). + * + * \return bool Returns false if the initializatin failed + */ +bool D3D12VARenderer::initialiazeAdapterInformation() +{ + int adapterIndex = 0; + int outputIndex = 0; + + // Identify the GPU plug to the display + { + if (SDL_DXGIGetOutputInfo(SDL_GetWindowDisplayIndex(m_DecoderParams.window), + &adapterIndex, + &outputIndex)) + { + m_AdapterIndex = static_cast(adapterIndex); + m_OutputIndex = static_cast(outputIndex); + } else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "SDL_DXGIGetOutputInfo() failed: %s", + SDL_GetError()); + return false; + } + } + + m_hr = m_Factory->EnumAdapters1(m_AdapterIndex, &m_Adapter); + if(!verifyHResult(m_hr, "m_Factory->EnumAdapters1(m_AdapterIndex, &m_Adapter);")){ + return false; + } + + m_hr = m_Adapter->GetDesc1(&m_AdapterDesc); + if(!verifyHResult(m_hr, "m_Adapter->GetDesc1(&m_AdapterDesc);")){ + return false; + } + if (m_AdapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { + // WARP device will fail. + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "WRAP Device not supported: %x", + m_hr); + return false; + } + + // A dedicated GPU (dGPU) doesn’t need shared memory, generally less than 512 MB, we can set a max limit at 2 GB. + // Conversely, an integrated GPU (iGPU) relies mostly on shared memory, generally more than 2 GB, we can set a min limit at 512 MB. + // We check that Shared memeory is more than 512 MB and DedicatedMemory less than 2 GB + if(m_AdapterDesc.SharedSystemMemory >= (512 * 1024 * 1024) && m_AdapterDesc.DedicatedVideoMemory <= (2048ull * 1024 * 1024)){ + m_IsIntegratedGPU = true; + } + + // Check if on battery + SYSTEM_POWER_STATUS status; + if (GetSystemPowerStatus(&status)) { + m_IsOnBattery = status.ACLineStatus == 0; // 0 = on battery, 1 = plugged in + } + + // Low-end GPU are less than 4GB + if(m_AdapterDesc.DedicatedVideoMemory <= (4096ull * 1024 * 1024)){ + m_IsLowEndGPU = true; + } + + // Cap the enhancer quality with the amount of VRAM. The DNN based upscalers cost + // roughly a full frame budget at high refresh rate on mid-range GPUs, so anything + // up to 8 GB starts at Medium and anything below 4 GB starts at Low. + if (m_IsLowEndGPU) { + m_VsrQualityCeiling = NVSDK_NGX_VSR_Quality_Low; + } else if (m_AdapterDesc.DedicatedVideoMemory <= (8192ull * 1024 * 1024)) { + m_VsrQualityCeiling = NVSDK_NGX_VSR_Quality_Medium; + } else { + m_VsrQualityCeiling = NVSDK_NGX_VSR_Quality_High; + } + + // Running on battery, stay on the cheapest quality + if (m_IsOnBattery) { + m_VsrQualityCeiling = NVSDK_NGX_VSR_Quality_Low; + } + + m_VideoEnhancement->setAdapterIndex(m_AdapterIndex); + m_VideoEnhancement->setVendorID(m_AdapterDesc.VendorId); + m_VideoEnhancement->setIntegratedGPU(m_IsIntegratedGPU); + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Detected GPU %d: %S (%x:%x)", + m_AdapterIndex, + m_AdapterDesc.Description, + m_AdapterDesc.VendorId, + m_AdapterDesc.DeviceId); + + return true; +} + +/** + * \brief Timer checkpoint + * + * Trace the code with comment and time + * + * \return void + */ +void D3D12VARenderer::TimerInfo(const char* comment, bool start) +{ +#ifdef QT_DEBUG + if(!m_TimerInfo) + return; + + qInfo() << "Timer Info: " << QString::number(m_Timer.nsecsElapsed() / 1'000'000.0, 'f', 3).toUtf8().constData() << "ms" << comment; + + if(start) + m_Timer.start(); +#endif +} + +/** + * \brief Check decoder support for the configured video format + * + * Query the D3D11 video device to verify hardware decoding capability + * for the current video format, profile, and output pixel format. + * + * \return bool True if hardware decoding is supported, false otherwise + */ +bool D3D12VARenderer::checkDecoderDX11Support() +{ + struct { + GUID profile; + DXGI_FORMAT format; + const char* name; + } decodeConfig = {}; + + switch (m_DecoderParams.videoFormat) + { + case VIDEO_FORMAT_H264: + decodeConfig = { + D3D11_DECODER_PROFILE_H264_VLD_NOFGT, + DXGI_FORMAT_NV12, + "H.264" + }; + break; + + case VIDEO_FORMAT_H264_HIGH8_444: + // Unsupported by DXVA + return false; + + case VIDEO_FORMAT_H265: + decodeConfig = { + D3D11_DECODER_PROFILE_HEVC_VLD_MAIN, + DXGI_FORMAT_NV12, + "HEVC Main" + }; + break; + + case VIDEO_FORMAT_H265_MAIN10: + decodeConfig = { + D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10, + DXGI_FORMAT_P010, + "HEVC Main10" + }; + break; + + case VIDEO_FORMAT_H265_REXT8_444: + decodeConfig = { + k_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN_444, + DXGI_FORMAT_AYUV, + "HEVC Main 444 8-bit" + }; + break; + + case VIDEO_FORMAT_H265_REXT10_444: + decodeConfig = { + k_D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10_444, + DXGI_FORMAT_Y410, + "HEVC Main 444 10-bit" + }; + break; + + case VIDEO_FORMAT_AV1_MAIN8: + decodeConfig = { + D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0, + DXGI_FORMAT_NV12, + "AV1 Profile0" + }; + break; + + case VIDEO_FORMAT_AV1_MAIN10: + decodeConfig = { + D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0, + DXGI_FORMAT_P010, + "AV1 Main 10-bit" + }; + break; + + case VIDEO_FORMAT_AV1_HIGH8_444: + decodeConfig = { + D3D11_DECODER_PROFILE_AV1_VLD_PROFILE1, + DXGI_FORMAT_AYUV, + "AV1 High 444 8-bit" + }; + break; + + case VIDEO_FORMAT_AV1_HIGH10_444: + decodeConfig = { + D3D11_DECODER_PROFILE_AV1_VLD_PROFILE1, + DXGI_FORMAT_Y410, + "AV1 High 444 10-bit" + }; + break; + + default: + SDL_assert(false); + return false; + } + + BOOL supported = FALSE; + m_hr = m_D3D11VideoDevice->CheckVideoDecoderFormat(&decodeConfig.profile, + decodeConfig.format, + &supported); + + if (!verifyHResult(m_hr, "m_D3D11VideoDevice->CheckVideoDecoderFormat();")) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "GPU doesn't support %s decoding: %x", + decodeConfig.name, m_hr); + return false; + } + + if (!supported) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "GPU doesn't support %s decoding to target format", + decodeConfig.name); + return false; + } + + if (DXUtil::isFormatHybridDecodedByHardware(m_DecoderParams.videoFormat, m_AdapterDesc.VendorId, m_AdapterDesc.DeviceId)) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "GPU decoding for format %x is blocked due to hardware limitations", + m_DecoderParams.videoFormat); + return false; + } + + return true; +} + +/** + * \brief Check decoder support for the configured video format + * + * Query the D3D12 video device to verify hardware decoding capability + * for the current video format, profile, and output pixel format. + * + * \return bool True if hardware decoding is supported, false otherwise + */ +bool D3D12VARenderer::checkDecoderDX12Support() +{ + struct { + GUID profile; + DXGI_FORMAT format; + const char* name; + } decodeConfig = {}; + + switch (m_DecoderParams.videoFormat) + { + case VIDEO_FORMAT_H264: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_H264, + DXGI_FORMAT_NV12, + "H.264" + }; + break; + + case VIDEO_FORMAT_H264_HIGH8_444: + // Unsupported by DXVA + return false; + + case VIDEO_FORMAT_H265: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN, + DXGI_FORMAT_NV12, + "HEVC Main" + }; + break; + + case VIDEO_FORMAT_H265_MAIN10: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN10, + DXGI_FORMAT_P010, + "HEVC Main10" + }; + break; + + case VIDEO_FORMAT_H265_REXT8_444: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN_444, + DXGI_FORMAT_AYUV, + "HEVC Main 444 8-bit" + }; + break; + + case VIDEO_FORMAT_H265_REXT10_444: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_HEVC_MAIN10_444, + DXGI_FORMAT_Y410, + "HEVC Main 444 10-bit" + }; + break; + + case VIDEO_FORMAT_AV1_MAIN8: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_AV1_PROFILE0, + DXGI_FORMAT_NV12, + "AV1 Profile0" + }; + break; + + case VIDEO_FORMAT_AV1_MAIN10: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_AV1_PROFILE0, + DXGI_FORMAT_P010, + "AV1 Main 10-bit" + }; + break; + + case VIDEO_FORMAT_AV1_HIGH8_444: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_AV1_PROFILE1, + DXGI_FORMAT_AYUV, + "AV1 High 444 8-bit" + }; + break; + + case VIDEO_FORMAT_AV1_HIGH10_444: + decodeConfig = { + D3D12_VIDEO_DECODE_PROFILE_AV1_PROFILE1, + DXGI_FORMAT_Y410, + "AV1 High 444 10-bit" + }; + break; + + default: + SDL_assert(false); + return false; + } + + D3D12_VIDEO_DECODE_CONFIGURATION config = {}; + config.DecodeProfile = decodeConfig.profile; + config.BitstreamEncryption = D3D12_BITSTREAM_ENCRYPTION_TYPE_NONE; + config.InterlaceType = D3D12_VIDEO_FRAME_CODED_INTERLACE_TYPE_NONE; + + DXGI_RATIONAL frameRate = {}; + frameRate.Numerator = static_cast(m_DecoderParams.frameRate); + frameRate.Denominator = 1; + + D3D12_FEATURE_DATA_VIDEO_DECODE_SUPPORT decodeSupport = {}; + decodeSupport.NodeIndex = 0; + decodeSupport.Configuration = config; + decodeSupport.Width = m_DecoderParams.width; + decodeSupport.Height = m_DecoderParams.height; + decodeSupport.DecodeFormat = decodeConfig.format; + decodeSupport.FrameRate = frameRate; + decodeSupport.BitRate = 0; + + m_hr = m_VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_SUPPORT, + &decodeSupport, + sizeof(decodeSupport)); + + if(!verifyHResult(m_hr, "m_VideoDevice->CheckFeatureSupport(D3D12_FEATURE_VIDEO_DECODE_SUPPORT...);")){ + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "GPU doesn't support %s decoding: %x", + decodeConfig.name, m_hr); + return false; + } + + if (!(decodeSupport.SupportFlags & D3D12_VIDEO_DECODE_SUPPORT_FLAG_SUPPORTED)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "GPU doesn't support %s decoding to target format", + decodeConfig.name); + return false; + } + + if (DXUtil::isFormatHybridDecodedByHardware(m_DecoderParams.videoFormat, m_AdapterDesc.VendorId, m_AdapterDesc.DeviceId)) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "GPU decoding for format %x is blocked due to hardware limitations", + m_DecoderParams.videoFormat); + return false; + } + + return true; +} + +/** + * \brief Check Decoder type acceptance + * + * Due to some GPU and driver limitation, FFmpeg may not work properly. + * + * \return bool, Return true if accepted + */ +bool D3D12VARenderer::checkDecoderType() +{ + // FFmpeg decoder in yuv 4:4:4 only works with D3D11 + if (m_IsTextureYUV444) { + return m_IsFrameD3D11; + } + + // For H264 and AV1, AMD is more stable for decoding with FFmpeg in D3D11 + else if (m_VideoEnhancement->isVendorAMD()) { + // Force FFmpeg decoder on D3D11VA, D3D12VA is unstable. + // H.264 and AV1 are freezing and stuttering due to reference frame issues: + // https://ffmpeg.org/pipermail/ffmpeg-devel/2025-February/340089.html + // HEVC is better, but still has issues with reference frame (can see an heavy block effect at window login page). + return m_IsFrameD3D11; + } + + // IntelVPL can work with D3D12, but I have issue with copying NV12 resource, + // therefore I use D3D11, no additional latency impact + else if (m_VideoEnhancement->isVendorIntel()) { + if (m_VendorVSRenabled) + return m_IsFrameD3D11; + } + + // NVIDIA GPUs always support well the decoding in DX12 + else if (m_VideoEnhancement->isVendorNVIDIA()) { + return !m_IsFrameD3D11; + } + + // FFmpeg for Snapdragon GPU only works with DX11 + else if (m_VideoEnhancement->isVendorQualcomm()) { + return m_IsFrameD3D11; + } + + // By default, only accept D3D12va + return !m_IsFrameD3D11; +} + +/** + * \brief Initialization + * + * Initialization of the renderer. + * + * \param PDECODER_PARAMETERS params + * \return bool, Returns true if success + */ +bool D3D12VARenderer::initialize(PDECODER_PARAMETERS params) +{ + // Variables initalization + { + m_DecoderParams = *params; + + // D3D12VideoProcessor only supports hardware decoding + if (m_DecoderParams.vds == StreamingPreferences::VDS_FORCE_SOFTWARE) { + return false; + } + + // Check if HDR is enabled by the user in the UI settings. + m_IsTexture10bits = m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT; + + // NOTE: We ignore the HDR setting as we now have a dynamic way to adapt the stream SDR/HDR<->SDR/HDR + // Check if the Client display has HDR activated + D3D12VARenderer::m_IsClientHDR = getDisplayHDRStatus(); + + // Check if the input stream is YUV 4:4:4 + m_IsTextureYUV444 = m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_YUV444; + + // For stability reasons (like FFmpeg for AMD GPU, or YUV 4:4:4) we need to receive a D3D11 frame. + // Some textures will be shared between the device D3D12 and D3D11. + m_IsFrameD3D11 = m_VideoEnhancement->getDeviceType() == AV_HWDEVICE_TYPE_D3D11VA; + + // For vSync, we don't use m_DecoderParams.enableVsync + m_Vsync = m_Preferences->enableVsync; + + // Setup the display resolution and frequency of the display, + // It overwrite the behavior of Session::updateOptimalWindowDisplayMode() as for fullscreen exclusive mode, + // we need to allow a higher resolution (with a different frequency thus) to leverage upscaling capability. + if (!m_DecoderParams.testOnly) { + + do { + + bool fullscreenExclusive = false; + bool fullscreenBorderless = false; + + switch (m_Preferences->windowMode) { + case StreamingPreferences::WM_FULLSCREEN: + fullscreenExclusive = true; + break; + case StreamingPreferences::WM_FULLSCREEN_DESKTOP: + fullscreenBorderless = true; + break; + default: + break; + } + + if ((SDL_GetWindowFlags(m_DecoderParams.window) & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN) { + // Only print when the window is actually in full-screen exclusive mode, + // otherwise we're not actually using the mode we've set here + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "Chosen best display mode: %dx%dx%d"); + } + + DISPLAY_DEVICEW m_DisplayDevice = {}; + m_DisplayDevice.cb = sizeof(m_DisplayDevice); + + DEVMODEW m_DevMode = {}; + m_DevMode.dmSize = sizeof(m_DevMode); + + DEVMODEW dmTemp = {}; + dmTemp.dmSize = sizeof(dmTemp); + + // Get the display where the application is running + int displayIndex = SDL_GetWindowDisplayIndex(m_DecoderParams.window); + if (displayIndex < 0) + break; + + // Get the position of the display + SDL_Rect sdlBounds = {}; + if (SDL_GetDisplayBounds(displayIndex, &sdlBounds) != 0) + break; + + // The desktop setup + SDL_DisplayMode desktopMode; + if (SDL_GetDesktopDisplayMode(displayIndex, &desktopMode) != 0) + break; + + // The targeted ressolution and frequency + SDL_DisplayMode targetMode = desktopMode; + + bool displayFound = false; + + // Find the corresponding Window device + DWORD index = 0; + while (EnumDisplayDevicesW(nullptr, index, &m_DisplayDevice, 0)) { + if (m_DisplayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) { + + if (!EnumDisplaySettingsExW(m_DisplayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &dmTemp, 0)) + continue; + + // Confirm this is the right display by comparing its position + if (dmTemp.dmPosition.x == sdlBounds.x && dmTemp.dmPosition.y == sdlBounds.y) { + displayFound = true; + m_DevMode = dmTemp; + break; + } + + } + index++; + } + + // No display device found + if (!displayFound) + break; + + // Find Frequency configurations + index = 0; + // Get highest frequency at the targeted resolution + // It will be used in vSync and "fake" exclusive mode to take advantage of VRR capability. + uint highestFrameRate = 0; + while (EnumDisplaySettingsExW(m_DisplayDevice.DeviceName, index, &dmTemp, 0)) { + // Only check setups with the same resolution + if (dmTemp.dmPelsWidth == targetMode.w && dmTemp.dmPelsHeight == targetMode.h) { + + // Highest + if (dmTemp.dmDisplayFrequency > highestFrameRate) { + highestFrameRate = dmTemp.dmDisplayFrequency; + } + + } + index++; + } + + // No frequency found + if (highestFrameRate == 0) + break; + + if (fullscreenExclusive || m_Vsync) + targetMode.refresh_rate = highestFrameRate; + + // NOTE: + // Windowed + Borderless: Keep display frequency + // Windowed + Borderless + vSync: Set closest Set highest frequency (to get use of VRR) + // Exclusive: Set highest frequency (to reduce tearing) + // Exclusive + vSync: Set highest frequency (to get use of VRR) + + // We update only if the target is different as the initial setup. + // For excluse, we force the update to enable VRR + if (targetMode.refresh_rate != m_DevMode.dmDisplayFrequency) { + + // By default, do not change anything + m_DevMode.dmFields = 0; + + // Update the frequency only when vSync is enabled or in fullscreen mode + if (fullscreenExclusive || m_Vsync) { + if (targetMode.refresh_rate != m_DevMode.dmDisplayFrequency) { + m_DevMode.dmFields |= DM_DISPLAYFREQUENCY; + m_DevMode.dmDisplayFrequency = highestFrameRate; + } + } + + // We skip if we do no change + if (m_DevMode.dmFields == 0) + break; + + // Do not use exclusive CDS_FULLSCREEN as it doesn't work with VRR. + // VRR is important due to the non-fixed streaming frame rate. + LONG result = ChangeDisplaySettingsExW( + m_DisplayDevice.DeviceName, + &m_DevMode, + NULL, + 0, // Change globally + NULL + ); + + if (result != DISP_CHANGE_SUCCESSFUL) + break; + + // Switch to fullscreen + if (fullscreenExclusive || fullscreenBorderless) { + SDL_SetWindowDisplayMode(m_DecoderParams.window, &targetMode); + if (SDL_SetWindowFullscreen(m_DecoderParams.window, SDL_WINDOW_FULLSCREEN_DESKTOP) != 0) + break; + } else { + if (SDL_SetWindowFullscreen(m_DecoderParams.window, 0) != 0) + break; + } + + m_DecoderParams.frameRate = targetMode.refresh_rate; + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Display setup: %dx%d @ %dHz", + m_DevMode.dmPelsWidth, m_DevMode.dmPelsHeight, m_DevMode.dmDisplayFrequency); + } + + } while (false); // Run only once + + } + + // Calculate and fill the allocation sizes using the bitwise "round up to even" method. + m_DecoderParams.textureWidth = (m_DecoderParams.width + 1) & ~1; + m_DecoderParams.textureHeight = (m_DecoderParams.height + 1) & ~1; + + // Surfaces must be 16 pixel aligned for H.264 and 128 pixel aligned for everything else + // https://github.com/FFmpeg/FFmpeg/blob/a234e5cd80224c95a205c1f3e297d8c04a1374c3/libavcodec/dxva2.c#L609-L616 + m_TextureAlignment = (m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_H264) ? 16 : 128; + + m_FrameWidth = FFALIGN(m_DecoderParams.textureWidth, m_TextureAlignment); + m_FrameHeight = FFALIGN(m_DecoderParams.textureHeight, m_TextureAlignment); + + // Decoder information + m_Decoder = {}; + m_Decoder.ColorRange = getDecoderColorRange(); + if (m_IsTexture10bits) { + m_Decoder.Format = m_IsTextureYUV444 ? DXGI_FORMAT_Y410 : DXGI_FORMAT_P010; + m_Decoder.AVFormat = m_IsTextureYUV444 ? AV_PIX_FMT_XV30 : AV_PIX_FMT_P010; + } else { + m_Decoder.Format = m_IsTextureYUV444 ? DXGI_FORMAT_AYUV : DXGI_FORMAT_NV12; + m_Decoder.AVFormat = m_IsTextureYUV444 ? AV_PIX_FMT_VUYX : AV_PIX_FMT_NV12; + } + if (D3D12VARenderer::m_IsFrameHDR) { + m_Decoder.ColorSpace = (getDecoderColorRange() & COLOR_RANGE_FULL) ? DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020 : DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020; + } else { + m_Decoder.ColorSpace = (getDecoderColorRange() & COLOR_RANGE_FULL) ? DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709 : DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709; + } + } + + // Dimensions initialization + { + // Used to crop the frame texture receive as the frame need to be aligned by blocks for performance purpose + m_D3D11SrcBox.left = 0; + m_D3D11SrcBox.top = 0; + m_D3D11SrcBox.right = m_DecoderParams.textureWidth; + m_D3D11SrcBox.bottom = m_DecoderParams.textureHeight; + m_D3D11SrcBox.front = 0; + m_D3D11SrcBox.back = 1; + + m_SrcBox.left = 0; + m_SrcBox.top = 0; + m_SrcBox.right = m_DecoderParams.textureWidth; + m_SrcBox.bottom = m_DecoderParams.textureHeight; + m_SrcBox.front = 0; + m_SrcBox.back = 1; + + // Use the current window size as the swapchain size + SDL_GetWindowSize(m_DecoderParams.window, (int*)&m_DisplayWidth, (int*)&m_DisplayHeight); + + // Rounddown to even number to avoid a crash at texture creation + // If the window is odd in a direction, it will crop 1px the backbuffer in that direction + m_DisplayWidth = (m_DisplayWidth + 1) & ~1; + m_DisplayHeight = (m_DisplayHeight + 1) & ~1; + + // As m_Display corresponds to the application window, which may not have the same ratio as the Frame, + // we calculate the size of the final texture to fit in the window without distortion + m_OutputTextureInfo.width = m_DisplayWidth; + m_OutputTextureInfo.height = m_DisplayHeight; + m_OutputTextureInfo.left = 0; + m_OutputTextureInfo.top = 0; + + // Scale the source to the destination surface while keeping the same ratio + float ratioWidth = static_cast(m_OutputTextureInfo.width) / static_cast(m_DecoderParams.textureWidth); + float ratioHeight = static_cast(m_OutputTextureInfo.height) / static_cast(m_DecoderParams.textureHeight); + + if (ratioHeight < ratioWidth) { + // Adjust the Width + m_OutputTextureInfo.width = static_cast(std::floor(m_DecoderParams.textureWidth * ratioHeight)); + m_OutputTextureInfo.width = m_OutputTextureInfo.width & ~1; + m_OutputTextureInfo.left = static_cast(std::floor( abs(m_DisplayWidth - m_OutputTextureInfo.width) / 2 )); + m_OutputTextureInfo.left = m_OutputTextureInfo.left & ~1; + } else if (ratioWidth < ratioHeight) { + // Adjust the Height + m_OutputTextureInfo.height = static_cast(std::floor(m_DecoderParams.textureHeight * ratioWidth)); + m_OutputTextureInfo.height = m_OutputTextureInfo.height & ~1; + m_OutputTextureInfo.top = static_cast(std::floor( abs(m_DisplayHeight - m_OutputTextureInfo.height) / 2 )); + m_OutputTextureInfo.top = m_OutputTextureInfo.top & ~1; + } + + m_D3D11OutputBox.left = 0; + m_D3D11OutputBox.top = 0; + m_D3D11OutputBox.front = 0; + m_D3D11OutputBox.right = m_OutputTextureInfo.width; + m_D3D11OutputBox.bottom = m_OutputTextureInfo.height; + m_D3D11OutputBox.back = 1; + + m_OutputBox.left = 0; + m_OutputBox.top = 0; + m_OutputBox.front = 0; + m_OutputBox.right = m_OutputTextureInfo.width; + m_OutputBox.bottom = m_OutputTextureInfo.height; + m_OutputBox.back = 1; + } + + // Debug Layer + { + if (Utils::getEnvironmentVariableOverride("D3D11VA_DEBUG_LAYER", &m_DebugLayer)) { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "Using D3D11VA_DEBUG_LAYER to override default debug layer behavior"); + } + else { + #ifdef QT_DEBUG + m_DebugLayer = true; + #else + m_DebugLayer = false; + #endif + } + + // Check if Graphics Tools are installed + if (m_DebugLayer) { + HMODULE dxgiDebug = LoadLibraryExW(L"DXGIDebug.dll", 0, LOAD_LIBRARY_SEARCH_SYSTEM32); + if (dxgiDebug) { + FreeLibrary(dxgiDebug); + } + else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "DXGI/D3D11 debug layer unavailable. Enable 'Graphics Tools' optional feature!"); + m_DebugLayer = false; + } + } + } + + UINT dxgiFactoryFlags = m_DebugLayer ? DXGI_CREATE_FACTORY_DEBUG : 0; + + m_hr = CreateDXGIFactory2(dxgiFactoryFlags, __uuidof(IDXGIFactory6), (void**)m_Factory.GetAddressOf()); + if (FAILED(m_hr)) { + // Debug mode may crash for Snapdragon GPU, try without + m_hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory6), (void**)m_Factory.GetAddressOf()); + if(!verifyHResult(m_hr, "CreateDXGIFactory2(0, __uuidof(IDXGIFactory6), (void**)m_Factory.GetAddressOf());")){ + return false; + } + } + + if (!initialiazeAdapterInformation()) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "initialiazeAdapterInformation() failed"); + return false; + } + + // Both of these are permanent for the lifetime of the process, so they latch + // the D3D12 renderer as unavailable to let D3D11VA take over. Setting + // D3D12VA_ENABLED=0 therefore reproduces exactly what a system without the + // required D3D12 interfaces does. + if (qgetenv("D3D12VA_ENABLED") == "0") { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "D3D12VA is disabled by environment variable"); + m_VideoEnhancement->setD3D12Available(false); + return false; + } else if (!IsWindows10OrGreater()) { + // Use DXVA2 on anything older than Win10, so we don't have to handle a bunch + // of legacy Win7/Win8 codepaths in here. + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "D3D12VA renderer is only supported on Windows 10 or later."); + m_VideoEnhancement->setD3D12Available(false); + return false; + } + + // Device creation + m_hr = D3D12CreateDevice( + m_Adapter.Get(), + D3D_FEATURE_LEVEL_12_0, + IID_PPV_ARGS(&m_Device) + ); + if(!verifyHResult(m_hr, "D3D12CreateDevice(... m_Device)")){ + // This system cannot host a D3D12 device at all, so there is no point + // retrying this renderer. Let D3D11VA take over instead of falling all + // the way through to the Vulkan renderer. + m_VideoEnhancement->setD3D12Available(false); + return false; + } + + // VideoDevice creation + m_hr = m_Device.As(&m_VideoDevice); + if(!verifyHResult(m_hr, "m_Device.As(&m_VideoDevice);")){ + m_VideoEnhancement->setD3D12Available(false); + return false; + } + + // Debug + if (m_DebugLayer) { + // Provide more information, but could slow down the run + if (m_DebugVerbose) { + ComPtr debugController; + if (SUCCEEDED(D3D12GetDebugInterface(IID_PPV_ARGS(&debugController)))) { + // Note: EnableDebugLayer makes the code less permissive and could fail in DEBUG mode while it works in Production mode. + // WARNING: It easily bugs the application (like VideoProcessCommandList which can't be closed) and returns missleading information. + debugController->EnableDebugLayer(); + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "D3D12 Debug Layer is enabled."); + } + + ComPtr debugControllerGPU; + if (SUCCEEDED(debugController.As(&debugControllerGPU))) { + debugControllerGPU->SetEnableGPUBasedValidation(TRUE); + } + + ComPtr debugDevice; + if (SUCCEEDED(m_Device.As(&debugDevice))) { + D3D12_DEBUG_FEATURE mask = + D3D12_DEBUG_FEATURE_ALLOW_BEHAVIOR_CHANGING_DEBUG_AIDS | + D3D12_DEBUG_FEATURE_CONSERVATIVE_RESOURCE_STATE_TRACKING; + debugDevice->SetDebugParameter( + D3D12_DEBUG_DEVICE_PARAMETER_FEATURE_FLAGS, + &mask, + sizeof(mask) + ); + } + + ComPtr infoQueue; + if (SUCCEEDED(m_Device.As(&infoQueue))) + { + // Stop the code on Error + // infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_ERROR, TRUE); + // infoQueue->SetBreakOnSeverity(D3D12_MESSAGE_SEVERITY_CORRUPTION, TRUE); + + // Do not display INFO messages + D3D12_MESSAGE_SEVERITY severities[] = { + D3D12_MESSAGE_SEVERITY_INFO + }; + D3D12_INFO_QUEUE_FILTER filter = {}; + filter.DenyList.NumSeverities = _countof(severities); + filter.DenyList.pSeverityList = severities; + infoQueue->PushStorageFilter(&filter); + } + } + } + + // Device D3D11 initialization + // We need to instantiate it as it can be used to check some features availability (Intel VPL) + { + D3D_FEATURE_LEVEL supportedFeatureLevels[] = { D3D_FEATURE_LEVEL_11_1 }; + + m_D3D11Device.Reset(); + m_D3D11DeviceContext.Reset(); + + ComPtr D3D11Device; + ComPtr D3D11DeviceContext; + + D3D_FEATURE_LEVEL featureLevel; + m_hr = D3D11CreateDevice(m_Adapter.Get(), + D3D_DRIVER_TYPE_UNKNOWN, + nullptr, + D3D11_CREATE_DEVICE_VIDEO_SUPPORT, + supportedFeatureLevels, + ARRAYSIZE(supportedFeatureLevels), + D3D11_SDK_VERSION, + D3D11Device.GetAddressOf(), + &featureLevel, + D3D11DeviceContext.GetAddressOf()); + if(!verifyHResult(m_hr, "D3D11CreateDevice(... D3D11Device)")){ + return false; + } + D3D11Device.As(&m_D3D11Device); + D3D11DeviceContext.As(&m_D3D11DeviceContext); + + // DX11 Device creation + m_hr = D3D11Device.As(&m_D3D11VideoDevice); + if(!verifyHResult(m_hr, "D3D11Device.As(&m_D3D11VideoDevice);")){ + return false; + } + + // DX11 VideoDevice creation + m_hr = D3D11Device.As(&m_D3D11VideoDevice); + if(!verifyHResult(m_hr, "D3D11Device.As(&m_D3D11VideoDevice);")){ + return false; + } + + // DX11 DeviceContext creation + m_hr = D3D11DeviceContext.As(&m_D3D11DeviceContext); + if(!verifyHResult(m_hr, "D3D11DeviceContext.As(&m_D3D11DeviceContext);")){ + return false; + } + } + + // Check the codec support + { + if (m_IsFrameD3D11) { + if (!checkDecoderDX11Support()){ + return false; + } + } else { + if (!checkDecoderDX12Support()){ + return false; + } + } + } + + // Command allocator and command list initialization + { + // PROCESS + for (UINT n = 0; n < m_FrameCount; n++) { + m_hr = m_Device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS, + IID_PPV_ARGS(&m_VideoProcessCommandAllocators[n]) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandAllocator(... m_VideoProcessCommandAllocators)")){ + return false; + } + } + + m_hr = m_Device->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS, + m_VideoProcessCommandAllocators[0].Get(), + nullptr, + IID_PPV_ARGS(&m_VideoProcessCommandList) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandList(... m_VideoProcessCommandList)")){ + return false; + } + + // Command lists are created in recording state. Close for now. + m_hr = m_VideoProcessCommandList->Close(); + if(!verifyHResult(m_hr, "m_VideoProcessCommandList->Close();")){ + return false; + } + + D3D12_COMMAND_QUEUE_DESC queueProcessDesc = {}; + queueProcessDesc.Type = D3D12_COMMAND_LIST_TYPE_VIDEO_PROCESS; + queueProcessDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH; + queueProcessDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueProcessDesc.NodeMask = 0; + m_hr = m_Device->CreateCommandQueue(&queueProcessDesc, IID_PPV_ARGS(&m_VideoProcessCommandQueue)); + if(!verifyHResult(m_hr, "m_Device->CreateCommandQueue(&queueProcessDesc, IID_PPV_ARGS(&m_VideoProcessCommandQueue));")){ + return false; + } + + // GRAPHICS + for (UINT n = 0; n < m_FrameCount; n++) { + m_hr = m_Device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&m_GraphicsCommandAllocators[n]) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandAllocator(... m_GraphicsCommandAllocators)")){ + return false; + } + } + + m_hr = m_Device->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_DIRECT, + m_GraphicsCommandAllocators[0].Get(), + nullptr, + IID_PPV_ARGS(&m_GraphicsCommandList) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandList(... m_GraphicsCommandList)")){ + return false; + } + + // Command lists are created in recording state. Close for now. + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + return false; + } + + D3D12_COMMAND_QUEUE_DESC queueGraphicsDesc = {}; + queueGraphicsDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueGraphicsDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_HIGH; + queueGraphicsDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueGraphicsDesc.NodeMask = 0; + m_hr = m_Device->CreateCommandQueue(&queueGraphicsDesc, IID_PPV_ARGS(&m_GraphicsCommandQueue)); + if(!verifyHResult(m_hr, "m_Device->CreateCommandQueue(&queueGraphicsDesc, IID_PPV_ARGS(&m_GraphicsCommandQueue));")){ + return false; + } + + // OVERLAY + m_hr = m_Device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&m_OverlayCommandAllocator) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandAllocator(... m_OverlayCommandAllocator)")){ + return false; + } + + m_hr = m_Device->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_DIRECT, + m_OverlayCommandAllocator.Get(), + nullptr, + IID_PPV_ARGS(&m_OverlayCommandList) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandList(... m_OverlayCommandList)")){ + return false; + } + + // Command lists are created in recording state. Close for now. + m_hr = m_OverlayCommandList->Close(); + if(!verifyHResult(m_hr, "m_OverlayCommandList->Close();")){ + return false; + } + + D3D12_COMMAND_QUEUE_DESC queueOverlayDesc = {}; + queueOverlayDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queueOverlayDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + queueOverlayDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queueOverlayDesc.NodeMask = 0; + m_hr = m_Device->CreateCommandQueue(&queueOverlayDesc, IID_PPV_ARGS(&m_OverlayCommandQueue)); + if(!verifyHResult(m_hr, "m_Device->CreateCommandQueue(&queueOverlayDesc, IID_PPV_ARGS(&m_OverlayCommandQueue));")){ + return false; + } + + // PICTURE + m_hr = m_Device->CreateCommandAllocator( + D3D12_COMMAND_LIST_TYPE_DIRECT, + IID_PPV_ARGS(&m_PictureCommandAllocator) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandAllocator(... m_PictureCommandAllocator)")){ + return false; + } + + m_hr = m_Device->CreateCommandList( + 0, + D3D12_COMMAND_LIST_TYPE_DIRECT, + m_PictureCommandAllocator.Get(), + nullptr, + IID_PPV_ARGS(&m_PictureCommandList) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommandList(... m_PictureCommandList)")){ + return false; + } + + // Command lists are created in recording state. Close for now. + m_hr = m_PictureCommandList->Close(); + if(!verifyHResult(m_hr, "m_PictureCommandList->Close();")){ + return false; + } + + D3D12_COMMAND_QUEUE_DESC queuePictureDesc = {}; + queuePictureDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT; + queuePictureDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL; + queuePictureDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE; + queuePictureDesc.NodeMask = 0; + m_hr = m_Device->CreateCommandQueue(&queuePictureDesc, IID_PPV_ARGS(&m_PictureCommandQueue)); + if(!verifyHResult(m_hr, "m_Device->CreateCommandQueue(&queuePictureDesc, IID_PPV_ARGS(&m_PictureCommandQueue));")){ + return false; + } + } + + // YUV Textures initialization + { + // Texture to receive the frame texture + CD3DX12_HEAP_PROPERTIES heapFrameProps(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC descFrame = {}; + descFrame.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + descFrame.Alignment = 0; + descFrame.Width = m_FrameWidth; + descFrame.Height = m_FrameHeight; + descFrame.DepthOrArraySize = 1; + descFrame.MipLevels = 1; + descFrame.Format = m_Decoder.Format; + descFrame.SampleDesc.Count = 1; + descFrame.SampleDesc.Quality = 0; + descFrame.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + descFrame.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; + if (m_IsFrameD3D11) + descFrame.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; + m_hr = m_Device->CreateCommittedResource( + &heapFrameProps, + m_IsFrameD3D11 ? D3D12_HEAP_FLAG_SHARED : D3D12_HEAP_FLAG_NONE, + &descFrame, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_PPV_ARGS(&m_FrameTexture) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... m_FrameTexture)")){ + return false; + } + + // m_D3D11FrameTexture + if (m_IsFrameD3D11) { + HANDLE sharedHandle1 = nullptr; + m_Device->CreateSharedHandle( + m_FrameTexture.Get(), + nullptr, + GENERIC_ALL, + nullptr, + &sharedHandle1); + + m_hr = m_D3D11Device->OpenSharedResource1(sharedHandle1, IID_PPV_ARGS(m_D3D11FrameTexture.GetAddressOf())); + if(!verifyHResult(m_hr, "OpenSharedResource1(... m_D3D11FrameTexture)")){ + return false; + } + + CloseHandle(sharedHandle1); + } + + // Upscaled YUV texture + CD3DX12_HEAP_PROPERTIES heapYUVProps(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC descYUV = {}; + descYUV.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + descYUV.Alignment = 0; + descYUV.Width = m_OutputTextureInfo.width; + descYUV.Height = m_OutputTextureInfo.height; + descYUV.DepthOrArraySize = 1; + descYUV.MipLevels = 1; + descYUV.Format = m_Decoder.Format; + descYUV.SampleDesc.Count = 1; + descYUV.SampleDesc.Quality = 0; + descYUV.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + descYUV.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + if (m_IsFrameD3D11) + descYUV.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; + m_hr = m_Device->CreateCommittedResource( + &heapYUVProps, + m_IsFrameD3D11 ? D3D12_HEAP_FLAG_SHARED : D3D12_HEAP_FLAG_NONE, + &descYUV, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_PPV_ARGS(&m_YUVTextureUpscaled) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... m_YUVTextureUpscaled)")){ + return false; + } + + // m_D3D11YUVTextureUpscaled + if (m_IsFrameD3D11) { + HANDLE sharedHandle1 = nullptr; + m_Device->CreateSharedHandle( + m_YUVTextureUpscaled.Get(), + nullptr, + GENERIC_ALL, + nullptr, + &sharedHandle1); + + m_hr = m_D3D11Device->OpenSharedResource1(sharedHandle1, IID_PPV_ARGS(m_D3D11YUVTextureUpscaled.GetAddressOf())); + if(!verifyHResult(m_hr, "OpenSharedResource1(... m_D3D11YUVTextureUpscaled)")){ + return false; + } + + CloseHandle(sharedHandle1); + } + } + + // Set Converter and Upscaler according to the GPU + enhanceAutoSelection(); + + // Check if we use FFmpeg decoder in D3D12 or fallback to D3D11 in specifics cases + if(!checkDecoderType()){ + return false; + } + + m_RGBFormat = (m_IsTexture10bits || m_VendorHDRenabled) ? DXGI_FORMAT_R10G10B10A2_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM; + m_RGBColorSpace = (D3D12VARenderer::m_IsFrameHDR || m_VendorHDRenabled) ? DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020 : DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709; + + // RGB Textures initialization + { + D3D12_CLEAR_VALUE clearValueRGB = {}; + clearValueRGB.Format = m_RGBFormat; + clearValueRGB.Color[0] = 0.0f; + clearValueRGB.Color[1] = 0.0f; + clearValueRGB.Color[2] = 0.0f; + clearValueRGB.Color[3] = 1.0f; + + D3D12_CLEAR_VALUE clearValueRGBoutput = {}; + clearValueRGBoutput.Format = m_RGBFormat; + clearValueRGBoutput.Color[0] = 0.0f; + clearValueRGBoutput.Color[1] = 0.0f; + clearValueRGBoutput.Color[2] = 0.0f; + clearValueRGBoutput.Color[3] = 1.0f; + + // Converted texture into RGB format + CD3DX12_HEAP_PROPERTIES heapRGBProps(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC descRGB = {}; + descRGB.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + descRGB.Alignment = 0; + descRGB.Width = m_DecoderParams.textureWidth; + descRGB.Height = m_DecoderParams.textureHeight; + descRGB.DepthOrArraySize = 1; + descRGB.MipLevels = 1; + descRGB.Format = m_RGBFormat; + descRGB.SampleDesc.Count = 1; + descRGB.SampleDesc.Quality = 0; + descRGB.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + descRGB.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + m_hr = m_Device->CreateCommittedResource( + &heapRGBProps, + D3D12_HEAP_FLAG_NONE, + &descRGB, + D3D12_RESOURCE_STATE_COMMON, + &clearValueRGB, + IID_PPV_ARGS(&m_RGBTexture) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... m_RGBTexture)")){ + return false; + } + + // Upscaled RGB texture + descRGB.Width = m_OutputTextureInfo.width; + descRGB.Height = m_OutputTextureInfo.height; + m_hr = m_Device->CreateCommittedResource( + &heapRGBProps, + D3D12_HEAP_FLAG_NONE, + &descRGB, + D3D12_RESOURCE_STATE_COMMON, + &clearValueRGB, + IID_PPV_ARGS(&m_RGBTextureUpscaled) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... m_RGBTextureUpscaled)")){ + return false; + } + + // Texture processed and ready to be copied into the back buffer resource + CD3DX12_HEAP_PROPERTIES heapOutputProps(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC descOutput = {}; + descOutput.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + descOutput.Alignment = 0; + descOutput.Width = m_OutputTextureInfo.width; + descOutput.Height = m_OutputTextureInfo.height; + descOutput.DepthOrArraySize = 1; + descOutput.MipLevels = 1; + descOutput.Format = m_RGBFormat; + descOutput.SampleDesc.Count = 1; + descOutput.SampleDesc.Quality = 0; + descOutput.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + descOutput.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; + + m_hr = m_Device->CreateCommittedResource( + &heapOutputProps, + D3D12_HEAP_FLAG_NONE, + &descOutput, + D3D12_RESOURCE_STATE_COMMON, + &clearValueRGBoutput, + IID_PPV_ARGS(&m_OutputTexture) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... m_OutputTexture)")){ + return false; + } + } + + // m_D3D12Fence & m_D3D11Fence + { + m_hr = m_Device->CreateFence( + 0, D3D12_FENCE_FLAG_SHARED, IID_PPV_ARGS(&m_D3D12Fence)); + if(!verifyHResult(m_hr, "CreateFence(... m_D3D12Fence)")){ + return false; + } + + HANDLE fenceSharedHandle = nullptr; + m_hr = m_Device->CreateSharedHandle( + m_D3D12Fence.Get(), + nullptr, + GENERIC_ALL, + nullptr, + &fenceSharedHandle); + if(!verifyHResult(m_hr, "CreateFence(... m_D3D12Fence)")){ + return false; + } + + m_hr = m_D3D11Device->OpenSharedFence( + fenceSharedHandle, + IID_PPV_ARGS(&m_D3D11Fence) + ); + if(!verifyHResult(m_hr, "OpenSharedFence(... m_D3D11Fence)")){ + return false; + } + CloseHandle(fenceSharedHandle); + } + + // IntelVPL textures + if (m_RenderStep1 == RenderStep::UPSCALE_VPL && m_VppSession) { + + // Resize + m_VppSurfaceIn.resize(m_VppReq[0].NumFrameSuggested); + m_VppSurfaceOut.resize(m_VppReq[1].NumFrameSuggested); + + // Input VPL Texture + D3D11_TEXTURE2D_DESC descIn11 = {}; + descIn11.Width = ALIGN16(m_DecoderParams.textureWidth); + descIn11.Height = ALIGN16(m_DecoderParams.textureHeight); + descIn11.MipLevels = 1; + descIn11.ArraySize = 1; + descIn11.Format = m_Decoder.Format; + descIn11.SampleDesc.Quality = 0; + descIn11.SampleDesc.Count = 1; + descIn11.CPUAccessFlags = 0; + descIn11.Usage = D3D11_USAGE_DEFAULT; + descIn11.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + descIn11.MiscFlags = D3D11_RESOURCE_MISC_SHARED; + + CD3DX12_HEAP_PROPERTIES heapInProps(D3D12_HEAP_TYPE_DEFAULT); + + D3D12_RESOURCE_DESC descIn12 = {}; + descIn12.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + descIn12.Alignment = 0; + descIn12.Width = ALIGN16(m_DecoderParams.textureWidth); + descIn12.Height = ALIGN16(m_DecoderParams.textureHeight); + descIn12.DepthOrArraySize = 1; + descIn12.MipLevels = 1; + descIn12.Format = m_Decoder.Format; + descIn12.SampleDesc.Count = 1; + descIn12.SampleDesc.Quality = 0; + descIn12.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + descIn12.Flags = D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET | D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; + + for (int i = 0; i < m_VppReq[0].NumFrameSuggested; i++) { + if (m_IsFrameD3D11) { + + m_hr = m_D3D11Device->CreateTexture2D(&descIn11, nullptr, m_VppSurfaceIn[i].textureD3D11.GetAddressOf()); + if(!verifyHResult(m_hr, "m_D3D11Device->CreateTexture2D(... m_VppSurfaceIn[i].textureD3D11)")){ + return false; + } + + m_VppSurfaceIn[i].textureLinkD3D11.SurfaceInterface.Header.SurfaceType = MFX_SURFACE_TYPE_D3D11_TEX2D; + m_VppSurfaceIn[i].textureLinkD3D11.SurfaceInterface.Header.SurfaceFlags = MFX_SURFACE_FLAG_IMPORT_SHARED; + m_VppSurfaceIn[i].textureLinkD3D11.SurfaceInterface.Header.StructSize = sizeof(mfxSurfaceD3D11Tex2D ); + m_VppSurfaceIn[i].textureLinkD3D11.SurfaceInterface.Version.Major = 1; + m_VppSurfaceIn[i].textureLinkD3D11.SurfaceInterface.Version.Minor = 0; + m_VppSurfaceIn[i].textureLinkD3D11.texture2D = m_VppSurfaceIn[i].textureD3D11.Get(); + + } else { + + m_hr = m_Device->CreateCommittedResource( + &heapInProps, + D3D12_HEAP_FLAG_SHARED, + &descIn12, + D3D12_RESOURCE_STATE_COMMON, + nullptr, + IID_PPV_ARGS(&m_VppSurfaceIn[i].textureD3D12) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... m_VppSurfaceIn[i].textureD3D12)")){ + return false; + } + + m_VppSurfaceIn[i].textureLinkD3D12.SurfaceInterface.Header.SurfaceType = MFX_SURFACE_TYPE_D3D12_TEX2D; + m_VppSurfaceIn[i].textureLinkD3D12.SurfaceInterface.Header.SurfaceFlags = MFX_SURFACE_FLAG_IMPORT_SHARED; + m_VppSurfaceIn[i].textureLinkD3D12.SurfaceInterface.Header.StructSize = sizeof(mfxSurfaceD3D12Tex2D ); + m_VppSurfaceIn[i].textureLinkD3D12.SurfaceInterface.Version.Major = 1; + m_VppSurfaceIn[i].textureLinkD3D12.SurfaceInterface.Version.Minor = 0; + m_VppSurfaceIn[i].textureLinkD3D12.texture2D = m_VppSurfaceIn[i].textureD3D12.Get(); + + } + } + + // Output VPL Texture + + for (int i = 0; i < m_VppReq[1].NumFrameSuggested; i++) { + if (m_IsFrameD3D11) { + + m_VppSurfaceOut[i].textureLinkD3D11.SurfaceInterface.Header.SurfaceType = MFX_SURFACE_TYPE_D3D11_TEX2D; + m_VppSurfaceOut[i].textureLinkD3D11.SurfaceInterface.Header.SurfaceFlags = MFX_SURFACE_FLAG_IMPORT_SHARED; + m_VppSurfaceOut[i].textureLinkD3D11.SurfaceInterface.Header.StructSize = sizeof(mfxSurfaceD3D11Tex2D); + m_VppSurfaceOut[i].textureLinkD3D11.SurfaceInterface.Version.Major = 1; + m_VppSurfaceOut[i].textureLinkD3D11.SurfaceInterface.Version.Minor = 0; + m_VppSurfaceOut[i].textureLinkD3D11.texture2D = nullptr; + + } else { + + m_VppSurfaceOut[i].textureLinkD3D12.SurfaceInterface.Header.SurfaceType = MFX_SURFACE_TYPE_D3D12_TEX2D; + m_VppSurfaceOut[i].textureLinkD3D12.SurfaceInterface.Header.SurfaceFlags = MFX_SURFACE_FLAG_IMPORT_SHARED; + m_VppSurfaceOut[i].textureLinkD3D12.SurfaceInterface.Header.StructSize = sizeof(mfxSurfaceD3D12Tex2D); + m_VppSurfaceOut[i].textureLinkD3D12.SurfaceInterface.Version.Major = 1; + m_VppSurfaceOut[i].textureLinkD3D12.SurfaceInterface.Version.Minor = 0; + m_VppSurfaceOut[i].textureLinkD3D12.texture2D = nullptr; + + } + } + } + + // SwapChain initialization + { + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {}; + swapChainDesc.Width = m_DisplayWidth; + swapChainDesc.Height = m_DisplayHeight; + swapChainDesc.Format = m_RGBFormat; + swapChainDesc.Stereo = FALSE; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = m_FrameCount; + swapChainDesc.Scaling = DXGI_SCALING_STRETCH; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE; + swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + // Use DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING with flip mode for non-vsync case, if possible. + // NOTE: This is only possible in windowed or borderless windowed mode. + if (!m_Vsync) { + BOOL allowTearing = false; + m_hr = m_Factory->CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING, + &allowTearing, + sizeof(allowTearing)); + if (SUCCEEDED(m_hr)) { + if (allowTearing) { + // Use flip discard with allow tearing mode if possible. + swapChainDesc.Flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + m_AllowTearing = true; + } + else { + SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, + "OS/GPU doesn't support DXGI_FEATURE_PRESENT_ALLOW_TEARING"); + } + } + else { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "IDXGIFactory::CheckFeatureSupport(DXGI_FEATURE_PRESENT_ALLOW_TEARING) failed: %x", + m_hr); + } + } + + SDL_SysWMinfo info; + SDL_VERSION(&info.version); + SDL_GetWindowWMInfo(m_DecoderParams.window, &info); + SDL_assert(info.subsystem == SDL_SYSWM_WINDOWS); + + // swapChain + ComPtr swapChain; + m_hr = m_Factory->CreateSwapChainForHwnd( + m_GraphicsCommandQueue.Get(), + info.info.win.window, + &swapChainDesc, + nullptr, + nullptr, + &swapChain + ); + if(!verifyHResult(m_hr, "m_Factory->CreateSwapChainForHwnd(... swapChain)")){ + return false; + } + + m_hr = swapChain.As(&m_SwapChain); + if(!verifyHResult(m_hr, "swapChain.As(&m_SwapChain);")){ + return false; + } + + // Reduce latency + m_FrameLatencyWaitableObject = m_SwapChain->GetFrameLatencyWaitableObject(); + m_SwapChain->SetMaximumFrameLatency(1); + + // SDR/HDR + m_SwapChain->SetColorSpace1(m_RGBColorSpace); + + // Disable Alt+Enter, PrintScreen, and window message snooping. This makes + // it safe to run the renderer on a separate rendering thread rather than + // requiring the main (message loop) thread. + m_hr = m_Factory->MakeWindowAssociation(info.info.win.window, DXGI_MWA_NO_WINDOW_CHANGES); + } + + // Video Processor initialization + { + // D3D12_VIDEO_PROCESS_INPUT_STREAM_ARGUMENTS1 inputStreamFiltersArgs = {}; // Unused + + D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC inputStreamConvert = {}; + inputStreamConvert.Format = m_Decoder.Format; + inputStreamConvert.ColorSpace = m_Decoder.ColorSpace; + inputStreamConvert.SourceAspectRatio = {1, 1}; + inputStreamConvert.DestinationAspectRatio = {1, 1}; + inputStreamConvert.FrameRate.Numerator = m_DecoderParams.frameRate; + inputStreamConvert.FrameRate.Denominator = 1; + inputStreamConvert.SourceSizeRange = { + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight), + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + inputStreamConvert.DestinationSizeRange = { + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight), + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + inputStreamConvert.EnableOrientation = FALSE; + inputStreamConvert.FilterFlags = D3D12_VIDEO_PROCESS_FILTER_FLAG_NONE; + inputStreamConvert.StereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE; + inputStreamConvert.FieldType = D3D12_VIDEO_FIELD_TYPE_NONE; + inputStreamConvert.DeinterlaceMode = D3D12_VIDEO_PROCESS_DEINTERLACE_FLAG_NONE; + inputStreamConvert.EnableAlphaBlending = FALSE; + inputStreamConvert.LumaKey = {0, 0}; + inputStreamConvert.NumPastFrames = 0; + inputStreamConvert.NumFutureFrames = 0; + inputStreamConvert.EnableAutoProcessing = FALSE; + + // Render Step 2 + D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC inputStreamUpscaler = inputStreamConvert; + inputStreamUpscaler.Format = m_RGBFormat; + inputStreamUpscaler.ColorSpace = m_RGBColorSpace; + inputStreamUpscaler.DestinationSizeRange = { + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height), + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height) + }; + + D3D12_VIDEO_PROCESS_INPUT_STREAM_DESC inputStreamUpscalerConvert = inputStreamConvert; + inputStreamUpscalerConvert.DestinationSizeRange = { + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height), + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height) + }; + + D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC outputStreamRGB = {}; + outputStreamRGB.Format = m_RGBFormat; + outputStreamRGB.ColorSpace = m_RGBColorSpace; + outputStreamRGB.AlphaFillMode = D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE; + outputStreamRGB.AlphaFillModeSourceStreamIndex = 0; + outputStreamRGB.BackgroundColor[0] = 0.0f; + outputStreamRGB.BackgroundColor[1] = 0.0f; + outputStreamRGB.BackgroundColor[2] = 0.0f; + outputStreamRGB.BackgroundColor[3] = 1.0f; + outputStreamRGB.FrameRate.Numerator = m_DecoderParams.frameRate; + outputStreamRGB.FrameRate.Denominator = 1; + outputStreamRGB.EnableStereo = FALSE; + + D3D12_VIDEO_PROCESS_OUTPUT_STREAM_DESC outputStreamYUV = {}; + outputStreamYUV.Format = m_Decoder.Format; + outputStreamYUV.ColorSpace = m_Decoder.ColorSpace; + outputStreamYUV.AlphaFillMode = D3D12_VIDEO_PROCESS_ALPHA_FILL_MODE_OPAQUE; + outputStreamYUV.AlphaFillModeSourceStreamIndex = 0; + outputStreamYUV.BackgroundColor[0] = 0.0f; + outputStreamYUV.BackgroundColor[1] = 0.0f; + outputStreamYUV.BackgroundColor[2] = 0.0f; + outputStreamYUV.BackgroundColor[3] = 1.0f; + outputStreamYUV.FrameRate.Numerator = m_DecoderParams.frameRate; + outputStreamYUV.FrameRate.Denominator = 1; + outputStreamYUV.EnableStereo = FALSE; + + // Check support + struct KVFormat { + DXGI_FORMAT key; + std::string value; + }; + struct KVCS { + DXGI_COLOR_SPACE_TYPE key; + std::string value; + }; + + // Texture formats + std::unordered_map formats = { + {DXGI_FORMAT_NV12, "DXGI_FORMAT_NV12"}, + {DXGI_FORMAT_P010, "DXGI_FORMAT_P010"}, + {DXGI_FORMAT_AYUV, "DXGI_FORMAT_AYUV"}, + {DXGI_FORMAT_Y410, "DXGI_FORMAT_Y410"}, + {DXGI_FORMAT_R8G8B8A8_UNORM, "DXGI_FORMAT_R8G8B8A8_UNORM"}, + {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, "DXGI_FORMAT_R8G8B8A8_UNORM_SRGB"}, + {DXGI_FORMAT_R10G10B10A2_UNORM, "DXGI_FORMAT_R10G10B10A2_UNORM"}, + {DXGI_FORMAT_R16G16B16A16_UNORM, "DXGI_FORMAT_R16G16B16A16_UNORM"} + }; + + // Color Spaces + std::unordered_map colorSpaces = { + {DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601, "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601"}, + {DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709, "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709"}, + {DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020, "DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020"}, + {DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020, "DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020"}, + {DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601, "DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601"}, + {DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709, "DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709"}, + {DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020, "DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020"}, + {DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709, "DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P709"}, + {DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020, "DXGI_COLOR_SPACE_RGB_FULL_G2084_NONE_P2020"}, + {DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020, "DXGI_COLOR_SPACE_RGB_FULL_G22_NONE_P2020"} + }; + + D3D12_FEATURE_DATA_VIDEO_PROCESS_SUPPORT supportVideoProcess = {}; + supportVideoProcess.NodeIndex = 0; + supportVideoProcess.InputSample.Format.Format = m_Decoder.Format; + supportVideoProcess.InputSample.Format.ColorSpace = m_Decoder.ColorSpace; + supportVideoProcess.InputSample.Width = m_DecoderParams.textureWidth; + supportVideoProcess.InputSample.Height = m_DecoderParams.textureHeight; + supportVideoProcess.InputFieldType = D3D12_VIDEO_FIELD_TYPE_NONE; + supportVideoProcess.InputStereoFormat = D3D12_VIDEO_FRAME_STEREO_FORMAT_NONE; + supportVideoProcess.InputFrameRate = { static_cast(m_DecoderParams.frameRate), 1 }; + supportVideoProcess.OutputFormat.Format = m_RGBFormat; + supportVideoProcess.OutputFormat.ColorSpace = m_RGBColorSpace; + + // Check if the conversion YUV -> RGB is supported + if (SUCCEEDED(m_VideoDevice->CheckFeatureSupport( + D3D12_FEATURE_VIDEO_PROCESS_SUPPORT, + &supportVideoProcess, + sizeof(supportVideoProcess) + ))) { + + m_VideoProcessorConvertEnabled = true; + + qInfo().nospace().noquote() + << "VideoProcessor conversion YUV->RGB supported: input=" << formats[supportVideoProcess.InputSample.Format.Format] + << " (" << colorSpaces[supportVideoProcess.InputSample.Format.ColorSpace] << ")" + << " -> output=" << formats[supportVideoProcess.OutputFormat.Format] + << " (" << colorSpaces[supportVideoProcess.OutputFormat.ColorSpace] << ")"; + } else { + qWarning().nospace().noquote() + << "VideoProcessor conversion YUV->RGB not supported: input=" << formats[supportVideoProcess.InputSample.Format.Format] + << " (" << colorSpaces[supportVideoProcess.InputSample.Format.ColorSpace] << ")" + << " -> output=" << formats[supportVideoProcess.OutputFormat.Format] + << " (" << colorSpaces[supportVideoProcess.OutputFormat.ColorSpace] << ")"; + } + + supportVideoProcess.OutputFormat.Format = m_Decoder.Format; + supportVideoProcess.OutputFormat.ColorSpace = m_Decoder.ColorSpace; + + // Check if the Upscaler is supported + if (SUCCEEDED(m_VideoDevice->CheckFeatureSupport( + D3D12_FEATURE_VIDEO_PROCESS_SUPPORT, + &supportVideoProcess, + sizeof(supportVideoProcess) + ))) { + + if( + supportVideoProcess.ScaleSupport.OutputSizeRange.MinWidth <= static_cast(m_OutputTextureInfo.width) + && supportVideoProcess.ScaleSupport.OutputSizeRange.MaxWidth >= static_cast(m_OutputTextureInfo.width) + && supportVideoProcess.ScaleSupport.OutputSizeRange.MinHeight <= static_cast(m_OutputTextureInfo.height) + && supportVideoProcess.ScaleSupport.OutputSizeRange.MaxHeight >= static_cast(m_OutputTextureInfo.height) + ) { + m_VideoProcessorUpscalerEnabled = true; + + // Check is Auto Super Resolution is supported + if( + supportVideoProcess.AutoProcessingSupport & D3D12_VIDEO_PROCESS_AUTO_PROCESSING_FLAG_SUPER_RESOLUTION + || supportVideoProcess.AutoProcessingSupport & D3D12_VIDEO_PROCESS_AUTO_PROCESSING_FLAG_EDGE_ENHANCEMENT + ){ + inputStreamConvert.EnableAutoProcessing = TRUE; + inputStreamUpscaler.EnableAutoProcessing = TRUE; + inputStreamUpscalerConvert.EnableAutoProcessing = TRUE; + } + + qInfo().nospace().noquote() + << "VideoProcessor upscaling supported: input=" << m_DecoderParams.textureWidth + << "x" << m_DecoderParams.textureHeight + << " -> output=" << m_OutputTextureInfo.width + << "x" << m_OutputTextureInfo.height; + } else { + qWarning().nospace().noquote() + << "VideoProcessor upscaling not supported: input=" << m_DecoderParams.textureWidth + << "x" << m_DecoderParams.textureHeight + << " -> output=" << m_OutputTextureInfo.width + << "x" << m_OutputTextureInfo.height; + } + + D3D12_VIDEO_PROCESS_FILTER_RANGE range; + float precent; + + if (!m_IsIntegratedGPU && supportVideoProcess.FilterSupport & D3D12_VIDEO_PROCESS_FILTER_FLAG_NOISE_REDUCTION) { + // Apply 15% to Noise Reduction + range = supportVideoProcess.FilterRangeSupport[D3D12_VIDEO_PROCESS_FILTER_NOISE_REDUCTION]; + precent = 0.15f; + m_NoiseReductionValue = static_cast(std::round((range.Minimum + (range.Maximum - range.Minimum) * precent) / range.Multiplier)) * range.Multiplier; + // Enable the filter at VideoProcessor level + inputStreamUpscaler.FilterFlags |= D3D12_VIDEO_PROCESS_FILTER_FLAG_NOISE_REDUCTION; + inputStreamUpscalerConvert.FilterFlags |= D3D12_VIDEO_PROCESS_FILTER_FLAG_NOISE_REDUCTION; + qInfo() << "Noise Reduction Filter value: " << m_NoiseReductionValue << " [" << range.Minimum << "-" << range.Maximum << "]"; + } + + if (supportVideoProcess.FilterSupport & D3D12_VIDEO_PROCESS_FILTER_FLAG_EDGE_ENHANCEMENT) { + // Apply 35% to Edge Enhancement + range = supportVideoProcess.FilterRangeSupport[D3D12_VIDEO_PROCESS_FILTER_EDGE_ENHANCEMENT]; + precent = 0.35f; + m_EdgeEnhancementValue = static_cast(std::round((range.Minimum + (range.Maximum - range.Minimum) * precent) / range.Multiplier)) * range.Multiplier; + // Enable the filter at VideoProcessor level + inputStreamUpscaler.FilterFlags |= D3D12_VIDEO_PROCESS_FILTER_FLAG_EDGE_ENHANCEMENT; + inputStreamUpscalerConvert.FilterFlags |= D3D12_VIDEO_PROCESS_FILTER_FLAG_EDGE_ENHANCEMENT; + qInfo() << "Edge Reduction Filter value: " << m_EdgeEnhancementValue << " [" << range.Minimum << "-" << range.Maximum << "]"; + } + } else { + qWarning().nospace().noquote() + << "VideoProcessor upscaling not supported: input=" << m_DecoderParams.textureWidth + << "x" << m_DecoderParams.textureHeight + << " -> output=" << m_OutputTextureInfo.width + << "x" << m_OutputTextureInfo.height; + } + + m_InputArgsConvert.resize(m_FrameCount); + m_OutputArgsConvert.resize(m_FrameCount); + m_InputArgsUpscaler.resize(m_FrameCount); + m_OutputArgsUpscaler.resize(m_FrameCount); + m_InputArgsUpscalerConvert.resize(m_FrameCount); + m_OutputArgsUpscalerConvert.resize(m_FrameCount); + + for (UINT n = 0; n < m_FrameCount; n++) { + + // CONVERT + + // Input + m_InputArgsConvert[n].InputStream[0].pTexture2D = m_FrameTexture.Get(); + m_InputArgsConvert[n].InputStream[0].Subresource = 0; + m_InputArgsConvert[n].InputStream[1].pTexture2D = nullptr; + m_InputArgsConvert[n].InputStream[1].Subresource = 0; + m_InputArgsConvert[n].Transform.Orientation = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT; + m_InputArgsConvert[n].Transform.SourceRectangle = { + 0, + 0, + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + m_InputArgsConvert[n].Transform.DestinationRectangle = { + 0, + 0, + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + m_InputArgsConvert[n].Flags = D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE; + m_InputArgsConvert[n].RateInfo.OutputIndex = 0; + m_InputArgsConvert[n].RateInfo.InputFrameOrField = 0; + m_InputArgsConvert[n].AlphaBlending.Enable = FALSE; + m_InputArgsConvert[n].AlphaBlending.Alpha = 1.0f; + m_InputArgsConvert[n].FieldType = D3D12_VIDEO_FIELD_TYPE_NONE; + + // Output + m_OutputArgsConvert[n].OutputStream[0].pTexture2D = m_RGBTexture.Get(); + m_OutputArgsConvert[n].OutputStream[0].Subresource = 0; + m_OutputArgsConvert[n].OutputStream[1].pTexture2D = nullptr; + m_OutputArgsConvert[n].OutputStream[1].Subresource = 0; + m_OutputArgsConvert[n].TargetRectangle = { + 0, + 0, + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + + // UPSCALER + + // Input + m_InputArgsUpscaler[n].InputStream[0].pTexture2D = m_RGBTexture.Get(); + m_InputArgsUpscaler[n].InputStream[0].Subresource = 0; + m_InputArgsUpscaler[n].InputStream[1].pTexture2D = nullptr; + m_InputArgsUpscaler[n].InputStream[1].Subresource = 0; + m_InputArgsUpscaler[n].Transform.Orientation = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT; + m_InputArgsUpscaler[n].Transform.SourceRectangle = { + 0, + 0, + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + m_InputArgsUpscaler[n].Transform.DestinationRectangle = { + 0, + 0, + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height) + }; + m_InputArgsUpscaler[n].Flags = D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE; + m_InputArgsUpscaler[n].RateInfo.OutputIndex = 0; + m_InputArgsUpscaler[n].RateInfo.InputFrameOrField = 0; + m_InputArgsUpscaler[n].AlphaBlending.Enable = FALSE; + m_InputArgsUpscaler[n].AlphaBlending.Alpha = 1.0f; + m_InputArgsUpscaler[n].FieldType = D3D12_VIDEO_FIELD_TYPE_NONE; + m_InputArgsUpscaler[n].FilterLevels[D3D12_VIDEO_PROCESS_FILTER_NOISE_REDUCTION] = m_NoiseReductionValue; + m_InputArgsUpscaler[n].FilterLevels[D3D12_VIDEO_PROCESS_FILTER_EDGE_ENHANCEMENT] = m_EdgeEnhancementValue; + + // Output + m_OutputArgsUpscaler[n].OutputStream[0].pTexture2D = m_OutputTexture.Get(); + m_OutputArgsUpscaler[n].OutputStream[0].Subresource = 0; + m_OutputArgsUpscaler[n].OutputStream[1].pTexture2D = nullptr; + m_OutputArgsUpscaler[n].OutputStream[1].Subresource = 0; + m_OutputArgsUpscaler[n].TargetRectangle = { + 0, + 0, + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height) + }; + + // CONVERT & UPSCALER + + // Input + m_InputArgsUpscalerConvert[n].InputStream[0].pTexture2D = m_FrameTexture.Get(); + m_InputArgsUpscalerConvert[n].InputStream[0].Subresource = 0; + m_InputArgsUpscalerConvert[n].InputStream[1].pTexture2D = nullptr; + m_InputArgsUpscalerConvert[n].InputStream[1].Subresource = 0; + m_InputArgsUpscalerConvert[n].Transform.Orientation = D3D12_VIDEO_PROCESS_ORIENTATION_DEFAULT; + m_InputArgsUpscalerConvert[n].Transform.SourceRectangle = { + 0, + 0, + static_cast(m_DecoderParams.textureWidth), + static_cast(m_DecoderParams.textureHeight) + }; + m_InputArgsUpscalerConvert[n].Transform.DestinationRectangle = { + 0, + 0, + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height) + }; + m_InputArgsUpscalerConvert[n].Flags = D3D12_VIDEO_PROCESS_INPUT_STREAM_FLAG_NONE; + m_InputArgsUpscalerConvert[n].RateInfo.OutputIndex = 0; + m_InputArgsUpscalerConvert[n].RateInfo.InputFrameOrField = 0; + m_InputArgsUpscalerConvert[n].AlphaBlending.Enable = FALSE; + m_InputArgsUpscalerConvert[n].AlphaBlending.Alpha = 1.0f; + m_InputArgsUpscalerConvert[n].FieldType = D3D12_VIDEO_FIELD_TYPE_NONE; + m_InputArgsUpscalerConvert[n].FilterLevels[D3D12_VIDEO_PROCESS_FILTER_NOISE_REDUCTION] = m_NoiseReductionValue; + m_InputArgsUpscalerConvert[n].FilterLevels[D3D12_VIDEO_PROCESS_FILTER_EDGE_ENHANCEMENT] = m_EdgeEnhancementValue; + + // Output + m_OutputArgsUpscalerConvert[n].OutputStream[0].pTexture2D = m_SkipRenderStep2 ? m_OutputTexture.Get() : m_RGBTextureUpscaled.Get(); + m_OutputArgsUpscalerConvert[n].OutputStream[0].Subresource = 0; + m_OutputArgsUpscalerConvert[n].OutputStream[1].pTexture2D = nullptr; + m_OutputArgsUpscalerConvert[n].OutputStream[1].Subresource = 0; + m_OutputArgsUpscalerConvert[n].TargetRectangle = { + 0, + 0, + static_cast(m_OutputTextureInfo.width), + static_cast(m_OutputTextureInfo.height) + }; + } + + m_VideoProcessorUpscalerConvertEnabled = m_VideoProcessorConvertEnabled && m_VideoProcessorUpscalerEnabled; + + // Convert YUV->RGB (RenderStep1) + // Note: VideoProcessor1 does not support: + // DXGI_FORMAT_Y410 input (780M) + // DXGI_FORMAT_AYUV input (780M) + // G2084 all (780M) + if(m_VideoProcessorConvertEnabled){ + m_hr = m_VideoDevice->CreateVideoProcessor1( + 0, + &outputStreamRGB, + 1, + &inputStreamConvert, + nullptr, + IID_PPV_ARGS(&m_VideoProcessorConvert) + ); + if(!verifyHResult(m_hr, "m_VideoDevice->CreateVideoProcessor1(... m_VideoProcessorConvert)")){ + m_VideoProcessorConvertEnabled = false; + } + } + + // Upscaler YUV (RenderStep1) + // We exclude Upscaler RGB as YUV is a lot faster + if(m_VideoProcessorUpscalerEnabled){ + m_hr = m_VideoDevice->CreateVideoProcessor1( + 0, + &outputStreamRGB, + 1, + &inputStreamUpscaler, + nullptr, + IID_PPV_ARGS(&m_VideoProcessorUpscaler) + ); + if(!verifyHResult(m_hr, "m_VideoDevice->CreateVideoProcessor1(... m_VideoProcessorUpscaler)")){ + m_VideoProcessorUpscalerEnabled = false; + } + } + + // Upscaler + Convert YUV->RGB (RenderStep1) + // RenderStep2 can be used for sharpening like RCAS (if m_EdgeEnhancementValue == 0) + if(m_VideoProcessorUpscalerConvertEnabled){ + m_hr = m_VideoDevice->CreateVideoProcessor1( + 0, + &outputStreamRGB, + 1, + &inputStreamUpscalerConvert, + nullptr, + IID_PPV_ARGS(&m_VideoProcessorUpscalerConvert) + ); + if(!verifyHResult(m_hr, "m_VideoDevice->CreateVideoProcessor1(... m_VideoProcessorUpscalerConvert)")){ + m_VideoProcessorUpscalerConvertEnabled = false; + } + } + } + + // If VideoProcessor is not available we fallback to Shader + { + if(!m_VideoProcessorConvertEnabled){ + + // Render Step 1 + switch (m_RenderStep1) { + case RenderStep::CONVERT_VIDEOPROCESSOR: + m_RenderStep1 = RenderStep::CONVERT_SHADER; + break; + case RenderStep::ALL_VIDEOPROCESSOR: + m_EnhancerType = D3D12VideoShaders::Enhancer::SGSR1; + m_RenderStep1 = RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "SGSR1 Upscaler"; + m_InfoSharpener = "SGSR1 Sharpener"; + m_InfoAlgo = "Shader SGSR1"; + if(m_VendorHDRenabled){ + m_InfoAlgo = m_InfoAlgo + " (SDR->HDR)"; + } + m_VideoEnhancement->setAlgo(m_InfoAlgo); + break; + default: + break; + } + + // Render Step 2 + switch (m_RenderStep2) { + case RenderStep::CONVERT_VIDEOPROCESSOR: + m_RenderStep2 = RenderStep::CONVERT_SHADER; + break; + default: + break; + } + + } + + if(!m_VideoProcessorUpscalerEnabled){ + + // Render Step 1 + switch (m_RenderStep1) { + case RenderStep::ALL_VIDEOPROCESSOR: + m_EnhancerType = D3D12VideoShaders::Enhancer::SGSR1; + m_RenderStep1 = (m_IsTextureYUV444 && m_VideoProcessorConvertEnabled) ? RenderStep::CONVERT_VIDEOPROCESSOR : RenderStep::CONVERT_SHADER; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "SGSR1 Upscaler"; + m_InfoSharpener = "SGSR1 Sharpener"; + m_InfoAlgo = "Shader SGSR1"; + if(m_VendorHDRenabled){ + m_InfoAlgo = m_InfoAlgo + " (SDR->HDR)"; + } + m_VideoEnhancement->setAlgo(m_InfoAlgo); + break; + default: + break; + } + + // Render Step 2 + switch (m_RenderStep2) { + case RenderStep::UPSCALE_VIDEOPROCESSOR: + m_EnhancerType = D3D12VideoShaders::Enhancer::SGSR1; + m_RenderStep2 = RenderStep::UPSCALE_SHADER; + m_InfoUpscaler = "SGSR1 Upscaler"; + m_InfoSharpener = "SGSR1 Sharpener"; + m_InfoAlgo = "SGSR1 FSR1"; + if(m_VendorHDRenabled){ + m_InfoAlgo = m_InfoAlgo + " (SDR->HDR)"; + } + m_VideoEnhancement->setAlgo(m_InfoAlgo); + break; + default: + break; + } + + } + } + + // Create frame resources (render target views) + { + D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc = {}; + rtvHeapDesc.NumDescriptors = m_FrameCount; + rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + + m_hr = m_Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_RtvHeap)); + if(!verifyHResult(m_hr, "m_Device->CreateDescriptorHeap(&rtvHeapDesc, IID_PPV_ARGS(&m_RtvHeap));")){ + return false; + } + + m_RtvDescriptorSize = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + + m_BackBuffers.resize(m_FrameCount); + m_BackBufferRTVs.resize(m_FrameCount); + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_RtvHeap->GetCPUDescriptorHandleForHeapStart()); + for (UINT n = 0; n < m_FrameCount; n++) { + m_hr = m_SwapChain->GetBuffer(n, IID_PPV_ARGS(&m_BackBuffers[n])); + if(!verifyHResult(m_hr, "m_SwapChain->GetBuffer(n, IID_PPV_ARGS(&m_BackBuffers[n]));")){ + return false; + } + m_Device->CreateRenderTargetView(m_BackBuffers[n].Get(), nullptr, rtvHandle); + m_BackBufferRTVs[n] = rtvHandle; + rtvHandle.Offset(1, m_RtvDescriptorSize); + } + } + + // Use the corresponding decoder (FFmpeg) + { + if (m_IsFrameD3D11) { + // Use D3D11va to decode + + int err; + + // Initialize FFmpeg + m_HwDeviceContext = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D11VA); + if (!m_HwDeviceContext) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to allocate D3D11VA device context"); + return false; + } + + AVHWDeviceContext* deviceContext = (AVHWDeviceContext*)m_HwDeviceContext->data; + AVD3D11VADeviceContext* d3d11vaDeviceContext = (AVD3D11VADeviceContext*)deviceContext->hwctx; + + // FFmpeg will take ownership of these pointers, so we use CopyTo() to bump the ref count + m_D3D11Device.CopyTo(&d3d11vaDeviceContext->device); + m_D3D11DeviceContext.CopyTo(&d3d11vaDeviceContext->device_context); + + // Set lock functions that we will use to synchronize with FFmpeg's usage of our device context + d3d11vaDeviceContext->lock = lockContext; + d3d11vaDeviceContext->unlock = unlockContext; + d3d11vaDeviceContext->lock_ctx = this; + + err = av_hwdevice_ctx_init(m_HwDeviceContext); + if (err < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to initialize D3D11VA device context: %d", + err); + return false; + } + + } else { + // Use D3D12va to decode + + int err; + + m_HwDeviceContext = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_D3D12VA); + if (!m_HwDeviceContext) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to allocate D3D12VA device context"); + return false; + } + + AVHWDeviceContext* deviceContext = (AVHWDeviceContext*)m_HwDeviceContext->data; + AVD3D12VADeviceContext* d3d12vaDeviceContext = (AVD3D12VADeviceContext*)deviceContext->hwctx; + + // Attach Device + d3d12vaDeviceContext->device = m_Device.Get(); + if (d3d12vaDeviceContext->device) { + d3d12vaDeviceContext->device->AddRef(); + } else { + av_buffer_unref(&m_HwDeviceContext); + return false; + } + + // Attach VideoDevice + d3d12vaDeviceContext->video_device = m_VideoDevice.Get(); + if (d3d12vaDeviceContext->video_device) { + d3d12vaDeviceContext->video_device->AddRef(); + } else { + av_buffer_unref(&m_HwDeviceContext); + return false; + } + + // DirectX12 is Thread-safe by defaut as synchronisation is based on Fence, + // therefor it is not necessary to lock/unlock in order to synchronise with ffmpeg + d3d12vaDeviceContext->lock = [](void* ctx){ + Q_UNUSED(ctx); + }; // Do nothing + d3d12vaDeviceContext->unlock = [](void* ctx){ + Q_UNUSED(ctx); + }; // Do nothing + d3d12vaDeviceContext->lock_ctx = this; + + err = av_hwdevice_ctx_init(m_HwDeviceContext); + if (err < 0) { + d3d12vaDeviceContext->device->Release(); + av_buffer_unref(&m_HwDeviceContext); + return false; + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to initialize D3D12VA device context: %d", + err); + return false; + } + + } + } + + // Create fence for synchronization + { + m_hr = m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceVideoProcess)); + if(!verifyHResult(m_hr, "m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceVideoProcess));")){ + return false; + } + m_FenceVideoProcessEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (m_FenceVideoProcessEvent == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "ID3D12VideoDevice2::CreateEvent() failed: %x", + m_hr); + return false; + } + + m_hr = m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceGraphics)); + if(!verifyHResult(m_hr, "m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceGraphics));")){ + return false; + } + m_FenceGraphicsEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (m_FenceGraphicsEvent == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "ID3D12VideoDevice2::CreateEvent() failed: %x", + m_hr); + return false; + } + + m_hr = m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceOverlay)); + if(!verifyHResult(m_hr, "m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceOverlay));")){ + return false; + } + m_FenceOverlayEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (m_FenceOverlayEvent == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "ID3D12VideoDevice2::CreateEvent() failed: %x", + m_hr); + return false; + } + + m_hr = m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceAMF)); + if(!verifyHResult(m_hr, "m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&m_FenceAMF));")){ + return false; + } + m_FenceAMFEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); + if (m_FenceAMFEvent == nullptr) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "ID3D12VideoDevice2::CreateEvent() failed: %x", + m_hr); + return false; + } + } + + // GPU timing of the graphics queue, used to adapt the enhancer quality at runtime. + // This is best effort: if it cannot be set up we simply keep a fixed quality. + { + D3D12_QUERY_HEAP_DESC queryHeapDesc = {}; + queryHeapDesc.Type = D3D12_QUERY_HEAP_TYPE_TIMESTAMP; + queryHeapDesc.Count = m_FrameCount * 2; + queryHeapDesc.NodeMask = 0; + + if (SUCCEEDED(m_Device->CreateQueryHeap(&queryHeapDesc, IID_PPV_ARGS(&m_QueryHeap))) && + SUCCEEDED(m_GraphicsCommandQueue->GetTimestampFrequency(&m_TimestampFrequency))) { + + CD3DX12_HEAP_PROPERTIES readbackProps(D3D12_HEAP_TYPE_READBACK); + CD3DX12_RESOURCE_DESC readbackDesc = + CD3DX12_RESOURCE_DESC::Buffer(m_FrameCount * 2 * sizeof(UINT64)); + + if (FAILED(m_Device->CreateCommittedResource( + &readbackProps, + D3D12_HEAP_FLAG_NONE, + &readbackDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&m_TimestampReadbackBuffer)))) { + m_QueryHeap.Reset(); + } + } else { + m_QueryHeap.Reset(); + m_TimestampFrequency = 0; + } + + m_TimestampPending = {}; + m_GpuFrameTimeMs = 0.0; + + // A previous instance may already have found that this GPU cannot sustain the + // top level. Keep its verdict, but never above what this GPU's VRAM allows. + if (m_VsrQualityCap == 0) { + m_VsrQualityCap = m_VsrQualityCeiling; + } + m_VsrQualityCap = qMin(m_VsrQualityCap, m_VsrQualityCeiling); + if (m_VsrQualityLevel == 0) { + m_VsrQualityLevel = m_VsrQualityCap; + } + m_VsrQualityLevel = qBound((int)NVSDK_NGX_VSR_Quality_Low, m_VsrQualityLevel, m_VsrQualityCap); + + m_VsrQualityLastCheckMs = 0; + m_VsrQualityStableCount = 0; + m_EnhancerQualitySettled = false; + m_VsrQualityTimer.start(); + } + + // Prepare for the first frame + { + waitForVideoProcess(true); + waitForGraphics(true); + waitForOverlay(true); + + m_FenceVideoProcessValue = m_FenceVideoProcess->GetCompletedValue(); + m_FenceGraphicsValue = m_FenceGraphics->GetCompletedValue(); + m_FenceOverlayValue = m_FenceOverlay->GetCompletedValue(); + m_FenceAMFValue = m_FenceAMF->GetCompletedValue(); + + m_VideoProcessAllocatorFence = {}; + m_GraphicsAllocatorFence = {}; + + resetVideoProcessCommandList(); + resetGraphicsCommandList(); + m_OverlayCommandAllocator->Reset(); + m_OverlayCommandList->Reset(m_OverlayCommandAllocator.Get(), nullptr); + } + + // Initialize the Shaders + { + D3D12_VIEWPORT viewport = {}; + D3D12_RECT scissorRect = {}; + + // Render Step 1 + switch (m_RenderStep1) { + case RenderStep::CONVERT_SHADER: + + // Viewport + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(m_FrameTexture->GetDesc().Width); + viewport.Height = static_cast(m_FrameTexture->GetDesc().Height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + // Scissor (Crop to fit into the Output texture) + scissorRect.left = 0; + scissorRect.top = 0; + scissorRect.right = m_DecoderParams.textureWidth; + scissorRect.bottom = m_DecoderParams.textureHeight; + + // Convert m_FrameTexture YUV (original size with alignment) + // Pixel shader is faster 30% than compute shader + m_ShaderConverter.reset(); + m_ShaderConverter = std::make_unique( + m_Device.Get(), + m_GraphicsCommandList.Get(), + m_GraphicsCommandQueue.Get(), + m_VideoEnhancement, + m_FrameTexture.Get(), + m_RGBTexture.Get(), + viewport, + scissorRect, + D3D12VideoShaders::Enhancer::CONVERT_PS, + m_Decoder.ColorSpace + ); + if (!m_ShaderConverter) + return false; + + break; + default: + break; + } + + // Render Step 2 + switch (m_RenderStep2) { + case RenderStep::CONVERT_SHADER: + + // Viewport + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(m_OutputTextureInfo.width); + viewport.Height = static_cast(m_OutputTextureInfo.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + // Scissor + scissorRect.left = 0; + scissorRect.top = 0; + scissorRect.right = m_OutputTextureInfo.width; + scissorRect.bottom = m_OutputTextureInfo.height; + + // Convert + // Pixel shader is faster 30% than compute shader + m_ShaderConverter.reset(); + m_ShaderConverter = std::make_unique( + m_Device.Get(), + m_GraphicsCommandList.Get(), + m_GraphicsCommandQueue.Get(), + m_VideoEnhancement, + m_YUVTextureUpscaled.Get(), + m_OutputTexture.Get(), + viewport, + scissorRect, + D3D12VideoShaders::Enhancer::CONVERT_PS, + m_Decoder.ColorSpace + ); + if (!m_ShaderConverter) + return false; + + break; + case RenderStep::UPSCALE_SHADER: + + // Viewport + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(m_OutputTextureInfo.width); + viewport.Height = static_cast(m_OutputTextureInfo.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + // Scissor + scissorRect.left = 0; + scissorRect.top = 0; + scissorRect.right = m_OutputTextureInfo.width; + scissorRect.bottom = m_OutputTextureInfo.height; + + // Upscale RGB Only + m_ShaderUpscaler.reset(); + m_ShaderUpscaler = std::make_unique( + m_Device.Get(), + m_GraphicsCommandList.Get(), + m_GraphicsCommandQueue.Get(), + m_VideoEnhancement, + m_RGBTexture.Get(), + m_OutputTexture.Get(), + viewport, + scissorRect, + m_EnhancerType, + m_Decoder.ColorSpace + ); + if (!m_ShaderUpscaler) + return false; + + break; + case RenderStep::SHARPEN_SHADER: + + // Viewport + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(m_OutputTextureInfo.width); + viewport.Height = static_cast(m_OutputTextureInfo.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + // Scissor + scissorRect.left = 0; + scissorRect.top = 0; + scissorRect.right = m_OutputTextureInfo.width; + scissorRect.bottom = m_OutputTextureInfo.height; + + // Upscale RGB Only + m_ShaderSharpener.reset(); + m_ShaderSharpener = std::make_unique( + m_Device.Get(), + m_GraphicsCommandList.Get(), + m_GraphicsCommandQueue.Get(), + m_VideoEnhancement, + m_RGBTextureUpscaled.Get(), + m_OutputTexture.Get(), + viewport, + scissorRect, + m_EnhancerType, + m_Decoder.ColorSpace + ); + if (!m_ShaderSharpener) + return false; + + break; + default: + break; + } + + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + return false; + } + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForGraphics(); + + resetGraphicsCommandList(); + } + + // Initialize Upscaler + { + // Enable VSR feature + if (m_VendorVSRenabled) { + if (m_VideoEnhancement->isVendorAMD()) { + enableAMDVideoSuperResolution(); + } else if (m_VideoEnhancement->isVendorIntel()) { + enableIntelVideoSuperResolution(); + } else if (m_VideoEnhancement->isVendorNVIDIA()) { + enableNvidiaVideoSuperResolution(); + } + } + + // Enable SDR->HDR simulation feature if available. + // Disable the feature when streaming in HDR + if (m_VendorHDRenabled) { + if (m_VideoEnhancement->isVendorAMD()) { + enableAMDHDR(); + } else if (m_VideoEnhancement->isVendorIntel()) { + enableIntelHDR(); + } else if (m_VideoEnhancement->isVendorNVIDIA()) { + enableNvidiaHDR(); + } + } + } + + // Overlay + { + + D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {}; + srvHeapDesc.NumDescriptors = 16; + srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + + m_hr = m_Device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_OverlaySrvHeap)); + if(!verifyHResult(m_hr, "m_Device->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&m_OverlaySrvHeap));")){ + return false; + } + + ComPtr errorBlob; + QByteArray hlslSource; + + // RootSignature + CD3DX12_DESCRIPTOR_RANGE1 srvRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + CD3DX12_ROOT_PARAMETER1 rootParam; + rootParam.InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_PIXEL); + + CD3DX12_STATIC_SAMPLER_DESC staticSampler(0, D3D12_FILTER_MIN_MAG_MIP_LINEAR); + + D3D12_VERSIONED_ROOT_SIGNATURE_DESC rootSigDesc = {}; + rootSigDesc.Version = D3D_ROOT_SIGNATURE_VERSION_1_1; + rootSigDesc.Desc_1_1.NumParameters = 1; + rootSigDesc.Desc_1_1.pParameters = &rootParam; + rootSigDesc.Desc_1_1.NumStaticSamplers = 1; + rootSigDesc.Desc_1_1.pStaticSamplers = &staticSampler; + rootSigDesc.Desc_1_1.Flags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; + + ComPtr serializedRootSig; + D3D12SerializeVersionedRootSignature( + &rootSigDesc, &serializedRootSig, &errorBlob); + m_hr = m_Device->CreateRootSignature( + 0, serializedRootSig->GetBufferPointer(), + serializedRootSig->GetBufferSize(), + IID_PPV_ARGS(&m_OverlayRootSignature)); + if(!verifyHResult(m_hr, "m_Device->CreateRootSignature(... m_OverlayRootSignature)")){ + return false; + } + // Compile Overlay Vertex shader + QFile fileVS(":/enhancer/overlay_vs.hlsl"); + if (!fileVS.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open overlay_vs.hlsl"); + return false; + } + hlslSource = fileVS.readAll(); + fileVS.close(); + ComPtr shaderVSblob; + m_hr = D3DCompile(hlslSource.constData(), hlslSource.size(), "overlay_vs.hlsl", nullptr, nullptr, "main", "vs_5_0", + D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &shaderVSblob, &errorBlob); + if(!verifyHResult(m_hr, "D3DCompile(... overlay_vs)")){ + if (errorBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "VS compile error: %s", + (char*)errorBlob->GetBufferPointer()); + } + return false; + } + + // Compile Overlay Pixel shader + QFile filePS(":/enhancer/overlay_ps.hlsl"); + if (!filePS.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open overlay_ps.hlsl"); + return false; + } + hlslSource = filePS.readAll(); + filePS.close(); + ComPtr shaderPSblob; + m_hr = D3DCompile(hlslSource.constData(), hlslSource.size(), "overlay_ps.hlsl", nullptr, nullptr, "main", "ps_5_0", + D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &shaderPSblob, &errorBlob); + if(!verifyHResult(m_hr, "D3DCompile(... overlay_ps.hlsl)")){ + if (errorBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "VS compile error: %s", + (char*)errorBlob->GetBufferPointer()); + } + return false; + } + + D3D12_BLEND_DESC blendDesc = {}; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = FALSE; + auto& rt = blendDesc.RenderTarget[0]; + rt.BlendEnable = TRUE; + rt.SrcBlend = D3D12_BLEND_SRC_ALPHA; + rt.DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + rt.BlendOp = D3D12_BLEND_OP_ADD; + rt.SrcBlendAlpha = D3D12_BLEND_ONE; + rt.DestBlendAlpha = D3D12_BLEND_ZERO; + rt.BlendOpAlpha = D3D12_BLEND_OP_ADD; + rt.RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + + D3D12_RASTERIZER_DESC rastDesc = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + rastDesc.CullMode = D3D12_CULL_MODE_NONE; + rastDesc.FillMode = D3D12_FILL_MODE_SOLID; + + D3D12_DEPTH_STENCIL_DESC depthDesc = {}; + depthDesc.DepthEnable = FALSE; + depthDesc.StencilEnable = FALSE; + + // Pipeline + DXGI_SWAP_CHAIN_DESC swapDesc; + m_SwapChain->GetDesc(&swapDesc); + D3D12_INPUT_ELEMENT_DESC inputLayout[] = { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(VERTEX, x), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(VERTEX, u), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(VERTEX, r), D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + }; + + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { inputLayout, _countof(inputLayout) }; + psoDesc.pRootSignature = m_OverlayRootSignature.Get(); + psoDesc.VS = { shaderVSblob->GetBufferPointer(), shaderVSblob->GetBufferSize() }; + psoDesc.PS = { shaderPSblob->GetBufferPointer(), shaderPSblob->GetBufferSize() }; + psoDesc.RasterizerState = rastDesc; + psoDesc.BlendState = blendDesc; + psoDesc.DepthStencilState = depthDesc; + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = swapDesc.BufferDesc.Format; + psoDesc.SampleDesc.Count = 1; + psoDesc.SampleDesc.Quality = 0; + psoDesc.NodeMask = 0; + psoDesc.CachedPSO.pCachedBlob = nullptr; + psoDesc.CachedPSO.CachedBlobSizeInBytes = 0; + + m_hr = m_Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_OverlayPSO)); + if(!verifyHResult(m_hr, "m_Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_OverlayPSO));")){ + return false; + } + } + + m_TimerFPS.start(); + + return true; +} + +/** + * \brief Wait for the frame to be processed + * + * Wait for the frame to be processed before rendering it. + * + * \param bool waitCPU, at true the CPU is blocked until the GPU is done + * \return void + */ +void D3D12VARenderer::waitForVideoProcess(bool waitCPU) +{ + if(!m_FenceVideoProcess || !m_FenceVideoProcessEvent) + return; + + // Insure to complete the process before presenting + const UINT64 fence = ++m_FenceVideoProcessValue; + m_hr = m_VideoProcessCommandQueue->Signal(m_FenceVideoProcess.Get(), fence); + if(!verifyHResult(m_hr, "m_VideoProcessCommandQueue->Signal(m_FenceVideoProcess.Get(), fence);")){ + return; + } + m_VideoProcessAllocatorFence[m_CurrentFrameIndex] = fence; + if (!waitCPU) { + // The graphics queue is about to read what the VideoProcess queue just wrote, + // whether or not V-sync is on + m_GraphicsCommandQueue->Wait(m_FenceVideoProcess.Get(), fence); + if(m_AmfCommandQueue) m_AmfCommandQueue->Wait(m_FenceVideoProcess.Get(), fence); + } else if (m_FenceVideoProcess->GetCompletedValue() < fence) { + m_hr = m_FenceVideoProcess->SetEventOnCompletion(fence, m_FenceVideoProcessEvent); + if(!verifyHResult(m_hr, "m_FenceVideoProcess->SetEventOnCompletion(fence, m_FenceVideoProcessEvent);")){ + return; + } + WaitForSingleObject(m_FenceVideoProcessEvent, INFINITE); + } +} + +/** + * \brief Wait for the frame to be rendered + * + * Synchronizes CPU with GPU by waiting for the frame to finish rendering. + * Updates the current back buffer index after synchronization. + * + * \param bool waitCPU, at true the CPU is blocked until the GPU is done + * \return void + */ +void D3D12VARenderer::waitForGraphics(bool waitCPU) +{ + if(!m_FenceGraphics || !m_FenceGraphicsEvent) + return; + + // Insure to complete the process before presenting + const UINT64 fence = ++m_FenceGraphicsValue; + m_hr = m_GraphicsCommandQueue->Signal(m_FenceGraphics.Get(), fence); + if(!verifyHResult(m_hr, "m_GraphicsCommandQueue->Signal(m_FenceGraphics.Get(), fence);")){ + return; + } + m_GraphicsAllocatorFence[m_CurrentFrameIndex] = fence; + if (!waitCPU) { + // Only a queue that actually runs work may be made to wait. Queuing a Wait on an + // idle queue piles up thousands of never drained waits over a session. + if (m_UsesVideoProcessQueue) { + m_VideoProcessCommandQueue->Wait(m_FenceGraphics.Get(), fence); + } + if(m_AmfCommandQueue) m_AmfCommandQueue->Wait(m_FenceGraphics.Get(), fence); + } else if (m_FenceGraphics->GetCompletedValue() < fence) { + m_hr = m_FenceGraphics->SetEventOnCompletion(fence, m_FenceGraphicsEvent); + if(!verifyHResult(m_hr, "m_FenceGraphics->SetEventOnCompletion(fence, m_FenceGraphicsEvent);")){ + return; + } + WaitForSingleObject(m_FenceGraphicsEvent, INFINITE); + } +} + +/** + * \brief Recycle the VideoProcess command list for the current frame slot + * + * Resetting a command allocator while the GPU still runs commands recorded from it is + * invalid, so each frame slot owns its own. The wait below is therefore only reached + * if the GPU fell more than m_FrameCount frames behind. + * + * \return void + */ +void D3D12VARenderer::resetVideoProcessCommandList() +{ + ID3D12CommandAllocator* allocator = m_VideoProcessCommandAllocators[m_CurrentFrameIndex].Get(); + if (!allocator) { + return; + } + + const UINT64 fence = m_VideoProcessAllocatorFence[m_CurrentFrameIndex]; + if (fence > 0 && m_FenceVideoProcess && m_FenceVideoProcessEvent && + m_FenceVideoProcess->GetCompletedValue() < fence) { + if (SUCCEEDED(m_FenceVideoProcess->SetEventOnCompletion(fence, m_FenceVideoProcessEvent))) { + WaitForSingleObject(m_FenceVideoProcessEvent, INFINITE); + } + } + + allocator->Reset(); + m_VideoProcessCommandList->Reset(allocator); +} + +/** + * \brief Recycle the Graphics command list for the current frame slot + * + * See resetVideoProcessCommandList() for the rationale. + * + * \return void + */ +void D3D12VARenderer::resetGraphicsCommandList() +{ + ID3D12CommandAllocator* allocator = m_GraphicsCommandAllocators[m_CurrentFrameIndex].Get(); + if (!allocator) { + return; + } + + const UINT64 fence = m_GraphicsAllocatorFence[m_CurrentFrameIndex]; + if (fence > 0 && m_FenceGraphics && m_FenceGraphicsEvent && + m_FenceGraphics->GetCompletedValue() < fence) { + if (SUCCEEDED(m_FenceGraphics->SetEventOnCompletion(fence, m_FenceGraphicsEvent))) { + WaitForSingleObject(m_FenceGraphicsEvent, INFINITE); + } + } + + allocator->Reset(); + m_GraphicsCommandList->Reset(allocator, nullptr); +} + +/** + * \brief Re-present the last frame that was successfully rendered + * + * Used when a frame cannot be produced. Presenting the current back buffer as-is + * would show either black or a stale image from m_FrameCount presents ago, which + * reads as a flash. Copying the previously presented back buffer instead simply + * repeats the last visible frame. + * + * \param UINT backBufferIndex, index of the back buffer to present + * \return void + */ +void D3D12VARenderer::repeatLastFrame(UINT backBufferIndex) +{ + const UINT previousIndex = (backBufferIndex + m_FrameCount - 1) % m_FrameCount; + if (previousIndex == backBufferIndex || !m_BackBuffers[previousIndex]) { + return; + } + + resetGraphicsCommandList(); + + CD3DX12_RESOURCE_BARRIER barriers[2]; + barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[previousIndex].Get(), + D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); + barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[backBufferIndex].Get(), + D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_COPY_DEST + ); + m_GraphicsCommandList->ResourceBarrier(2, barriers); + + m_GraphicsCommandList->CopyResource(m_BackBuffers[backBufferIndex].Get(), + m_BackBuffers[previousIndex].Get()); + + barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[previousIndex].Get(), + D3D12_RESOURCE_STATE_COPY_SOURCE, + D3D12_RESOURCE_STATE_PRESENT + ); + barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[backBufferIndex].Get(), + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_PRESENT + ); + m_GraphicsCommandList->ResourceBarrier(2, barriers); + + if (FAILED(m_GraphicsCommandList->Close())) { + return; + } + + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + // Publishes the fence guarding this slot's allocator. The command list is left + // closed, the next frame reopens it on its own slot. + waitForGraphics(); +} + +/** + * \brief Read back the GPU time measured on the graphics queue + * + * renderFrame() waits for the GPU before returning, so by the time the next frame + * starts the timestamps of every pending slot have been resolved into the readback + * buffer. This never blocks. + * + * \return void + */ +void D3D12VARenderer::collectGpuFrameTime() +{ + if (m_EnhancerQualitySettled || !m_QueryHeap || !m_TimestampReadbackBuffer || + m_TimestampFrequency == 0) { + return; + } + + for (UINT slot = 0; slot < m_FrameCount; slot++) { + if (!m_TimestampPending[slot]) { + continue; + } + + m_TimestampPending[slot] = false; + + D3D12_RANGE readRange = { slot * 2 * sizeof(UINT64), (slot * 2 + 2) * sizeof(UINT64) }; + UINT64* mapped = nullptr; + if (FAILED(m_TimestampReadbackBuffer->Map(0, &readRange, reinterpret_cast(&mapped)))) { + continue; + } + + const UINT64 begin = mapped[slot * 2]; + const UINT64 end = mapped[slot * 2 + 1]; + + D3D12_RANGE writeRange = { 0, 0 }; + m_TimestampReadbackBuffer->Unmap(0, &writeRange); + + if (end <= begin) { + continue; + } + + const double elapsedMs = (double)(end - begin) * 1000.0 / (double)m_TimestampFrequency; + + // Exponential moving average to smooth out the occasional spike + if (m_GpuFrameTimeMs == 0.0) { + m_GpuFrameTimeMs = elapsedMs; + } else { + m_GpuFrameTimeMs = (m_GpuFrameTimeMs * 0.9) + (elapsedMs * 0.1); + } + } +} + +/** + * \brief Adapt the enhancer quality to what the GPU can actually sustain + * + * The quality ceiling is picked from the amount of VRAM, then lowered further at + * runtime when the measured GPU time does not fit in the frame budget. Without this, + * a high frame rate stream on a mid-range GPU renders far below the stream rate + * (measured: 17 ms/frame for VSR High at 1440p on a RTX 3060 Ti, i.e. 53 FPS max). + * + * \return void + */ +void D3D12VARenderer::adjustEnhancerQuality() +{ + if (m_EnhancerQualitySettled) { + return; + } + + // Only the VSR pipeline exposes a quality level, every other enhancer runs at a + // fixed cost. Settle immediately so we never pay for the GPU timing at all. + if (m_RenderStep2 != RenderStep::UPSCALE_VSR) { + m_EnhancerQualitySettled = true; + return; + } + + if (m_GpuFrameTimeMs == 0.0) { + return; + } + + // Only reconsider the quality every 2 seconds, so that a burst does not make it oscillate + const qint64 nowMs = m_VsrQualityTimer.isValid() ? m_VsrQualityTimer.elapsed() : 0; + if (nowMs - m_VsrQualityLastCheckMs < 2000) { + return; + } + m_VsrQualityLastCheckMs = nowMs; + + // Time we are allowed to spend per frame to sustain the stream frame rate + const double budgetMs = 1000.0 / (double)qMax(1, m_DecoderParams.frameRate); + + int quality = m_VsrQualityLevel; + + if (m_GpuFrameTimeMs > budgetMs * 0.80 && quality > NVSDK_NGX_VSR_Quality_Low) { + quality--; + } else if (m_GpuFrameTimeMs < budgetMs * 0.40 && quality < m_VsrQualityCap) { + quality++; + } + + static const char* names[] = { "Low", "Medium", "High" }; + + if (quality == m_VsrQualityLevel) { + // Already at the best quality this GPU is allowed and comfortably inside the + // frame budget: there is nothing left to decide. Stop timing the GPU until the + // renderer is reinitialized, which happens on any resolution, HDR or display + // change and re-arms the whole measurement. + if (m_VsrQualityLevel == m_VsrQualityCap && m_GpuFrameTimeMs < budgetMs * 0.40) { + if (++m_VsrQualityStableCount >= 2) { + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "NVIDIA RTX Video Super Resolution settled on quality %s (GPU %.2f ms, budget %.2f ms)", + names[qBound(0, m_VsrQualityLevel - 1, 2)], + m_GpuFrameTimeMs, + budgetMs); + m_EnhancerQualitySettled = true; + } + } else { + m_VsrQualityStableCount = 0; + } + return; + } + + SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, + "NVIDIA RTX Video Super Resolution quality %s -> %s (GPU %.2f ms, budget %.2f ms), reloading renderer", + names[qBound(0, m_VsrQualityLevel - 1, 2)], + names[qBound(0, quality - 1, 2)], + m_GpuFrameTimeMs, + budgetMs); + + if (quality < m_VsrQualityLevel) { + // This level proved too expensive on this GPU, never climb back to it + m_VsrQualityCap = quality; + } + + m_VsrQualityLevel = quality; + + // NGX sizes the internal resources of the feature from the quality level given at + // creation time, so the level cannot be swapped on a live feature: evaluating with + // another one hangs the device. Reload the renderer instead, which rebuilds the + // feature through enableNvidiaVideoSuperResolution() at the new level. + m_EnhancerQualitySettled = true; + + // Note: the session event loop only handles SDL_RENDER_DEVICE_RESET, + // SDL_RENDER_TARGETS_RESET goes through unhandled. + SDL_Event event; + event.type = SDL_RENDER_DEVICE_RESET; + SDL_PushEvent(&event); +} + +/** + * \brief Wait for the overlay to be ready + * + * Wait for the overlay to be ready before displaying it. + * + * \param bool waitCPU, at true the CPU is blocked until the GPU is done + * \return void + */ +void D3D12VARenderer::waitForOverlay(bool waitCPU) +{ + if(!m_FenceOverlay || !m_FenceOverlayEvent) + return; + + // Insure to complete the Overlay before presenting + const UINT64 fence = ++m_FenceOverlayValue; + m_hr = m_OverlayCommandQueue->Signal(m_FenceOverlay.Get(), fence); + if(!verifyHResult(m_hr, "m_OverlayCommandQueue->Signal(m_FenceOverlay.Get(), fence);")){ + return; + } + if (!waitCPU) { + m_VideoProcessCommandQueue->Wait(m_FenceOverlay.Get(), fence); + m_GraphicsCommandQueue->Wait(m_FenceOverlay.Get(), fence); + if(m_AmfCommandQueue) m_AmfCommandQueue->Wait(m_FenceOverlay.Get(), fence); + } else if (m_FenceOverlay->GetCompletedValue() < fence) { + m_hr = m_FenceOverlay->SetEventOnCompletion(fence, m_FenceOverlayEvent); + if(!verifyHResult(m_hr, "m_FenceOverlay->SetEventOnCompletion(fence, m_FenceOverlayEvent);")){ + return; + } + WaitForSingleObject(m_FenceOverlayEvent, INFINITE); + } +} + +/** + * \brief Update overlayed stats information + * + * Update the statistics information displayed as overlay + * This function can be called on an arbitrary thread. + * + * \param Overlay::OverlayType type + * \return void + */ +void D3D12VARenderer::notifyOverlayUpdated(Overlay::OverlayType type) +{ + // Re-entrancy guard only. The overlay currently on screen keeps being rendered + // while the new one is built, otherwise it visibly blinks out on every update. + if (m_OverlaySkip.exchange(true)) { + return; + } + + SDL_Surface* newSurface = Session::get()->getOverlayManager().getUpdatedOverlaySurface(type); + bool overlayEnabled = Session::get()->getOverlayManager().isOverlayEnabled(type); + if (newSurface == nullptr) { + m_OverlaySkip = false; + return; + } + + if (!overlayEnabled) { + SDL_FreeSurface(newSurface); + m_OverlaySkip = false; + return; + } + + // Everything is built into locals and only published at the very end, so the + // renderer never observes a half updated overlay + ComPtr newTexture; + ComPtr newVertexBuffer; + ComPtr uploadHeap; + + // Create texture resources + D3D12_RESOURCE_DESC texDesc = {}; + texDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + texDesc.Width = newSurface->w; + texDesc.Height = newSurface->h; + texDesc.MipLevels = 1; + texDesc.DepthOrArraySize = 1; + texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texDesc.SampleDesc.Count = 1; + texDesc.SampleDesc.Quality = 0; + texDesc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + texDesc.Flags = D3D12_RESOURCE_FLAG_NONE; + + CD3DX12_HEAP_PROPERTIES heapDefaultProps(D3D12_HEAP_TYPE_DEFAULT); + + m_hr = m_Device->CreateCommittedResource( + &heapDefaultProps, + D3D12_HEAP_FLAG_NONE, + &texDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&newTexture)); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... newTexture)")){ + SDL_FreeSurface(newSurface); + m_OverlaySkip = false; + return; + } + + // Create an upload heap to transfer texture data + UINT64 uploadBufferSize; + m_Device->GetCopyableFootprints(&texDesc, 0, 1, 0, nullptr, nullptr, nullptr, &uploadBufferSize); + CD3DX12_RESOURCE_DESC ubDesc = CD3DX12_RESOURCE_DESC::Buffer(uploadBufferSize); + CD3DX12_HEAP_PROPERTIES heapUploadProps(D3D12_HEAP_TYPE_UPLOAD); + + m_hr = m_Device->CreateCommittedResource( + &heapUploadProps, + D3D12_HEAP_FLAG_NONE, + &ubDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&uploadHeap)); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... uploadHeap)")){ + SDL_FreeSurface(newSurface); + m_OverlaySkip = false; + return; + } + + SDL_FRect renderRect = {}; + if (type == Overlay::OverlayStatusUpdate) { + // Bottom Left + renderRect.x = 0; + renderRect.y = 0; + } + else if (type == Overlay::OverlayDebug) { + // Top left + renderRect.x = 0; + renderRect.y = m_OutputTextureInfo.height - newSurface->h; + } + + // Offsets + renderRect.x += m_OutputTextureInfo.left; + renderRect.y -= m_OutputTextureInfo.top; + + renderRect.w = newSurface->w; + renderRect.h = newSurface->h; + + // Convert screen space to normalized device coordinates + StreamUtils::screenSpaceToNormalizedDeviceCoords(&renderRect, m_OutputTextureInfo.width, m_OutputTextureInfo.height); + + // Create vertex buffer + VERTEX verts[4]; + verts[0] = {renderRect.x, renderRect.y, 0, 1, 0, 0, 0, 0.0f}; + verts[1] = {renderRect.x, renderRect.y+renderRect.h, 0, 0, 0, 0, 0, 0.0f}; + verts[2] = {renderRect.x+renderRect.w, renderRect.y, 1, 1, 0, 0, 0, 0.0f}; + verts[3] = {renderRect.x+renderRect.w, renderRect.y+renderRect.h, 1, 0, 0, 0, 0, 0.0f}; + + CD3DX12_HEAP_PROPERTIES uploadHeapVB(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC vbDesc = CD3DX12_RESOURCE_DESC::Buffer(sizeof(verts)); + + m_hr = m_Device->CreateCommittedResource( + &uploadHeapVB, + D3D12_HEAP_FLAG_NONE, + &vbDesc, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&newVertexBuffer) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... newVertexBuffer)")){ + SDL_FreeSurface(newSurface); + m_OverlaySkip = false; + return; + } + + void* pMappedData = nullptr; + if (SUCCEEDED(newVertexBuffer->Map(0, nullptr, &pMappedData))) { + memcpy(pMappedData, verts, sizeof(verts)); + newVertexBuffer->Unmap(0, nullptr); + } + + // Copy data to the upload heap and then to the default texture + D3D12_SUBRESOURCE_DATA textureData = {}; + textureData.pData = newSurface->pixels; + textureData.RowPitch = newSurface->pitch; + textureData.SlicePitch = (SIZE_T)newSurface->pitch * newSurface->h; + + m_OverlayCommandAllocator->Reset(); + m_OverlayCommandList->Reset(m_OverlayCommandAllocator.Get(), nullptr); + + UpdateSubresources(m_OverlayCommandList.Get(), newTexture.Get(), uploadHeap.Get(), 0, 0, 1, &textureData); + + // The surface is no longer required + SDL_FreeSurface(newSurface); + newSurface = nullptr; + + D3D12_RESOURCE_BARRIER barrier = CD3DX12_RESOURCE_BARRIER::Transition( + newTexture.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE + ); + m_OverlayCommandList->ResourceBarrier(1, &barrier); + + m_OverlayCommandList->Close(); + ID3D12CommandList* lists[] = { m_OverlayCommandList.Get() }; + m_OverlayCommandQueue->ExecuteCommandLists(1, lists); + + // Wait for the texture to be ready. This runs on the overlay thread, the render + // thread is not blocked by it. + waitForOverlay(true); + + // Publish. The lock is only held for the swap, which is what the renderer reads. + { + SDL_AtomicLock(&m_OverlayLock); + + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.Format = texDesc.Format; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + + // Each overlay type owns its own descriptor slot, matching the offset + // renderOverlay() applies when it binds the descriptor table + CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle( + m_OverlaySrvHeap->GetCPUDescriptorHandleForHeapStart(), + type, + m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV)); + m_Device->CreateShaderResourceView(newTexture.Get(), &srvDesc, srvHandle); + + m_VbSize = sizeof(verts); + m_OverlayTextures[type] = std::move(newTexture); + m_OverlayVertexBuffers[type] = std::move(newVertexBuffer); + + SDL_AtomicUnlock(&m_OverlayLock); + } + + m_OverlaySkip = false; +} + +/** + * \brief Render stats as overlay + * + * Render statitics information as overlay + * + * \param Overlay::OverlayType type + * \return void + */ +void D3D12VARenderer::renderOverlay(Overlay::OverlayType type) +{ + if (!m_OverlaySrvHeap || !Session::get()->getOverlayManager().isOverlayEnabled(type)) { + return; + } + + ComPtr overlayTexture = m_OverlayTextures[type]; + ComPtr overlayVertexBuffer = m_OverlayVertexBuffers[type]; + + if (!overlayTexture) { + return; + } + + // Record commands + m_GraphicsCommandList->SetPipelineState(m_OverlayPSO.Get()); + m_GraphicsCommandList->SetGraphicsRootSignature(m_OverlayRootSignature.Get()); + + ID3D12DescriptorHeap* heaps[] = { m_OverlaySrvHeap.Get() }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + D3D12_GPU_DESCRIPTOR_HANDLE srvGPU = m_OverlaySrvHeap->GetGPUDescriptorHandleForHeapStart(); + srvGPU.ptr += type * m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + m_GraphicsCommandList->SetGraphicsRootDescriptorTable(0, srvGPU); + + // Viewport + D3D12_VIEWPORT viewport = {}; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = static_cast(m_OutputTextureInfo.width); + viewport.Height = static_cast(m_OutputTextureInfo.height); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + m_GraphicsCommandList->RSSetViewports(1, &viewport); + + // Scissor + D3D12_RECT scissor = {}; + scissor.left = 0; + scissor.top = 0; + scissor.right = m_OutputTextureInfo.width; + scissor.bottom = m_OutputTextureInfo.height; + m_GraphicsCommandList->RSSetScissorRects(1, &scissor); + + // Vertex buffer + D3D12_VERTEX_BUFFER_VIEW m_VbView = {}; + m_VbView.BufferLocation = overlayVertexBuffer->GetGPUVirtualAddress(); + m_VbView.SizeInBytes = m_VbSize; + m_VbView.StrideInBytes = sizeof(VERTEX); + m_GraphicsCommandList->IASetVertexBuffers(0, 1, &m_VbView); + m_GraphicsCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Draw + m_GraphicsCommandList->DrawInstanced(4, 1, 0, 0); +} + +/** + * \brief Render the frame + * + * Convert the frame YUV to RGB, and process it with an upscaler method if needed before render it. + * + * \param AVFrame* frame, the frame provided by the decoder FFmpeg + * \return void + */ +void D3D12VARenderer::renderFrame(AVFrame* frame) +{ + bool resetVideoProcessCommand = false; + bool resetGraphicsCommand = false; + + bool detachRGBTexture = false; + bool detachRGBTextureUpscaled = false; + bool detachYUVTextureUpscaled = false; + bool detachOutputTexture = false; + + // Set once the back buffer holds the frame we are about to present + bool frameDrawn = false; + + SDL_AtomicLock(&m_OverlayLock); + + m_CurrentFrameIndex = (m_CurrentFrameIndex + 1) % m_FrameCount; + + // Take ownership of this slot's command allocators + if (m_UsesVideoProcessQueue) { + resetVideoProcessCommandList(); + } + resetGraphicsCommandList(); + + // Read back the GPU times that completed since the last frame and adapt the + // enhancer quality if it does not fit in the frame budget + collectGpuFrameTime(); + adjustEnhancerQuality(); + + if (m_QueryHeap && !m_EnhancerQualitySettled) { + m_GraphicsCommandList->EndQuery(m_QueryHeap.Get(), + D3D12_QUERY_TYPE_TIMESTAMP, + m_CurrentFrameIndex * 2); + } + + // Wait for previous frame to be rendered + WaitForSingleObjectEx(m_FrameLatencyWaitableObject, 1000, true); + + m_Timer.start(); + TimerInfo("-----------------------------------------------", true); + + AVD3D12VAFrame* f = nullptr; + UINT backBufferIndex = m_SwapChain->GetCurrentBackBufferIndex(); + CD3DX12_RESOURCE_BARRIER m_Barriers[2]; + + // We simply skip the frame with the previous operation is not yet completed + if (m_SkipFrame) { + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + // Repeat previous Texture + goto Draw; + } else { + // Draw a black screen + goto Present; + } + } + m_SkipFrame = true; + + if(m_IsFrameD3D11){ + // Some pipelines need D3D11 + + if (m_RenderStep1 == RenderStep::UPSCALE_VPL) { + // It does it own CopySubresourceRegion of the frame to be directly in the correct format + goto RenderStep1; + } + + lockContext(this); + + m_D3D11DeviceContext->CopySubresourceRegion(m_D3D11FrameTexture.Get(), 0, 0, 0, 0, (ID3D11Resource*)frame->data[0], (int)(intptr_t)frame->data[1], &m_D3D11SrcBox); + + m_D3D11FenceValue++; + + m_D3D11DeviceContext->Signal(m_D3D11Fence.Get(), m_D3D11FenceValue); + m_D3D11DeviceContext->Flush(); + + unlockContext(this); + + m_VideoProcessCommandQueue->Wait(m_D3D12Fence.Get(), m_D3D11FenceValue); + m_GraphicsCommandQueue->Wait(m_D3D12Fence.Get(), m_D3D11FenceValue); + if(m_AmfCommandQueue) m_AmfCommandQueue->Wait(m_D3D12Fence.Get(), m_D3D11FenceValue); + + } else { + // We default on D3D12 + + f = reinterpret_cast(frame->data[0]); + m_FrameTexture = f->texture; + + // In DX12, GPU work is asynchronous, so FFmpeg may still be writing to the texture. + // We wait on the frame's fence to ensure the GPU has finished writing before use. + // Regardless m_Vsync, we always force the synchronisation to avoid strong stuttering. + if (f->sync_ctx.fence && f->sync_ctx.event) { + m_VideoProcessCommandQueue->Wait(f->sync_ctx.fence, f->sync_ctx.fence_value); + m_GraphicsCommandQueue->Wait(f->sync_ctx.fence, f->sync_ctx.fence_value); + if(m_AmfCommandQueue) m_AmfCommandQueue->Wait(f->sync_ctx.fence, f->sync_ctx.fence_value); + } + + } + +RenderStep1: + + TimerInfo("(FFmpeg Frame)", true); + + // DebugExportToPNG(frameTexture, D3D12_RESOURCE_STATE_COMMON, "frameTexture.png"); + + // VideoProcessor is used for the whole pipeline. + // We convert directly frameTexture to m_OutputTexture. + if(m_RenderStep1 == RenderStep::ALL_VIDEOPROCESSOR){ + + resetVideoProcessCommand = true; + + m_InputArgsUpscalerConvert[m_CurrentFrameIndex].InputStream[0].pTexture2D = m_FrameTexture.Get(); + + // Convert & Upscale + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_FrameTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_SkipRenderStep2 ? m_OutputTexture.Get() : m_RGBTextureUpscaled.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE + ); + m_VideoProcessCommandList->ResourceBarrier(2, m_Barriers); + + m_VideoProcessCommandList->ProcessFrames1( + m_VideoProcessorUpscalerConvert.Get(), + &m_OutputArgsUpscalerConvert[m_CurrentFrameIndex], + 1, + &m_InputArgsUpscalerConvert[m_CurrentFrameIndex] + ); + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_FrameTexture.Get(), + D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ, + D3D12_RESOURCE_STATE_COMMON + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_SkipRenderStep2 ? m_OutputTexture.Get() : m_RGBTextureUpscaled.Get(), + D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE, + D3D12_RESOURCE_STATE_COMMON + ); + m_VideoProcessCommandList->ResourceBarrier(2, m_Barriers); + + m_hr = m_VideoProcessCommandList->Close(); + if(!verifyHResult(m_hr, "m_VideoProcessCommandList->Close();")){ + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + + // Submit the command + ID3D12CommandList* cmdLists[] = { m_VideoProcessCommandList.Get() }; + m_VideoProcessCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForVideoProcess(); + + TimerInfo("(VP Upscale YUV + Convert YUV)", true); + + if(m_SkipRenderStep2){ + goto Draw; + } + + goto RenderStep2; + } + + // YUV->RGB Conversion using Video Procesor + else if(m_RenderStep1 == RenderStep::CONVERT_VIDEOPROCESSOR){ + + resetVideoProcessCommand = true; + + m_InputArgsConvert[m_CurrentFrameIndex].InputStream[0].pTexture2D = m_FrameTexture.Get(); + + // Convert + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_FrameTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_RGBTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE + ); + m_VideoProcessCommandList->ResourceBarrier(2, m_Barriers); + + m_VideoProcessCommandList->ProcessFrames1( + m_VideoProcessorConvert.Get(), + &m_OutputArgsConvert[m_CurrentFrameIndex], + 1, + &m_InputArgsConvert[m_CurrentFrameIndex] + ); + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_FrameTexture.Get(), + D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ, + D3D12_RESOURCE_STATE_COMMON + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_RGBTexture.Get(), + D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE, + D3D12_RESOURCE_STATE_COMMON + ); + m_VideoProcessCommandList->ResourceBarrier(2, m_Barriers); + + m_hr = m_VideoProcessCommandList->Close(); + if(!verifyHResult(m_hr, "m_VideoProcessCommandList->Close();")){ + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + + // Submit the command + ID3D12CommandList* cmdLists[] = { m_VideoProcessCommandList.Get() }; + m_VideoProcessCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForVideoProcess(); + + TimerInfo("(VP Convert YUV)", true); + + goto RenderStep2; + } + + // YUV->RGB Conversion using Shader + else if(m_RenderStep1 == RenderStep::CONVERT_SHADER){ + + resetGraphicsCommand = true; + + m_ShaderConverter->updateShaderResourceView(m_FrameTexture.Get()); + + // Input: m_FrameTexture / Output: m_RGBTexture + m_ShaderConverter->draw( + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON + ); + + if(m_RenderStep2 != RenderStep::UPSCALE_SHADER){ + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForGraphics(); + resetGraphicsCommandList(); + + resetGraphicsCommand = false; + } + + TimerInfo("(Shader Convert YUV)", true); + + goto RenderStep2; + } + + // AMF is used for the whole pipeline. + // We convert directly m_FrameTexture to m_OutputTexture. + else if(m_RenderStep1 == RenderStep::ALL_AMF){ + + m_AmfContext->CreateSurfaceFromDX12Native(m_FrameTexture.Get(), &m_AmfSurfaceYUV, nullptr); + m_AmfSurfaceYUV->SetCrop(0, 0, m_DecoderParams.textureWidth, m_DecoderParams.textureHeight); + + // Upscaling + m_AmfUpscalerYUV->SubmitInput(m_AmfSurfaceYUV); + m_AmfUpscalerYUV->QueryOutput(&m_AmfData); + + // Convert to RGB + m_AmfVideoConverterUpscaled->SubmitInput(m_AmfData); + m_AmfVideoConverterUpscaled->QueryOutput(&m_AmfData); + + m_AmfCompute->FinishQueue(); + + m_AmfData->QueryInterface(AMFSurface::IID(), reinterpret_cast(&m_AmfSurfaceUpscaledRGB)); + ID3D12Resource* amfTexture = (ID3D12Resource*)m_AmfSurfaceUpscaledRGB->GetPlane(AMF_PLANE_PACKED)->GetNative(); + amfTexture->AddRef(); + + if(m_SkipRenderStep2){ + m_OutputTexture.Attach(amfTexture); + detachOutputTexture = true; + } else { + m_RGBTextureUpscaled.Attach(amfTexture); + detachRGBTextureUpscaled = true; + } + + TimerInfo("(AMF Upscale YUV -> AMF Convert RGB)", true); + + if(m_SkipRenderStep2){ + goto Draw; + } + + goto RenderStep2; + } + + // YUV Upscaling using AMF + else if(m_RenderStep1 == RenderStep::UPSCALE_AMF){ + + m_AmfContext->CreateSurfaceFromDX12Native(m_FrameTexture.Get(), &m_AmfSurfaceYUV, nullptr); + m_AmfSurfaceYUV->SetCrop(0, 0, m_DecoderParams.textureWidth, m_DecoderParams.textureHeight); + + m_AmfUpscalerYUV->SubmitInput(m_AmfSurfaceYUV); + m_AmfUpscalerYUV->QueryOutput(&m_AmfData); + m_AmfCompute->FinishQueue(); + + m_AmfData->QueryInterface(AMFSurface::IID(), reinterpret_cast(&m_AmfSurfaceUpscaledYUV)); + ID3D12Resource* amfTexture = (ID3D12Resource*)m_AmfSurfaceUpscaledYUV->GetPlane(AMF_PLANE_Y)->GetNative(); + amfTexture->AddRef(); + m_YUVTextureUpscaled.Attach(amfTexture); + detachYUVTextureUpscaled = true; + + TimerInfo("(AMF Upscale YUV)", true); + + goto RenderStep2; + } + + // YUV->RGB Conversion using AMF + else if(m_RenderStep1 == RenderStep::CONVERT_AMF){ + + m_AmfContext->CreateSurfaceFromDX12Native(m_FrameTexture.Get(), &m_AmfSurfaceYUV, nullptr); + m_AmfSurfaceYUV->SetCrop(0, 0, m_DecoderParams.textureWidth, m_DecoderParams.textureHeight); + + m_AmfVideoConverter->SubmitInput(m_AmfSurfaceYUV); + m_AmfVideoConverter->QueryOutput(&m_AmfData); + m_AmfCompute->FinishQueue(); + + m_AmfData->QueryInterface(AMFSurface::IID(), reinterpret_cast(&m_AmfSurfaceRGB)); + ID3D12Resource* amfTexture = (ID3D12Resource*)m_AmfSurfaceRGB->GetPlane(AMF_PLANE_PACKED)->GetNative(); + amfTexture->AddRef(); + m_RGBTexture.Attach(amfTexture); + detachRGBTexture = true; + + TimerInfo("(AMF Convert YUV)", true); + + goto RenderStep2; + } + + // YUV Upscaling using Intel VPL + else if(m_RenderStep1 == RenderStep::UPSCALE_VPL){ + + // Working D3D11, but slow over x1.40 + mfxStatus sts; + VppSurface* vppSurfaceIn = findUnlockedSurface(m_VppSurfaceIn); + VppSurface* vppSurfaceOut = findUnlockedSurface(m_VppSurfaceOut); + + // IntelVPL upscaling + bool vppError = false; + + // Ask IntelVPL to consume directly the texture given (zero-copy), + // otherwise IntelVPL will copy to its internal allocated resource. + if (vppSurfaceIn && !vppSurfaceIn->surface) { + sts = m_MemoryInterface->ImportFrameSurface( + m_MemoryInterface, + MFX_SURFACE_COMPONENT_VPP_INPUT, + m_IsFrameD3D11 ? &vppSurfaceIn->textureLinkD3D11.SurfaceInterface.Header : &vppSurfaceIn->textureLinkD3D12.SurfaceInterface.Header, + &vppSurfaceIn->surface); + + if (sts != MFX_ERR_NONE) { + vppError = true; + } + } else { + vppError = true; + } + + if (vppError) { + + // Do nothing + + } else if (m_IsFrameD3D11) { + + lockContext(this); + + m_D3D11DeviceContext->CopySubresourceRegion(vppSurfaceIn->textureD3D11.Get(), 0, 0, 0, 0, (ID3D11Resource*)frame->data[0], (int)(intptr_t)frame->data[1], &m_D3D11SrcBox); + + m_D3D11FenceValue++; + + m_D3D11DeviceContext->Signal(m_D3D11Fence.Get(), m_D3D11FenceValue); + m_D3D11DeviceContext->Flush(); + + unlockContext(this); + + m_GraphicsCommandQueue->Wait(m_D3D12Fence.Get(), m_D3D11FenceValue); + + } else { + // [Bug] Upscaling works (not faster as DX11), but NV12 copy operation has issue on the second plane UV. + // It looks like the data is wrongly copied, resulting of UV at 0 and a green picture while converting into RGB. + + resetGraphicsCommand = true; + + // Copy + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_FrameTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + vppSurfaceIn->textureD3D12.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_DEST + ); + m_GraphicsCommandList->ResourceBarrier(2, m_Barriers); + + D3D12_RESOURCE_DESC inDesc = m_FrameTexture->GetDesc(); + UINT planeCount = 1; + // Check 2-Planes + switch (inDesc.Format) { + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + planeCount = 2; + break; + default: + planeCount = 1; + break; + } + + for (UINT plane = 0; plane < planeCount; ++plane) + { + D3D12_TEXTURE_COPY_LOCATION src = {}; + src.pResource = m_FrameTexture.Get(); + src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + src.SubresourceIndex = plane; + + D3D12_TEXTURE_COPY_LOCATION dst = {}; + dst.pResource = vppSurfaceIn->textureD3D12.Get(); + dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dst.SubresourceIndex = plane; + + D3D12_BOX srcBox = m_SrcBox; + if (plane == 1) { + srcBox.bottom = inDesc.Height / 2; + srcBox.right = inDesc.Width; + } + + m_GraphicsCommandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &srcBox); + } + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_FrameTexture.Get(), + D3D12_RESOURCE_STATE_COPY_SOURCE, + D3D12_RESOURCE_STATE_COMMON + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + vppSurfaceIn->textureD3D12.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_COMMON + ); + m_GraphicsCommandList->ResourceBarrier(2, m_Barriers); + + m_hr = m_GraphicsCommandList->Close(); + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForGraphics(true); + + } + + // Process the upscaling + sts = MFXVideoVPP_ProcessFrameAsync(m_VppSession, vppSurfaceIn->surface, &vppSurfaceOut->surface); + + if (sts == MFX_ERR_NONE && !vppError) { + + // Wait for the result + sts = vppSurfaceOut->surface->FrameInterface->Synchronize(vppSurfaceOut->surface, 1000); + + if (sts == MFX_ERR_NONE) { + + // Copy the result into m_YUVTextureUpscaled + + if (m_IsFrameD3D11) { + + mfxHDL d3d11Tex = nullptr; + mfxResourceType resourceType = MFX_RESOURCE_DX11_TEXTURE; + vppSurfaceOut->surface->FrameInterface->GetNativeHandle( + vppSurfaceOut->surface, + &d3d11Tex, + &resourceType + ); + + m_D3D11DeviceContext->CopySubresourceRegion(m_D3D11YUVTextureUpscaled.Get(), 0, 0, 0, 0, reinterpret_cast(d3d11Tex), 0, &m_D3D11OutputBox); + + m_D3D11FenceValue++; + m_D3D11DeviceContext->Signal(m_D3D11Fence.Get(), m_D3D11FenceValue); + m_D3D11DeviceContext->Flush(); + + m_GraphicsCommandQueue->Wait(m_D3D12Fence.Get(), m_D3D11FenceValue); + + } else { + + mfxExtSurfaceD3D12Tex2DExportDescription d3d12ExportDesc = {}; + d3d12ExportDesc.Header.BufferId = MFX_EXTBUFF_EXPORT_SHARING_DESC_D3D12; + d3d12ExportDesc.Header.BufferSz = sizeof(d3d12ExportDesc); + d3d12ExportDesc.d3d12Device = m_Device.Get(); + + mfxExtBuffer* extParams[1] = {}; + extParams[0] = &d3d12ExportDesc.Header; + + mfxSurfaceHeader exportHeader = {}; + exportHeader.SurfaceType = MFX_SURFACE_TYPE_D3D12_TEX2D; + exportHeader.SurfaceFlags = MFX_SURFACE_FLAG_EXPORT_SHARED; + exportHeader.ExtParam = extParams; + exportHeader.NumExtParam = 1; + + mfxSurfaceHeader* exportedHeader = nullptr; + sts = vppSurfaceOut->surface->FrameInterface->Export( + vppSurfaceOut->surface, + exportHeader, + &exportedHeader + ); + + auto* exportedD3D12 = reinterpret_cast(exportedHeader); + + ID3D12Resource* d3d12Tex = reinterpret_cast(exportedD3D12->texture2D); + + DebugExportToPNG(d3d12Tex, D3D12_RESOURCE_STATE_COMMON, "d3d12Tex.png"); + + resetGraphicsCommandList(); + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + d3d12Tex, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_YUVTextureUpscaled.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_DEST + ); + m_GraphicsCommandList->ResourceBarrier(2, m_Barriers); + + D3D12_RESOURCE_DESC inDesc = d3d12Tex->GetDesc(); + UINT planeCount = 1; + // Check 2-Planes + switch (inDesc.Format) { + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + planeCount = 2; + break; + default: + planeCount = 1; + break; + } + + for (UINT plane = 0; plane < planeCount; ++plane) + { + D3D12_TEXTURE_COPY_LOCATION src = {}; + src.pResource = d3d12Tex; + src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + src.SubresourceIndex = plane; + + D3D12_TEXTURE_COPY_LOCATION dst = {}; + dst.pResource = m_YUVTextureUpscaled.Get(); + dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dst.SubresourceIndex = plane; + + D3D12_BOX srcBox = m_OutputBox; + if (plane == 1) { + srcBox.bottom = inDesc.Height / 2; + srcBox.right = inDesc.Width; + } + + m_GraphicsCommandList->CopyTextureRegion(&dst, 0, 0, 0, &src, &srcBox); + } + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + d3d12Tex, + D3D12_RESOURCE_STATE_COPY_SOURCE, + D3D12_RESOURCE_STATE_COMMON + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_YUVTextureUpscaled.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_COMMON + ); + m_GraphicsCommandList->ResourceBarrier(2, m_Barriers); + + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + resetGraphicsCommandList(); + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForGraphics(true); + + resetGraphicsCommandList(); + } + + } else if (sts == MFX_ERR_GPU_HANG || sts == MFX_WRN_IN_EXECUTION) { + vppError = true; + } + + } else { + vppError = true; + } + + if (vppError) { + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + + TimerInfo("(Intel VPL Convert YUV)", true); + + goto RenderStep2; + + } + +RenderStep2: + + // D3D11DebugExportToPNG(m_D3D11FrameTexture.Get(), "m_D3D11FrameTexture.png"); + // DebugExportToPNG(m_FrameTexture.Get(), D3D12_RESOURCE_STATE_COMMON, "m_FrameTexture.png"); + // DebugExportToPNG(m_RGBTexture.Get(), D3D12_RESOURCE_STATE_COMMON, "m_RGBTexture.png"); + // DebugExportToPNG(m_YUVTextureUpscaled.Get(), D3D12_RESOURCE_STATE_COMMON, "m_YUVTextureUpscaled.png"); + + // RGB Upscaling using VideoProcessor + if(m_RenderStep2 == RenderStep::UPSCALE_VIDEOPROCESSOR){ + + if(resetVideoProcessCommand){ + resetVideoProcessCommandList(); + } + resetVideoProcessCommand = true; + + m_InputArgsUpscaler[m_CurrentFrameIndex].InputStream[0].pTexture2D = m_RGBTexture.Get(); + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_RGBTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_OutputTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE + ); + m_VideoProcessCommandList->ResourceBarrier(2, m_Barriers); + + m_VideoProcessCommandList->ProcessFrames1( + m_VideoProcessorUpscaler.Get(), + &m_OutputArgsUpscaler[m_CurrentFrameIndex], + 1, + &m_InputArgsUpscaler[m_CurrentFrameIndex] + ); + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_RGBTexture.Get(), + D3D12_RESOURCE_STATE_VIDEO_PROCESS_READ, + D3D12_RESOURCE_STATE_COMMON + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_OutputTexture.Get(), + D3D12_RESOURCE_STATE_VIDEO_PROCESS_WRITE, + D3D12_RESOURCE_STATE_COMMON + ); + m_VideoProcessCommandList->ResourceBarrier(2, m_Barriers); + + m_hr = m_VideoProcessCommandList->Close(); + if(!verifyHResult(m_hr, "m_VideoProcessCommandList->Close();")){ + resetVideoProcessCommandList(); + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + + // Submit the command + ID3D12CommandList* cmdLists[] = { m_VideoProcessCommandList.Get() }; + m_VideoProcessCommandQueue->ExecuteCommandLists(1, cmdLists); + + waitForVideoProcess(); + + TimerInfo("(VP Upscale RGB)", true); + + goto Draw; + } + + // RGB Upscaling using NVIDIA VSR + else if(m_RenderStep2 == RenderStep::UPSCALE_VSR){ + + resetGraphicsCommand = true; + + // Must stay identical to the level the feature was created with, see + // adjustEnhancerQuality() + const NVSDK_NGX_VSR_QualityLevel vsrQuality = (NVSDK_NGX_VSR_QualityLevel)m_VsrQualityLevel; + + // Setup VSR params + NVSDK_NGX_D3D12_VSR_Eval_Params vsrEvalParams = {}; + vsrEvalParams.pInput = m_RGBTexture.Get(); + vsrEvalParams.pOutput = m_VendorHDRenabled ? m_RGBTextureUpscaled.Get() : m_OutputTexture.Get(); + vsrEvalParams.InputSubrectBase.X = 0; + vsrEvalParams.InputSubrectBase.Y = 0; + vsrEvalParams.InputSubrectSize.Width = m_DecoderParams.textureWidth; + vsrEvalParams.InputSubrectSize.Height = m_DecoderParams.textureHeight; + vsrEvalParams.OutputSubrectBase.X = 0; + vsrEvalParams.OutputSubrectBase.Y = 0; + vsrEvalParams.OutputSubrectSize.Width = m_OutputTextureInfo.width; + vsrEvalParams.OutputSubrectSize.Height = m_OutputTextureInfo.height; + vsrEvalParams.QualityLevel = vsrQuality; + + // Evaluate VSR + NVSDK_NGX_Result ResultVSR = NGX_D3D12_EVALUATE_VSR_EXT(m_GraphicsCommandList.Get(), m_VSRFeature, m_VSRngxParameters, &vsrEvalParams); + if (NVSDK_NGX_FAILED(ResultVSR)) { + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + + if(m_VendorHDRenabled){ + // Setup TrueHDR params + NVSDK_NGX_D3D12_TRUEHDR_Eval_Params trueHDREvalParams = {}; + trueHDREvalParams.pInput = m_RGBTextureUpscaled.Get(); + trueHDREvalParams.pOutput = m_OutputTexture.Get(); + trueHDREvalParams.InputSubrectTL.X = 0; + trueHDREvalParams.InputSubrectTL.Y = 0; + trueHDREvalParams.InputSubrectBR.Width = m_OutputTextureInfo.width; + trueHDREvalParams.InputSubrectBR.Height = m_OutputTextureInfo.height; + trueHDREvalParams.OutputSubrectTL.X = 0; + trueHDREvalParams.OutputSubrectTL.Y = 0; + trueHDREvalParams.OutputSubrectBR.Width = m_OutputTextureInfo.width; + trueHDREvalParams.OutputSubrectBR.Height = m_OutputTextureInfo.height; + trueHDREvalParams.Contrast = 100; + trueHDREvalParams.Saturation = 100; + trueHDREvalParams.MiddleGray = 50; + trueHDREvalParams.MaxLuminance = m_MaxLuminance; + + // Evaluate TrueHDR + NVSDK_NGX_Result ResultTrueHDR = NGX_D3D12_EVALUATE_TRUEHDR_EXT(m_GraphicsCommandList.Get(), m_TrueHDRFeature, m_TrueHDRngxParameters, &trueHDREvalParams); + if (NVSDK_NGX_FAILED(ResultTrueHDR)) { + if (m_OutputTexturePrevious) { + m_OutputTexture = m_OutputTexturePrevious; + goto Draw; + } else { + goto Present; + } + } + } + + TimerInfo("(VSR Upscale RGB)", true); + + goto Draw; + } + + // RGB Upscaling using AMD AMF + else if(m_RenderStep2 == RenderStep::UPSCALE_AMF){ + + m_AmfContext->CreateSurfaceFromDX12Native(m_RGBTexture.Get(), &m_AmfSurfaceRGB, nullptr); + + m_AmfUpscalerRGB->SubmitInput(m_AmfSurfaceRGB); + m_AmfUpscalerRGB->QueryOutput(&m_AmfData); + m_AmfCompute->FinishQueue(); + + m_AmfData->QueryInterface(AMFSurface::IID(), reinterpret_cast(&m_AmfSurfaceUpscaledRGB)); + ID3D12Resource* amfTexture = (ID3D12Resource*)m_AmfSurfaceUpscaledRGB->GetPlane(AMF_PLANE_PACKED)->GetNative(); + amfTexture->AddRef(); + m_OutputTexture.Attach(amfTexture); + detachOutputTexture = true; + + TimerInfo("(AMF Upscale RGB)", true); + + goto Draw; + } + + // YUV->RGB Conversion using AMF + else if(m_RenderStep2 == RenderStep::CONVERT_AMF){ + + m_AmfContext->CreateSurfaceFromDX12Native(m_YUVTextureUpscaled.Get(), &m_AmfSurfaceUpscaledYUV, nullptr); + + m_AmfVideoConverter->SubmitInput(m_AmfSurfaceUpscaledYUV); + m_AmfVideoConverter->QueryOutput(&m_AmfData); + m_AmfCompute->FinishQueue(); + + m_AmfData->QueryInterface(AMFSurface::IID(), reinterpret_cast(&m_AmfSurfaceUpscaledRGB)); + ID3D12Resource* amfTexture = (ID3D12Resource*)m_AmfSurfaceUpscaledRGB->GetPlane(AMF_PLANE_PACKED)->GetNative(); + amfTexture->AddRef(); + m_OutputTexture.Attach(amfTexture); + detachOutputTexture = true; + + TimerInfo("(AMF Convert YUV)", true); + + goto Draw; + } + + // YUV->RGB Conversion using Shader + else if(m_RenderStep2 == RenderStep::CONVERT_SHADER){ + + resetGraphicsCommand = true; + + m_ShaderConverter->updateShaderResourceView(m_YUVTextureUpscaled.Get()); + + // Input: m_YUVTextureUpscaled / Output: m_OutputTexture + m_ShaderConverter->draw( + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON + ); + + TimerInfo("(Shader Convert YUV)", true); + + goto Draw; + } + + // RGB Upscaling using Shader + else if(m_RenderStep2 == RenderStep::UPSCALE_SHADER){ + + resetGraphicsCommand = true; + + m_ShaderUpscaler->updateShaderResourceView(m_RGBTexture.Get()); + + // Input: m_RGBTexture / Output: m_OutputTexture + m_ShaderUpscaler->draw( + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON + ); + + TimerInfo("(Shader Upscale RGB)", true); + + goto Draw; + } + + // RGB Sharpening using Shader + else if(m_RenderStep2 == RenderStep::SHARPEN_SHADER){ + + resetGraphicsCommand = true; + + m_ShaderSharpener->updateShaderResourceView(m_RGBTextureUpscaled.Get()); + + // Input: m_RGBTextureUpscaled / Output: m_OutputTexture + m_ShaderSharpener->draw( + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COMMON + ); + + TimerInfo("(Shader Sharpen RGB)", true); + + goto Draw; + } + +Draw: + + // DebugExportToPNG(m_RGBTextureUpscaled.Get(), D3D12_RESOURCE_STATE_COMMON, "m_RGBTextureUpscaled.png"); + // DebugExportToPNG(m_OutputTexture.Get(), D3D12_RESOURCE_STATE_COMMON, "m_OutputTexture.png"); + + // Copy the processed texture into the backbuffer to present + { + resetGraphicsCommand = true; + + // Add black background + m_Barrier = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[backBufferIndex].Get(), + D3D12_RESOURCE_STATE_PRESENT, + D3D12_RESOURCE_STATE_RENDER_TARGET + ); + m_GraphicsCommandList->ResourceBarrier(1, &m_Barrier); + + m_GraphicsCommandList->OMSetRenderTargets(1, &m_BackBufferRTVs[backBufferIndex], FALSE, nullptr); + + FLOAT black[4] = {0, 0, 0, 1}; + m_GraphicsCommandList->ClearRenderTargetView( + m_BackBufferRTVs[backBufferIndex], + black, + 0, + nullptr + ); + + // Copy + D3D12_TEXTURE_COPY_LOCATION src = {}; + src.pResource = m_OutputTexture.Get(); + src.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + src.SubresourceIndex = 0; + + D3D12_TEXTURE_COPY_LOCATION dst = {}; + dst.pResource = m_BackBuffers[backBufferIndex].Get(); + dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + dst.SubresourceIndex = 0; + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_OutputTexture.Get(), + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[backBufferIndex].Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_COPY_DEST + ); + m_GraphicsCommandList->ResourceBarrier(2, m_Barriers); + + m_GraphicsCommandList->CopyTextureRegion(&dst, m_OutputTextureInfo.left, m_OutputTextureInfo.top, 0, &src, &m_OutputBox); + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_OutputTexture.Get(), + D3D12_RESOURCE_STATE_COPY_SOURCE, + D3D12_RESOURCE_STATE_COMMON + ); + m_Barriers[1] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[backBufferIndex].Get(), + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_RENDER_TARGET + ); + m_GraphicsCommandList->ResourceBarrier(2, m_Barriers); + + // Render overlays stats on top of the video stream. notifyOverlayUpdated() + // only swaps the textures in under m_OverlayLock, which we hold, so there is + // always a complete overlay to draw here. + for (int i = 0; i < Overlay::OverlayMax; i++) { + renderOverlay((Overlay::OverlayType)i); + } + + m_Barriers[0] = CD3DX12_RESOURCE_BARRIER::Transition( + m_BackBuffers[backBufferIndex].Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + D3D12_RESOURCE_STATE_PRESENT + ); + m_GraphicsCommandList->ResourceBarrier(1, m_Barriers); + + if (m_QueryHeap && !m_EnhancerQualitySettled) { + m_GraphicsCommandList->EndQuery(m_QueryHeap.Get(), + D3D12_QUERY_TYPE_TIMESTAMP, + m_CurrentFrameIndex * 2 + 1); + m_GraphicsCommandList->ResolveQueryData(m_QueryHeap.Get(), + D3D12_QUERY_TYPE_TIMESTAMP, + m_CurrentFrameIndex * 2, + 2, + m_TimestampReadbackBuffer.Get(), + m_CurrentFrameIndex * 2 * sizeof(UINT64)); + } + + m_hr = m_GraphicsCommandList->Close(); + if(!verifyHResult(m_hr, "m_GraphicsCommandList->Close();")){ + goto Present; + } + ID3D12CommandList* cmdLists[] = { m_GraphicsCommandList.Get() }; + m_GraphicsCommandQueue->ExecuteCommandLists(1, cmdLists); + + if (m_QueryHeap && !m_EnhancerQualitySettled) { + m_TimestampPending[m_CurrentFrameIndex] = true; + } + + frameDrawn = true; + + TimerInfo("(VP Copy m_OutputTexture -> m_BackBuffers)", true); + } + +Present: + + // Present the BackBuffer texture to the display + { + // This back buffer holds whatever was presented m_FrameCount frames ago, which + // shows up as a black or stale flash. We must still present to release the frame + // latency waitable object, so repeat the last visible frame instead. + if (!frameDrawn) { + repeatLastFrame(backBufferIndex); + } + + // When vSync is enabled, we do Present(0, 0) instead of (1, 0) to leverage VRR capability of the screen if any. + m_hr = m_SwapChain->Present(0, m_AllowTearing ? DXGI_PRESENT_ALLOW_TEARING : 0); + + TimerInfo("(Present)", true); + + // DebugExportToPNG(m_BackBuffers[backBufferIndex].Get(), D3D12_RESOURCE_STATE_PRESENT, "m_BackBuffers.png"); + + if(!verifyHResult(m_hr, "m_SwapChain->Present(0, m_AllowTearing ? DXGI_PRESENT_ALLOW_TEARING : 0);")){ + // The card may have been removed or crashed. Reset the decoder. + SDL_Event event; + event.type = SDL_RENDER_TARGETS_RESET; + SDL_AtomicUnlock(&m_OverlayLock); + m_SkipFrame = false; + SDL_PushEvent(&event); + return; + } + } + + // Keep the pointer to the Output texture in case we need to skip the next frame. + // It help to redraw the previous texture. + m_OutputTexturePrevious = m_OutputTexture; + + // Detach textures pointer + { + if(detachRGBTexture){ + m_RGBTexture.Detach(); + } + if(detachRGBTextureUpscaled){ + m_RGBTextureUpscaled.Detach(); + } + if(detachYUVTextureUpscaled){ + m_YUVTextureUpscaled.Detach(); + } + if(detachOutputTexture){ + m_OutputTexture.Detach(); + } + } + + // Wait for the GPU to be done with this frame before returning. + // + // This looks like it could be replaced by a fence and several command allocators to + // let frames overlap, but it cannot: the shader helpers rewrite their descriptors + // through updateShaderResourceView() on every frame, the NGX VSR feature is a single + // instance, and m_RGBTexture / m_OutputTexture are single buffered. Letting frame N+1 + // record while frame N is still executing makes all three race, which the driver + // reports as DXGI_ERROR_DEVICE_HUNG, "invalid command passed by the calling + // application". Overlapping frames requires per-frame copies of every one of those + // resources first. + { + // VideoProcessor + if(resetVideoProcessCommand){ + waitForVideoProcess(true); // Force the CPU waiting (true), otherwise the tearing is too agressive + resetVideoProcessCommandList(); + } + + // Graphics + if(resetGraphicsCommand){ + waitForGraphics(true); + resetGraphicsCommandList(); + } + + TimerInfo("(Reinitialization)", true); + } + + SDL_AtomicUnlock(&m_OverlayLock); + m_SkipFrame = false; + + // Disable HDR renderer setting if the display HDR is not activate, + // and reanable it if it does. + updateDisplayHDRStatusAsync(frame->color_trc == AVCOL_TRC_SMPTE2084); + + return; +} + + +#ifndef QT_DEBUG + +/** + * \brief Export a texture D3D12 as PNG (Debug only) + * + * Export a texture as PNG at root directory of the application. + * RGB and YUV in SDR are color correct. + * HDR will display something wrong, but at least helpful to know it is loaded. + * It generates a PNG only in Debug mode, just does nothing in Production. + * + * \param ID3D12Resource* srcTexture, Texture to export + * \param D3D12_RESOURCE_STATES state, Current texture state + * \param const char* filename, Filename used to export + * \return void + */ +void D3D12VARenderer::DebugExportToPNG( + ID3D12Resource* srcTexture, + D3D12_RESOURCE_STATES state, + const char* filename + ) +{ + return; +} + +/** + * \brief Export a texture D3D11 as PNG (Debug only) + * + * Export a texture as PNG at root directory of the application. + * RGB and YUV in SDR are color correct. + * HDR will display something wrong, but at least helpful to know it is loaded. + * It generates a PNG only in Debug mode, just does nothing in Production. + * + * \param ID3D11Texture2D* srcTexture, Texture to export + * \param const char* filename, Filename used to export + * \return void + */ + +void D3D12VARenderer::D3D11DebugExportToPNG( + ID3D11Texture2D* srcTexture, + const char* filename) +{ + return; +} + +#else + +// Used for debug purpose only +#define STB_IMAGE_WRITE_IMPLEMENTATION +#include "stb_image_write.h" + +/** + * \brief Export a texture D3D12 as PNG (Debug only) + * + * Export a texture as PNG at root directory of the application. + * RGB in SDR is color correct. + * YUV in SDR displays only Y (grey). + * HDR will display something wrong, but at least helpful to know it is loaded. + * It generates a PNG only in Debug mode, just does nothing in Production. + * + * \param ID3D12Resource* srcTexture, Texture to export + * \param D3D12_RESOURCE_STATES state, Current texture state + * \param const char* filename, Filename used to export + * \return void + */ +void D3D12VARenderer::DebugExportToPNG( + ID3D12Resource* srcTexture, + D3D12_RESOURCE_STATES state, + const char* filename) +{ + D3D12_RESOURCE_DESC desc = srcTexture->GetDesc(); + int textureWidth = desc.Width; + int textureHeight = desc.Height; + + UINT64 totalBytes = 0; + D3D12_PLACED_SUBRESOURCE_FOOTPRINT layout = {}; + m_Device->GetCopyableFootprints(&desc, 0, 1, 0, &layout, nullptr, nullptr, &totalBytes); + + ComPtr readback; + D3D12_HEAP_PROPERTIES heapProps = {}; + heapProps.Type = D3D12_HEAP_TYPE_READBACK; + + D3D12_RESOURCE_DESC bufDesc = {}; + bufDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; + bufDesc.Width = totalBytes; + bufDesc.Height = 1; + bufDesc.DepthOrArraySize = 1; + bufDesc.MipLevels = 1; + bufDesc.SampleDesc.Count = 1; + bufDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; + + m_Device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &bufDesc, + D3D12_RESOURCE_STATE_COPY_DEST, + nullptr, + IID_PPV_ARGS(&readback)); + + D3D12_TEXTURE_COPY_LOCATION srcLoc = {}; + srcLoc.pResource = srcTexture; + srcLoc.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX; + srcLoc.SubresourceIndex = 0; + + D3D12_TEXTURE_COPY_LOCATION dstLoc = {}; + dstLoc.pResource = readback.Get(); + dstLoc.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT; + m_Device->GetCopyableFootprints(&desc, 0, 1, 0, &dstLoc.PlacedFootprint, nullptr, nullptr, nullptr); + + m_PictureCommandAllocator->Reset(); + m_PictureCommandList->Reset(m_PictureCommandAllocator.Get(), nullptr); + + m_Barrier = CD3DX12_RESOURCE_BARRIER::Transition( + srcTexture, + state, + D3D12_RESOURCE_STATE_COPY_SOURCE + ); + m_PictureCommandList->ResourceBarrier(1, &m_Barrier); + + m_PictureCommandList->CopyTextureRegion(&dstLoc, 0, 0, 0, &srcLoc, nullptr); + + m_Barrier = CD3DX12_RESOURCE_BARRIER::Transition( + srcTexture, + D3D12_RESOURCE_STATE_COPY_SOURCE, + state + ); + m_PictureCommandList->ResourceBarrier(1, &m_Barrier); + + m_PictureCommandList->Close(); + ID3D12CommandList* lists[] = { m_PictureCommandList.Get() }; + m_PictureCommandQueue->ExecuteCommandLists(1, lists); + + ComPtr fence; + m_Device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(&fence)); + HANDLE evt = CreateEvent(nullptr, FALSE, FALSE, nullptr); + m_PictureCommandQueue->Signal(fence.Get(), 1); + fence->SetEventOnCompletion(1, evt); + WaitForSingleObject(evt, INFINITE); + CloseHandle(evt); + + void* mappedData; + D3D12_RANGE readRange = { 0, totalBytes }; + readback->Map(0, &readRange, &mappedData); + const UINT yPlaneSize = textureWidth * textureHeight; + const uint8_t* sourceBytes = static_cast(mappedData); + + const UINT rowPitch = layout.Footprint.RowPitch; + + if (desc.Format == DXGI_FORMAT_NV12) + { + std::vector yPlaneData(yPlaneSize); + for (int y = 0; y < textureHeight; ++y) { + memcpy( + yPlaneData.data() + y * textureWidth, + sourceBytes + y * rowPitch, + textureWidth + ); + } + readback->Unmap(0, nullptr); + stbi_write_png( + filename, + textureWidth, + textureHeight, + 1, + yPlaneData.data(), + textureWidth + ); + + // std::vector rgbData(textureWidth * textureHeight * 3); + + // const uint8_t* base = static_cast(mappedData) + layout.Offset; + // const uint8_t* yPlane = base; // premier plan + // const uint8_t* uvPlane = base + layout.Footprint.RowPitch * (desc.Height); + + // // const uint8_t* yPlane = sourceBytes; + // // const uint8_t* uvPlane = sourceBytes + rowPitch * textureHeight; + + // for (int y = 0; y < textureHeight; ++y) { + // for (int x = 0; x < textureWidth; ++x) { + // // int yValue = yPlane[y * rowPitch + x]; + // int yValue = yPlane[y * layout.Footprint.RowPitch + x]; + + // int uvRow = y / 2; + // int uvCol = x / 2; + // // int uvIndex = uvRow * rowPitch + uvCol * 2; + // int uvIndex = uvRow * layout.Footprint.RowPitch + uvCol * 2; + // int uValue = uvPlane[uvIndex] - 128; + // int vValue = uvPlane[uvIndex + 1] - 128; + + // // Conversion YUV -> RGB (BT.709) + // int r = yValue + (int)(1.5748 * vValue); + // int g = yValue - (int)(0.1873 * uValue) - (int)(0.4681 * vValue); + // int b = yValue + (int)(1.8556 * uValue); + + // // Clamp to [0, 255] + // r = (r < 0) ? 0 : (r > 255) ? 255 : r; + // g = (g < 0) ? 0 : (g > 255) ? 255 : g; + // b = (b < 0) ? 0 : (b > 255) ? 255 : b; + + // int pixelIndex = (y * textureWidth + x) * 3; + // rgbData[pixelIndex + 0] = (uint8_t)r; + // rgbData[pixelIndex + 1] = (uint8_t)g; + // rgbData[pixelIndex + 2] = (uint8_t)b; + // } + // } + + // readback->Unmap(0, nullptr); + + // stbi_write_png( + // filename, + // textureWidth, + // textureHeight, + // 3, + // rgbData.data(), + // textureWidth * 3 + // ); + } + else if (desc.Format == DXGI_FORMAT_P010) + { + std::vector rgbData(textureWidth * textureHeight * 3); + + const uint16_t* yPlane = reinterpret_cast(sourceBytes); + const uint16_t* uvPlane = reinterpret_cast(sourceBytes + rowPitch * textureHeight); + + for (int y = 0; y < textureHeight; ++y) { + for (int x = 0; x < textureWidth; ++x) { + int yValue = yPlane[y * (rowPitch / 2) + x] >> 8; + + int uvRow = y / 2; + int uvCol = x / 2; + int uValue = (uvPlane[uvRow * (rowPitch / 2) + uvCol * 2] >> 8) - 128; + int vValue = (uvPlane[uvRow * (rowPitch / 2) + uvCol * 2 + 1] >> 8) - 128; + + int r = yValue + (int)(1.5748 * vValue); + int g = yValue - (int)(0.1873 * uValue) - (int)(0.4681 * vValue); + int b = yValue + (int)(1.8556 * uValue); + + r = (r < 0) ? 0 : (r > 255) ? 255 : r; + g = (g < 0) ? 0 : (g > 255) ? 255 : g; + b = (b < 0) ? 0 : (b > 255) ? 255 : b; + + int pixelIndex = (y * textureWidth + x) * 3; + rgbData[pixelIndex + 0] = (uint8_t)r; + rgbData[pixelIndex + 1] = (uint8_t)g; + rgbData[pixelIndex + 2] = (uint8_t)b; + } + } + + readback->Unmap(0, nullptr); + + stbi_write_png( + filename, + textureWidth, + textureHeight, + 3, + rgbData.data(), + textureWidth * 3 + ); + } else if(desc.Format == DXGI_FORMAT_AYUV || desc.Format == DXGI_FORMAT_Y410) { + std::vector yPlaneData(yPlaneSize); + for (int y = 0; y < textureHeight; ++y) { + memcpy( + yPlaneData.data() + y * textureWidth, + sourceBytes + y * rowPitch, + textureWidth + ); + } + readback->Unmap(0, nullptr); + stbi_write_png( + filename, + textureWidth, + textureHeight, + 1, + yPlaneData.data(), + textureWidth + ); + } else { + // RGB/RGBA formats + std::vector rgbData(textureWidth * textureHeight * 4); + for (int y = 0; y < textureHeight; ++y) { + memcpy( + rgbData.data() + y * textureWidth * 4, + sourceBytes + y * rowPitch, + textureWidth * 4 + ); + } + readback->Unmap(0, nullptr); + stbi_write_png( + filename, + textureWidth, + textureHeight, + 4, + rgbData.data(), + textureWidth * 4 + ); + } +} + +/** + * \brief Export a texture D3D11 as PNG (Debug only) + * + * Export a texture as PNG at root directory of the application. + * RGB and YUV in SDR are color correct. + * HDR will display something wrong, but at least helpful to know it is loaded. + * It generates a PNG only in Debug mode, just does nothing in Production. + * + * \param ID3D11Texture2D* srcTexture, Texture to export + * \param const char* filename, Filename used to export + * \return void + */ +void D3D12VARenderer::D3D11DebugExportToPNG( + ID3D11Texture2D* srcTexture, + const char* filename) +{ + if (!srcTexture || !m_D3D11Device || !m_D3D11DeviceContext) + return; + + D3D11_TEXTURE2D_DESC desc; + srcTexture->GetDesc(&desc); + + int textureWidth = desc.Width; + int textureHeight = desc.Height; + + D3D11_TEXTURE2D_DESC stagingDesc = desc; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ComPtr stagingTexture; + HRESULT hr = m_D3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture); + if (FAILED(hr)) + return; + + m_D3D11DeviceContext->CopyResource(stagingTexture.Get(), srcTexture); + + const UINT yPlaneSize = textureWidth * textureHeight; + + D3D11_MAPPED_SUBRESOURCE mappedResource; + hr = m_D3D11DeviceContext->Map(stagingTexture.Get(), 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(hr)) + return; + + const uint8_t* sourceBytes = static_cast(mappedResource.pData); + const UINT rowPitch = mappedResource.RowPitch; + + if (desc.Format == DXGI_FORMAT_NV12) { + std::vector rgbData(textureWidth * textureHeight * 3); + + const uint8_t* yPlane = sourceBytes; + const uint8_t* uvPlane = sourceBytes + rowPitch * textureHeight; + + for (int y = 0; y < textureHeight; ++y) { + for (int x = 0; x < textureWidth; ++x) { + int yValue = yPlane[y * rowPitch + x]; + + int uvRow = y / 2; + int uvCol = x / 2; + int uvIndex = uvRow * rowPitch + uvCol * 2; + int uValue = uvPlane[uvIndex] - 128; + int vValue = uvPlane[uvIndex + 1] - 128; + + // Conversion YUV -> RGB (BT.709) + int r = yValue + (int)(1.5748 * vValue); + int g = yValue - (int)(0.1873 * uValue) - (int)(0.4681 * vValue); + int b = yValue + (int)(1.8556 * uValue); + + // Clamp to [0, 255] + r = (r < 0) ? 0 : (r > 255) ? 255 : r; + g = (g < 0) ? 0 : (g > 255) ? 255 : g; + b = (b < 0) ? 0 : (b > 255) ? 255 : b; + + int pixelIndex = (y * textureWidth + x) * 3; + rgbData[pixelIndex + 0] = (uint8_t)r; + rgbData[pixelIndex + 1] = (uint8_t)g; + rgbData[pixelIndex + 2] = (uint8_t)b; + } + } + + m_D3D11DeviceContext->Unmap(stagingTexture.Get(), 0); + + stbi_write_png( + filename, + textureWidth, + textureHeight, + 3, + rgbData.data(), + textureWidth * 3 + ); + } else if (desc.Format == DXGI_FORMAT_P010) { + std::vector rgbData(textureWidth * textureHeight * 3); + + const uint16_t* yPlane = reinterpret_cast(sourceBytes); + const uint16_t* uvPlane = reinterpret_cast(sourceBytes + rowPitch * textureHeight); + + for (int y = 0; y < textureHeight; ++y) { + for (int x = 0; x < textureWidth; ++x) { + int yValue = yPlane[y * (rowPitch / 2) + x] >> 8; + + int uvRow = y / 2; + int uvCol = x / 2; + int uValue = (uvPlane[uvRow * (rowPitch / 2) + uvCol * 2] >> 8) - 128; + int vValue = (uvPlane[uvRow * (rowPitch / 2) + uvCol * 2 + 1] >> 8) - 128; + + int r = yValue + (int)(1.5748 * vValue); + int g = yValue - (int)(0.1873 * uValue) - (int)(0.4681 * vValue); + int b = yValue + (int)(1.8556 * uValue); + + r = (r < 0) ? 0 : (r > 255) ? 255 : r; + g = (g < 0) ? 0 : (g > 255) ? 255 : g; + b = (b < 0) ? 0 : (b > 255) ? 255 : b; + + int pixelIndex = (y * textureWidth + x) * 3; + rgbData[pixelIndex + 0] = (uint8_t)r; + rgbData[pixelIndex + 1] = (uint8_t)g; + rgbData[pixelIndex + 2] = (uint8_t)b; + } + } + + m_D3D11DeviceContext->Unmap(stagingTexture.Get(), 0); + + stbi_write_png( + filename, + textureWidth, + textureHeight, + 3, + rgbData.data(), + textureWidth * 3 + ); + } else if(desc.Format == DXGI_FORMAT_AYUV || desc.Format == DXGI_FORMAT_Y410) { + std::vector yPlaneData(yPlaneSize); + for (int y = 0; y < textureHeight; ++y) { + memcpy( + yPlaneData.data() + y * textureWidth, + sourceBytes + y * rowPitch, + textureWidth + ); + } + + m_D3D11DeviceContext->Unmap(stagingTexture.Get(), 0); + + stbi_write_png( + filename, + textureWidth, + textureHeight, + 1, + yPlaneData.data(), + textureWidth + ); + } else { + // RGB/RGBA formats + std::vector rgbData(textureWidth * textureHeight * 4); + for (int y = 0; y < textureHeight; ++y) { + memcpy( + rgbData.data() + y * textureWidth * 4, + sourceBytes + y * rowPitch, + textureWidth * 4 + ); + } + + m_D3D11DeviceContext->Unmap(stagingTexture.Get(), 0); + + stbi_write_png( + filename, + textureWidth, + textureHeight, + 4, + rgbData.data(), + textureWidth * 4 + ); + } +} + +#endif diff --git a/app/streaming/video/ffmpeg-renderers/d3d12va.h b/app/streaming/video/ffmpeg-renderers/d3d12va.h new file mode 100644 index 000000000..c7d7a6a34 --- /dev/null +++ b/app/streaming/video/ffmpeg-renderers/d3d12va.h @@ -0,0 +1,419 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include "qfileinfo.h" +#include "streaming/video/videoenhancement.h" +#include "settings/streamingpreferences.h" +#include "streaming/session.h" +#include "streaming/streamutils.h" +#include "streaming/video/decoder.h" +#include "d3d12va_shaders.h" +#include "renderer.h" +#include "dxutil.h" +#include "utils.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// AMD AMF +#include "public/common/AMFFactory.h" +#include "public/include/core/Context.h" +#include "public/include/core/Factory.h" +#include "public/include/core/Result.h" +#include "public/include/components/HQScaler.h" +#include "public/include/components/VideoConverter.h" +using namespace amf; + +// NVIDIA VSR +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +#include +#include +#include +} + +#define DECODER_BUFFER_POOL_SIZE 17 + +// NVIDIA VSR +#define APP_ID 0 +#define APP_PATH L"." + +// Intel VPL +#define ONEVPL_EXPERIMENTAL 1 +#include + +#include +using Microsoft::WRL::ComPtr; + +#define ALIGN16(value) (((value + 15) >> 4) << 4) + +class D3D12VARenderer : public QObject, public IFFmpegRenderer +{ +public: + D3D12VARenderer(int decoderSelectionPass); + virtual ~D3D12VARenderer() override; + virtual bool initialize(PDECODER_PARAMETERS params) override; + virtual void setHdrMode(bool enabled) override; + virtual bool prepareDecoderContext(AVCodecContext* context, AVDictionary**) override; + virtual bool prepareDecoderContextInGetFormat(AVCodecContext* context, AVPixelFormat pixelFormat) override; + virtual void renderFrame(AVFrame* frame) override; + virtual void notifyOverlayUpdated(Overlay::OverlayType) override; + virtual bool notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO stateInfo) override; + virtual int getRendererAttributes() override; + virtual int getDecoderCapabilities() override; + virtual int getDecoderColorspace() override; + virtual int getDecoderColorRange() override; + +private: + + struct decoder { + int ColorRange; + DXGI_FORMAT Format; + AVPixelFormat AVFormat; + DXGI_COLOR_SPACE_TYPE ColorSpace; + }; + + struct TextureInfo { + int width; + int height; + int left; + int top; + }; + + struct VppSurface { + mfxFrameSurface1* surface = nullptr; + mfxSurfaceD3D11Tex2D textureLinkD3D11; + mfxSurfaceD3D12Tex2D textureLinkD3D12; + ComPtr textureD3D11; + ComPtr textureD3D12; + }; + + static void lockContext(void* lock_ctx); + static void unlockContext(void* lock_ctx); + + // The frame color space is SMPTE2084 (HDR content) + static bool m_IsFrameHDR; + // The client display HDR status is On + static bool m_IsClientHDR; + // The frame texture is 10-bits (HDR and SDR) + bool m_IsTexture10bits = false; + // The frame texture is YUV 4:4:4 + bool m_IsTextureYUV444 = false; + // The Decoder is providing a D3D11 frame + bool m_IsFrameD3D11 = false; + + bool verifyHResult(HRESULT hr, const char* operation); + bool checkDecoderDX11Support(); + bool checkDecoderDX12Support(); + bool checkDecoderType(); + bool setupResources(); + void enhanceAutoSelection(); + bool enableAMDVideoSuperResolution(bool activate = true, bool logInfo = true); + bool enableIntelVideoSuperResolution(bool activate = true, bool logInfo = true); + bool enableNvidiaVideoSuperResolution(bool activate = true, bool logInfo = true); + bool enableAMDHDR(bool activate = true, bool logInfo = true); + bool enableIntelHDR(bool activate = true, bool logInfo = true); + bool enableNvidiaHDR(bool activate = true, bool logInfo = true); + void setAMDHdr(); + bool isNvidiaVSRSupport(); + bool getDisplayHDRStatus(); + void updateDisplayHDRStatusAsync(bool isFrameHDR); + void waitForVideoProcess(bool waitCPU = false); + void waitForGraphics(bool waitCPU = false); + void waitForOverlay(bool waitCPU = false); + void resetVideoProcessCommandList(); + void resetGraphicsCommandList(); + void collectGpuFrameTime(); + void adjustEnhancerQuality(); + void repeatLastFrame(UINT backBufferIndex); + void renderOverlay(Overlay::OverlayType type); + VppSurface* findUnlockedSurface(std::vector& pool); + + bool initialiazeAdapterInformation(); + void TimerInfo(const char* comment, bool start); + + // Inform which step of the renderering process need to follow fr YUV->RGB concersion, then for Upscaling + enum class RenderStep { + ALL_VIDEOPROCESSOR, + ALL_AMF, + CONVERT_SHADER, + CONVERT_VIDEOPROCESSOR, + CONVERT_AMF, + UPSCALE_SHADER, + UPSCALE_VIDEOPROCESSOR, + UPSCALE_AMF, + UPSCALE_VSR, + UPSCALE_VPL, + SHARPEN_SHADER, + NONE + }; + RenderStep m_RenderStep1 = RenderStep::CONVERT_SHADER; + RenderStep m_RenderStep2 = RenderStep::NONE; + + struct VERTEX { + float x, y; // Position + float u, v; // Texcoord + float r, g, b, a; // Background color + }; + UINT m_VbSize; + D3D12_VERTEX_BUFFER_VIEW m_VbView; + + + // ---- DEBUG ---- + bool m_DebugLayer = false; + // Change to true to get debugging more verbose + // Note: At true, it bugs VideoProcessCommandList->close() + bool m_DebugVerbose = false; + // Change to true to see rendering steps + // Note: At true, it could freeze your IDE due to large amount of logs to display + bool m_TimerInfo = false; + + QElapsedTimer m_Timer; + QElapsedTimer m_TimerFPS; + uint m_Seconds = 0; + + std::string m_InfoUpscaler = "None"; + std::string m_InfoSharpener = "None"; + std::string m_InfoAlgo = "None"; + + bool m_Vsync = false; + DECODER_PARAMETERS m_DecoderParams; + DXGI_ADAPTER_DESC1 m_AdapterDesc; + UINT m_OutputIndex = 0; + UINT m_AdapterIndex = 0; + ComPtr m_Factory; + ComPtr m_Adapter; + ComPtr m_Device; + ComPtr m_VideoDevice; + decoder m_Decoder; + bool m_SkipRenderStep2 = false; + int m_LastColorSpace = -1; + bool m_LastFullRange; + UINT m_MaxLuminance = 1000; + bool m_SkipFrame = false; + SDL_mutex* m_ContextLock; + bool m_ReloadRenderer = false; + + HRESULT m_hr; + VideoEnhancement* m_VideoEnhancement; + StreamingPreferences* m_Preferences; + int m_DisplayWidth; + int m_DisplayHeight; + TextureInfo m_OutputTextureInfo; + ComPtr m_FrameTexture; + ComPtr m_RGBTexture; + ComPtr m_RGBTextureUpscaled; + ComPtr m_YUVTextureUpscaled; + ComPtr m_OutputTexture; + ComPtr m_OutputTexturePrevious; + DXGI_FORMAT m_RGBFormat; + DXGI_COLOR_SPACE_TYPE m_RGBColorSpace; + bool m_AllowTearing = false; + bool m_cancelHDRUpdate = false; + QFuture m_HDRUpdateFuture = QFuture(); + bool m_PauseHDRUpdate = false; + int m_CheckHDRCount = 0; + DXGI_HDR_METADATA_HDR10 m_StreamHDRMetaData; + DXGI_HDR_METADATA_HDR10 m_OutputHDRMetaData; + + // Overlay + std::atomic m_OverlaySkip = false; + SDL_SpinLock m_OverlayLock; + std::array, Overlay::OverlayMax> m_OverlayVertexBuffers; + std::array, Overlay::OverlayMax> m_OverlayTextures; + ComPtr m_OverlayRootSignature; + ComPtr m_OverlayPSO; + ComPtr m_OverlaySrvHeap; + + const UINT m_FrameCount = 3; + UINT m_CurrentFrameIndex = 0; + ComPtr m_RtvHeap; + UINT m_RtvDescriptorSize = 0; + std::vector> m_BackBuffers; + std::vector m_BackBufferRTVs; + ComPtr m_SwapChain; + HANDLE m_FrameLatencyWaitableObject; + + bool m_VideoProcessorConvertEnabled = false; + bool m_VideoProcessorUpscalerEnabled = false; + bool m_VideoProcessorUpscalerConvertEnabled = false; + INT32 m_NoiseReductionValue = 0; + INT32 m_EdgeEnhancementValue = 0; + ComPtr m_VideoProcessorConvert; + ComPtr m_VideoProcessorUpscaler; + ComPtr m_VideoProcessorUpscalerConvert; + std::vector m_InputArgsConvert; + std::vector m_OutputArgsConvert; + std::vector m_InputArgsUpscaler; + std::vector m_OutputArgsUpscaler; + std::vector m_InputArgsUpscalerConvert; + std::vector m_OutputArgsUpscalerConvert; + + // One allocator per frame slot. Recycling the allocator of frame N then only ever + // has to wait on the frame that used that same slot, m_FrameCount frames earlier. + std::array, 3> m_VideoProcessCommandAllocators; + std::array m_VideoProcessAllocatorFence = {}; + ComPtr m_VideoProcessCommandList; + ComPtr m_VideoProcessCommandQueue; + std::array, 3> m_GraphicsCommandAllocators; + std::array m_GraphicsAllocatorFence = {}; + ComPtr m_GraphicsCommandList; + ComPtr m_GraphicsCommandQueue; + ComPtr m_OverlayCommandAllocator; + ComPtr m_OverlayCommandList; + ComPtr m_OverlayCommandQueue; + D3D12_RESOURCE_BARRIER m_Barrier; + + // Wait for next frame to save compute + ComPtr m_FenceVideoProcess; + UINT64 m_FenceVideoProcessValue = 0; + HANDLE m_FenceVideoProcessEvent = nullptr; + ComPtr m_FenceGraphics; + UINT64 m_FenceGraphicsValue = 0; + HANDLE m_FenceGraphicsEvent = nullptr; + ComPtr m_FenceOverlay; + UINT64 m_FenceOverlayValue = 0; + HANDLE m_FenceOverlayEvent = nullptr; + ComPtr m_FenceAMF; + UINT64 m_FenceAMFValue = 0; + HANDLE m_FenceAMFEvent = nullptr; + + AVBufferRef* m_HwDeviceContext; + int m_TextureAlignment; + int m_FrameWidth; + int m_FrameHeight; + + // D3D11 to D3D12 transfer + ComPtr m_D3D11Device; + ComPtr m_D3D11VideoDevice; + ComPtr m_D3D11DeviceContext; + ComPtr m_D3D11FrameTexture; // Input AMF + ComPtr m_D3D11YUVTextureUpscaled; // Output VPL + ComPtr m_D3D11Fence; + ComPtr m_D3D12Fence; + UINT64 m_D3D11FenceValue = 1; + D3D11_BOX m_D3D11SrcBox; + D3D12_BOX m_SrcBox; + D3D11_BOX m_D3D11OutputBox; + D3D12_BOX m_OutputBox; + + // GPU timing of the graphics queue, used to adapt the enhancer quality at runtime. + // Two timestamps (begin/end) per in-flight frame, read back without blocking the CPU. + ComPtr m_QueryHeap; + ComPtr m_TimestampReadbackBuffer; + UINT64 m_TimestampFrequency = 0; + std::array m_TimestampPending = {}; + // Exponential moving average of the GPU time spent on the graphics queue, in ms + double m_GpuFrameTimeMs = 0.0; + // Highest quality this GPU is allowed, derived from its VRAM. Recomputed identically + // at every initialization, so it does not need to survive a renderer reload. + int m_VsrQualityCeiling = NVSDK_NGX_VSR_Quality_High; + // Quality currently in use. NGX bakes the level into the feature at creation time, + // so changing it means reloading the renderer: both of these have to outlive the + // renderer instance. 0 means not decided yet. + static int m_VsrQualityLevel; + // Highest level still believed to be sustainable. It only ever ratchets down, which + // is what keeps the renderer from oscillating between two levels for a whole session. + static int m_VsrQualityCap; + QElapsedTimer m_VsrQualityTimer; + qint64 m_VsrQualityLastCheckMs = 0; + // Consecutive checks that found the quality already optimal + int m_VsrQualityStableCount = 0; + // Set once there is nothing left to decide, which stops the GPU timing entirely + bool m_EnhancerQualitySettled = false; + // True when the pipeline actually submits work on the VideoProcess queue. When it + // does not, the two queues have no dependency and must not wait on each other. + bool m_UsesVideoProcessQueue = false; + + int m_DecoderSelectionPass; + UINT m_BackBufferIndex = 0; + + bool m_IsIntegratedGPU = false; + bool m_IsOnBattery = false; + bool m_IsLowEndGPU = false; + bool m_VendorVSRenabled = false; + bool m_VendorHDRenabled = false; + bool m_AmfInitialized = false; + bool m_IntelInitialized = false; + bool m_NvidiaInitialized = false; + + DXGI_FORMAT m_TextureFormat; + + // Shaders class + D3D12VideoShaders::Enhancer m_EnhancerType = D3D12VideoShaders::Enhancer::NONE; + std::unique_ptr m_ShaderConverter = nullptr; + std::unique_ptr m_ShaderUpscaler = nullptr; + std::unique_ptr m_ShaderSharpener = nullptr; + + // AMD AMF + AMFContext2Ptr m_AmfContext; + AMFComputePtr m_AmfCompute; + ComPtr m_AmfCommandQueue; + AMFDataPtr m_AmfData; + bool m_AmfUpscalerSharpness = false; + ComPtr m_AmfFence; + UINT64 m_AmfFenceValue = 1; + AMFBufferPtr m_HdrBuffer; + // Correct result in HDR with m_AmfHdrEnabled at false for unknown reasons + bool m_AmfHdrColorSpaceEnabled = false; + // AMFComponentPtr does not work for m_AmfUpscaler, have to use raw pointer + AMFComponent* m_AmfUpscalerYUV; + AMFComponentPtr m_AmfVideoConverter; + AMFComponent* m_AmfUpscalerRGB; + AMFComponentPtr m_AmfVideoConverterUpscaled; + AMFSurfacePtr m_AmfSurfaceYUV; + AMFSurfacePtr m_AmfSurfaceRGB; + AMFSurfacePtr m_AmfSurfaceUpscaledYUV; + AMFSurfacePtr m_AmfSurfaceUpscaledRGB; + + // NVIDIA VSR + bool m_bNGXInitialized = false; + NVSDK_NGX_Parameter* m_VSRngxParameters = nullptr; + NVSDK_NGX_Parameter* m_TrueHDRngxParameters = nullptr; + NVSDK_NGX_Handle* m_VSRFeature = nullptr; + NVSDK_NGX_Handle* m_TrueHDRFeature = nullptr; + RECT m_NGXSrcRect = {}; + RECT m_NGXDstRect = {}; + + // Intel VPL + mfxVideoParam m_VppParams; + mfxSession m_VppSession; + mfxLoader m_VppLoader; + mfxFrameAllocRequest m_VppReq[2]; + std::vector m_VppSurfaceIn; + std::vector m_VppSurfaceOut; + mfxMemoryInterface* m_MemoryInterface = nullptr; + + // Used for debug purpose only + ComPtr m_PictureCommandAllocator; + ComPtr m_PictureCommandList; + ComPtr m_PictureCommandQueue; + void DebugExportToPNG( + ID3D12Resource* srctexture, + D3D12_RESOURCE_STATES state, + const char* filename); + void D3D11DebugExportToPNG( + ID3D11Texture2D* srctexture, + const char* filename); + +}; diff --git a/app/streaming/video/ffmpeg-renderers/d3d12va_shaders.cpp b/app/streaming/video/ffmpeg-renderers/d3d12va_shaders.cpp new file mode 100644 index 000000000..4971b3914 --- /dev/null +++ b/app/streaming/video/ffmpeg-renderers/d3d12va_shaders.cpp @@ -0,0 +1,3040 @@ +#include +#include "d3d12va_shaders.h" +#include "SDL_log.h" +#include "qdebug.h" +#include +#include +#include +#include +#include + +using Microsoft::WRL::ComPtr; + +/** + * \brief Custom IDxcIncludeHandler for Qt resources + * + * This class implements IDxcIncludeHandler to allow the DirectX Shader Compiler + * (DXC) to load HLSL include files directly from Qt resources (e.g., ":/enhancer/"). + * When a shader contains #include "filename.hlsl", this handler provides + * the corresponding resource to the compiler. + */ +class QtIncludeHandler : public IDxcIncludeHandler { +public: + QtIncludeHandler() : m_refCount(1) {} + virtual ~QtIncludeHandler() = default; + + HRESULT STDMETHODCALLTYPE LoadSource( + LPCWSTR pFilename, IDxcBlob** ppIncludeSource) override + { + QString path = QString::fromWCharArray(pFilename); + QFile file(":/enhancer/" + path); + if (!file.open(QIODevice::ReadOnly)) + return E_FAIL; + + QByteArray data = file.readAll(); + file.close(); + + IDxcBlobEncoding* blob = nullptr; + ComPtr library; + DxcCreateInstance(CLSID_DxcLibrary, IID_PPV_ARGS(&library)); + library->CreateBlobWithEncodingOnHeapCopy( + data.constData(), data.size(), CP_UTF8, &blob); + + *ppIncludeSource = blob; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject) override { + if (riid == IID_IUnknown || riid == __uuidof(IDxcIncludeHandler)) { + *ppvObject = this; + AddRef(); + return S_OK; + } + *ppvObject = nullptr; + return E_NOINTERFACE; + } + + ULONG STDMETHODCALLTYPE AddRef() override { return ++m_refCount; } + ULONG STDMETHODCALLTYPE Release() override { + ULONG count = --m_refCount; + if (count == 0) delete this; + return count; + } + +private: + std::atomic m_refCount; +}; + +/** + * \brief Constructor + */ +D3D12VideoShaders::D3D12VideoShaders( + ID3D12Device* device, + ID3D12GraphicsCommandList* graphicsCommandList, + ID3D12CommandQueue* graphicsCommandQueue, + VideoEnhancement* videoEnhancement, + ID3D12Resource* textureIn, + ID3D12Resource* textureOut, + D3D12_VIEWPORT viewport, + D3D12_RECT scissorRect, + Enhancer enhancer, + DXGI_COLOR_SPACE_TYPE colorSpace + ) : + m_Device(device), + m_GraphicsCommandList(graphicsCommandList), + m_GraphicsCommandQueue(graphicsCommandQueue), + m_VideoEnhancement(videoEnhancement), + m_TextureIn(textureIn), + m_TextureOut(textureOut), + m_Viewport(viewport), + m_ScissorRect(scissorRect), + m_Enhancer(enhancer), + m_ColorSpace(colorSpace), + m_isYUV(false), + m_IsYUV444(false), + m_IsHDR(false), + m_Is2Planes(false) +{ + // Texture must be provided + if (!m_TextureIn || !m_TextureOut) { + return; + } + + D3D12_RESOURCE_DESC inDesc = m_TextureIn->GetDesc(); + m_InWidth = static_cast(inDesc.Width); + m_InHeight = static_cast(inDesc.Height); + + D3D12_RESOURCE_DESC outDesc = m_TextureOut->GetDesc(); + m_OutWidth = static_cast(outDesc.Width); + m_OutHeight = static_cast(outDesc.Height); + + // YUV + switch (inDesc.Format) { + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + m_isYUV = true; + break; + default: + m_isYUV = false; + break; + } + + // YUV 4:4:4 + switch (inDesc.Format) { + case DXGI_FORMAT_AYUV: + case DXGI_FORMAT_Y410: + m_IsYUV444 = true; + break; + default: + m_IsYUV444 = false; + break; + } + + // HDR + switch (inDesc.Format) { + case DXGI_FORMAT_P010: + case DXGI_FORMAT_Y410: + case DXGI_FORMAT_R10G10B10A2_UNORM: + m_IsHDR = true; + break; + default: + m_IsHDR = false; + break; + } + + // 2-Planes + switch (inDesc.Format) { + case DXGI_FORMAT_NV12: + case DXGI_FORMAT_P010: + m_Is2Planes = true; + break; + default: + m_Is2Planes = false; + break; + } + + m_IsUpscaling = isUpscaler(m_Enhancer); + m_IsUsingShader = isUsingShader(m_Enhancer); + + m_AdvancedShader = isSupportingAdvancedShader(); + + switch (m_Enhancer) { + case Enhancer::CONVERT_PS: + initializeCONVERT_PS(); + break; + case Enhancer::NIS: + initializeNIS(); + break; + case Enhancer::NIS_SHARPENER: + initializeNIS(false); + break; + case Enhancer::FSR1: + initializeFSR1(); + break; + case Enhancer::SGSR1: + initializeSGSR1(); + break; + case Enhancer::RCAS: + initializeRCAS(); + break; + case Enhancer::COPY: + initializeCOPY(); + break; + default: + break; + } +} + +/** + * \brief Destructor + */ +D3D12VideoShaders::~D3D12VideoShaders() +{ + m_TextureInterm.Reset(); + m_TextureIn.Reset(); + m_TextureOut.Reset(); + m_PipelineState.Reset(); + m_RootSignature.Reset(); + m_DescriptorHeapCBV_SRV_UAV.Reset(); + m_DescriptorHeapRTV.Reset(); + m_DescriptorHeapSampler.Reset(); + + m_GraphicsCommandList.Reset(); + m_GraphicsCommandQueue.Reset(); + + m_Device.Reset(); +} + +/** + * \brief Verify the result and display error logs + * + * Verify if the operation succeed + * Display error log in case of failed + * + * \param HRESULT hr Result of the operation + * \param const char* operation Additional message + * \return bool Return true if succeed + */ +bool D3D12VideoShaders::verifyHResult(HRESULT hr, const char* operation) +{ + if (FAILED(hr)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "%s failed with HRESULT: 0x%08X", operation, hr); + + // Convert HRESULT in a readable string + char errorMsg[256]; + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, nullptr, hr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorMsg, sizeof(errorMsg), nullptr); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error message: %s", errorMsg); + + if (m_Device) { + // If debug layer available, print messages from ID3D12InfoQueue + ComPtr infoQueue; + if (SUCCEEDED(m_Device->QueryInterface(IID_PPV_ARGS(&infoQueue)))) { + UINT64 num = infoQueue->GetNumStoredMessages(); + for (UINT64 i = 0; i < num; ++i) { + SIZE_T msgSize = 0; + infoQueue->GetMessage(i, nullptr, &msgSize); + std::vector buf(msgSize); + D3D12_MESSAGE* msg = reinterpret_cast(buf.data()); + infoQueue->GetMessage(i, msg, &msgSize); + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "D3D12Msg %u: %s", (unsigned)i, msg->pDescription); + } + infoQueue->ClearStoredMessages(); + } + + HRESULT removedHr = m_Device->GetDeviceRemovedReason(); + if (removedHr != S_OK) { + char errorMsg[256]; + FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM, + nullptr, + removedHr, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + errorMsg, + sizeof(errorMsg), + nullptr + ); + + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Device removed! HRESULT: 0x%08X, Message: %s", + removedHr, errorMsg); + } + } + + return false; + } + return true; +} + +/** + * \brief Check if enhancer supports advanced shaders + * + * Tests for 16-bit precision support and attempts to compile + * an advanced shader to determine hardware compatibility. + * + * \return bool True if advanced shaders are supported + */ +bool D3D12VideoShaders::isSupportingAdvancedShader() +{ + // Verify if the GPU is able to support Shader 6.2 version to support half-precision feature + D3D12_FEATURE_DATA_SHADER_MODEL shaderModel = { D3D_SHADER_MODEL_6_2 }; + + m_hr = m_Device->CheckFeatureSupport( + D3D12_FEATURE_SHADER_MODEL, + &shaderModel, + sizeof(shaderModel) + ); + if (!verifyHResult(m_hr, "m_Device->CheckFeatureSupport(...options)")) { + qInfo() << "Shader Model 6.2 is not supported"; + return false; + } + if (shaderModel.HighestShaderModel < D3D_SHADER_MODEL_6_2) { + qInfo() << "Shader Model 6.2 is not supported"; + return false; + } + + // Check 16-bit support + D3D12_FEATURE_DATA_D3D12_OPTIONS options = {}; + m_hr = m_Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS, &options, sizeof(options)); + if (!verifyHResult(m_hr, "m_Device->CheckFeatureSupport(...options)")) { + return false; + } + if (!(options.MinPrecisionSupport & D3D12_SHADER_MIN_PRECISION_SUPPORT_16_BIT)) { + return false; + } + + // Force to load shader 6.2 + m_AdvancedShader = true; + + // At true if succeed to load a shader 6.2 + m_AdvancedShader = initializeCONVERT_PS(); + + // Reset variables + m_PipelineState.Reset(); + m_RootSignature.Reset(); + m_DescriptorHeapCBV_SRV_UAV.Reset(); + m_DescriptorHeapRTV.Reset(); + m_DescriptorHeapSampler.Reset(); + + return m_AdvancedShader; +} + +/** + * \brief Check if enhancer is an upscaler + * + * Determines if the specified enhancer performs upscaling. + * + * \param Enhancer enhancer Enhancer type to check + * \return bool True if enhancer is an upscaler + */ +bool D3D12VideoShaders::isUpscaler(Enhancer enhancer) +{ + switch (enhancer) { + case Enhancer::FSR1: + case Enhancer::NIS: + return true; + default: + return false; + } +} + +/** + * \brief Check if enhancer is a sharpener + * + * Determines if the specified enhancer performs sharpening. + * + * \param Enhancer enhancer Enhancer type to check + * \return bool True if enhancer is a sharpener + */ +bool D3D12VideoShaders::isSharpener(Enhancer enhancer) +{ + switch (enhancer) { + case Enhancer::FSR1: + case Enhancer::NIS: + case Enhancer::RCAS: + case Enhancer::NIS_SHARPENER: + return true; + default: + return false; + } +} + +/** + * \brief Check if enhancer uses shaders + * + * Determines if the enhancer requires shader processing. + * + * \param Enhancer enhancer Enhancer type to check + * \return bool True if enhancer uses shaders + */ +bool D3D12VideoShaders::isUsingShader(Enhancer enhancer) +{ + return enhancer != Enhancer::NONE; +} + +/** + * \brief Update shader resource views for input texture + * + * Creates SRVs based on texture format (RGB, NV12/P010, AYUV/Y410) + * with appropriate DXGI formats for each plane. + * + * \param ID3D12Resource* resource Input texture resource + * \return bool True if SRVs created successfully + */ +bool D3D12VideoShaders::updateShaderResourceView(ID3D12Resource* resource) +{ + D3D12_RESOURCE_DESC desc = resource->GetDesc(); + + // RGB + if (!m_isYUV) { + // t0 + if (!createSRVforResource(resource, 0, desc.Format, 0)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createSRVforResource(input) failed"); + return false; + } + } + + // NV12 or P010 + else if (m_Is2Planes) { + // t0: Prepare Luma plane + DXGI_FORMAT formatY = m_IsHDR ? DXGI_FORMAT_R16_UNORM : DXGI_FORMAT_R8_UNORM; + if (!createSRVforResource(resource, 0, formatY, 0)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createSRVforResource(input) failed"); + return false; + } + + // t1: Prepare Chroma plane + DXGI_FORMAT formatUV = m_IsHDR ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R8G8_UNORM; + if (!createSRVforResource(resource, 1, formatUV, 1)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createSRVforResource(input) failed"); + return false; + } + } + + // AYUV or Y410 + else { + // t0: AYUV and Y410 only use 1 plan + if (!createSRVforResource(resource, 0, desc.Format, 0)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createSRVforResource(input) failed"); + return false; + } + } + + return true; +} + +/** + * \brief Update YUV offset constants + * + * Sets the YUV channel offset values in root constants. + * + * \param XMFLOAT3 offset Offset values for Y, U, V channels + */ +void D3D12VideoShaders::updateRootConstsOffset(XMFLOAT3 offset){ + m_RootConsts.g_OffsetY = offset.x; + m_RootConsts.g_OffsetU = offset.y; + m_RootConsts.g_OffsetV = offset.z; +} + +/** + * \brief Initialize root constants structure + * + * Sets up conversion matrices, gamma correction, color range, + * and format-specific constants based on input texture properties. + */ +void D3D12VideoShaders::initializeRootConsts() +{ + m_RootConsts = {}; + + // SDR and HDR invert bits + m_RootConsts.g_INV_8BIT = 1.0f / 255.0f; + m_RootConsts.g_INV_10BIT = 1.0f / 1023.0f; + + // PQ constants + m_RootConsts.g_M1Inv = 16384.0f / 2610.0f; + m_RootConsts.g_M2Inv = 4096.0f / (2523.0f * 128.0f);//32.0f / 2523.0f; + m_RootConsts.g_C1 = 3424.0f / 4096.0f; + m_RootConsts.g_C2 = 2413.0f / 128.0f; + m_RootConsts.g_C3 = 2392.0f / 128.0f; + + // Texture format In/Out + D3D12_RESOURCE_DESC desc = m_TextureIn->GetDesc(); + DXGI_FORMAT formatIn = desc.Format; + switch (formatIn) { + case DXGI_FORMAT_NV12: + m_RootConsts.g_InputFormat = 0; // FMT_NV12 + m_RootConsts.g_OutputFormat = 0; // OUT_RGBA8; + break; + case DXGI_FORMAT_P010: + m_RootConsts.g_InputFormat = 1; // FMT_P010 + m_RootConsts.g_OutputFormat = 1; // OUT_RGB10; + break; + case DXGI_FORMAT_AYUV: + m_RootConsts.g_InputFormat = 2; // FMT_AYUV + m_RootConsts.g_OutputFormat = 0; // OUT_RGBA8; + break; + case DXGI_FORMAT_Y410: + m_RootConsts.g_InputFormat = 3; // FMT_Y410 + m_RootConsts.g_OutputFormat = 1; // OUT_RGB10; + break; + default: + m_RootConsts.g_InputFormat = 0; // FMT_NV12 + m_RootConsts.g_OutputFormat = 0; // OUT_RGBA8; + break; + } + + // Gamma correction (not needed) + switch (m_ColorSpace) { + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601: + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601: + m_RootConsts.g_GammaCorrection = 1; // GC_G22 + break; + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709: + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020: + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709: + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020: + m_RootConsts.g_GammaCorrection = 2; // GC_G24 + break; + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020: + m_RootConsts.g_GammaCorrection = 3; // GC_PQ + break; + default: + m_RootConsts.g_GammaCorrection = 0; // GC_LINEAR + break; + } + + switch (m_ColorSpace) { + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601: + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709: + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020: + m_RootConsts.g_Range = 1; // CR_FULL + break; + default: + m_RootConsts.g_Range = 0; // CR_LIMTED + break; + } + + // Convertion matrix + XMFLOAT3 g_CSC_Row0; + XMFLOAT3 g_CSC_Row1; + XMFLOAT3 g_CSC_Row2; + switch (m_ColorSpace) { + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P601: + // BT.601 limited + g_CSC_Row0 = { 1.1644f, 0.0000f, 1.5960f}; + g_CSC_Row1 = { 1.1644f, -0.3918f, -0.8130f}; + g_CSC_Row2 = { 1.1644f, 2.0172f, 0.0000f}; + break; + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P601: + // BT.601 full + g_CSC_Row0 = { 1.0000f, 0.0000f, 1.4020f}; + g_CSC_Row1 = { 1.0000f, -0.3441f, -0.7141f}; + g_CSC_Row2 = { 1.0000f, 1.7720f, 0.0000f}; + break; + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P709: + // BT.709 limited + g_CSC_Row0 = { 1.1644f, 0.0000f, 1.7927f}; + g_CSC_Row1 = { 1.1644f, -0.2132f, -0.5329f}; + g_CSC_Row2 = { 1.1644f, 2.1124f, 0.0000f}; + break; + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P709: + // BT.709 full + g_CSC_Row0 = { 1.0000f, 0.0000f, 1.5748f}; + g_CSC_Row1 = { 1.0000f, -0.1873f, -0.4681f}; + g_CSC_Row2 = { 1.0000f, 1.8556f, 0.0000f}; + break; + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G22_LEFT_P2020: + // BT.2020 limited (HDR) + g_CSC_Row0 = { 1.1644f, 0.0000f, 1.6780f}; + g_CSC_Row1 = { 1.1644f, -0.1874f, -0.6504f}; + g_CSC_Row2 = { 1.1644f, 2.1418f, 0.0000f}; + break; + case DXGI_COLOR_SPACE_YCBCR_FULL_G22_LEFT_P2020: + // BT.2020 full (HDR) + g_CSC_Row0 = { 1.0000f, 0.0000f, 1.4746f}; + g_CSC_Row1 = { 1.0000f, -0.1646f, -0.5713f}; + g_CSC_Row2 = { 1.0000f, 1.8814f, 0.0000f}; + break; + case DXGI_COLOR_SPACE_YCBCR_STUDIO_G2084_LEFT_P2020: + // BT.2020 limited (PQ/HDR) + g_CSC_Row0 = { 1.1644f, 0.0000f, 1.6780f}; + g_CSC_Row1 = { 1.1644f, -0.1874f, -0.6504f}; + g_CSC_Row2 = { 1.1644f, 2.1418f, 0.0000f}; + break; + default: + // BT.601 limited + g_CSC_Row0 = { 1.1644f, 0.0000f, 1.5960f}; + g_CSC_Row1 = { 1.1644f, -0.3918f, -0.8130f}; + g_CSC_Row2 = { 1.1644f, 2.0172f, 0.0000f}; + break; + } + + m_RootConsts.g_CSC_Row0_x = g_CSC_Row0.x; + m_RootConsts.g_CSC_Row0_y = g_CSC_Row0.y; + m_RootConsts.g_CSC_Row0_z = g_CSC_Row0.z; + + m_RootConsts.g_CSC_Row1_x = g_CSC_Row1.x; + m_RootConsts.g_CSC_Row1_y = g_CSC_Row1.y; + m_RootConsts.g_CSC_Row1_z = g_CSC_Row1.z; + + m_RootConsts.g_CSC_Row2_x = g_CSC_Row2.x; + m_RootConsts.g_CSC_Row2_y = g_CSC_Row2.y; + m_RootConsts.g_CSC_Row2_z = g_CSC_Row2.z; + + if(m_IsYUV444){ + // 4:4:4 has no subsampling + m_RootConsts.g_ScaleY = 1.0f; + m_RootConsts.g_OffsetY = 0.0f; + m_RootConsts.g_OffsetU = 0.0f; + m_RootConsts.g_OffsetV = 0.0f; + } else { + // Color range and YUV Offset + m_RootConsts.g_ScaleY = 1.0f; + m_RootConsts.g_OffsetY = 0.0f; + m_RootConsts.g_OffsetU = 0.5f; + m_RootConsts.g_OffsetV = 0.5f; + } +} + +/** + * \brief Create descriptor heaps + * + * Allocates CBV/SRV/UAV, RTV, and sampler descriptor heaps + * with specified capacities. + * + * \param UINT cbvSrvUavCount Number of CBV/SRV/UAV descriptors + * \param UINT rtvCount Number of RTV descriptors + * \param UINT samplerCount Number of sampler descriptors + * \return bool True if heaps created successfully + */ +bool D3D12VideoShaders::createDescriptorHeaps(UINT cbvSrvUavCount, UINT rtvCount, UINT samplerCount) +{ + if (!m_Device) return false; + + // CBV_SRV_UAV descriptor heap + if(cbvSrvUavCount > 0){ + D3D12_DESCRIPTOR_HEAP_DESC cbvSrvUavdesc = {}; + cbvSrvUavdesc.NumDescriptors = cbvSrvUavCount; + cbvSrvUavdesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + cbvSrvUavdesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + cbvSrvUavdesc.NodeMask = 0; + m_hr = m_Device->CreateDescriptorHeap(&cbvSrvUavdesc, IID_PPV_ARGS(&m_DescriptorHeapCBV_SRV_UAV)); + if(!verifyHResult(m_hr, "m_Device->CreateDescriptorHeap(&cbvSrvUavdesc, IID_PPV_ARGS(&m_DescriptorHeapCBV_SRV_UAV));")){ + return false; + } + SDL_Log("SRV Descriptor Heap created successfully"); + m_DescriptorSizeCBV_SRV_UAV = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + SDL_Log("SRV Descriptor Size: %u", m_DescriptorSizeCBV_SRV_UAV); + } + + // RTV descriptor heap (non shader-visible) + if(rtvCount){ + D3D12_DESCRIPTOR_HEAP_DESC rtvDesc = {}; + rtvDesc.NumDescriptors = rtvCount; + rtvDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV; + rtvDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE; + m_hr = m_Device->CreateDescriptorHeap(&rtvDesc, IID_PPV_ARGS(&m_DescriptorHeapRTV)); + if(!verifyHResult(m_hr, "m_Device->CreateDescriptorHeap(&rtvDesc, IID_PPV_ARGS(&m_DescriptorHeapRTV));")){ + return false; + } + SDL_Log("RTV Descriptor Heap created successfully"); + m_DescriptorSizeRTV = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV); + SDL_Log("RTV Descriptor Size: %u", m_DescriptorSizeRTV); + } + + // Sampler descriptor heap + if(samplerCount){ + D3D12_DESCRIPTOR_HEAP_DESC samplerDesc = {}; + samplerDesc.NumDescriptors = samplerCount; + samplerDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER; + samplerDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE; + m_hr = m_Device->CreateDescriptorHeap(&samplerDesc, IID_PPV_ARGS(&m_DescriptorHeapSampler)); + if(!verifyHResult(m_hr, "m_Device->CreateDescriptorHeap(&samplerDesc, IID_PPV_ARGS(&m_DescriptorHeapSampler));")){ + return false; + } + SDL_Log("Sampler Descriptor Heap created successfully"); + m_DescriptorSizeSampler = m_Device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + SDL_Log("Sampler Descriptor Size: %u", m_DescriptorSizeSampler); + } + + return true; +} + +/** + * \brief Create a 2D texture resource + * + * Creates a committed texture resource with specified dimensions, + * format, flags, and initial state. + * + * \param ComPtr& pTexture Output texture pointer + * \param int width Texture width + * \param int height Texture height + * \param DXGI_FORMAT format Texture format + * \param D3D12_RESOURCE_FLAGS flags Resource flags + * \param D3D12_RESOURCE_STATES textureState Initial resource state + * \return bool True if texture created successfully + */ +bool D3D12VideoShaders::createTexture(ComPtr& pTexture, int width, int height, DXGI_FORMAT format, + D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES textureState) +{ + D3D12_RESOURCE_DESC desc = {}; + desc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D; + desc.Alignment = 0; + desc.Width = width; + desc.Height = height; + desc.DepthOrArraySize = 1; + desc.MipLevels = 1; + desc.Format = format; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN; + desc.Flags = flags; + + CD3DX12_HEAP_PROPERTIES heapProps(D3D12_HEAP_TYPE_DEFAULT); + + m_hr = m_Device->CreateCommittedResource( + &heapProps, + D3D12_HEAP_FLAG_NONE, + &desc, + textureState, + nullptr, + IID_PPV_ARGS(&pTexture) + ); + if(!verifyHResult(m_hr, "m_Device->CreateCommittedResource(... resource)")){ + return false; + } + return true; +} + +/** + * \brief Create constant buffer view + * + * Creates a CBV for the specified resource at the given + * descriptor heap index. + * + * \param ID3D12Resource* resource Constant buffer resource + * \param UINT descriptorIndex Heap index for CBV + * \return bool True if CBV created successfully + */ +bool D3D12VideoShaders::createCBVforResource(ID3D12Resource* resource, UINT descriptorIndex) +{ + if (!m_Device || !m_DescriptorHeapCBV_SRV_UAV || !resource) return false; + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = resource->GetGPUVirtualAddress(); + // Align to 256 bytes + UINT sizeInBytes = static_cast(resource->GetDesc().Width); + cbvDesc.SizeInBytes = (sizeInBytes + 255) & ~255u; + CD3DX12_CPU_DESCRIPTOR_HANDLE handle( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + descriptorIndex, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateConstantBufferView(&cbvDesc, handle); + return true; +} + +/** + * \brief Create shader resource view + * + * Creates an SRV for the specified texture resource with + * format and plane slice information. + * + * \param ID3D12Resource* resource Texture resource + * \param UINT descriptorIndex Heap index for SRV + * \param DXGI_FORMAT format View format + * \param UINT planeSlice Plane slice index + * \return bool True if SRV created successfully + */ +bool D3D12VideoShaders::createSRVforResource(ID3D12Resource* resource, UINT descriptorIndex, DXGI_FORMAT format, UINT planeSlice) +{ + if (!m_Device || !m_DescriptorHeapCBV_SRV_UAV) return false; + D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {}; + srvDesc.Format = format; + srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = 1; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.PlaneSlice = planeSlice; + srvDesc.Texture2D.ResourceMinLODClamp = 0.0f; + CD3DX12_CPU_DESCRIPTOR_HANDLE handle( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + descriptorIndex, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateShaderResourceView(resource, &srvDesc, handle); + return true; +} + +/** + * \brief Create unordered access view + * + * Creates a UAV for the specified texture resource with + * format and plane slice information. + * + * \param ID3D12Resource* resource Texture resource + * \param UINT descriptorIndex Heap index for UAV + * \param DXGI_FORMAT format View format + * \param UINT planeSlice Plane slice index + * \return bool True if UAV created successfully + */ +bool D3D12VideoShaders::createUAVforResource(ID3D12Resource* resource, UINT descriptorIndex, DXGI_FORMAT format, UINT planeSlice) +{ + if (!m_Device || !m_DescriptorHeapCBV_SRV_UAV) return false; + D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + uavDesc.Format = format; + uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + uavDesc.Texture2D.PlaneSlice = planeSlice; + CD3DX12_CPU_DESCRIPTOR_HANDLE handle( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + descriptorIndex, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateUnorderedAccessView(resource, nullptr, &uavDesc, handle); + return true; +} + +/** + * \brief Create render target view + * + * Creates an RTV for the specified resource in the RTV heap. + * + * \param ID3D12Resource* resource Texture resource + * \param UINT rtvIndex RTV heap index + * \param DXGI_FORMAT format View format + * \param UINT planeSlice Plane slice index + * \return bool True if RTV created successfully + */ +bool D3D12VideoShaders::createRTVforResource(ID3D12Resource* resource, UINT rtvIndex, DXGI_FORMAT format, UINT planeSlice) +{ + if (!m_Device || !m_DescriptorHeapRTV) return false; + D3D12_RENDER_TARGET_VIEW_DESC rtvDesc = {}; + rtvDesc.Format = format; + rtvDesc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.PlaneSlice = planeSlice; + CD3DX12_CPU_DESCRIPTOR_HANDLE handle(m_DescriptorHeapRTV->GetCPUDescriptorHandleForHeapStart(), rtvIndex, m_DescriptorSizeRTV); + m_Device->CreateRenderTargetView(resource, &rtvDesc, handle); + return true; +} + +/** + * \brief Initialize YUV to RGB conversion pipeline + * + * Compiles vertex and pixel shaders, creates root signature with + * SRV descriptors and root constants, and sets up graphics PSO. + * + * \return bool True if initialization succeeded + */ +bool D3D12VideoShaders::initializeCONVERT_PS() +{ + // Initialize RootConts + initializeRootConsts(); + + // 2 SRV heaps / 1 RTV heap + createDescriptorHeaps(2, 1, 0); + + // Create SRVs for m_TextureIn + if (!updateShaderResourceView(m_TextureIn.Get())) { + return false; + } + + // Create RTV descriptor for m_TextureOut at RTV index 0 + if (!createRTVforResource(m_TextureOut.Get(), 0, m_TextureOut.Get()->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createRTVforResource failed"); + return false; + } + SDL_Log("Created RTV for output texture"); + + ComPtr compiler; + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + ComPtr includeHandler = new QtIncludeHandler(); + ComPtr result; + + // Vertex shader + QFile fileVS(":/enhancer/yuv_to_rgb_ps.hlsl"); + if (!fileVS.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open yuv_to_rgb_ps.hlsl for Vertex shader"); + return false; + } + QByteArray hlslSourceVS = fileVS.readAll(); + fileVS.close(); + + DxcBuffer sourceBufferVS = {}; + sourceBufferVS.Ptr = hlslSourceVS.data(); + sourceBufferVS.Size = hlslSourceVS.size(); + sourceBufferVS.Encoding = DXC_CP_UTF8; + + m_Args = { + L"-E", L"mainVS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"vs_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + m_Args.push_back(L"-T"); + m_Args.push_back(L"vs_6_0"); + } + + m_hr = compiler->Compile( + &sourceBufferVS, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBufferVS)")){ + return false; + } + + if(result){ + ComPtr errorsBlob; + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "VS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobVS; + ComPtr shaderNameVS; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobVS), &shaderNameVS); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobVS || shaderBlobVS->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob Vertex shader is empty!"); + return false; + } + SDL_Log("Vertex Shader compiled successfully"); + + // Pixel shader + QFile filePS(":/enhancer/yuv_to_rgb_ps.hlsl"); + if (!filePS.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open yuv_to_rgb_ps.hlsl for Pixel shader"); + return false; + } + QByteArray hlslSourcePS = filePS.readAll(); + filePS.close(); + + DxcBuffer sourceBufferPS = {}; + sourceBufferPS.Ptr = hlslSourcePS.data(); + sourceBufferPS.Size = hlslSourcePS.size(); + sourceBufferPS.Encoding = DXC_CP_UTF8; + + m_Args = { + L"-E", L"mainPS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"ps_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + m_Args.push_back(L"-T"); + m_Args.push_back(L"ps_6_0"); + } + + m_hr = compiler->Compile( + &sourceBufferPS, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBufferPS)")){ + return false; + } + + if(result){ + ComPtr errorsBlob; + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "PS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobPS; + ComPtr shaderNamePS; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobPS), &shaderNamePS); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobPS || shaderBlobPS->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob Pixel shader is empty!"); + return false; + } + SDL_Log("Pixel Shader compiled successfully"); + + // Descriptor Range + CD3DX12_DESCRIPTOR_RANGE1 srvRange = {}; + srvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0); // 2 SRV, t0 (Y) + t1 (UV) + + // Root Parameters : descriptor table (index 0) + root constants (index 1) + CD3DX12_ROOT_PARAMETER1 rootParameters[2] = {}; + rootParameters[0].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_PIXEL); + + // Add root constants: 32 dwords mapped to register b0 in shader + const UINT NUM_ROOT_DWORDS = 32; + rootParameters[1].InitAsConstants(NUM_ROOT_DWORDS, 0, 0, D3D12_SHADER_VISIBILITY_PIXEL); + + // Static sampler + D3D12_STATIC_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + samplerDesc.ShaderRegister = 0; // s0 + samplerDesc.RegisterSpace = 0; + samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + // Root Signature + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; + rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 1, &samplerDesc, + rootSignatureFlags); + + ComPtr signature; + ComPtr error; + m_hr = D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, + D3D_ROOT_SIGNATURE_VERSION_1_1, + &signature, &error); + + if(!verifyHResult(m_hr, "D3DX12SerializeVersionedRootSignature(... rootSignatureDesc)")){ + if (error) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Root signature serialization error: %s", + (char*)error->GetBufferPointer()); + } + return false; + } + + m_hr = m_Device->CreateRootSignature(0, signature->GetBufferPointer(), + signature->GetBufferSize(), + IID_PPV_ARGS(&m_RootSignature)); + if(!verifyHResult(m_hr, "m_Device->CreateRootSignature(... m_RootSignature)")){ + return false; + } + SDL_Log("Root Signature created successfully"); + + // Pipeline State Object + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = m_RootSignature.Get(); + psoDesc.VS = CD3DX12_SHADER_BYTECODE(shaderBlobVS->GetBufferPointer(), shaderBlobVS->GetBufferSize()); + psoDesc.PS = CD3DX12_SHADER_BYTECODE(shaderBlobPS->GetBufferPointer(), shaderBlobPS->GetBufferSize()); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + psoDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + psoDesc.DepthStencilState.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + psoDesc.InputLayout = { nullptr, 0 }; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_TextureOut->GetDesc().Format; + psoDesc.SampleDesc.Count = 1; + psoDesc.SampleDesc.Quality = 0; + psoDesc.SampleMask = UINT_MAX; + + m_hr = m_Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState)); + if(!verifyHResult(m_hr, "m_Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState));")){ + return false; + } + SDL_Log("Pipeline State Object created successfully"); + + SDL_Log("initializeCONVERT completed successfully"); + + return true; +} + +/** + * \brief Initialize NVIDIA Image Scaling pipeline + * + * Compiles NIS compute shader with optimal block dimensions, + * creates coefficient textures, and configures upscaling or sharpening. + * + * \param bool isUpscaling True for upscaling mode, false for sharpening + * \return bool True if initialization succeeded + */ +bool D3D12VideoShaders::initializeNIS(bool isUpscaling) +{ + // Compile compute shader (NIS_Main.hlsl) + QFile file(":/enhancer/NIS_Main.hlsl"); + if (!file.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open NIS_Main.hlsl"); + return false; + } + QByteArray hlslSource = file.readAll(); + file.close(); + + DxcBuffer sourceBuffer = {}; + sourceBuffer.Ptr = hlslSource.data(); + sourceBuffer.Size = hlslSource.size(); + sourceBuffer.Encoding = DXC_CP_UTF8; + + ComPtr compiler; + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + + // Default on NVIDIA_Generic + NISGPUArchitecture GPUArchitecture = NISGPUArchitecture::NVIDIA_Generic; + if(m_AdvancedShader){ + GPUArchitecture = NISGPUArchitecture::NVIDIA_Generic_fp16; + } else if(m_VideoEnhancement->isVendorAMD()){ + GPUArchitecture = NISGPUArchitecture::AMD_Generic; + } else if(m_VideoEnhancement->isVendorIntel()){ + GPUArchitecture = NISGPUArchitecture::Intel_Generic; + } else if(m_VideoEnhancement->isVendorNVIDIA()){ + GPUArchitecture = NISGPUArchitecture::NVIDIA_Generic; + } + + NISOptimizer opt(true, GPUArchitecture); + uint32_t blockWidth = opt.GetOptimalBlockWidth(); + uint32_t blockHeight = opt.GetOptimalBlockHeight(); + uint32_t threadGroupSize = opt.GetOptimalThreadGroupSize(); + + m_DispatchX = static_cast(std::ceil(m_OutWidth / float(blockWidth))); + m_DispatchY = static_cast(std::ceil(m_OutHeight / float(blockHeight))); + + m_NIS_SCALER = std::wstring(L"NIS_SCALER=") + (isUpscaling ? L"1" : L"0"); + m_NIS_HDR_MODE = std::wstring(L"NIS_HDR_MODE=") + (m_IsHDR ? L"2" : L"0"); + m_NIS_BLOCK_WIDTH = std::wstring(L"NIS_BLOCK_WIDTH=") + std::to_wstring(blockWidth); + m_NIS_BLOCK_HEIGHT = std::wstring(L"NIS_BLOCK_HEIGHT=") + std::to_wstring(blockHeight); + m_NIS_THREAD_GROUP_SIZE = std::wstring(L"NIS_THREAD_GROUP_SIZE=") + std::to_wstring(threadGroupSize); + + m_Args = { + L"-E", L"main", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + L"-D", m_NIS_SCALER.c_str(), + L"-D", m_NIS_HDR_MODE.c_str(), + L"-D", m_NIS_BLOCK_WIDTH.c_str(), + L"-D", m_NIS_BLOCK_HEIGHT.c_str(), + L"-D", m_NIS_THREAD_GROUP_SIZE.c_str(), + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"NIS_HLSL_6_2=1"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"NIS_USE_HALF_PRECISION=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_0"); + } + + ComPtr includeHandler = new QtIncludeHandler(); + + ComPtr result; + m_hr = compiler->Compile( + &sourceBuffer, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBuffer)")){ + return false; + } + + if(result){ + ComPtr errorsBlob; + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlob; + ComPtr shaderName; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlob), &shaderName); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlob || shaderBlob->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob is empty!"); + return false; + } + SDL_Log("Compute Shader compiled successfully"); + + // Create buffer m_stagingBuffer + NISCreateBuffer(sizeof(NISConfig), D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ, &m_StagingBuffer); + + // Create buffer m_constatBuffer + NISCreateBuffer(sizeof(NISConfig), D3D12_HEAP_TYPE_DEFAULT, D3D12_RESOURCE_STATE_COMMON, &m_ConstatBuffer); + + // Define root table layout + constexpr uint32_t nParams = 6; + CD3DX12_DESCRIPTOR_RANGE descriptorRange[nParams] = {}; + descriptorRange[0] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0); + descriptorRange[1] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0); + descriptorRange[2] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); + descriptorRange[3] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0); + descriptorRange[4] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1); + descriptorRange[5] = CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 2); + + CD3DX12_ROOT_PARAMETER rootParams[nParams] = {}; + rootParams[0].InitAsDescriptorTable(1, &descriptorRange[0]); + rootParams[1].InitAsDescriptorTable(1, &descriptorRange[1]); + rootParams[2].InitAsDescriptorTable(1, &descriptorRange[2]); + rootParams[3].InitAsDescriptorTable(1, &descriptorRange[3]); + rootParams[4].InitAsDescriptorTable(1, &descriptorRange[4]); + rootParams[5].InitAsDescriptorTable(1, &descriptorRange[5]); + + // Create the root signature + D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc; + rootSignatureDesc.NumParameters = nParams; + rootSignatureDesc.pParameters = rootParams; + rootSignatureDesc.NumStaticSamplers = 0; + rootSignatureDesc.pStaticSamplers = nullptr; + rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + ComPtr serializedSignature; + ComPtr error; + m_hr = D3D12SerializeRootSignature( + &rootSignatureDesc, + D3D_ROOT_SIGNATURE_VERSION_1, + &serializedSignature, + &error); + if(!verifyHResult(m_hr, "D3D12SerializeRootSignature(... rootSignatureDesc)")){ + if (error) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Root signature serialization error: %s", + (char*)error->GetBufferPointer()); + } + return false; + } + m_hr = m_Device->CreateRootSignature( + 0, + serializedSignature->GetBufferPointer(), + serializedSignature->GetBufferSize(), + IID_PPV_ARGS(&m_RootSignature)); + m_RootSignature->SetName(L"NVScaler"); + + // Create compute pipeline state + D3D12_COMPUTE_PIPELINE_STATE_DESC descComputePSO = {}; + descComputePSO.pRootSignature = m_RootSignature.Get(); + descComputePSO.CS.pShaderBytecode = shaderBlob->GetBufferPointer(); + descComputePSO.CS.BytecodeLength = shaderBlob->GetBufferSize(); + + m_hr = m_Device->CreateComputePipelineState(&descComputePSO, IID_PPV_ARGS(&m_PipelineState)); + if(!verifyHResult(m_hr, "m_Device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState));")){ + return false; + } + m_PipelineState->SetName(L"NVScaler Compute PSO"); + + m_RowPitch = kFilterSize * 4; + const int rowPitchAligned = (m_RowPitch + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1) / D3D12_TEXTURE_DATA_PITCH_ALIGNMENT * D3D12_TEXTURE_DATA_PITCH_ALIGNMENT; + const int coefSize = rowPitchAligned * kPhaseCount; + + // Create buffer texture Scaler + NISCreateBuffer(coefSize, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ, &m_CoefScalerUpload); + NISCreateTexture2D(kFilterSize / 4, kPhaseCount, + DXGI_FORMAT_R16G16B16A16_FLOAT, + D3D12_RESOURCE_STATE_COMMON, &m_CoefScaler); + NISCreateAlignedCoefficients( + (uint16_t*)coef_scale_fp16, + m_CoefScalerHost, + rowPitchAligned); + + // Create buffer texture USM + NISCreateBuffer(coefSize, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ, &m_CoefUSMUpload); + NISCreateTexture2D(kFilterSize / 4, kPhaseCount, + DXGI_FORMAT_R16G16B16A16_FLOAT, + D3D12_RESOURCE_STATE_COMMON, &m_CoefUSM); + NISCreateAlignedCoefficients( + (uint16_t*)coef_usm_fp16, + m_CoefUSMHost, + rowPitchAligned); + + // Create: 6 SRV descriptor heaps / 1 Sampler descriptor heap + createDescriptorHeaps(6, 0, 1); + + // Sampler + D3D12_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + CD3DX12_CPU_DESCRIPTOR_HANDLE handleSampler( + m_DescriptorHeapSampler->GetCPUDescriptorHandleForHeapStart(), + 0, + m_DescriptorSizeSampler); + m_Device->CreateSampler(&samplerDesc, handleSampler); + + // CBV + D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc = {}; + cbvDesc.BufferLocation = m_ConstatBuffer.Get()->GetGPUVirtualAddress(); + cbvDesc.SizeInBytes = sizeof(NISConfig); + CD3DX12_CPU_DESCRIPTOR_HANDLE handleCBV( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + 1, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateConstantBufferView(&cbvDesc, handleCBV); + + // TextureIn + CD3DX12_CPU_DESCRIPTOR_HANDLE handleTextureIn( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + 2, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateShaderResourceView(m_TextureIn.Get(), nullptr, handleTextureIn); + + // TextureOut + CD3DX12_CPU_DESCRIPTOR_HANDLE handleTextureOut( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + 3, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateShaderResourceView(m_TextureOut.Get(), nullptr, handleTextureOut); + + // CoefScaler + CD3DX12_CPU_DESCRIPTOR_HANDLE handleCoefScaler( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + 4, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateShaderResourceView(m_CoefScaler.Get(), nullptr, handleCoefScaler); + + // CoefUSM + CD3DX12_CPU_DESCRIPTOR_HANDLE handleCoefUSM( + m_DescriptorHeapCBV_SRV_UAV->GetCPUDescriptorHandleForHeapStart(), + 5, + m_DescriptorSizeCBV_SRV_UAV); + m_Device->CreateShaderResourceView(m_CoefUSM.Get(), nullptr, handleCoefUSM); + + // Initialize NVScaler + if(isUpscaling){ + NVScalerUpdateConfig(m_ConfigNIS, 0.15f, + 0, 0, m_InWidth, m_InHeight, m_InWidth, m_InHeight, + 0, 0, m_OutWidth, m_OutHeight, m_OutWidth, m_OutHeight, + m_IsHDR ? NISHDRMode::PQ : NISHDRMode::None); + } else { + NVSharpenUpdateConfig(m_ConfigNIS, 0.35f, + 0, 0, m_InWidth, m_InHeight, m_InWidth, m_InHeight, + 0, 0, m_IsHDR ? NISHDRMode::PQ : NISHDRMode::None); + } + + // Copy m_config (data) to m_constatBuffer (Constant Buffer) + NISUploadBufferData(&m_ConfigNIS, sizeof(NISConfig), m_ConstatBuffer.Get(), m_StagingBuffer.Get()); + + + // Copy m_coefScalerHost (data) to m_coefScaler (Texture) + NISUploadTextureData((void*)m_CoefScalerHost.data(), sizeof(m_CoefScalerHost[0]) * uint32_t(m_CoefScalerHost.size()), + m_RowPitch, m_CoefScaler.Get(), m_CoefScalerUpload.Get()); + + // Copy m_coefUSMHost (data) to m_coefUSM (Texture) + NISUploadTextureData((void*)m_CoefUSMHost.data(), sizeof(m_CoefUSMHost[0]) * uint32_t(m_CoefUSMHost.size()), + m_RowPitch, m_CoefUSM.Get(), m_CoefUSMUpload.Get()); + + return true; +} + +/** + * \brief Initialize FidelityFX Super Resolution 1.0 pipeline + * + * Compiles EASU (upscaler) and RCAS (sharpener) compute shaders, + * creates intermediate texture, and sets up two-pass pipeline. + * + * \return bool True if initialization succeeded + */ +bool D3D12VideoShaders::initializeFSR1() +{ + // FSR1 Documentation implementation: + // https://github.com/GPUOpen-Effects/FidelityFX-FSR/blob/master/docs/FidelityFX-FSR-Overview-Integration.pdf + + // 2 SRV heaps + 2 UAV heaps + createDescriptorHeaps(4, 0, 0); + + // Intermediate Texture from EASU to RCAS + createTexture(m_TextureInterm, + m_OutWidth, + m_OutHeight, + m_TextureOut->GetDesc().Format, + D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS); + + // Create SRV for m_TextureIn (RGB) + if (!updateShaderResourceView(m_TextureIn.Get())) { + return false; + } + + // Create SRV descriptor for m_TextureInterm + if (!createSRVforResource(m_TextureInterm.Get(), 1, m_TextureInterm->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createSRVforResource failed"); + return false; + } + SDL_Log("Created SRV for intermediate texture"); + + // Create UAV descriptor for m_TextureInterm + if (!createUAVforResource(m_TextureInterm.Get(), 2, m_TextureInterm->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createUAVforResource failed"); + return false; + } + SDL_Log("Created UAV for intermediate texture"); + + // Create UAV descriptor for m_TextureOut + if (!createUAVforResource(m_TextureOut.Get(), 3, m_TextureOut->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createUAVforResource failed"); + return false; + } + SDL_Log("Created UAV for output texture"); + + m_DispatchX = static_cast(std::ceil(m_OutWidth / float(16))); + m_DispatchY = static_cast(std::ceil(m_OutHeight / float(16))); + + ComPtr compiler; + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + ComPtr includeHandler = new QtIncludeHandler(); + ComPtr result; + ComPtr errorsBlob; + + // FSR1 EASU (Upscaler) + FsrEasuCon( + reinterpret_cast(m_EASUConstants.const0), + reinterpret_cast(m_EASUConstants.const1), + reinterpret_cast(m_EASUConstants.const2), + reinterpret_cast(m_EASUConstants.const3), + static_cast(m_InWidth), + static_cast(m_InHeight), + static_cast(m_InWidth), + static_cast(m_InHeight), + static_cast(m_OutWidth), + static_cast(m_OutHeight)); + + // EASU Shader Preparation + // Compile compute shader (FSR_Pass.hlsl) + QFile file(":/enhancer/FSR_Pass.hlsl"); + if (!file.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open FSR_Pass.hlsl"); + return false; + } + QByteArray hlslSource = file.readAll(); + file.close(); + + DxcBuffer sourceBuffer = {}; + sourceBuffer.Ptr = hlslSource.data(); + sourceBuffer.Size = hlslSource.size(); + sourceBuffer.Encoding = DXC_CP_UTF8; + + m_Args = { + L"-E", L"mainCS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + L"-HV", L"2018", + L"-D", L"APPLY_EASU=1", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_0"); + } + + m_hr = compiler->Compile( + &sourceBuffer, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBuffer)")){ + return false; + } + + if(result){ + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobEASU; + ComPtr shaderNameEASU; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobEASU), &shaderNameEASU); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobEASU || shaderBlobEASU->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob is empty!"); + return false; + } + SDL_Log("FSR1 EASU Shader compiled successfully"); + + // FSR1 RCAS (Sharpener) + AF1 sharpeness = 0.75f; + FsrRcasCon( + reinterpret_cast(m_RCASConstants.const0), + sharpeness); + + m_Args = { + L"-E", L"mainCS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + L"-HV", L"2018", + L"-D", L"APPLY_RCAS=1", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_0"); + } + + m_hr = compiler->Compile( + &sourceBuffer, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBuffer)")){ + return false; + } + + if(result){ + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobRCAS; + ComPtr shaderNameRCAS; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobRCAS), &shaderNameRCAS); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobRCAS || shaderBlobRCAS->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob is empty!"); + return false; + } + SDL_Log("FSR1 RCAS Shader compiled successfully"); + + + // Descriptor Range + CD3DX12_DESCRIPTOR_RANGE1 srvRange = {}; + srvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); // 1 SRV, t0 (RGB) + + // Descriptor Range + CD3DX12_DESCRIPTOR_RANGE1 uavRange = {}; + uavRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0); // 1 UAV, u0 (RGB) + + // Root Parameters : descriptor table (index 0) + root constants (index 1) + CD3DX12_ROOT_PARAMETER1 rootParameters[3] = {}; + rootParameters[0].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_ALL); + rootParameters[1].InitAsDescriptorTable(1, &uavRange, D3D12_SHADER_VISIBILITY_ALL); + + // Add root constants: 32 dwords mapped to register b0 in shader + const UINT NUM_ROOT_DWORDS = 32; + rootParameters[2].InitAsConstants(NUM_ROOT_DWORDS, 0, 0, D3D12_SHADER_VISIBILITY_ALL); + + // Sampler + D3D12_STATIC_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + samplerDesc.ShaderRegister = 0; // s0 + samplerDesc.RegisterSpace = 0; + samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Signature + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 1, &samplerDesc, + rootSignatureFlags); + + ComPtr signature; + ComPtr error; + m_hr = D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, + D3D_ROOT_SIGNATURE_VERSION_1_1, + &signature, &error); + + if(!verifyHResult(m_hr, "D3DX12SerializeVersionedRootSignature(... rootSignatureDesc)")){ + if (error) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Root signature serialization error: %s", + (char*)error->GetBufferPointer()); + } + return false; + } + + m_hr = m_Device->CreateRootSignature(0, signature->GetBufferPointer(), + signature->GetBufferSize(), + IID_PPV_ARGS(&m_RootSignature)); + if(!verifyHResult(m_hr, "m_Device->CreateRootSignature(... m_RootSignature)")){ + return false; + } + SDL_Log("Root Signature created successfully"); + + // --- Create Compute PSO --- + + // FSR1 EASU (Upscaler) + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDescEASU = {}; + psoDescEASU.pRootSignature = m_RootSignature.Get(); + psoDescEASU.CS = CD3DX12_SHADER_BYTECODE(shaderBlobEASU->GetBufferPointer(), shaderBlobEASU->GetBufferSize()); + psoDescEASU.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + m_hr = m_Device->CreateComputePipelineState(&psoDescEASU, IID_PPV_ARGS(&m_PipelineStateEASU)); + if(!verifyHResult(m_hr, "m_Device->CreateComputePipelineState(&psoDescEASU, IID_PPV_ARGS(&m_PipelineStateEASU));")){ + return false; + } + + // FSR1 RCAS (Sharpener) + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDescRCAS = {}; + psoDescRCAS.pRootSignature = m_RootSignature.Get(); + psoDescRCAS.CS = CD3DX12_SHADER_BYTECODE(shaderBlobRCAS->GetBufferPointer(), shaderBlobRCAS->GetBufferSize()); + psoDescRCAS.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + m_hr = m_Device->CreateComputePipelineState(&psoDescRCAS, IID_PPV_ARGS(&m_PipelineStateRCAS)); + if(!verifyHResult(m_hr, "m_Device->CreateComputePipelineState(&psoDescRCAS, IID_PPV_ARGS(&m_PipelineStateRCAS));")){ + return false; + } + + return true; +} + +/** + * \brief Initialize Snapdragon Gaming Super Resolution pipeline + * + * Compiles GSRS pixel shader. + * Made for Snapdragon GPUs (Adreno). + * Lower quality than FSR1, but fast as 1-Pass only. + * + * \return bool True if initialization succeeded + */ +bool D3D12VideoShaders::initializeSGSR1() +{ + // 1 SRV heap / 1 RTV heap + createDescriptorHeaps(1, 1, 0); + + // Create SRVs for m_TextureIn + if (!updateShaderResourceView(m_TextureIn.Get())) { + return false; + } + + // Create RTV descriptor for m_TextureOut at RTV index 0 + if (!createRTVforResource(m_TextureOut.Get(), 0, m_TextureOut.Get()->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createRTVforResource failed"); + return false; + } + SDL_Log("Created RTV for output texture"); + + ComPtr compiler; + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + ComPtr includeHandler = new QtIncludeHandler(); + ComPtr result; + + // Vertex shader + QFile fileVS(":/enhancer/sgsr1_shader.hlsl"); + if (!fileVS.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open sgsr1_shader.hlsl for Vertex shader"); + return false; + } + QByteArray hlslSourceVS = fileVS.readAll(); + fileVS.close(); + + DxcBuffer sourceBufferVS = {}; + sourceBufferVS.Ptr = hlslSourceVS.data(); + sourceBufferVS.Size = hlslSourceVS.size(); + sourceBufferVS.Encoding = DXC_CP_UTF8; + + m_Args = { + L"-E", L"mainVS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"vs_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + m_Args.push_back(L"-T"); + m_Args.push_back(L"vs_6_0"); + } + + m_hr = compiler->Compile( + &sourceBufferVS, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBufferVS)")){ + return false; + } + + if(result){ + ComPtr errorsBlob; + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "VS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobVS; + ComPtr shaderNameVS; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobVS), &shaderNameVS); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobVS || shaderBlobVS->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob Vertex shader is empty!"); + return false; + } + SDL_Log("Vertex Shader compiled successfully"); + + // Pixel shader + QFile filePS(":/enhancer/sgsr1_shader.hlsl"); + if (!filePS.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open sgsr1_shader.hlsl for Pixel shader"); + return false; + } + QByteArray hlslSourcePS = filePS.readAll(); + filePS.close(); + + DxcBuffer sourceBufferPS = {}; + sourceBufferPS.Ptr = hlslSourcePS.data(); + sourceBufferPS.Size = hlslSourcePS.size(); + sourceBufferPS.Encoding = DXC_CP_UTF8; + + m_Args = { + L"-E", L"mainPS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"ps_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + m_Args.push_back(L"-T"); + m_Args.push_back(L"ps_6_0"); + } + + m_hr = compiler->Compile( + &sourceBufferPS, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBufferPS)")){ + return false; + } + + if(result){ + ComPtr errorsBlob; + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "PS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobPS; + ComPtr shaderNamePS; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobPS), &shaderNamePS); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobPS || shaderBlobPS->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob Pixel shader is empty!"); + return false; + } + SDL_Log("Pixel Shader compiled successfully"); + + // Descriptor Range + CD3DX12_DESCRIPTOR_RANGE1 srvRange = {}; + srvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); // 1 SRV, t0 (RGB) + + // Root Parameters : descriptor table (index 0) + CD3DX12_ROOT_PARAMETER1 rootParameters[2] = {}; + // index 0 : CBV b0 → ViewportInfo + rootParameters[0].InitAsConstantBufferView( + 0, 0, + D3D12_ROOT_DESCRIPTOR_FLAG_NONE, + D3D12_SHADER_VISIBILITY_PIXEL); + // index 1 : SRV descriptor table t0 + rootParameters[1].InitAsDescriptorTable( + 1, &srvRange, + D3D12_SHADER_VISIBILITY_PIXEL); + + // Static sampler + D3D12_STATIC_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_MIN_MAG_MIP_LINEAR; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + samplerDesc.ShaderRegister = 0; // s0 + samplerDesc.RegisterSpace = 0; + samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_PIXEL; + + // Root Signature + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = + D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT | + D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS | + D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS; + rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 1, &samplerDesc, + rootSignatureFlags); + + ComPtr signature; + ComPtr error; + m_hr = D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, + D3D_ROOT_SIGNATURE_VERSION_1_1, + &signature, &error); + + if(!verifyHResult(m_hr, "D3DX12SerializeVersionedRootSignature(... rootSignatureDesc)")){ + if (error) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Root signature serialization error: %s", + (char*)error->GetBufferPointer()); + } + return false; + } + + m_hr = m_Device->CreateRootSignature(0, signature->GetBufferPointer(), + signature->GetBufferSize(), + IID_PPV_ARGS(&m_RootSignature)); + if(!verifyHResult(m_hr, "m_Device->CreateRootSignature(... m_RootSignature)")){ + return false; + } + SDL_Log("Root Signature created successfully"); + + // Viewport constant + // Aligned to 256 bytes (required for D3D12 CBV) + const UINT cbSize = (sizeof(SGSRConstants) + 255) & ~255; + + CD3DX12_HEAP_PROPERTIES heapPropsCB(D3D12_HEAP_TYPE_UPLOAD); + CD3DX12_RESOURCE_DESC resDescCB = CD3DX12_RESOURCE_DESC::Buffer(cbSize); + + m_hr = m_Device->CreateCommittedResource( + &heapPropsCB, + D3D12_HEAP_FLAG_NONE, + &resDescCB, + D3D12_RESOURCE_STATE_GENERIC_READ, + nullptr, + IID_PPV_ARGS(&m_SGSRConstantBuffer)); + if (!verifyHResult(m_hr, "CreateCommittedResource SGSRConstantBuffer")) { + return false; + } + + m_SGSRConstants = { + 1.0f / static_cast(m_InWidth), // con1.x = 1/inputWidth + 1.0f / static_cast(m_InHeight), // con1.y = 1/inputHeight + static_cast(m_InWidth), // con1.z = inputWidth + static_cast(m_InHeight) // con1.w = inputHeight + }; + + // Map → memcpy → Unmap + void* pDataCB = nullptr; + CD3DX12_RANGE readRangeCB(0, 0); + m_SGSRConstantBuffer->Map(0, &readRangeCB, &pDataCB); + memcpy(pDataCB, &m_SGSRConstants, sizeof(SGSRConstants)); + m_SGSRConstantBuffer->Unmap(0, nullptr); + + // Pipeline State Object + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = m_RootSignature.Get(); + psoDesc.VS = CD3DX12_SHADER_BYTECODE(shaderBlobVS->GetBufferPointer(), shaderBlobVS->GetBufferSize()); + psoDesc.PS = CD3DX12_SHADER_BYTECODE(shaderBlobPS->GetBufferPointer(), shaderBlobPS->GetBufferSize()); + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = FALSE; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_ALWAYS; + psoDesc.DepthStencilState.FrontFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + psoDesc.DepthStencilState.BackFace.StencilFunc = D3D12_COMPARISON_FUNC_ALWAYS; + psoDesc.InputLayout = { nullptr, 0 }; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = m_TextureOut->GetDesc().Format; + psoDesc.SampleDesc.Count = 1; + psoDesc.SampleDesc.Quality = 0; + psoDesc.SampleMask = UINT_MAX; + + m_hr = m_Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState)); + if(!verifyHResult(m_hr, "m_Device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState));")){ + return false; + } + SDL_Log("Pipeline State Object created successfully"); + + SDL_Log("initializeSGSR1 completed successfully"); + + return true; +} + +/** + * \brief Initialize RCAS sharpening pipeline + * + * Compiles RCAS compute shader and creates pipeline for + * standalone sharpening without upscaling. + * + * \return bool True if initialization succeeded + */ +bool D3D12VideoShaders::initializeRCAS() +{ + // FSR1 Documentation implementation: + // https://github.com/GPUOpen-Effects/FidelityFX-FSR/blob/master/docs/FidelityFX-FSR-Overview-Integration.pdf + + // 1 SRV heap + 1 UAV heap + createDescriptorHeaps(2, 0, 0); + + // Create SRV for m_TextureIn (RGB) + if (!updateShaderResourceView(m_TextureIn.Get())) { + return false; + } + + // Create UAV descriptor for m_TextureOut + if (!createUAVforResource(m_TextureOut.Get(), 1, m_TextureOut->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createUAVforResource failed"); + return false; + } + SDL_Log("Created UAV for output texture"); + + m_DispatchX = static_cast(std::ceil(m_OutWidth / float(16))); + m_DispatchY = static_cast(std::ceil(m_OutHeight / float(16))); + + ComPtr compiler; + DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&compiler)); + ComPtr includeHandler = new QtIncludeHandler(); + ComPtr result; + ComPtr errorsBlob; + + // FSR1 RCAS (Sharpener) + AF1 sharpeness = 0.6f; + FsrRcasCon( + reinterpret_cast(m_RCASConstants.const0), + sharpeness); + + // RCAS Shader Preparation + // Compile compute shader (FSR_Pass.hlsl) + QFile file(":/enhancer/FSR_Pass.hlsl"); + if (!file.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open FSR_Pass.hlsl"); + return false; + } + QByteArray hlslSource = file.readAll(); + file.close(); + + DxcBuffer sourceBuffer = {}; + sourceBuffer.Ptr = hlslSource.data(); + sourceBuffer.Size = hlslSource.size(); + sourceBuffer.Encoding = DXC_CP_UTF8; + + m_Args = { + L"-E", L"mainCS", + L"-O3", + L"-Qstrip_reflect", + L"-Qstrip_debug", + L"-HV", L"2018", + L"-D", L"APPLY_RCAS=1", + }; + if(m_AdvancedShader){ + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_2"); + m_Args.push_back(L"-D"); + m_Args.push_back(L"ADVANCED_SHADER=1"); + m_Args.push_back(L"-enable-16bit-types"); + } else { + m_Args.push_back(L"-T"); + m_Args.push_back(L"cs_6_0"); + } + + m_hr = compiler->Compile( + &sourceBuffer, + m_Args.data(), + (UINT32)m_Args.size(), + includeHandler.Get(), + IID_PPV_ARGS(&result)); + if(!verifyHResult(m_hr, "compiler->Compile(... sourceBuffer)")){ + return false; + } + + if(result){ + m_hr = result->GetErrorBuffer(&errorsBlob); + if(!verifyHResult(m_hr, "result->GetErrorBuffer(&errorsBlob)")){ + if (errorsBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CS compile error: %s", + (char*)errorsBlob->GetBufferPointer()); + } + return false; + } + } + + ComPtr shaderBlobRCAS; + ComPtr shaderNameRCAS; + m_hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&shaderBlobRCAS), &shaderNameRCAS); + if (!verifyHResult(m_hr, "result->GetOutput(DXC_OUT_OBJECT, ...)")) { + return false; + } + if (!shaderBlobRCAS || shaderBlobRCAS->GetBufferSize() == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Shader blob is empty!"); + return false; + } + SDL_Log("FSR1 RCAS Shader compiled successfully"); + + + // Descriptor Range + CD3DX12_DESCRIPTOR_RANGE1 srvRange = {}; + srvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); // 1 SRV, t0 (RGB) + + // Descriptor Range + CD3DX12_DESCRIPTOR_RANGE1 uavRange = {}; + uavRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0); // 1 UAV, u0 (RGB) + + // Root Parameters : descriptor table (index 0) + root constants (index 1) + CD3DX12_ROOT_PARAMETER1 rootParameters[3] = {}; + rootParameters[0].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_ALL); + rootParameters[1].InitAsDescriptorTable(1, &uavRange, D3D12_SHADER_VISIBILITY_ALL); + + // Add root constants: 32 dwords mapped to register b0 in shader + const UINT NUM_ROOT_DWORDS = 32; + rootParameters[2].InitAsConstants(NUM_ROOT_DWORDS, 0, 0, D3D12_SHADER_VISIBILITY_ALL); + + // Sampler + D3D12_STATIC_SAMPLER_DESC samplerDesc = {}; + samplerDesc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT; + samplerDesc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_CLAMP; + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = 1; + samplerDesc.ComparisonFunc = D3D12_COMPARISON_FUNC_ALWAYS; + samplerDesc.BorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK; + samplerDesc.MinLOD = 0.0f; + samplerDesc.MaxLOD = D3D12_FLOAT32_MAX; + samplerDesc.ShaderRegister = 0; // s0 + samplerDesc.RegisterSpace = 0; + samplerDesc.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; + + // Root Signature + CD3DX12_VERSIONED_ROOT_SIGNATURE_DESC rootSignatureDesc = {}; + D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags = D3D12_ROOT_SIGNATURE_FLAG_NONE; + rootSignatureDesc.Init_1_1(_countof(rootParameters), rootParameters, 1, &samplerDesc, + rootSignatureFlags); + + ComPtr signature; + ComPtr error; + m_hr = D3DX12SerializeVersionedRootSignature(&rootSignatureDesc, + D3D_ROOT_SIGNATURE_VERSION_1_1, + &signature, &error); + + if(!verifyHResult(m_hr, "D3DX12SerializeVersionedRootSignature(... rootSignatureDesc)")){ + if (error) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Root signature serialization error: %s", + (char*)error->GetBufferPointer()); + } + return false; + } + + m_hr = m_Device->CreateRootSignature(0, signature->GetBufferPointer(), + signature->GetBufferSize(), + IID_PPV_ARGS(&m_RootSignature)); + if(!verifyHResult(m_hr, "m_Device->CreateRootSignature(... m_RootSignature)")){ + return false; + } + SDL_Log("Root Signature created successfully"); + + // --- Create Compute PSO --- + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDescRCAS = {}; + psoDescRCAS.pRootSignature = m_RootSignature.Get(); + psoDescRCAS.CS = CD3DX12_SHADER_BYTECODE(shaderBlobRCAS->GetBufferPointer(), shaderBlobRCAS->GetBufferSize()); + psoDescRCAS.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + m_hr = m_Device->CreateComputePipelineState(&psoDescRCAS, IID_PPV_ARGS(&m_PipelineStateRCAS)); + if(!verifyHResult(m_hr, "m_Device->CreateComputePipelineState(&psoDescRCAS, IID_PPV_ARGS(&m_PipelineStateRCAS));")){ + return false; + } + + + return true; +} + +/** + * \brief Initialize simple copy pipeline + * + * Creates a basic compute shader pipeline for copying RGB + * textures without enhancement. + * + * \return bool True if initialization succeeded + */ +bool D3D12VideoShaders::initializeCOPY() +{ + // Works only for RGB + if (m_isYUV) return false; + + // 1 SRV heap + 1 UAV heap + createDescriptorHeaps(2, 0, 0); + + // Create SRV for m_TextureIn + if (!updateShaderResourceView(m_TextureIn.Get())) { + return false; + } + + // Create UAV for m_TextureOut + if (!createUAVforResource(m_TextureOut.Get(), 1, m_TextureOut->GetDesc().Format)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "createUAVforResource failed"); + return false; + } + + // --- Root signature with descriptor table (t0 + u0) + root constants (4 DWORDs) --- + CD3DX12_DESCRIPTOR_RANGE ranges[2] = {}; + // range 0 = SRV range with 1 descriptor starting at t0 + ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0); // numDescriptors=1, baseShaderRegister=0 (t0) + // range 1 = UAV range with 1 descriptor starting at u0 + ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, 1, 0); // numDescriptors=1, baseShaderRegister=0 (u0) + + CD3DX12_ROOT_PARAMETER rootParams[2] = {}; + // Table 0 = SRV range + rootParams[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_ALL); + // Table 1 = UAV range + rootParams[1].InitAsDescriptorTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_ALL); + + + // Compile compute shader (copy_cs.hlsl) + QFile file(":/enhancer/copy_cs.hlsl"); + if (!file.open(QIODevice::ReadOnly)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Cannot open copy_cs.hlsl"); + return false; + } + QByteArray hlslSource = file.readAll(); + file.close(); + + ComPtr shaderBlob; + ComPtr errorBlob; + m_hr = D3DCompile(hlslSource.constData(), hlslSource.size(), "copy_cs.hlsl", nullptr, nullptr, "mainCS", "cs_5_0", + D3DCOMPILE_OPTIMIZATION_LEVEL3, 0, &shaderBlob, &errorBlob); + if(!verifyHResult(m_hr, "D3DCompile(... copy_cs.hlsl)")){ + if (errorBlob) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "CS compile error: %s", + (char*)errorBlob->GetBufferPointer()); + } + return false; + } + + // create root signature + CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc = {}; + rootSigDesc.Init(_countof(rootParams), rootParams, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_NONE); + + ComPtr rsBlob; + ComPtr rsErr; + m_hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rsBlob, &rsErr); + if(!verifyHResult(m_hr, "D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rsBlob, &rsErr);")){ + if (rsErr) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "RootSig serialize error: %s", (char*)rsErr->GetBufferPointer()); + } + return false; + } + m_hr = m_Device->CreateRootSignature( + 0, + rsBlob->GetBufferPointer(), + rsBlob->GetBufferSize(), + IID_PPV_ARGS(&m_RootSignature) + ); + if(!verifyHResult(m_hr, "m_Device->CreateRootSignature(... m_RootSignature)")){ + return false; + } + + // --- Create Compute PSO --- + D3D12_COMPUTE_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.pRootSignature = m_RootSignature.Get(); + psoDesc.CS.pShaderBytecode = shaderBlob->GetBufferPointer(); + psoDesc.CS.BytecodeLength = shaderBlob->GetBufferSize(); + psoDesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + m_hr = m_Device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState)); + if(!verifyHResult(m_hr, "m_Device->CreateComputePipelineState(&psoDesc, IID_PPV_ARGS(&m_PipelineState));")){ + return false; + } + + m_DispatchX = static_cast(std::ceil(m_OutWidth / float(16))); + m_DispatchY = static_cast(std::ceil(m_OutHeight / float(16))); + + return true; +} + +/** + * \brief Record draw commands for selected enhancer + * + * Transitions resources to required states and dispatches + * the appropriate shader passes for the current enhancer. + * + * \param D3D12_RESOURCE_STATES inputTextureStateIn Initial state of input texture + * \param D3D12_RESOURCE_STATES inputTextureStateOut Final state of input texture + * \param D3D12_RESOURCE_STATES outputTextureStateIn Initial state of output texture + * \param D3D12_RESOURCE_STATES outputTextureStateOut Final state of output texture + */ +void D3D12VideoShaders::draw( + D3D12_RESOURCE_STATES inputTextureStateIn, + D3D12_RESOURCE_STATES inputTextureStateOut, + D3D12_RESOURCE_STATES outputTextureStateIn, + D3D12_RESOURCE_STATES outputTextureStateOut + ) +{ + if (!m_GraphicsCommandList) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "No command list for draw()"); + return; + } + + m_InputTextureStateIn = inputTextureStateIn; + m_InputTextureStateOut = inputTextureStateOut; + m_OutputTextureStateIn = outputTextureStateIn; + m_OutputTextureStateOut = outputTextureStateOut; + + switch (m_Enhancer) { + case Enhancer::CONVERT_PS: + applyCONVERT_PS(); + break; + case Enhancer::NIS: + applyNIS(); + break; + case Enhancer::NIS_SHARPENER: + applyNIS(); + break; + case Enhancer::FSR1: + applyFSR1(); + break; + case Enhancer::SGSR1: + applySGSR1(); + break; + case Enhancer::RCAS: + applyRCAS(); + break; + case Enhancer::COPY: + applyCOPY(); + break; + default: + break; + } +} + +/** + * \brief Apply YUV to RGB conversion + * + * Transitions resources, sets graphics pipeline, binds descriptors, + * and draws fullscreen triangle to convert YUV input to RGB output. + * + * \return bool True if conversion applied successfully + */ +bool D3D12VideoShaders::applyCONVERT_PS() +{ + if (!m_GraphicsCommandList || !m_PipelineState) return false; + + CD3DX12_RESOURCE_BARRIER barriers[2]; + UINT NbrBarriers; + + NbrBarriers = 0; + if(m_InputTextureStateIn != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + m_InputTextureStateIn, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE + ); + NbrBarriers++; + } + if(m_OutputTextureStateIn != D3D12_RESOURCE_STATE_RENDER_TARGET){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + m_OutputTextureStateIn, + D3D12_RESOURCE_STATE_RENDER_TARGET + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + m_GraphicsCommandList->SetPipelineState(m_PipelineState.Get()); + m_GraphicsCommandList->SetGraphicsRootSignature(m_RootSignature.Get()); + + // Set descriptor heap and root signature/PSO + ID3D12DescriptorHeap* heaps[] = { m_DescriptorHeapCBV_SRV_UAV.Get() }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + m_GraphicsCommandList->SetGraphicsRootDescriptorTable( + 0, + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart() + ); + + m_GraphicsCommandList->RSSetViewports(1, &m_Viewport); + m_GraphicsCommandList->RSSetScissorRects(1, &m_ScissorRect); + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_DescriptorHeapRTV->GetCPUDescriptorHandleForHeapStart()); + + m_GraphicsCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); + + // Clear the texture in black + const float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + m_GraphicsCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + + // Root Constants + m_GraphicsCommandList->SetGraphicsRoot32BitConstants(1, 32, &m_RootConsts, 0); + + // Set primitive topology (triangle) and draw fullscreen triangle with SV_VertexID + m_GraphicsCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + m_GraphicsCommandList->DrawInstanced(3, 1, 0, 0); + + NbrBarriers = 0; + if(m_InputTextureStateOut != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + m_InputTextureStateOut + ); + NbrBarriers++; + } + if(m_OutputTextureStateOut != D3D12_RESOURCE_STATE_RENDER_TARGET){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + m_OutputTextureStateOut + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + return true; +} + +/** + * \brief Apply NVIDIA Image Scaling + * + * Transitions resources, sets compute pipeline, binds descriptors + * and constant buffers, and dispatches NIS compute shader. + * + * \return bool True if NIS applied successfully + */ +bool D3D12VideoShaders::applyNIS() +{ + if (!m_GraphicsCommandList || !m_PipelineState) return false; + + CD3DX12_RESOURCE_BARRIER barriers[2]; + UINT NbrBarriers; + + NbrBarriers = 0; + if(m_InputTextureStateIn != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + m_InputTextureStateIn, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE + ); + NbrBarriers++; + } + if(m_OutputTextureStateIn != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + m_OutputTextureStateIn, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + m_GraphicsCommandList->SetPipelineState(m_PipelineState.Get()); + m_GraphicsCommandList->SetComputeRootSignature(m_RootSignature.Get()); + + // Set descriptor heap and root signature/PSO + ID3D12DescriptorHeap* heaps[] = { + m_DescriptorHeapCBV_SRV_UAV.Get(), // SRV/UAV/CBV + m_DescriptorHeapSampler.Get() // Samplers + }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Sampler + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuSampler = CD3DX12_GPU_DESCRIPTOR_HANDLE( + m_DescriptorHeapSampler->GetGPUDescriptorHandleForHeapStart(), + 0, + m_DescriptorSizeSampler + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(0, gpuSampler); + + // CBV + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuCBV = CD3DX12_GPU_DESCRIPTOR_HANDLE( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 1, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(1, gpuCBV); + + // SRV (Input texture) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuSRV = CD3DX12_GPU_DESCRIPTOR_HANDLE( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 2, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(2, gpuSRV); + + // UAV (Output) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuUAV = CD3DX12_GPU_DESCRIPTOR_HANDLE( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 3, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(3, gpuUAV); + + // SRV (Coef Scaler) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuSRVScaler = CD3DX12_GPU_DESCRIPTOR_HANDLE( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 4, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(4, gpuSRVScaler); + + // SRV (Coef USM) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuSRVUSM = CD3DX12_GPU_DESCRIPTOR_HANDLE( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 5, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(5, gpuSRVUSM); + + // Dispatch + m_GraphicsCommandList->Dispatch(m_DispatchX, m_DispatchY, 1); + + NbrBarriers = 0; + if(m_InputTextureStateOut != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + m_InputTextureStateOut + ); + NbrBarriers++; + } + if(m_OutputTextureStateOut != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + m_OutputTextureStateOut + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + return true; +} + +/** + * \brief Apply FSR1 two-pass enhancement + * + * Executes EASU upscaling pass to intermediate texture, + * then RCAS sharpening pass to final output. + * + * \return bool True if FSR1 applied successfully + */ +bool D3D12VideoShaders::applyFSR1() +{ + if (!m_GraphicsCommandList || !m_PipelineStateEASU || !m_PipelineStateRCAS) return false; + + CD3DX12_RESOURCE_BARRIER barriers[2]; + UINT NbrBarriers; + + + // Set descriptor heap and root signature/PSO + ID3D12DescriptorHeap* heaps[] = { m_DescriptorHeapCBV_SRV_UAV.Get() }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + NbrBarriers = 0; + if(m_InputTextureStateIn != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + m_InputTextureStateIn, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE + ); + NbrBarriers++; + } + if(m_OutputTextureStateIn != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + m_OutputTextureStateIn, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + // =============================== + // PASS 1 : EASU + // =============================== + + { + m_GraphicsCommandList->SetPipelineState(m_PipelineStateEASU.Get()); + m_GraphicsCommandList->SetComputeRootSignature(m_RootSignature.Get()); + + // Set SRV descriptor table (descriptor 0) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleSRVs( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 0, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(0, gpuHandleSRVs); + + // Set UAV descriptor table (descriptor 1) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleUAV( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 1, + m_DescriptorSizeCBV_SRV_UAV); + m_GraphicsCommandList->SetComputeRootDescriptorTable(1, gpuHandleUAV); + + // Root Constants + m_GraphicsCommandList->SetComputeRoot32BitConstants(2, 32, &m_EASUConstants, 0); + + // Dispatch + m_GraphicsCommandList->Dispatch(m_DispatchX, m_DispatchY, 1); + } + + // =============================== + // PASS 2 : RCAS + // =============================== + + { + m_GraphicsCommandList->SetPipelineState(m_PipelineStateRCAS.Get()); + m_GraphicsCommandList->SetComputeRootSignature(m_RootSignature.Get()); + + // Set SRV descriptor table (descriptor 2) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleSRVs( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 2, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(0, gpuHandleSRVs); + + // Set UAV descriptor table (descriptor 3) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleUAV( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 3, + m_DescriptorSizeCBV_SRV_UAV); + m_GraphicsCommandList->SetComputeRootDescriptorTable(1, gpuHandleUAV); + + // Root Constants + m_GraphicsCommandList->SetComputeRoot32BitConstants(2, 32, &m_RCASConstants, 0); + + // Dispatch + m_GraphicsCommandList->Dispatch(m_DispatchX, m_DispatchY, 1); + } + + NbrBarriers = 0; + if(m_InputTextureStateOut != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + m_InputTextureStateOut + ); + NbrBarriers++; + } + if(m_OutputTextureStateOut != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + m_OutputTextureStateOut + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + return true; +} + +/** + * \brief Apply SGRS1 one-pass enhancement + * + * Execute SGRS1 upscaling and sharpening pass to the texture. + * + * \return bool True if copy applied successfully + */ +bool D3D12VideoShaders::applySGSR1() +{ + if (!m_GraphicsCommandList || !m_PipelineState) return false; + + CD3DX12_RESOURCE_BARRIER barriers[2]; + UINT NbrBarriers; + + NbrBarriers = 0; + if(m_InputTextureStateIn != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + m_InputTextureStateIn, + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE + ); + NbrBarriers++; + } + if(m_OutputTextureStateIn != D3D12_RESOURCE_STATE_RENDER_TARGET){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + m_OutputTextureStateIn, + D3D12_RESOURCE_STATE_RENDER_TARGET + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + m_GraphicsCommandList->SetPipelineState(m_PipelineState.Get()); + m_GraphicsCommandList->SetGraphicsRootSignature(m_RootSignature.Get()); + + // Set descriptor heap and root signature/PSO + ID3D12DescriptorHeap* heaps[] = { m_DescriptorHeapCBV_SRV_UAV.Get() }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + m_GraphicsCommandList->SetGraphicsRootConstantBufferView(0, m_SGSRConstantBuffer->GetGPUVirtualAddress()); + + m_GraphicsCommandList->SetGraphicsRootDescriptorTable( + 1, + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart() + ); + + m_GraphicsCommandList->RSSetViewports(1, &m_Viewport); + m_GraphicsCommandList->RSSetScissorRects(1, &m_ScissorRect); + + CD3DX12_CPU_DESCRIPTOR_HANDLE rtvHandle(m_DescriptorHeapRTV->GetCPUDescriptorHandleForHeapStart()); + + m_GraphicsCommandList->OMSetRenderTargets(1, &rtvHandle, FALSE, nullptr); + + // Clear the texture in black + const float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + m_GraphicsCommandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr); + + // Set primitive topology (triangle) and draw fullscreen triangle with SV_VertexID + m_GraphicsCommandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + m_GraphicsCommandList->DrawInstanced(3, 1, 0, 0); + + NbrBarriers = 0; + if(m_InputTextureStateOut != D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE, + m_InputTextureStateOut + ); + NbrBarriers++; + } + if(m_OutputTextureStateOut != D3D12_RESOURCE_STATE_RENDER_TARGET){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, + m_OutputTextureStateOut + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + return true; +} + + +/** + * \brief Apply RCAS sharpening + * + * Transitions resources, sets compute pipeline, and dispatches + * RCAS shader for standalone sharpening. + * + * \return bool True if RCAS applied successfully + */ +bool D3D12VideoShaders::applyRCAS() +{ + if (!m_GraphicsCommandList || !m_PipelineStateRCAS) return false; + + CD3DX12_RESOURCE_BARRIER barriers[2]; + UINT NbrBarriers; + + + // Set descriptor heap and root signature/PSO + ID3D12DescriptorHeap* heaps[] = { m_DescriptorHeapCBV_SRV_UAV.Get() }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + NbrBarriers = 0; + if(m_InputTextureStateIn != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + m_InputTextureStateIn, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE + ); + NbrBarriers++; + } + if(m_OutputTextureStateIn != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + m_OutputTextureStateIn, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + m_GraphicsCommandList->SetPipelineState(m_PipelineStateRCAS.Get()); + m_GraphicsCommandList->SetComputeRootSignature(m_RootSignature.Get()); + + // Set SRV descriptor table (descriptor 0) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleSRVs( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 0, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(0, gpuHandleSRVs); + + // Set UAV descriptor table (descriptor 1) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleUAV( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 1, + m_DescriptorSizeCBV_SRV_UAV); + m_GraphicsCommandList->SetComputeRootDescriptorTable(1, gpuHandleUAV); + + // Root Constants + m_GraphicsCommandList->SetComputeRoot32BitConstants(2, 32, &m_RCASConstants, 0); + + // Dispatch + m_GraphicsCommandList->Dispatch(m_DispatchX, m_DispatchY, 1); + + NbrBarriers = 0; + if(m_InputTextureStateOut != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + m_InputTextureStateOut + ); + NbrBarriers++; + } + if(m_OutputTextureStateOut != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + m_OutputTextureStateOut + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + return true; +} + +/** + * \brief Apply simple texture copy + * + * Transitions resources and dispatches compute shader to + * copy input texture to output without modification. + * + * \return bool True if copy applied successfully + */ +bool D3D12VideoShaders::applyCOPY() +{ + if (!m_GraphicsCommandList || !m_PipelineState) return false; + + CD3DX12_RESOURCE_BARRIER barriers[2]; + UINT NbrBarriers; + + NbrBarriers = 0; + if(m_InputTextureStateIn != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + m_InputTextureStateIn, + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE + ); + NbrBarriers++; + } + if(m_OutputTextureStateIn != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + m_OutputTextureStateIn, + D3D12_RESOURCE_STATE_UNORDERED_ACCESS + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + // Guarantee descriptor heap is set + ID3D12DescriptorHeap* heaps[] = { m_DescriptorHeapCBV_SRV_UAV.Get() }; + m_GraphicsCommandList->SetDescriptorHeaps(_countof(heaps), heaps); + + // Bind compute root signature & PSO + m_GraphicsCommandList->SetComputeRootSignature(m_RootSignature.Get()); + m_GraphicsCommandList->SetPipelineState(m_PipelineState.Get()); + + // Set SRV descriptor table (descriptor 0) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleSRVs( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 0, + m_DescriptorSizeCBV_SRV_UAV + ); + m_GraphicsCommandList->SetComputeRootDescriptorTable(0, gpuHandleSRVs); + + // Set UAV descriptor table (descriptor 1) + CD3DX12_GPU_DESCRIPTOR_HANDLE gpuHandleUAV( + m_DescriptorHeapCBV_SRV_UAV->GetGPUDescriptorHandleForHeapStart(), + 1, + m_DescriptorSizeCBV_SRV_UAV); + m_GraphicsCommandList->SetComputeRootDescriptorTable(1, gpuHandleUAV); + + // Dispatch + m_GraphicsCommandList->Dispatch(m_DispatchX, m_DispatchY, 1); + + NbrBarriers = 0; + if(m_InputTextureStateOut != D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureIn.Get(), + D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, + m_InputTextureStateOut + ); + NbrBarriers++; + } + if(m_OutputTextureStateOut != D3D12_RESOURCE_STATE_UNORDERED_ACCESS){ + barriers[NbrBarriers] = CD3DX12_RESOURCE_BARRIER::Transition( + m_TextureOut.Get(), + D3D12_RESOURCE_STATE_UNORDERED_ACCESS, + m_OutputTextureStateOut + ); + NbrBarriers++; + } + if(NbrBarriers > 0){ + m_GraphicsCommandList->ResourceBarrier(NbrBarriers, barriers); + } + + return true; +} + + +// Following methods are specific to NIS + +/** + * \brief Create 2D texture for NIS + * + * Helper method to create a default heap texture with + * UAV flag for NIS coefficient storage. + * + * \param uint32_t width Texture width + * \param uint32_t height Texture height + * \param DXGI_FORMAT format Texture format + * \param D3D12_RESOURCE_STATES resourceState Initial state + * \param ID3D12Resource** pResource Output resource pointer + */ +void D3D12VideoShaders::NISCreateTexture2D(uint32_t width, uint32_t height, DXGI_FORMAT format, D3D12_RESOURCE_STATES resourceState, ID3D12Resource** pResource) +{ + auto heapProperties = CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT); + auto resourceDesc = CD3DX12_RESOURCE_DESC::Tex2D(format, width, height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS); + m_hr = m_Device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, resourceState, nullptr, __uuidof(ID3D12Resource), (void**)pResource); + if(!verifyHResult(m_hr, "NISCreateTexture2D")){ + return; + } +} + +/** + * \brief Create buffer for NIS + * + * Helper method to create a buffer resource with specified + * heap type for NIS data storage. + * + * \param uint32_t size Buffer size in bytes + * \param D3D12_HEAP_TYPE heapType Heap type (upload/default) + * \param D3D12_RESOURCE_STATES resourceState Initial state + * \param ID3D12Resource** pResource Output resource pointer + */ +void D3D12VideoShaders::NISCreateBuffer(uint32_t size, D3D12_HEAP_TYPE heapType, D3D12_RESOURCE_STATES resourceState, ID3D12Resource** pResource) +{ + auto resourceDesc = CD3DX12_RESOURCE_DESC::Buffer(size); + auto heapProperties = CD3DX12_HEAP_PROPERTIES(heapType); + m_hr = m_Device->CreateCommittedResource(&heapProperties, D3D12_HEAP_FLAG_NONE, &resourceDesc, resourceState, nullptr, __uuidof(ID3D12Resource), (void**)pResource); + if(!verifyHResult(m_hr, "NISCreateBuffer")){ + return; + } +} + +/** + * \brief Upload buffer data for NIS + * + * Copies data from CPU to GPU buffer via staging resource + * with appropriate resource state transitions. + * + * \param void* data Source data pointer + * \param uint32_t size Data size in bytes + * \param ID3D12Resource* pResource Destination buffer + * \param ID3D12Resource* pStagingResource Staging buffer for upload + */ +void D3D12VideoShaders::NISUploadBufferData(void* data, uint32_t size, ID3D12Resource* pResource, ID3D12Resource* pStagingResource) +{ + D3D12_RESOURCE_BARRIER barrier; + + barrier = CD3DX12_RESOURCE_BARRIER::Transition( + pResource, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_DEST + ); + m_GraphicsCommandList->ResourceBarrier(1, &barrier); + + uint8_t* mappedData = nullptr; + pStagingResource->Map(0, nullptr, reinterpret_cast(&mappedData)); + memcpy(mappedData, data, size); + pStagingResource->Unmap(0, nullptr); + m_GraphicsCommandList->CopyBufferRegion(pResource, 0, pStagingResource, 0, size); + + barrier = CD3DX12_RESOURCE_BARRIER::Transition( + pResource, + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_COMMON + ); + m_GraphicsCommandList->ResourceBarrier(1, &barrier); +} + +/** + * \brief Upload texture data for NIS + * + * Copies texture data from CPU to GPU via staging resource + * with proper row pitch alignment and state transitions. + * + * \param void* data Source data pointer + * \param uint32_t size Data size in bytes + * \param uint32_t rowPitch Row pitch in bytes + * \param ID3D12Resource* pResource Destination texture + * \param ID3D12Resource* pStagingResource Staging resource for upload + */ +void D3D12VideoShaders::NISUploadTextureData(void* data, uint32_t size, uint32_t rowPitch, ID3D12Resource* pResource, ID3D12Resource* pStagingResource) +{ + D3D12_RESOURCE_BARRIER barrier; + + barrier = CD3DX12_RESOURCE_BARRIER::Transition( + pResource, + D3D12_RESOURCE_STATE_COMMON, + D3D12_RESOURCE_STATE_COPY_DEST + ); + m_GraphicsCommandList->ResourceBarrier(1, &barrier); + + uint8_t* mappedData = nullptr; + pStagingResource->Map(0, nullptr, reinterpret_cast(&mappedData)); + memcpy(mappedData, data, size); + pStagingResource->Unmap(0, nullptr); + D3D12_RESOURCE_DESC desc = pResource->GetDesc(); + D3D12_PLACED_SUBRESOURCE_FOOTPRINT footprint = {}; + footprint.Footprint.Width = uint32_t(desc.Width); + footprint.Footprint.Height = uint32_t(desc.Height); + footprint.Footprint.Depth = 1; + footprint.Footprint.RowPitch = (rowPitch + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1) / D3D12_TEXTURE_DATA_PITCH_ALIGNMENT * D3D12_TEXTURE_DATA_PITCH_ALIGNMENT; + footprint.Footprint.Format = desc.Format; + CD3DX12_TEXTURE_COPY_LOCATION src(pStagingResource, footprint); + CD3DX12_TEXTURE_COPY_LOCATION dst(pResource, 0); + m_GraphicsCommandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr); + + barrier = CD3DX12_RESOURCE_BARRIER::Transition( + pResource, + D3D12_RESOURCE_STATE_COPY_DEST, + D3D12_RESOURCE_STATE_COMMON + ); + m_GraphicsCommandList->ResourceBarrier(1, &barrier); +} + +/** + * \brief Create aligned coefficient data for NIS + * + * Converts linear coefficient array to aligned format matching + * D3D12 texture data pitch alignment requirements. + * + * \param uint16_t* data Source coefficient data + * \param std::vector& coef Output aligned coefficient vector + * \param uint32_t rowPitchAligned Aligned row pitch in bytes + */ +void D3D12VideoShaders::NISCreateAlignedCoefficients(uint16_t* data, std::vector& coef, uint32_t rowPitchAligned) +{ + const int rowElements = rowPitchAligned / sizeof(uint16_t); + const int coefSize = rowElements * kPhaseCount; + coef.resize(coefSize); + for (uint32_t y = 0; y < kPhaseCount; ++y) + { + for (uint32_t x = 0; x < kFilterSize; ++x) { + coef[x + y * uint64_t(rowElements)] = data[x + y * kFilterSize]; + } + } +} diff --git a/app/streaming/video/ffmpeg-renderers/d3d12va_shaders.h b/app/streaming/video/ffmpeg-renderers/d3d12va_shaders.h new file mode 100644 index 000000000..7988e7ac2 --- /dev/null +++ b/app/streaming/video/ffmpeg-renderers/d3d12va_shaders.h @@ -0,0 +1,244 @@ +#pragma once + +#include + +#include +#include +#include +#include + +#include +using namespace DirectX::PackedVector; +#include +#include "streaming/video/videoenhancement.h" + +// NIS Declaration +#include "NIS_Config.h" + +// FSR1 Declaration +#define A_CPU +#include "ffx_a.h" +#include "ffx_fsr1.h" + +using Microsoft::WRL::ComPtr; +using namespace DirectX; + +class D3D12VideoShaders +{ +public: + enum class Enhancer { + NONE, + CONVERT_PS, + NIS, + NIS_SHARPENER, + FSR1, + SGSR1, + RCAS, + COPY + }; + + static bool isUpscaler(Enhancer enhancer); + static bool isSharpener(Enhancer enhancer); + static bool isUsingShader(Enhancer enhancer); + + D3D12VideoShaders( + ID3D12Device* device, + ID3D12GraphicsCommandList* graphicsCommandList, + ID3D12CommandQueue* graphicsCommandQueue, + VideoEnhancement* videoEnhancement, + ID3D12Resource* textureIn, + ID3D12Resource* textureOut, + D3D12_VIEWPORT viewport, + D3D12_RECT scissorRect, + Enhancer enhancer, + DXGI_COLOR_SPACE_TYPE colorSpace + ); + + ~D3D12VideoShaders(); + + void draw( + D3D12_RESOURCE_STATES inputTextureStateIn, + D3D12_RESOURCE_STATES inputTextureStateOut, + D3D12_RESOURCE_STATES outputTextureStateIn, + D3D12_RESOURCE_STATES outputTextureStateOut + ); + + bool updateShaderResourceView(ID3D12Resource* resource); + void updateRootConstsOffset(XMFLOAT3 offset); + +private: + + // FSR1 + struct alignas(16) FSR1Constants { + AU1 const0[4]; + AU1 const1[4]; + AU1 const2[4]; + AU1 const3[4]; + }; + FSR1Constants m_EASUConstants; + FSR1Constants m_RCASConstants; + ComPtr m_PipelineStateEASU; + ComPtr m_PipelineStateRCAS; + + // SGSR1 + struct SGSRConstants { + float viewportX; // 1.0f / inputWidth + float viewportY; // 1.0f / inputHeight + float viewportZ; // inputWidth + float viewportW; // inputHeight + }; + SGSRConstants m_SGSRConstants; + ComPtr m_SGSRConstantBuffer; + + struct alignas(16) RootConsts + { + // SDR and HDR invert bits + // Block 0 (0->16) + float g_INV_8BIT; + float g_INV_10BIT; + float _pad0[2]; + + // PQ converter constants + // Block 1 (16->32) + float g_M1Inv; + float g_M2Inv; + float g_C1; + float g_C2; + // Block 2 (32->48) + float g_C3; + float _pad2[3]; + + // CSC matrix rows + // Block 3 (48->64) + float g_CSC_Row0_x; + float g_CSC_Row0_y; + float g_CSC_Row0_z; + float _pad3; + + // Block 4 (64->80) + float g_CSC_Row1_x; + float g_CSC_Row1_y; + float g_CSC_Row1_z; + float _pad4; + + // Block 5 (80->96) + float g_CSC_Row2_x; + float g_CSC_Row2_y; + float g_CSC_Row2_z; + float _pad5; + + // Color range and YUV Offset + // Block 6 (96->112) + float g_ScaleY; + float g_OffsetY; + float g_OffsetU; + float g_OffsetV; + + // Texture format In/Out + // Block 7 (112->128) + uint32_t g_InputFormat; + uint32_t g_OutputFormat; + uint32_t g_GammaCorrection; + uint32_t g_Range; + }; + static_assert(sizeof(RootConsts) == 8 * 16, "RootConstsCPU must be 32 dwords (128 bytes)"); + + RootConsts m_RootConsts; + + ComPtr m_Device; + ComPtr m_GraphicsCommandList; + ComPtr m_GraphicsCommandQueue; + VideoEnhancement* m_VideoEnhancement; + ComPtr m_TextureIn; + ComPtr m_TextureOut; + int m_InWidth; + int m_InHeight; + int m_OutWidth; + int m_OutHeight; + D3D12_VIEWPORT m_Viewport = {}; + D3D12_RECT m_ScissorRect = {}; + Enhancer m_Enhancer = Enhancer::NONE; + DXGI_COLOR_SPACE_TYPE m_ColorSpace; + + HRESULT m_hr; + bool m_isYUV = false; + bool m_IsYUV444 = false; + bool m_IsHDR = false; + bool m_Is2Planes = false; + bool m_AdvancedShader = true; + + // States + D3D12_RESOURCE_STATES m_InputTextureStateIn; + D3D12_RESOURCE_STATES m_InputTextureStateOut; + D3D12_RESOURCE_STATES m_OutputTextureStateIn; + D3D12_RESOURCE_STATES m_OutputTextureStateOut; + + ComPtr m_RootSignature; + ComPtr m_PipelineState; + ComPtr m_DescriptorHeapCBV_SRV_UAV; + ComPtr m_DescriptorHeapRTV; + ComPtr m_DescriptorHeapSampler; + UINT m_DescriptorSizeCBV_SRV_UAV = 0; + UINT m_DescriptorSizeRTV = 0; + UINT m_DescriptorSizeSampler = 0; + UINT m_DispatchX; + UINT m_DispatchY; + ComPtr m_TextureInterm; + + bool m_IsUpscaling = true; + bool m_IsUsingShader = true; + + // NVIDIA Image Scaling + bool m_NISHalfprecision = true; // true: 16-bit (half precision) / false: 32-bit (full precision) + ComPtr m_ConstatBuffer; + ComPtr m_StagingBuffer; + ComPtr m_CoefScaler; + ComPtr m_CoefUSM; + ComPtr m_CoefScalerUpload; + ComPtr m_CoefUSMUpload; + std::vector m_CoefScalerHost; + std::vector m_CoefUSMHost; + uint32_t m_RowPitch; + NISConfig m_ConfigNIS; + // Use global variable in case the initializer finish before the compilation + std::wstring m_NIS_SCALER; + std::wstring m_NIS_HDR_MODE; + std::wstring m_NIS_BLOCK_WIDTH; + std::wstring m_NIS_BLOCK_HEIGHT; + std::wstring m_NIS_THREAD_GROUP_SIZE; + std::wstring m_NIS_USE_HALF_PRECISION; + std::vector m_Args; + + bool verifyHResult(HRESULT hr, const char* operation); + void initializeRootConsts(); + bool isSupportingAdvancedShader(); + + // Helpers + bool createDescriptorHeaps(UINT cbvSrvUavCount, UINT rtvCount, UINT samplerCount); + bool createTexture(ComPtr& pTexture, int width, int height, DXGI_FORMAT format, D3D12_RESOURCE_FLAGS flags, D3D12_RESOURCE_STATES textureState); + bool createCBVforResource(ID3D12Resource* resource, UINT descriptorIndex); + bool createSRVforResource(ID3D12Resource* resource, UINT descriptorIndex, DXGI_FORMAT format, UINT planeSlice = 0); + bool createUAVforResource(ID3D12Resource* resource, UINT descriptorIndex, DXGI_FORMAT format, UINT planeSlice = 0); + bool createRTVforResource(ID3D12Resource* resource, UINT rtvIndex, DXGI_FORMAT format, UINT planeSlice = 0); + + bool initializeCONVERT_PS(); + bool initializeNIS(bool isUpscaling = true); + bool initializeFSR1(); + bool initializeSGSR1(); + bool initializeRCAS(); + bool initializeCOPY(); + + bool applyCONVERT_PS(); + bool applyNIS(); + bool applyFSR1(); + bool applySGSR1(); + bool applyRCAS(); + bool applyCOPY(); + + // NVIDIA Image Scaling + void NISCreateTexture2D(uint32_t width, uint32_t height, DXGI_FORMAT format, D3D12_RESOURCE_STATES resourceState, ID3D12Resource** pResource); + void NISCreateBuffer(uint32_t size, D3D12_HEAP_TYPE heapType, D3D12_RESOURCE_STATES resourceState, ID3D12Resource** pResource); + void NISUploadTextureData(void* data, uint32_t size, uint32_t rowPitch, ID3D12Resource* pResource, ID3D12Resource* pStagingResource); + void NISUploadBufferData(void* data, uint32_t size, ID3D12Resource* pResource, ID3D12Resource* pStagingResource); + void NISCreateAlignedCoefficients(uint16_t* data, std::vector& coef, uint32_t rowPitchAligned); +}; diff --git a/app/streaming/video/ffmpeg-renderers/plvk.cpp b/app/streaming/video/ffmpeg-renderers/plvk.cpp index 3a7b2a105..5a79e678f 100644 --- a/app/streaming/video/ffmpeg-renderers/plvk.cpp +++ b/app/streaming/video/ffmpeg-renderers/plvk.cpp @@ -138,7 +138,8 @@ void PlVkRenderer::overlayUploadComplete(void* opaque) PlVkRenderer::PlVkRenderer(AVHWDeviceType hwDeviceType, IFFmpegRenderer *backendRenderer) : IFFmpegRenderer(RendererType::Vulkan), m_Backend(backendRenderer), - m_HwDeviceType(hwDeviceType) + m_HwDeviceType(hwDeviceType), + m_VideoEnhancement(&VideoEnhancement::getInstance()) { bool ok; @@ -181,6 +182,18 @@ PlVkRenderer::~PlVkRenderer() DrmMasterLocker locker; pl_renderer_destroy(&m_Renderer); + + // The FSR hooks own GPU resources, so they must be released while the + // pl_gpu they were parsed on is still alive. m_FsrHookHDR stays null when + // only the SDR variant was parsed and m_RenderParamsHDR points at m_FsrHook. + if (m_FsrHookHDR != nullptr && m_FsrHookHDR != m_FsrHook) { + pl_mpv_user_shader_destroy(&m_FsrHookHDR); + } + m_FsrHookHDR = nullptr; + if (m_FsrHook != nullptr) { + pl_mpv_user_shader_destroy(&m_FsrHook); + } + pl_swapchain_destroy(&m_Swapchain); #ifdef Q_OS_DARWIN m_MetalTextureFactory.reset(); @@ -628,9 +641,72 @@ bool PlVkRenderer::initialize(PDECODER_PARAMETERS params) } #endif + // Video Super Resolution via the Shader FSR1 + // https://gist.github.com/agyild/82219c545228d70c5604f865ce0b0ce5 + if (m_VideoEnhancement->isVideoEnhancementEnabled()) { + + // FSR1 (SDR) + // The shader has been customized to set the sharpening at 0.75 + std::string FsrShader = loadGLSL(":/enhancer/FSR1.glsl"); + m_FsrHook = pl_mpv_user_shader_parse(m_Vulkan->gpu, FsrShader.c_str(), FsrShader.size()); + m_RenderParams.hooks = &m_FsrHook; + m_RenderParams.num_hooks = m_FsrHook ? 1 : 0; + + // FSR1 (HDR) + // The shader has been customized to set the sharpening at 0.75 and PQ at true for HDR. + // Only a 10-bit stream can carry PQ frames, so for anything else the SDR hook is reused + // rather than parsing and allocating GPU resources for a second identical copy of it. + if (params->videoFormat & VIDEO_FORMAT_MASK_10BIT) { + std::string FsrShaderHDR = loadGLSL(":/enhancer/FSR1_HDR.glsl"); + m_FsrHookHDR = pl_mpv_user_shader_parse(m_Vulkan->gpu, FsrShaderHDR.c_str(), FsrShaderHDR.size()); + m_RenderParamsHDR.hooks = &m_FsrHookHDR; + m_RenderParamsHDR.num_hooks = m_FsrHookHDR ? 1 : 0; + } + else { + m_RenderParamsHDR.hooks = &m_FsrHook; + m_RenderParamsHDR.num_hooks = m_FsrHook ? 1 : 0; + } + + if (m_RenderParams.num_hooks == 0 || m_RenderParamsHDR.num_hooks == 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Failed to parse the FSR1 shader. Video enhancement is disabled for this session."); + m_VideoEnhancement->enableVideoEnhancement(false); + } + else { + int drawableWidth, drawableHeight; + SDL_Vulkan_GetDrawableSize(m_Window, &drawableWidth, &drawableHeight); + m_VideoEnhancement->setRatio(static_cast(drawableHeight) / static_cast(params->height)); + + m_VideoEnhancement->setAlgo("Shader FSR1"); + } + } + return true; } +/** + * \brief Load a GLSL shader file from the given path. + * + * Reads the file content and returns it as a string. Logs an error if the file cannot be opened. + * + * \param const QString& path Path to the GLSL shader file + * \return std::string File content as a string, or an empty string on failure + */ +std::string PlVkRenderer::loadGLSL(const QString& path) +{ + QFile file(path); + + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Cannot open GLSL file: %s", path.toUtf8().constData()); + return {}; + } + + QByteArray data = file.readAll(); + file.close(); + + return std::string(data.constData(), data.size()); +} bool PlVkRenderer::createSwapchain(int depth) { @@ -1077,7 +1153,14 @@ void PlVkRenderer::renderFrame(AVFrame *frame) // Render the video image and overlays into the swapchain buffer targetFrame.num_overlays = (int)overlays.size(); targetFrame.overlays = overlays.data(); - if (!pl_render_image(m_Renderer, &mappedFrame, &targetFrame, &pl_render_fast_params)) { + + pl_render_params renderParams = pl_render_fast_params; + if (m_VideoEnhancement->isVideoEnhancementEnabled()) { + // If the frame is HDR, load the Shader with HDR enabled + renderParams = (frame->color_trc == AVCOL_TRC_SMPTE2084) ? m_RenderParamsHDR : m_RenderParams; + } + + if (!pl_render_image(m_Renderer, &mappedFrame, &targetFrame, &renderParams)) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "pl_render_image() failed"); // NB: We must fallthrough to call pl_swapchain_submit_frame() @@ -1273,6 +1356,10 @@ void PlVkRenderer::notifyOverlayUpdated(Overlay::OverlayType type) bool PlVkRenderer::notifyWindowChanged(PWINDOW_STATE_CHANGE_INFO info) { + // We force the reinitialization of FFX API when the Window change + if (m_VideoEnhancement->isVideoEnhancementEnabled()) { + return !(info->stateChangeFlags & (WINDOW_STATE_CHANGE_DISPLAY | WINDOW_STATE_CHANGE_SIZE)); + } // We can transparently handle size and display changes return !(info->stateChangeFlags & ~(WINDOW_STATE_CHANGE_SIZE | WINDOW_STATE_CHANGE_DISPLAY)); } diff --git a/app/streaming/video/ffmpeg-renderers/plvk.h b/app/streaming/video/ffmpeg-renderers/plvk.h index fdef2f82b..818b1a145 100644 --- a/app/streaming/video/ffmpeg-renderers/plvk.h +++ b/app/streaming/video/ffmpeg-renderers/plvk.h @@ -1,6 +1,7 @@ #pragma once #include "renderer.h" +#include "streaming/video/videoenhancement.h" #ifdef Q_OS_WIN32 #define VK_USE_PLATFORM_WIN32_KHR @@ -9,6 +10,9 @@ #include #include #include +#include + +#include #ifdef Q_OS_DARWIN class MetalVulkanTextureFactory { @@ -75,6 +79,10 @@ class PlVkRenderer : public IFFmpegRenderer { bool isColorSpaceSupportedByPhysicalDevice(VkPhysicalDevice device, VkColorSpaceKHR colorSpace); bool isSurfacePresentationSupportedByPhysicalDevice(VkPhysicalDevice device); + // FSR1 + std::string loadGLSL(const QString& path); + void fsrHook(pl_hook_res *res, const pl_hook_params *params); + // The backend renderer if we're frontend-only IFFmpegRenderer* m_Backend; AVHWDeviceType m_HwDeviceType; @@ -141,6 +149,13 @@ class PlVkRenderer : public IFFmpegRenderer { // Device context used for hwaccel decoders AVBufferRef* m_HwDeviceCtx = nullptr; + // FSR1 + VideoEnhancement* m_VideoEnhancement; + const pl_hook *m_FsrHook = nullptr; + const pl_hook *m_FsrHookHDR = nullptr; + pl_render_params m_RenderParams = pl_render_fast_params; + pl_render_params m_RenderParamsHDR = pl_render_fast_params; + // Vulkan functions we call directly PFN_vkDestroySurfaceKHR fn_vkDestroySurfaceKHR = nullptr; PFN_vkGetPhysicalDeviceQueueFamilyProperties2 fn_vkGetPhysicalDeviceQueueFamilyProperties2 = nullptr; @@ -150,4 +165,5 @@ class PlVkRenderer : public IFFmpegRenderer { PFN_vkGetPhysicalDeviceProperties fn_vkGetPhysicalDeviceProperties = nullptr; PFN_vkGetPhysicalDeviceSurfaceSupportKHR fn_vkGetPhysicalDeviceSurfaceSupportKHR = nullptr; PFN_vkEnumerateDeviceExtensionProperties fn_vkEnumerateDeviceExtensionProperties = nullptr; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fn_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr; }; diff --git a/app/streaming/video/ffmpeg-renderers/renderer.h b/app/streaming/video/ffmpeg-renderers/renderer.h index ba125842e..5843960c7 100644 --- a/app/streaming/video/ffmpeg-renderers/renderer.h +++ b/app/streaming/video/ffmpeg-renderers/renderer.h @@ -144,6 +144,7 @@ class IFFmpegRenderer : public Overlay::IOverlayRenderer { Vulkan, CUDA, D3D11VA, + D3D12VA, DRM, DXVA2, EGL, @@ -322,6 +323,8 @@ class IFFmpegRenderer : public Overlay::IOverlayRenderer { return "CUDA"; case RendererType::D3D11VA: return "D3D11VA"; + case RendererType::D3D12VA: + return "D3D12VA"; case RendererType::DRM: return "DRM"; case RendererType::DXVA2: diff --git a/app/streaming/video/ffmpeg-renderers/vt_metal.mm b/app/streaming/video/ffmpeg-renderers/vt_metal.mm index 2852d4379..c2ce84266 100644 --- a/app/streaming/video/ffmpeg-renderers/vt_metal.mm +++ b/app/streaming/video/ffmpeg-renderers/vt_metal.mm @@ -15,8 +15,11 @@ #import #import #import -#import +#import #import +#import + +#include "streaming/video/videoenhancement.h" extern "C" { #include @@ -78,8 +81,13 @@ - (id)initWithRenderer:(VTMetalRenderer *)renderer; m_LastFrameWidth(-1), m_LastFrameHeight(-1), m_LastDrawableWidth(-1), - m_LastDrawableHeight(-1) + m_LastDrawableHeight(-1), + m_LumaUpscaledTexture(nullptr), + m_LumaUpscaler(nullptr), + m_ChromaUpscaledTexture(nullptr), + m_ChromaUpscaler(nullptr) { + m_VideoEnhancement = &VideoEnhancement::getInstance(); } virtual ~VTMetalRenderer() override @@ -130,10 +138,27 @@ - (id)initWithRenderer:(VTMetalRenderer *)renderer; [m_CommandQueue release]; } - if (m_TextureCache != nullptr) { - CFRelease(m_TextureCache); + if (m_LumaUpscaledTexture != nullptr) { + [m_LumaUpscaledTexture release]; + } + + if (m_LumaUpscaler != nullptr) { + [m_LumaUpscaler release]; + } + + if (m_ChromaUpscaledTexture != nullptr) { + [m_ChromaUpscaledTexture release]; } + if (m_ChromaUpscaler != nullptr) { + [m_ChromaUpscaler release]; + } + + // Note: CFRelease makes the application crash sometime as the m_TextureCache seems to be cleared before it is called + // if (m_TextureCache != nullptr) { + // CFRelease(m_TextureCache); + // } + if (m_MetalView != nullptr) { SDL_Metal_DestroyView(m_MetalView); } @@ -152,6 +177,8 @@ bool updateVideoRegionSizeForFrame(AVFrame* frame) return true; } + m_VideoEnhancement->setRatio(static_cast(drawableHeight) / static_cast(frame->height)); + // Determine the correct scaled size for the video region SDL_Rect src, dst; src.x = src.y = 0; @@ -480,32 +507,160 @@ virtual void renderFrameIntoDrawable(AVFrame* frame, id drawabl size_t planes = getFramePlaneCount(frame); SDL_assert(planes <= MAX_VIDEO_PLANES); + CVPixelBufferRef pixBuf = reinterpret_cast(frame->data[3]); + + CVMetalTextureRef cvLumaTexture = nullptr; + CVMetalTextureRef cvChromaTexture = nullptr; + if (frame->format == AV_PIX_FMT_VIDEOTOOLBOX) { - if (!createTexturesFromFrame(frame, cvMetalTextures)) { + + // Create Metal textures for the planes of the CVPixelBuffer + + switch (CVPixelBufferGetPixelFormatType(pixBuf)) { + case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: + case kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange: + case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: + case kCVPixelFormatType_444YpCbCr8BiPlanarFullRange: + m_LumaPixelFormart = MTLPixelFormatR8Unorm; + m_ChromaPixelFormart = MTLPixelFormatRG8Unorm; + break; + case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: + case kCVPixelFormatType_444YpCbCr10BiPlanarFullRange: + case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: + case kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange: + m_LumaPixelFormart = MTLPixelFormatR16Unorm; + m_ChromaPixelFormart = MTLPixelFormatRG16Unorm; + break; + default: + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "Unknown pixel format: %x", + CVPixelBufferGetPixelFormatType(pixBuf)); + return; + } + + CVReturn err; + + err = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, + m_TextureCache, + pixBuf, + nullptr, + m_LumaPixelFormart, + CVPixelBufferGetWidthOfPlane(pixBuf, 0), + CVPixelBufferGetHeightOfPlane(pixBuf, 0), + 0, + &cvLumaTexture); + if (err != kCVReturnSuccess) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "CVMetalTextureCacheCreateTextureFromImage() failed: %d", + err); + return; + } + + err = CVMetalTextureCacheCreateTextureFromImage(kCFAllocatorDefault, + m_TextureCache, + pixBuf, + nullptr, + m_ChromaPixelFormart, + CVPixelBufferGetWidthOfPlane(pixBuf, 1), + CVPixelBufferGetHeightOfPlane(pixBuf, 1), + 1, + &cvChromaTexture); + if (err != kCVReturnSuccess) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, + "CVMetalTextureCacheCreateTextureFromImage() failed: %d", + err); + CFRelease(cvLumaTexture); return; } } + id commandBuffer = [m_CommandQueue commandBuffer]; + + if(frame->format == AV_PIX_FMT_VIDEOTOOLBOX && m_VideoEnhancement->isVideoEnhancementEnabled()){ + m_LumaWidth = CVPixelBufferGetWidthOfPlane(pixBuf, 0); + m_LumaHeight = CVPixelBufferGetHeightOfPlane(pixBuf, 0); + m_ChromaWidth = CVPixelBufferGetWidthOfPlane(pixBuf, 1); + m_ChromaHeight = CVPixelBufferGetHeightOfPlane(pixBuf, 1); + + // Setup the Spatial scaler for Luma texture + if(m_LumaUpscaler == nullptr){ + MTLFXSpatialScalerDescriptor* Ldescriptor = [MTLFXSpatialScalerDescriptor new]; + Ldescriptor.inputWidth = m_LumaWidth; + Ldescriptor.inputHeight = m_LumaHeight; + Ldescriptor.outputWidth = m_LastDrawableWidth; + Ldescriptor.outputHeight = m_LastDrawableHeight; + Ldescriptor.colorTextureFormat = m_LumaPixelFormart; + Ldescriptor.outputTextureFormat = m_LumaPixelFormart; + // Perceptual is faster than Linear, Linear for HDR only + Ldescriptor.colorProcessingMode = m_IsTexture10bits ? + MTLFXSpatialScalerColorProcessingModeLinear + : MTLFXSpatialScalerColorProcessingModePerceptual; + m_LumaUpscaler = [Ldescriptor newSpatialScalerWithDevice:m_MetalLayer.device]; + [Ldescriptor release]; + + MTLTextureDescriptor *LtextureDescriptor = [[MTLTextureDescriptor alloc] init]; + LtextureDescriptor.pixelFormat = m_LumaPixelFormart; + LtextureDescriptor.width = m_LastDrawableWidth; + LtextureDescriptor.height = m_LastDrawableHeight; + LtextureDescriptor.storageMode = MTLStorageModePrivate; + LtextureDescriptor.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget; + + m_LumaUpscaledTexture = [m_MetalLayer.device newTextureWithDescriptor:LtextureDescriptor]; + } + + // Setup the Spacial scaler for Chroma texture + if(m_ChromaUpscaler == nullptr){ + + // Using Bilinear does not have have visual impact on Chroma and is faster to upscale than Lanczos + m_ChromaUpscaler = [[MPSImageBilinearScale alloc] initWithDevice:m_MetalLayer.device]; + // m_ChromaUpscaler = [[MPSImageLanczosScale alloc] initWithDevice:m_MetalLayer.device]; + m_ChromaUpscaler.edgeMode = MPSImageEdgeModeClamp; + + MTLTextureDescriptor* CtextureDescriptor = [MTLTextureDescriptor + texture2DDescriptorWithPixelFormat:m_ChromaPixelFormart + width:m_LastDrawableWidth + height:m_LastDrawableHeight + mipmapped:NO]; + CtextureDescriptor.storageMode = MTLStorageModePrivate; + CtextureDescriptor.usage = MTLTextureUsageShaderRead | MTLTextureUsageShaderWrite; + + m_ChromaUpscaledTexture = [m_MetalLayer.device newTextureWithDescriptor:CtextureDescriptor]; + } + + m_LumaUpscaler.colorTexture = CVMetalTextureGetTexture(cvLumaTexture); + m_LumaUpscaler.outputTexture = m_LumaUpscaledTexture; + [m_LumaUpscaler encodeToCommandBuffer:commandBuffer]; + + [m_ChromaUpscaler encodeToCommandBuffer:commandBuffer + sourceTexture:CVMetalTextureGetTexture(cvChromaTexture) + destinationTexture:m_ChromaUpscaledTexture]; + } + // Prepare a render pass to render into the next drawable - auto renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; + MTLRenderPassDescriptor *renderPassDescriptor = [MTLRenderPassDescriptor renderPassDescriptor]; renderPassDescriptor.colorAttachments[0].texture = drawable.texture; renderPassDescriptor.colorAttachments[0].loadAction = MTLLoadActionClear; renderPassDescriptor.colorAttachments[0].clearColor = MTLClearColorMake(0.0, 0.0, 0.0, 0.0); renderPassDescriptor.colorAttachments[0].storeAction = MTLStoreActionStore; - auto commandBuffer = [m_CommandQueue commandBuffer]; - auto renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; + + id renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor]; // Bind textures and buffers then draw the video region [renderEncoder setRenderPipelineState:m_VideoPipelineState]; if (frame->format == AV_PIX_FMT_VIDEOTOOLBOX) { - for (size_t i = 0; i < planes; i++) { - [renderEncoder setFragmentTexture:CVMetalTextureGetTexture(cvMetalTextures[i]) atIndex:i]; + if(m_VideoEnhancement->isVideoEnhancementEnabled()){ + // Use scaled textures + [renderEncoder setFragmentTexture:m_LumaUpscaledTexture atIndex:0]; + [renderEncoder setFragmentTexture:m_ChromaUpscaledTexture atIndex:1]; + } else { + [renderEncoder setFragmentTexture:CVMetalTextureGetTexture(cvLumaTexture) atIndex:0]; + [renderEncoder setFragmentTexture:CVMetalTextureGetTexture(cvChromaTexture) atIndex:1]; } + [commandBuffer addCompletedHandler:^(id) { // Free textures after completion of rendering per CVMetalTextureCache requirements - for (size_t i = 0; i < planes; i++) { - CFRelease(cvMetalTextures[i]); - } + if(cvLumaTexture != nullptr) CFRelease(cvLumaTexture); + if(cvChromaTexture != nullptr) CFRelease(cvChromaTexture); }]; } else { @@ -568,8 +723,11 @@ virtual void renderFrameIntoDrawable(AVFrame* frame, id drawabl [commandBuffer presentDrawable:drawable]; [commandBuffer commit]; - // Wait for the command buffer to complete and free our CVMetalTextureCache references - [commandBuffer waitUntilCompleted]; + // Note: cvLumaTexture and cvChromaTexture are already released, waitUntilCompleted should be unecessary now + if(!m_VideoEnhancement->isVideoEnhancementEnabled()){ + // Wait for the command buffer to complete and free our CVMetalTextureCache references + [commandBuffer waitUntilCompleted]; + } }} // Caller frees frame after we return @@ -662,8 +820,12 @@ virtual bool initialize(PDECODER_PARAMETERS params) override int err; m_Window = params->window; + m_DecoderParams = *params; m_FrameRateRange = CAFrameRateRangeMake(params->frameRate, params->frameRate, params->frameRate); + // Check if HDR is enabled by the user in the UI settings. + m_IsTexture10bits = m_DecoderParams.videoFormat & VIDEO_FORMAT_MASK_10BIT; + id device = getMetalDevice(); if (!device) { m_InitFailureReason = InitFailureReason::NoSoftwareSupport; @@ -678,6 +840,15 @@ virtual bool initialize(PDECODER_PARAMETERS params) override return false; } + // Video Super Resolution from MetalFX is available starting from MacOS 13+ + if (@available(macOS 13.0, *) && m_DecoderParams.enableVideoEnhancement) { + // Check if the user has enable Video enhancement + m_VideoEnhancement->setVSRcapable(true); + m_VideoEnhancement->setAlgo("MetalFX"); + } else { + m_VideoEnhancement->enableVideoEnhancement(false); + } + err = av_hwdevice_ctx_create(&m_HwContext, AV_HWDEVICE_TYPE_VIDEOTOOLBOX, nullptr, @@ -943,6 +1114,7 @@ void renderLatestFrameOnDrawable(id drawable, CFTimeInterval ta CAMetalLayer* m_MetalLayer; CAMetalDisplayLink* m_MetalDisplayLink API_AVAILABLE(macos(14.0)); CAFrameRateRange m_FrameRateRange; + bool m_IsTexture10bits = false; AVFrame* m_LatestUnrenderedFrame; SDL_mutex* m_FrameLock; SDL_cond* m_FrameReady; @@ -961,6 +1133,19 @@ void renderLatestFrameOnDrawable(id drawable, CFTimeInterval ta int m_LastFrameHeight; int m_LastDrawableWidth; int m_LastDrawableHeight; + + VideoEnhancement* m_VideoEnhancement; + DECODER_PARAMETERS m_DecoderParams; + id m_LumaUpscaledTexture; + id m_LumaUpscaler; + id m_ChromaUpscaledTexture; + MPSImageBilinearScale* m_ChromaUpscaler; + size_t m_LumaWidth; + size_t m_LumaHeight; + size_t m_ChromaWidth; + size_t m_ChromaHeight; + MTLPixelFormat m_LumaPixelFormart; + MTLPixelFormat m_ChromaPixelFormart; }; @implementation DisplayLinkDelegate { diff --git a/app/streaming/video/ffmpeg.cpp b/app/streaming/video/ffmpeg.cpp index c20d31266..5c7f11029 100644 --- a/app/streaming/video/ffmpeg.cpp +++ b/app/streaming/video/ffmpeg.cpp @@ -16,6 +16,7 @@ extern "C" { #ifdef Q_OS_WIN32 #include "ffmpeg-renderers/dxva2.h" #include "ffmpeg-renderers/d3d11va.h" +#include "ffmpeg-renderers/d3d12va.h" #endif #ifdef Q_OS_DARWIN @@ -236,7 +237,8 @@ FFmpegVideoDecoder::FFmpegVideoDecoder(bool testOnly) m_NeedsSpsFixup(false), m_TestOnly(testOnly), m_CurrentTestMode(TestMode::TestFrameOnly), - m_DecoderThread(nullptr) + m_DecoderThread(nullptr), + m_VideoEnhancement(&VideoEnhancement::getInstance()) { SDL_zero(m_ActiveWndVideoStats); SDL_zero(m_LastWndVideoStats); @@ -912,6 +914,21 @@ void FFmpegVideoDecoder::stringifyVideoStats(VIDEO_STATS& stats, char* output, i offset += ret; } + if(m_VideoEnhancement->isVideoEnhancementEnabled()){ + std::string videoEnhanced = "Video Enhancement: (x%.2f) %s\n"; + ret = snprintf(&output[offset], + length - offset, + videoEnhanced.c_str(), + m_VideoEnhancement->getRatio(), + m_VideoEnhancement->getAlgo().c_str()); + if (ret < 0 || ret >= length - offset) { + SDL_assert(false); + return; + } + + offset += ret; + } + ret = snprintf(&output[offset], length - offset, "Incoming frame rate from network: %.2f FPS\n" @@ -979,7 +996,7 @@ void FFmpegVideoDecoder::stringifyVideoStats(VIDEO_STATS& stats, char* output, i void FFmpegVideoDecoder::logVideoStats(VIDEO_STATS& stats, const char* title) { if (stats.renderedFps > 0 || stats.renderedFrames != 0) { - char videoStatsStr[512]; + char videoStatsStr[800]; stringifyVideoStats(stats, videoStatsStr, sizeof(videoStatsStr)); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, @@ -996,6 +1013,47 @@ IFFmpegRenderer* FFmpegVideoDecoder::createHwAccelRenderer(const AVCodecHWConfig return nullptr; } + // For Upscaling, only allow some decoders + if (params->enableVideoEnhancement) { + switch (hwDecodeCfg->device_type) { +#ifdef Q_OS_WIN32 + case AV_HWDEVICE_TYPE_D3D11VA: + break; + case AV_HWDEVICE_TYPE_D3D12VA: + break; +#endif +#ifdef Q_OS_DARWIN + case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: + break; +#endif +#ifdef HAVE_LIBPLACEBO_VULKAN + case AV_HWDEVICE_TYPE_VULKAN: + break; +#endif + default: + return nullptr; + break; + } + } + + // Keep track of the Device Type selected + VideoEnhancement::getInstance().setDeviceType(hwDecodeCfg->device_type); + + bool enableVideoEnhancement = params->enableVideoEnhancement; +#ifdef Q_OS_WIN32 + // D3D11VA is only reached with enhancement requested when the D3D12 renderer + // is unusable on this system. That renderer is the one providing the upscaler, + // so the session runs without enhancement rather than advertising a missing one. + if (enableVideoEnhancement && + hwDecodeCfg->device_type == AV_HWDEVICE_TYPE_D3D11VA && + !VideoEnhancement::getInstance().isD3D12Available()) { + enableVideoEnhancement = false; + } +#endif + + // Reset Video enhancer enabler + VideoEnhancement::getInstance().enableVideoEnhancement(enableVideoEnhancement); + // First pass using our top-tier hwaccel implementations if (pass == 0) { switch (hwDecodeCfg->device_type) { @@ -1003,7 +1061,16 @@ IFFmpegRenderer* FFmpegVideoDecoder::createHwAccelRenderer(const AVCodecHWConfig // DXVA2 appears in the hwaccel list before D3D11VA, so we only check for D3D11VA // on the first pass to ensure we prefer D3D11VA over DXVA2. case AV_HWDEVICE_TYPE_D3D11VA: - return new D3D11VARenderer(pass); + if (!params->enableVideoEnhancement || !VideoEnhancement::getInstance().isD3D12Available()){ + return new D3D11VARenderer(pass); + } + // Do not break here + case AV_HWDEVICE_TYPE_D3D12VA: + if (!VideoEnhancement::getInstance().isD3D12Available()){ + return nullptr; + } + // D3D12VARenderer is also able to receive frame from AV_HWDEVICE_TYPE_D3D11VA via Interop + return new D3D12VARenderer(pass); #endif #ifdef Q_OS_DARWIN case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: @@ -1059,13 +1126,22 @@ IFFmpegRenderer* FFmpegVideoDecoder::createHwAccelRenderer(const AVCodecHWConfig return new CUDARenderer(); #endif #ifdef Q_OS_WIN32 - // This gives us another shot if D3D11VA failed in the first pass. + // This gives us another shot if D3D11VA/D3D12VA failed in the first pass. // Since DXVA2 is in the hwaccel list first, we'll first try to fall back - // to that before giving D3D11VA another try as a last resort. + // to that before giving D3D11VA/D3D12VA another try as a last resort. case AV_HWDEVICE_TYPE_DXVA2: return new DXVA2Renderer(pass); case AV_HWDEVICE_TYPE_D3D11VA: - return new D3D11VARenderer(pass); + if (!params->enableVideoEnhancement || !VideoEnhancement::getInstance().isD3D12Available()){ + return new D3D11VARenderer(pass); + } + // Do not break here + case AV_HWDEVICE_TYPE_D3D12VA: + if (!VideoEnhancement::getInstance().isD3D12Available()){ + return nullptr; + } + // D3D12VARenderer is also able to receive frame from AV_HWDEVICE_TYPE_D3D11VA via Interop + return new D3D12VARenderer(pass); #endif #ifdef Q_OS_DARWIN case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: @@ -1531,6 +1607,41 @@ bool FFmpegVideoDecoder::tryInitializeHwAccelDecoder(PDECODER_PARAMETERS params, continue; } + // Check if any hwaccel hardware has Video Super Resolution available. + // We can loop on the Decoder, it shares the same GPU backend as the Renderer. + // Video Super Resolution is working via the renderes: D3D12 (Windows), VideoToolBox (Mac), Vulkan (Linux) + if (!VideoEnhancement::getInstance().isAvailable()) { + VideoEnhancement::getInstance().setAvailable(false); + for (int i = 0;; i++) { + const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i); + if (!config) { + // No remaining hwaccel options + break; + } + + switch (config->device_type) { +#ifdef Q_OS_WIN32 + case AV_HWDEVICE_TYPE_D3D12VA: + VideoEnhancement::getInstance().setAvailable(true); + break; +#endif +#ifdef Q_OS_DARWIN + case AV_HWDEVICE_TYPE_VIDEOTOOLBOX: + VideoEnhancement::getInstance().setAvailable(true); + break; +#endif +#ifdef HAVE_LIBPLACEBO_VULKAN + case AV_HWDEVICE_TYPE_VULKAN: + VideoEnhancement::getInstance().setAvailable(true); + break; +#endif + default: + break; + } + + } + } + // Look for the first matching hwaccel hardware decoder for (int i = 0;; i++) { const AVCodecHWConfig *config = avcodec_get_hw_config(decoder, i); diff --git a/app/streaming/video/ffmpeg.h b/app/streaming/video/ffmpeg.h index 1e9e9d185..c3d3b4eba 100644 --- a/app/streaming/video/ffmpeg.h +++ b/app/streaming/video/ffmpeg.h @@ -8,6 +8,7 @@ #include "decoder.h" #include "ffmpeg-renderers/renderer.h" #include "ffmpeg-renderers/pacer/pacer.h" +#include "streaming/video/videoenhancement.h" extern "C" { #include @@ -32,6 +33,8 @@ class FFmpegVideoDecoder : public IVideoDecoder { virtual IFFmpegRenderer* getBackendRenderer(); + const VIDEO_STATS& getGlobalVideoStats() const; + private: enum class TestMode { // No test frame and prepare for rendering @@ -132,6 +135,7 @@ class FFmpegVideoDecoder : public IVideoDecoder { TestMode m_CurrentTestMode; SDL_Thread* m_DecoderThread; SDL_atomic_t m_DecoderThreadShouldQuit; + VideoEnhancement* m_VideoEnhancement; // Data buffers in the queued DU are not valid QQueue m_FrameInfoQueue; diff --git a/app/streaming/video/videoenhancement.cpp b/app/streaming/video/videoenhancement.cpp new file mode 100644 index 000000000..3909ec5d1 --- /dev/null +++ b/app/streaming/video/videoenhancement.cpp @@ -0,0 +1,291 @@ +#include "videoenhancement.h" +#include + +/** + * \brief Constructor (Singleton) + * + * VideoEnhancement does not set its properties automatically at instance initiation. + * Therefore, it needs to be populated at the initialization of + * the renderer who makes use of it. + * + * \return void + */ +VideoEnhancement::VideoEnhancement(){} + +/** + * \brief Get the singleton instance + * + * Render the instance of the singleton + * + * \return VideoEnhancement instance + */ +VideoEnhancement &VideoEnhancement::getInstance(){ + static VideoEnhancement instance; + return instance; +} + +/** + * \brief Set the Adapter Index + * + * \param int adapterIndex + * \return void + */ +void VideoEnhancement::setAdapterIndex(int adapterIndex){ + m_AdapterIndex = adapterIndex; +} + +/** + * \brief Get the Adapter Index + * + * \return int Returns the Index of the most capable adapter for Video enhancement + */ +int VideoEnhancement::getAdapterIndex(){ + return m_AdapterIndex; +} + +/** + * \brief Set Vendor ID + * + * \param int vendorId + * \return void + */ +void VideoEnhancement::setVendorID(int vendorId){ + m_VendorId = vendorId; +} + +/** + * \brief Check if the vendor is AMD + * + * \return bool Returns true is the vendor is AMD + */ +bool VideoEnhancement::isVendorAMD(){ + return m_VendorId == VENDOR_ID_AMD; +} + +/** + * \brief Check if the vendor is Intel + * + * \return bool Returns true is the vendor is Intel + */ +bool VideoEnhancement::isVendorIntel(){ + return m_VendorId == VENDOR_ID_INTEL; +} + +/** + * \brief Check if the vendor is NVIDIA + * + * \return bool Returns true is the vendor is NVIDIA + */ +bool VideoEnhancement::isVendorNVIDIA(){ + return m_VendorId == VENDOR_ID_NVIDIA; +} + +/** + * \brief Check if the vendor is Qualcomm + * + * \return bool Returns true is the vendor is Qualcomm + */ +bool VideoEnhancement::isVendorQualcomm(){ + return m_VendorId == VENDOR_ID_QUALCOMM + || m_VendorId == VENDOR_ID_QUALCOMM2; +} + +/** + * \brief Set the Video Super-Resolution availability + * + * Keep track if the adapter has Video Super-Resolution available + * + * \param bool available, at False the feature is uncheckable in the setting + * \return void + */ +void VideoEnhancement::setAvailable(bool available){ + m_Available = available; +} + +/** + * \brief Check the Video Super-Resolution availability + * + * Check if the GPU adapter has Video Super-Resolution available + * + * \return bool Returns true if the VSR feature is available + */ +bool VideoEnhancement::isAvailable(){ + return m_Available; +} + +/** + * \brief Set the Video Super-Resolution capability + * + * Keep track if the adapter is capable of the Driver Video Super-Resolution + * + * \param bool capable + * \return void + */ +void VideoEnhancement::setVSRcapable(bool capable){ + m_VSRcapable = capable; +} + +/** + * \brief Check the Video Super-Resolution capability + * + * Check if the GPU used is capable of providing Driver VSR feature + * + * \return bool Returns true if the Driver VSR feature is available + */ +bool VideoEnhancement::isVSRcapable(){ + return m_VSRcapable; +} + +/** + * \brief Set the HDR capability + * + * Keep track if the adapter is capable of SDR to HDR by the Driver + * + * \param bool capable + * \return void + */ +void VideoEnhancement::setHDRcapable(bool capable){ + m_HDRcapable = capable; +} + +/** + * \brief Check the HDR capability + * + * Check if the GPU used is capable of providing the Driver SDR to HDR feature + * + * \return bool Returns true if the HDR feature is available + */ +bool VideoEnhancement::isHDRcapable(){ + return m_HDRcapable; +} + +/** + * \brief Set the D3D12 renderer availability + * + * The D3D12 renderer needs interfaces that are missing on older Windows releases. + * Once its initialization has failed, there is no point retrying it for the rest + * of the process, and the D3D11 renderer must be allowed to take over. + * + * \param bool available + * \return void + */ +void VideoEnhancement::setD3D12Available(bool available){ + m_D3D12Available = available; +} + +/** + * \brief Check the D3D12 renderer availability + * + * \return bool Returns false if the D3D12 renderer already failed to initialize + */ +bool VideoEnhancement::isD3D12Available(){ + return m_D3D12Available; +} + +/** + * \brief Check if Video Enhancement feature is enabled + * + * \return bool Returns true if the Video Enhancement feature is enabled + */ +bool VideoEnhancement::isVideoEnhancementEnabled(){ + return m_Enabled; +} + +/** + * \brief Enable Video Enhancement feature + * + * \param bool activate Default is true, at true it enables the use of Video Enhancement feature + * \return bool Returns true if the Video Enhancement feature is available + */ +bool VideoEnhancement::enableVideoEnhancement(bool activate){ + m_Enabled = m_Available && activate; + return m_Enabled; +} + +/** + * \brief Set the upscaling Ratio + * + * Set the value of the ratio which must be TextureOutputHeight/TextureInputHeight. + * + * \param float ratio + * \return void + */ +void VideoEnhancement::setRatio(float ratio){ + m_Ratio = ratio; +} + +/** + * \brief Get the upscaling Ratio + * + * Return the value of the upscaling ratio Output/Input. + * + * \return float Returns the upscaling Ratio + */ +float VideoEnhancement::getRatio(){ + return m_Ratio; +} + +/** + * \brief Set the upscaling Algorythm + * + * Set the value of the algorythm used to do the upscaling. + * + * \param std::string algo + * \return void + */ +void VideoEnhancement::setAlgo(std::string algo){ + m_Algo = algo; +} + +/** + * \brief Get the upscaling Algorythm + * + * Return the value of algorythm used to do the upscaling. + * + * \return float Returns the upscaling Algorythm + */ +std::string VideoEnhancement::getAlgo(){ + return m_Algo; +} + +/** + * \brief Set Integrated GPU + * + * Set the information that the GPU is integrated to the CPU (iGPU), or a discrete GPU + * + * \param bool isIntegratedGPU + * \return void + */ +void VideoEnhancement::setIntegratedGPU(bool isIntegratedGPU){ + m_IsIntegratedGPU = isIntegratedGPU; +} + +/** + * \brief Get Integrated GPU + * + * \return bool Returns true for iGPU, false for dGPU + */ +bool VideoEnhancement::isIntegratedGPU(){ + return m_IsIntegratedGPU; +} + +/** + * \brief Set AV Hardware Device Type + * + * Keep the information about the Device Type used + * + * \param int deviceType + * \return void + */ +void VideoEnhancement::setDeviceType(int deviceType){ + m_DeviceType = deviceType; +} + +/** + * \brief Get AV Hardware Device Type + * + * \return int Returns the Device type used, equivalent to AVHWDeviceType + */ +int VideoEnhancement::getDeviceType(){ + return m_DeviceType; +} diff --git a/app/streaming/video/videoenhancement.h b/app/streaming/video/videoenhancement.h new file mode 100644 index 000000000..934c3975d --- /dev/null +++ b/app/streaming/video/videoenhancement.h @@ -0,0 +1,75 @@ +#ifndef VIDEOENHANCEMENT_H +#define VIDEOENHANCEMENT_H + +#include + +#pragma once + +class VideoEnhancement +{ + +private: + + static VideoEnhancement* instance; + + // By default we make it unavailable + bool m_Available = false; + bool m_Enabled = false; + bool m_VSRcapable = false; + bool m_HDRcapable = false; + // Set to false once the D3D12 renderer proved it cannot be created on this system + bool m_D3D12Available = true; + float m_Ratio; + std::string m_Algo; + int m_DeviceType; + + // Vendors' name (PCI Special Interest Group) + const int VENDOR_ID_AMD = 0x1002; + const int VENDOR_ID_INTEL = 0x8086; + const int VENDOR_ID_NVIDIA = 0x10DE; + const int VENDOR_ID_QUALCOMM = 0x17CB; + const int VENDOR_ID_QUALCOMM2 = 0x4D4F4351; + + // GPU information + int m_VendorId = 0; + int m_AdapterIndex = -1; + bool m_IsIntegratedGPU = false; + + // Disable the constructor from outside to avoid a new instance + VideoEnhancement(); + + // Private copy constructor and assignment operator to prevent duplication + VideoEnhancement(const VideoEnhancement&); + VideoEnhancement& operator=(const VideoEnhancement&); + +public: + static VideoEnhancement& getInstance(); + void setVendorID(int vendorId); + bool isVendorAMD(); + bool isVendorIntel(); + bool isVendorNVIDIA(); + bool isVendorQualcomm(); + void setAvailable(bool available); + bool isAvailable(); + void setVSRcapable(bool capable); + bool isVSRcapable(); + void setHDRcapable(bool capable); + bool isHDRcapable(); + void setD3D12Available(bool available); + bool isD3D12Available(); + bool isVideoEnhancementEnabled(); + bool enableVideoEnhancement(bool activate = true); + void setAdapterIndex(int adapterIndex); + int getAdapterIndex(); + void setRatio(float ratio); + float getRatio(); + void setAlgo(std::string algo); + std::string getAlgo(); + void setIntegratedGPU(bool isIntegratedGPU); + bool isIntegratedGPU(); + void setDeviceType(int deviceType); + int getDeviceType(); + +}; + +#endif // VIDEOENHANCEMENT_H diff --git a/scripts/build-arch.bat b/scripts/build-arch.bat index aff4a249d..a6c48d18d 100644 --- a/scripts/build-arch.bat +++ b/scripts/build-arch.bat @@ -234,6 +234,22 @@ echo Copying AntiHooking.dll copy %BUILD_FOLDER%\AntiHooking\%BUILD_CONFIG%\AntiHooking.dll %DEPLOY_FOLDER% if !ERRORLEVEL! NEQ 0 goto Error +echo Copying dxcompiler.dll +copy %SOURCE_ROOT%\third-party\DirectXShaderCompiler\bin\%ARCH%\dxcompiler.dll %DEPLOY_FOLDER% +if !ERRORLEVEL! NEQ 0 goto Error + +echo Copying nvngx_vsr.dll +copy %SOURCE_ROOT%\third-party\RTX_Video_SDK\bin\Windows\%ARCH%\rel\nvngx_vsr.dll %DEPLOY_FOLDER% +if !ERRORLEVEL! NEQ 0 goto Error + +echo Copying nvngx_truehdr.dll +copy %SOURCE_ROOT%\third-party\RTX_Video_SDK\bin\Windows\%ARCH%\rel\nvngx_truehdr.dll %DEPLOY_FOLDER% +if !ERRORLEVEL! NEQ 0 goto Error + +echo Copying libvpl.dll +copy %SOURCE_ROOT%\third-party\IntelVPL\%ARCH%\bin\libvpl.dll %DEPLOY_FOLDER% +if !ERRORLEVEL! NEQ 0 goto Error + echo Copying GC mapping list copy %SOURCE_ROOT%\app\SDL_GameControllerDB\gamecontrollerdb.txt %DEPLOY_FOLDER% if !ERRORLEVEL! NEQ 0 goto Error diff --git a/third-party/AMF b/third-party/AMF new file mode 160000 index 000000000..16f7d73e0 --- /dev/null +++ b/third-party/AMF @@ -0,0 +1 @@ +Subproject commit 16f7d73e0b45c473e903e46981ed0b91efc4c091 diff --git a/third-party/DirectX-Headers b/third-party/DirectX-Headers new file mode 160000 index 000000000..e2593647e --- /dev/null +++ b/third-party/DirectX-Headers @@ -0,0 +1 @@ +Subproject commit e2593647eec33a204db6cc6fb38e132fc19a8557 diff --git a/third-party/DirectXShaderCompiler/LICENSE-LLVM.txt b/third-party/DirectXShaderCompiler/LICENSE-LLVM.txt new file mode 100644 index 000000000..f7d5c8ee5 --- /dev/null +++ b/third-party/DirectXShaderCompiler/LICENSE-LLVM.txt @@ -0,0 +1,43 @@ +============================================================================== +LLVM Release License +============================================================================== +University of Illinois/NCSA +Open Source License + +Copyright (c) 2003-2015 University of Illinois at Urbana-Champaign. +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. diff --git a/third-party/DirectXShaderCompiler/LICENSE-MIT.txt b/third-party/DirectXShaderCompiler/LICENSE-MIT.txt new file mode 100644 index 000000000..44378268b --- /dev/null +++ b/third-party/DirectXShaderCompiler/LICENSE-MIT.txt @@ -0,0 +1,21 @@ +Copyright (c) Microsoft Corporation. + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/third-party/DirectXShaderCompiler/LICENSE-MS.txt b/third-party/DirectXShaderCompiler/LICENSE-MS.txt new file mode 100644 index 000000000..384b174e0 --- /dev/null +++ b/third-party/DirectXShaderCompiler/LICENSE-MS.txt @@ -0,0 +1,158 @@ +MICROSOFT SOFTWARE LICENSE TERMS + +MICROSOFT DIRECTX SHADER COMPILER + +These license terms are an agreement between you and Microsoft +Corporation (or one of its affiliates). They apply to the software named +above and any Microsoft services or software updates (except to the +extent such services or updates are accompanied by new or additional +terms, in which case those different terms apply prospectively and do +not alter your or Microsoft’s rights relating to pre-updated software or +services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS +BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. + +INSTALLATION AND USE RIGHTS. + +General. Subject to the terms of this agreement, you may install and use any number of copies of the software, and solely for use on Windows. + +Included Microsoft Applications. The software may include other Microsoft applications. These license terms apply to those included applications, if any, unless other license terms are provided with the other Microsoft applications. + +Microsoft Platforms. The software may include components from Microsoft Windows. These components are governed by separate agreements and their own product support policies, as described in the license terms found in the installation directory for that component or in the “Licenses†folder accompanying the software. + +Third Party Components. The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. + +DATA. + +Data Collection. The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation.  There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at https://aka.ms/privacy. Your use of the software operates as your consent to these practices. + +Processing of Personal Data. To the extent Microsoft is a processor or subprocessor of personal data in connection with the software, Microsoft makes the commitments in the European Union General Data Protection Regulation Terms of the Online Services Terms to all customers effective May 25, 2018, at https://docs.microsoft.com/en-us/legal/gdpr. + +DISTRIBUTABLE CODE. The software may contain code you are permitted to distribute (i.e. make available for third parties) in applications you develop, as described in this Section. + +Distribution Rights. The code and test files described below are distributable if included with the software. + +Distributables. You may copy and distribute the object code form of the software listed in the distributables file list in the software; and + +Third Party Distribution. You may permit distributors of your applications to copy and distribute any of this distributable code you elect to distribute with your applications. + +Distribution Requirements. For any code you distribute, you must: + +add significant primary functionality to it in your applications; + +i. require distributors and external end users to agree to terms that protect it and Microsoft at least as much as this agreement; and + +ii. indemnify, defend, and hold harmless Microsoft from any claims, including attorneys’ fees, related to the distribution or use of your applications, except to the extent that any claim is based solely on the unmodified distributable code. + +Distribution Restrictions. You may not: + +use Microsoft’s trademarks or trade dress in your application in any way that suggests your application comes from or is endorsed by Microsoft; or modify or distribute the source code of any distributable code so that any part of it becomes subject to any license that requires that the distributable code, any other part of the software, or any of Microsoft’s other intellectual property be disclosed or distributed in source code form, or that others have the right to modify it. + +SCOPE OF LICENSE. The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): + +work around any technical limitations in the software that only allow you to use it in certain ways; + +reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the software; + +remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software; + +use the software in any way that is against the law or to create or propagate malware; or + +share, publish, distribute, or lease the software (except for any distributable code, subject to the terms above), provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. + +EXPORT RESTRICTIONS. You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit https://aka.ms/exporting. + +SUPPORT SERVICES. Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as isâ€, “with all faultsâ€, and without warranty of any kind. + +UPDATES. The software may periodically check for updates, and download and install them for you. You may obtain updates only from Microsoft or authorized sources. Microsoft may need to update your system to provide you with updates. You agree to receive these automatic updates without any additional notice. Updates may not include or support all existing software features, services, or peripheral devices. + +ENTIRE AGREEMENT. This agreement, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software. + +APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES. If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles. If you acquired the software in any other country, its laws apply. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court. If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court. + +CONSUMER RIGHTS; REGIONAL VARIATIONS. This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: + +a. Australia. You have statutory guarantees under the Australian + Consumer Law and nothing in this agreement is intended to affect + those rights. + +b. Canada. If you acquired this software in Canada, you may stop + receiving updates by turning off the automatic update feature, + disconnecting your device from the Internet (if and when you + re-connect to the Internet, however, the software will resume + checking for and installing updates), or uninstalling the software. + The product documentation, if any, may also specify how to turn off + updates for your specific device or software. + +c. Germany and Austria. + + i. Warranty. The properly licensed software will perform substantially + as described in any Microsoft materials that accompany the software. + However, Microsoft gives no contractual guarantee in relation to the + licensed software. + + ii. Limitation of Liability. In case of intentional conduct, gross + negligence, claims based on the Product Liability Act, as well as, in + case of death or personal or physical injury, Microsoft is liable + according to the statutory law. + +Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. + +DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.†YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. + +LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT, OR INCIDENTAL DAMAGES. + +This limitation applies to (a) anything related to the software, +services, content (including code) on third party Internet sites, or +third party applications; and (b) claims for breach of contract, +warranty, guarantee, or condition; strict liability, negligence, or +other tort; or any other claim; in each case to the extent permitted by +applicable law. + +It also applies even if Microsoft knew or should have known about the +possibility of the damages. The above limitation or exclusion may not +apply to you because your state, province, or country may not allow the +exclusion or limitation of incidental, consequential, or other damages. + +Please note: As this software is distributed in Canada, some of the +clauses in this agreement are provided below in French. + +Remarque: Ce logiciel étant distribué au Canada, certaines des clauses +dans ce contrat sont fournies ci-dessous en français. + +EXONÉRATION DE GARANTIE. Le logiciel visé par une licence est offert « +tel quel ». Toute utilisation de ce logiciel est à votre seule risque et +péril. Microsoft n’accorde aucune autre garantie expresse. Vous pouvez +bénéficier de droits additionnels en vertu du droit local sur la +protection des consommateurs, que ce contrat ne peut modifier. La ou +elles sont permises par le droit locale, les garanties implicites de +qualité marchande, d’adéquation à un usage particulier et d’absence de +contrefaçon sont exclues. + +LIMITATION DES DOMMAGES-INTÉRÊTS ET EXCLUSION DE RESPONSABILITÉ POUR LES +DOMMAGES. Vous pouvez obtenir de Microsoft et de ses fournisseurs une +indemnisation en cas de dommages directs uniquement à hauteur de 5,00 $ +US. Vous ne pouvez prétendre à aucune indemnisation pour les autres +dommages, y compris les dommages spéciaux, indirects ou accessoires et +pertes de bénéfices. + +Cette limitation concerne: + +• tout ce qui est relié au logiciel, aux services ou au contenu (y +compris le code) figurant sur des sites Internet tiers ou dans des +programmes tiers; et + +• les réclamations au titre de violation de contrat ou de garantie, ou +au titre de responsabilité stricte, de négligence ou d’une autre faute +dans la limite autorisée par la loi en vigueur. + +Elle s’applique également, même si Microsoft connaissait ou devrait +connaître l’éventualité d’un tel dommage. Si votre pays n’autorise pas +l’exclusion ou la limitation de responsabilité pour les dommages +indirects, accessoires ou de quelque nature que ce soit, il se peut que +la limitation ou l’exclusion ci-dessus ne s’appliquera pas à votre +égard. + +EFFET JURIDIQUE. Le présent contrat décrit certains droits juridiques. +Vous pourriez avoir d’autres droits prévus par les lois de votre pays. +Le présent contrat ne modifie pas les droits que vous confèrent les lois +de votre pays si celles-ci ne le permettent pas. diff --git a/third-party/DirectXShaderCompiler/ReleaseNotes.md b/third-party/DirectXShaderCompiler/ReleaseNotes.md new file mode 100644 index 000000000..a023d1d3f --- /dev/null +++ b/third-party/DirectXShaderCompiler/ReleaseNotes.md @@ -0,0 +1,219 @@ +# DirectX Shader Compiler Redistributable Package + +This package contains a copy of the DirectX Shader Compiler redistributable and its associated development headers. + +For help getting started, please see: + + + +## Licenses + +The included licenses apply to the following files: + +| License file | Applies to | +|---|---| +|LICENSE-MIT.txt |d3d12shader.h| +|LICENSE-LLVM.txt |all other files| + +## Changelog + +### Version 1.8.2505.1 + +- Fix regression: [#7510](https://github.com/microsoft/DirectXShaderCompiler/issues/7510) crash when calling `sizeof` on templated type. +- Fix regression: [#7508](https://github.com/microsoft/DirectXShaderCompiler/issues/7508) crash when calling `Load` with `status`. +- Header file `dxcpix.h` was added to the release package. + +### Version 1.8.2505 + +#### Potentially breaking changes + +- Typed buffers (including ROV buffers) no longer accept types other than vectors and scalars. Any other types will produce descriptive errors. This removes support for appropriately sized matrices and structs. Though it worked in some contexts, code generated from such types was unreliable. + - Load and Store operations have been refactored as a consequence. Behavior should be identical, please file issues if discrepancies are observed. +- The compiler will now always use the internal validator instead of searching for an external DXIL.dll. The (hidden) `-select-validator` option has been removed. + +#### Notable SPIR-V updates + +- Fix unnecessary Int64 requirement when loading Float64 +- Added vk::BufferPointer, see [proposal](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0010-vk-buffer-ref.md) for more details. +- Implement QuadAny and QuadAll (#7266) +- Fix -fvk-invert-y (#7447) + +#### Shader Model 6.9 Preview + +You can now compile shaders to SM 6.9, but this is a preview, so shader hashes will be set to the PREVIEW_BYPASS pattern. +SM 6.9 shaders will only work with AgilitySDK 1.717.0-preview, a supported preview driver, and use of experimental shader models in developer mode. +Preview shaders will not be compatible with the SM 6.9 release, or likely even later versions of the SM 6.9 preview. + +SM 6.9 Preview Additions: + +- Long vectors are allowed in HLSL when targeting shader model 6.9. Vectors up to 1024 elements in length can be loaded from/stored to raw buffers and used in elementwise operations. See the [long vector proposal](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0026-hlsl-long-vector-type.md) for more details. +- HLSL Vectors are still limited to a maximum of 4 elements when used in certain contexts: + - entry function inputs/outputs + - parameter, payload, attribute, and node record types for mesh, raytracing, and node shaders + - constant buffers (cbuffer), texture buffers (tbuffer), textures and typed buffers + - Note: some HLSL elementwise intrinsics do not yet support long vectors in this preview +- Native vectors of up to 1024 elements are now present in DXIL. This includes vector llvm instructions, load/store, and various elementwise DXIL operations. This may result in smaller DXIL and potentially other performance improvements. See the [dxil vectors proposal](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0030-dxil-vectors.md) for more details. +- Cooperative Vector operations, a subset of Linear Algebra (LinAlg). See the [cooperative vectors proposal](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0029-cooperative-vector.md) and the [HLSL header based API proposal](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0031-hlsl-vector-matrix-operations.md) for more details. + - New built-in operations are added for multiplying long vectors with a matrix in a ByteAddressBuffer, optionally with accumulation and bias data, as well as outer product and vector accumulate operations. + - An HLSL header shipped with this release provides a more convenient API for using these built-in operations. +- Support for [Opacity Micromaps](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0024-opacity-micromaps.md) in DXR shaders as well as for RayQuery. + - Unlocks DXR performance improvements using triangle sub-divisions for fast hit/miss detection to reduce the need for anyhit invocations. +- Support for [Shader Execution Reordering](https://github.com/microsoft/hlsl-specs/blob/main/proposals/0027-shader-execution-reordering.md) in DXR. + - Introduces `MaybeReorderThread()` to explicitly specify where and how shader execution coherence can be improved. `MaybeReorderThread()` can be used in raygeneration shaders. + - `HitObject` decouples traversal, intersection testing and anyhit shading from closesthit and miss shading for more control and better reordering opportunities. `HitObject` can be used in raygeneration, closesthit and miss shaders. + +### Version 1.8.2502 + +This cumulative release contains numerous bug fixes and stability improvements. + +Here are some highlights: + +- The incomplete WaveMatrix implementation has been removed. [#6807](https://github.com/microsoft/DirectXShaderCompiler/pull/6807) +- DXIL Validator Hash is open sourced. [#6846](https://github.com/microsoft/DirectXShaderCompiler/pull/6846) +- DXIL container validation for PSV0 part allows any content ordering inside string and semantic index tables. [#6859](https://github.com/microsoft/DirectXShaderCompiler/pull/6859) +- The and() and or() intrinsics will now accept non-integer parameters by casting them to bools. [#7060](https://github.com/microsoft/DirectXShaderCompiler/pull/7060) +- Released executables will now expect the filenames associated with the released pdbs. Instead of expecting `dxc_full.pdb`, `dxc.exe` will now expect `dxc.pdb`. + +### Version 1.8.2407 + +This cumulative release contains numerous bug fixes and stability improvments. + +Here are some highlights: + +- dxc generates invalid alignment on groupshared matrix load/store instructions in [#6416](https://github.com/microsoft/DirectXShaderCompiler/issues/6416) +- [Optimization] DXC is missing common factor optimization in some cases in [#6593](https://github.com/microsoft/DirectXShaderCompiler/issues/6593) +- [SPIR-V] Implement WaveMutliPrefix* in [#6600](https://github.com/microsoft/DirectXShaderCompiler/issues/6600) +- [SPIR-V] Implement SampleCmpLevel for SM6.7 in [#6613](https://github.com/microsoft/DirectXShaderCompiler/issues/6613) +- Avoid adding types to default namespace in [#6646](https://github.com/microsoft/DirectXShaderCompiler/issues/6646) +- Release notes once found in `README.md` can now be found in `ReleaseNotes.md` +- Fixed several bugs in the loop restructurizer. Shader developers who are using -opt-disable structurize-loop-exits-for-unroll to disable the loop restructurizer should consider removing that workaround. + +### Version 1.8.2405 + +DX Compiler Release for May 2024 + +This release includes two major new elements: + +- The introduction of the first component of HLSL 202x +- The inclusion of clang-built Windows binaries + +See [the official blog post](https://devblogs.microsoft.com/directx/dxc-1-8-2405-available) for a more detailed description of this release. + +HLSL 202x is a placeholder designation for what will ultimately be a new language version that further aligns HLSL with modern language features. It is intended to serve as a bridge to help transition to the expected behavior of the modernized compiler. + +To experiment with 202x, use the `-HV 202x` flag. We recommend enabling these warnings as well to catch potential changes in behavior: `-Wconversion -Wdouble-promotion -Whlsl-legacy-literal`. + +The first feature available in 202x updates HLSL's treatment of literals to better conform with C/C++. In previous versions, un-suffixed literal types targeted the highest possible precision. This feature revises that to mostly conform with C/C++ behavior. See the above blog post for details. + +Clang-built Windows binaries are included in addition to the MSVC-built binaries that have always been shipped before. The clang-built compiler is expected to improve HLSL compile times in many cases. We are eager for feedback about this build positive or negative, related to compile times or correctness. + +### Version 1.8.2403.2 + +DX Compiler Release for March 2024 - Patch 2 + +- Fix regression: [#6426](https://github.com/microsoft/DirectXShaderCompiler/issues/6426) Regression, SIGSEGV instead of diagnostics when encountering bool operator==(const T&, const T&). + +### Version 1.8.2403.1 + +DX Compiler Release for March 2024 - Patch 1 + +- Fix regression: [#6419](https://github.com/microsoft/DirectXShaderCompiler/issues/6419) crash when using literal arguments with `fmod`. + +### Version 1.8.2403 + +DX Compiler release for March 2024 + +- Shader Model 6.8 is fully supported + - Work Graphs allow node shaders with user-defined input and output payloads + - New Barrier builtin functions with specific memory types and semantics + - Expanded Comparison sampler intrinsics: SampleCmpBias, SampleCmpGrad, and CalculateLevelOfDetail + - StartVertexLocation and StartInstanceLocation semantics + - WaveSizeRange entry point attribute allows specifying a range of supported wave sizes +- Improved compile-time validation and runtime validation information +- Various stability improvements including numerous address sanitation fixes +- Several Diagnostic improvements + - Many diagnostics are generated earlier and with more detailed information + - Library profile diagnostic improvements + - No longer infer library shader type when not specified + - More helpful diagnostics for numthreads and other entry point attributes + - Validation errors more accurately determine usage by the entry point +- Improve debug info generation +- Further improvements to Linux build quality +- File paths arguments for `IDxcIncludeHandler::LoadSource` will now be normalized to use OS specific slashes + (`\` for windows, `/` for *nix) and no longer have double slashes except for UNC paths (`\\my\unc\path`).†+ +### Version 1.7.2308 + +DX Compiler release for August 2023 + +- HLSL 2021 is now enabled by default +- Various HLSL 2021 fixes have been made to + - Operator overloading fixes + - Templates fixes + - Select() with samplers + - Bitfields show in reflections + - Bitfields can be used on enums + - Allow function template default params +- Issues with loading and using Linux binaries have been resolved +- Support #pragma region/endregion +- Various stability and diagnostic improvements +- Dxcapi.h inline documentation is improved +- Linking of libraries created by different compilers is disallowed to prevent interface Issues +- Inout parameter correctness improved + +The package includes dxc.exe, dxcompiler.dll, corresponding lib and headers, and dxil.dll for x64 and arm64 platforms on Windows. +The package also includes Linux version of the compiler with corresponding executable, libdxcompiler.so, corresponding headers, and libdxil.so for x64 platforms. + +The new DirectX 12 Agility SDK (Microsoft.Direct3D.D3D12 nuget package) and a hardware driver with appropriate support +are required to run shader model 6.7 shaders. Please see for details. + +The SPIR-V backend of the compiler has been enabled in this release. + +### Version 1.7.2212 + +DX Compiler release for December 2022. + +- Includes full support of HLSL 2021 for SPIRV generation as well as many HLSL 2021 fixes and enhancements: + - HLSL 2021's `and`, `or` and `select` intrinsics are now exposed in all language modes. This was done to ease porting code bases to HLSL2021, but may cause name conflicts in existing code. + - Improved template utility with user-defined types + - Many additional bug fixes +- Linux binaries are now included. + This includes the compiler executable, the dynamic library, and the dxil signing library. +- New flags for inspecting compile times: + - `-ftime-report` flag prints a high level summary of compile time broken down by major phase or pass in the compiler. The DXC +command line will print the output to stdout. + - `-ftime-trace` flag prints a Chrome trace json file. The output can be routed to a specific file by providing a filename to +the argument using the format `-ftime-trace=`. Chrome trace files can be opened in Chrome by loading the built-in tracing tool +at chrome://tracing. The trace file captures hierarchial timing data with additional context enabling a much more in-depth profiling +experience. + - Both new options are supported via the DXC API using the `DXC_OUT_TIME_REPORT` and `DXC_OUT_TIME_TRACE` output kinds respectively. +- IDxcPdbUtils2 enables reading new PDB container part +- `-P` flag will now behave as it does with cl using the file specified by `-Fi` or a default +- Unbound multidimensional resource arrays are allowed +- Diagnostic improvements +- Reflection support on non-Windows platforms; minor updates adding RequiredFeatureFlags to library function reflection and thread group size for AS and MS. + +The package includes dxc.exe, dxcompiler.dll, corresponding lib and headers, and dxil.dll for x64 and arm64 platforms on Windows. +For the first time the package also includes Linux version of the compiler with corresponding executable, libdxcompiler.so, corresponding headers, and libdxil.so for x64 platforms. + +The new DirectX 12 Agility SDK (Microsoft.Direct3D.D3D12 nuget package) and a hardware driver with appropriate support +are required to run shader model 6.7 shaders. Please see for details. + +The SPIR-V backend of the compiler has been enabled in this release. Please note that Microsoft does not perform testing/verification of the SPIR-V backend. + +### Version 1.7.2207 + +DX Compiler release for July 2022. Contains shader model 6.7 and many bug fixes and improvements, such as: + +- Features: Shader Model 6.7 includes support for Raw Gather, Programmable Offsets, QuadAny/QuadAll, WaveOpsIncludeHelperLanes, and more! +- Platforms: ARM64 support +- HLSL 2021 : Enable “using†keyword +- Optimizations: Loop unrolling and dead code elimination improvements +- Developer tools: Improved disassembly output + +The package includes dxc.exe, dxcompiler.dll, corresponding lib and headers, and dxil.dll for x64 and, for the first time, arm64 platforms! + +The new DirectX 12 Agility SDK (Microsoft.Direct3D.D3D12 nuget package) and a hardware driver with appropriate support +are required to run shader model 6.7 shaders. Please see for details. + +The SPIR-V backend of the compiler has been enabled in this release. Please note that Microsoft does not perform testing/verification of the SPIR-V backend. diff --git a/third-party/DirectXShaderCompiler/bin/arm64/dxcompiler.dll b/third-party/DirectXShaderCompiler/bin/arm64/dxcompiler.dll new file mode 100644 index 000000000..d3192d60e Binary files /dev/null and b/third-party/DirectXShaderCompiler/bin/arm64/dxcompiler.dll differ diff --git a/third-party/DirectXShaderCompiler/bin/x64/dxcompiler.dll b/third-party/DirectXShaderCompiler/bin/x64/dxcompiler.dll new file mode 100644 index 000000000..a52c4ab72 Binary files /dev/null and b/third-party/DirectXShaderCompiler/bin/x64/dxcompiler.dll differ diff --git a/third-party/DirectXShaderCompiler/bin/x86/dxcompiler.dll b/third-party/DirectXShaderCompiler/bin/x86/dxcompiler.dll new file mode 100644 index 000000000..ca78b1d56 Binary files /dev/null and b/third-party/DirectXShaderCompiler/bin/x86/dxcompiler.dll differ diff --git a/third-party/FidelityFX-FSR b/third-party/FidelityFX-FSR new file mode 160000 index 000000000..a21ffb8f6 --- /dev/null +++ b/third-party/FidelityFX-FSR @@ -0,0 +1 @@ +Subproject commit a21ffb8f6c13233ba336352bdff293894c706575 diff --git a/third-party/IntelVPL/arm64/bin/libvpl.dll b/third-party/IntelVPL/arm64/bin/libvpl.dll new file mode 100644 index 000000000..97ef1e28a Binary files /dev/null and b/third-party/IntelVPL/arm64/bin/libvpl.dll differ diff --git a/third-party/IntelVPL/arm64/include/vpl/mfx.h b/third-party/IntelVPL/arm64/include/vpl/mfx.h new file mode 100644 index 000000000..ce24fcb28 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfx.h @@ -0,0 +1,31 @@ +/*############################################################################ + # 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" + +#include "mfxsurfacepool.h" + +#ifdef ONEVPL_EXPERIMENTAL +#include "mfxencodestats.h" +#endif + +#endif /* __MFXDEFS_H__ */ diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxadapter.h b/third-party/IntelVPL/arm64/include/vpl/mfxadapter.h new file mode 100644 index 000000000..6820da9de --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxadapter.h @@ -0,0 +1,85 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#include "mfxdefs.h" +#ifndef __MFXADAPTER_H__ +#define __MFXADAPTER_H__ + +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + @brief + Returns a list of adapters that are suitable to handle workload @p input_info. The list is sorted in priority order, with iGPU given the highest precedence. + This rule may change in the future. If the @p input_info pointer is NULL, the list of all available adapters will be returned. + + @param[in] input_info Pointer to workload description. See mfxComponentInfo description for details. + @param[out] adapters Pointer to output description of all suitable adapters for input workload. See mfxAdaptersInfo description for details. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR + @p input_info or adapters pointer is NULL. \n + MFX_ERR_NOT_FOUND No suitable adapters found. \n + MFX_WRN_OUT_OF_RANGE Not enough memory to report back entire list of adapters. In this case as many adapters as possible will be returned. + + @since This function is available since API version 1.31. + + @deprecated Deprecated in API version 2.9. Use MFXEnumImplementations and MFXSetConfigFilterProperty to query adapter capabilities and + to select a suitable adapter for the input workload. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. +*/ +MFX_DEPRECATED mfxStatus MFX_CDECL MFXQueryAdapters(mfxComponentInfo* input_info, mfxAdaptersInfo* adapters); + +/*! + @brief + Returns list of adapters that are suitable to decode the input bitstream. The list is sorted in priority order, with iGPU given the highest precedence. This rule may change in the future. This function is a simplification of MFXQueryAdapters, because bitstream is a description of the workload itself. + + @param[in] bitstream Pointer to bitstream with input data. + @param[in] codec_id Codec ID to determine the type of codec for the input bitstream. + @param[out] adapters Pointer to the output list of adapters. Memory should be allocated by user. See mfxAdaptersInfo description for details. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR bitstream or @p adapters pointer is NULL. \n + MFX_ERR_NOT_FOUND No suitable adapters found. \n + MFX_WRN_OUT_OF_RANGE Not enough memory to report back entire list of adapters. In this case as many adapters as possible will be returned. + + @since This function is available since API version 1.31. + + @deprecated Deprecated in API version 2.9. Use MFXEnumImplementations and MFXSetConfigFilterProperty to query adapter capabilities and + to select a suitable adapter for the input workload. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. +*/ +MFX_DEPRECATED mfxStatus MFX_CDECL MFXQueryAdaptersDecode(mfxBitstream* bitstream, mfxU32 codec_id, mfxAdaptersInfo* adapters); + +/*! + @brief + Returns the number of detected graphics adapters. It can be used before calling MFXQueryAdapters to determine the size of input data that the user will need to allocate. + + @param[out] num_adapters Pointer for the output number of detected graphics adapters. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR num_adapters pointer is NULL. + + @since This function is available since API version 1.31. + + @deprecated Deprecated in API version 2.9. Use MFXEnumImplementations and MFXSetConfigFilterProperty to query adapter capabilities and + to select a suitable adapter for the input workload. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. +*/ +MFX_DEPRECATED mfxStatus MFX_CDECL MFXQueryAdaptersNumber(mfxU32* num_adapters); +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MFXADAPTER_H__ + diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxbrc.h b/third-party/IntelVPL/arm64/include/vpl/mfxbrc.h new file mode 100644 index 000000000..da6f09aa3 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxbrc.h @@ -0,0 +1,175 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXBRC_H__ +#define __MFXBRC_H__ + +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! See the mfxExtBRC structure for details. */ +enum { + MFX_EXTBUFF_BRC = MFX_MAKEFOURCC('E','B','R','C') +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes frame parameters required for external BRC functions. +*/ +typedef struct { + mfxU32 reserved[23]; + mfxU16 SceneChange; /*!< Frame belongs to a new scene if non zero. */ + mfxU16 LongTerm; /*!< Frame is a Long Term Reference frame if non zero. */ + mfxU32 FrameCmplx; /*!< Frame Complexity Frame spatial complexity if non zero. Zero if complexity is not available. */ + mfxU32 EncodedOrder; /*!< The frame number in a sequence of reordered frames starting from encoder Init. */ + mfxU32 DisplayOrder; /*!< The frame number in a sequence of frames in display order starting from last IDR. */ + mfxU32 CodedFrameSize; /*!< Size of the frame in bytes after encoding. */ + mfxU16 FrameType; /*!< Frame type. See FrameType enumerator for possible values. */ + mfxU16 PyramidLayer; /*!< B-pyramid or P-pyramid layer that the frame belongs to. */ + mfxU16 NumRecode; /*!< Number of recodings performed for this frame. */ + mfxU16 NumExtParam; /*!< Reserved for future use. */ + mfxExtBuffer** ExtParam;/*!< Reserved for future use. */ +} mfxBRCFrameParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Specifies controls for next frame encoding provided by external BRC functions. +*/ +typedef struct { + mfxI32 QpY; /*!< Frame-level Luma QP. */ + mfxU32 InitialCpbRemovalDelay; /*!< See initial_cpb_removal_delay in codec standard. Ignored if no HRD control: + mfxExtCodingOption::VuiNalHrdParameters = MFX_CODINGOPTION_OFF. Calculated by encoder if + initial_cpb_removal_delay==0 && initial_cpb_removal_offset == 0 && HRD control is switched on. */ + mfxU32 InitialCpbRemovalOffset; /*!< See initial_cpb_removal_offset in codec standard. Ignored if no HRD control: + mfxExtCodingOption::VuiNalHrdParameters = MFX_CODINGOPTION_OFF. Calculated by encoder if + initial_cpb_removal_delay==0 && initial_cpb_removal_offset == 0 && HRD control is switched on. */ + mfxU32 reserved1[7]; + mfxU32 MaxFrameSize; /*!< Max frame size in bytes. Option for repack feature. Driver calls PAK until current frame size is + less than or equal to MaxFrameSize, or number of repacking for this frame is equal to MaxNumRePak. Repack is available + if there is driver support, MaxFrameSize !=0, and MaxNumRePak != 0. Ignored if MaxNumRePak == 0. */ + mfxU8 DeltaQP[8]; /*!< Option for repack feature. Ignored if MaxNumRePak == 0 or MaxNumRePak==0. If current + frame size > MaxFrameSize and/or number of repacking (nRepack) for this frame <= MaxNumRePak, + PAK is called with QP = mfxBRCFrameCtrl::QpY + Sum(DeltaQP[i]), where i = [0,nRepack]. + Non zero DeltaQP[nRepack] are ignored if nRepack > MaxNumRePak. + If repacking feature is on ( MaxFrameSize & MaxNumRePak are not zero), it is calculated by the encoder. */ + mfxU16 MaxNumRepak; /*!< Number of possible repacks in driver if current frame size > MaxFrameSize. Ignored if MaxFrameSize==0. + See MaxFrameSize description. Possible values are in the range of 0 to 8. */ + mfxU16 NumExtParam; /*!< Reserved for future use. */ + mfxExtBuffer** ExtParam; /*!< Reserved for future use. */ +} mfxBRCFrameCtrl; +MFX_PACK_END() + +/*! The BRCStatus enumerator itemizes instructions to the encoder by mfxExtBrc::Update. */ +enum { + MFX_BRC_OK = 0, /*!< CodedFrameSize is acceptable, no further recoding/padding/skip required, proceed to next frame. */ + MFX_BRC_BIG_FRAME = 1, /*!< Coded frame is too big, recoding required. */ + MFX_BRC_SMALL_FRAME = 2, /*!< Coded frame is too small, recoding required. */ + MFX_BRC_PANIC_BIG_FRAME = 3, /*!< Coded frame is too big, no further recoding possible - skip frame. */ + MFX_BRC_PANIC_SMALL_FRAME = 4 /*!< Coded frame is too small, no further recoding possible - required padding to mfxBRCFrameStatus::MinFrameSize. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Specifies instructions for the encoder provided by external BRC after each frame encoding. See the BRCStatus enumerator for details. +*/ +typedef struct { + mfxU32 MinFrameSize; /*!< Size in bytes, coded frame must be padded to when Status = MFX_BRC_PANIC_SMALL_FRAME. */ + mfxU16 BRCStatus; /*!< BRC status. See the BRCStatus enumerator for possible values. */ + mfxU16 reserved[25]; + mfxHDL reserved1; +} mfxBRCFrameStatus; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains a set of callbacks to perform external bitrate control. Can be attached to the mfxVideoParam structure during + encoder initialization. Set the mfxExtCodingOption2::ExtBRC option to ON to make the encoder use the external BRC instead of the native one. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_BRC. */ + + mfxU32 reserved[14]; + mfxHDL pthis; /*!< Pointer to the BRC object. */ + + /*! + @brief Initializes the BRC session according to parameters from input mfxVideoParam and attached structures. It does not modify the input mfxVideoParam and attached structures. Invoked during MFXVideoENCODE_Init. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function detected unsupported video parameters. + */ + mfxStatus (MFX_CDECL *Init) (mfxHDL pthis, mfxVideoParam* par); + + /*! + @brief Resets BRC session according to new parameters. It does not modify the input mfxVideoParam and attached structures. Invoked during MFXVideoENCODE_Reset. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function detected unsupported video parameters. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that the video parameters provided by the application are incompatible with + initialization parameters. Reset requires additional memory allocation and cannot be executed. + */ + mfxStatus (MFX_CDECL *Reset) (mfxHDL pthis, mfxVideoParam* par); + + /*! + @brief Deallocates any internal resources acquired in Init for this BRC session. Invoked during MFXVideoENCODE_Close. + + @param[in] pthis Pointer to the BRC object. + + @return + MFX_ERR_NONE The function completed successfully. + */ + mfxStatus (MFX_CDECL *Close) (mfxHDL pthis); + + /*! @brief Returns controls (@p ctrl) to encode next frame based on info from input mfxBRCFrameParam structure (@p par) and + internal BRC state. Invoked asynchronously before each frame encoding or recoding. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + @param[out] ctrl Pointer to the output mfxBRCFrameCtrl structure. + + @return + MFX_ERR_NONE The function completed successfully. + */ + mfxStatus (MFX_CDECL* GetFrameCtrl) (mfxHDL pthis, mfxBRCFrameParam* par, mfxBRCFrameCtrl* ctrl); + + /*! + @brief Updates internal BRC state and returns status to instruct encoder whether it should recode the previous frame, + skip the previous frame, do padding, or proceed to next frame based on info from input mfxBRCFrameParam and mfxBRCFrameCtrl structures. + Invoked asynchronously after each frame encoding or recoding. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + @param[in] ctrl Pointer to the output mfxBRCFrameCtrl structure. + @param[in] status Pointer to the output mfxBRCFrameStatus structure. + + + @return + MFX_ERR_NONE The function completed successfully. + */ + mfxStatus (MFX_CDECL* Update) (mfxHDL pthis, mfxBRCFrameParam* par, mfxBRCFrameCtrl* ctrl, mfxBRCFrameStatus* status); + + mfxHDL reserved1[10]; +} mfxExtBRC; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif + diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxcamera.h b/third-party/IntelVPL/arm64/include/vpl/mfxcamera.h new file mode 100644 index 000000000..72023a46a --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxcamera.h @@ -0,0 +1,375 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ +#ifndef __MFXCAMERA_H__ +#define __MFXCAMERA_H__ + +#include "mfxcommon.h" + + +#if !defined(__GNUC__) + #pragma warning(disable : 4201) +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*! + The ExtendedBufferID enumerator itemizes and defines identifiers (BufferId) for extended buffers in camera processing. + The application should attach these extended buffers to the mfxVideoParam structure to configure camera processing through VideoVPP functions. + And Implementation capabilities of camera processing features can be delivered by the function MFXQueryImplsDescription via VPP configuration + mfxVPPDescription. + */ +enum { + /*! + This extended buffer is mandatory for camera raw accelerator initialization. See the mfxExtCamPipeControl structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_PIPECONTROL = MFX_MAKEFOURCC('C', 'P', 'P', 'C'), + /*! + This extended buffer defines control parameters for the Camera White Balance filter algorithm. See mfxExtCamWhiteBalance structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_WHITE_BALANCE = MFX_MAKEFOURCC('C', 'W', 'B', 'L'), + /*! + This extended buffer defines control parameters for the Camera Hot Pixel Removal filter algorithm. See mfxExtCamHotPixelRemoval structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_HOT_PIXEL_REMOVAL = MFX_MAKEFOURCC('C', 'H', 'P', 'R'), + /*! + This extended buffer defines control parameters for the Camera Black Level Correction filter algorithm. See mfxExtCamBlackLevelCorrection structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_BLACK_LEVEL_CORRECTION = MFX_MAKEFOURCC('C', 'B', 'L', 'C'), + /*! + This extended buffer defines control parameters for the Camera Vignette Correction filter algorithm. See mfxCamVignetteCorrectionParam structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_VIGNETTE_CORRECTION = MFX_MAKEFOURCC('C', 'V', 'G', 'T'), + /*! + This extended buffer defines control parameters for the Camera Bayer Denoise filter algorithm. See mfxExtCamBayerDenoise structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_BAYER_DENOISE = MFX_MAKEFOURCC('C', 'D', 'N', 'S'), + /*! + This extended buffer defines control parameters for the Camera Color Correction filter algorithm. See mfxExtCamColorCorrection3x3 structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_COLOR_CORRECTION_3X3 = MFX_MAKEFOURCC('C', 'C', '3', '3'), + /*! + This extended buffer defines control parameters for the Camera Padding. See mfxExtCamPadding structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_PADDING = MFX_MAKEFOURCC('C', 'P', 'A', 'D'), + /*! + This extended buffer defines control parameters for the Camera Forward Gamma Correction filter algorithm. See mfxExtCamFwdGamma structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_FORWARD_GAMMA_CORRECTION = + MFX_MAKEFOURCC('C', 'F', 'G', 'C'), + /*! + This extended buffer defines control parameters for the Camera Lens Geometry Distortion and Chroma Aberration Correction filter algorithm. See mfxExtCamLensGeomDistCorrection structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_LENS_GEOM_DIST_CORRECTION = + MFX_MAKEFOURCC('C', 'L', 'G', 'D'), + /*! + This extended buffer defines control parameters for the Camera 3DLUT filter algorithm. See mfxExtCam3DLut structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_3DLUT = MFX_MAKEFOURCC('C', 'L', 'U', 'T'), + /*! + This extended buffer defines control parameters for the Camera Total Color Control algorithm. See mfxExtCamTotalColorControl structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_TOTAL_COLOR_CONTROL = MFX_MAKEFOURCC('C', 'T', 'C', 'C'), + /*! + This extended buffer defines control parameters for the Camera YUV to RGB conversion algorithm. See mfxExtCamCscYuvRgb structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_CSC_YUV_RGB = MFX_MAKEFOURCC('C', 'C', 'Y', 'R') +}; + +/*! + A enumeration that defines white balance mode. +*/ +typedef enum { + MFX_CAM_WHITE_BALANCE_MANUAL = 0x0001, /*!< White balance manual mode.*/ + MFX_CAM_WHITE_BALANCE_AUTO = 0x0002 /*!< White balance auto mode.*/ +} mfxCamWhiteBalanceMode; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera White Balance filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_WHITE_BALANCE. */ + mfxU32 Mode; /*!< Specifies one of White Balance operation modes defined in enumeration mfxCamWhiteBalanceMode. */ + mfxF64 R; /*!< White Balance Red correction.*/ + mfxF64 G0; /*!< White Balance Green Top correction.*/ + mfxF64 B; /*!< White Balance Blue correction.*/ + mfxF64 G1; /*!< White Balance Green Bottom correction. */ + mfxU32 reserved[8]; /*!< Reserved for future extension. */ +} mfxExtCamWhiteBalance; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Total Color Control filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_TOTAL_COLOR_CONTROL. */ + mfxU16 R; /*!< Red element.*/ + mfxU16 G; /*!< Green element.*/ + mfxU16 B; /*!< Blue element.*/ + mfxU16 C; /*!< Cyan element.*/ + mfxU16 M; /*!< Magenta element.*/ + mfxU16 Y; /*!< Yellow element.*/ + mfxU16 reserved[6]; /*!< Reserved for future extension.*/ +} mfxExtCamTotalColorControl; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera YUV to RGB format conversion. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_CSC_YUV_RGB. */ + mfxF32 PreOffset[3]; /*!< Specifies offset for conversion from full range RGB input to limited range YUV for input color coordinate.*/ + mfxF32 Matrix[3][3]; /*!< Specifies conversion matrix with CSC coefficients.*/ + mfxF32 PostOffset[3]; /*!< Specifies offset for conversion from full range RGB input to limited range YUV for output color coordinate.*/ + mfxU16 reserved[30]; /*!< Reserved for future extension.*/ +} mfxExtCamCscYuvRgb; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Hot Pixel Removal filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_HOT_PIXEL_REMOVAL. */ + mfxU16 PixelThresholdDifference; /*!< Threshold for Hot Pixel difference. */ + mfxU16 PixelCountThreshold; /*!< Count pixel detection.*/ + mfxU16 reserved[32]; /*!< Reserved for future extension.*/ +} mfxExtCamHotPixelRemoval; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +typedef struct { +/*! + A hint structure that configures Camera black level correction. +*/ + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_BLACK_LEVEL_CORRECTION. */ + mfxU16 R; /*!< Black Level Red correction.*/ + mfxU16 G0; /*!< Black Level Green Top correction.*/ + mfxU16 B; /*!< Black Level Blue correction.*/ + mfxU16 G1; /*!< Black Level Green Bottom correction.*/ + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxExtCamBlackLevelCorrection; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that defines Camera Vignette Correction Element. +*/ +typedef struct { + mfxU8 integer; /*!< Integer part of correction element.*/ + mfxU8 mantissa; /*!< Fractional part of correction element.*/ + mfxU8 reserved[6]; /*!< Reserved for future extension.*/ +} mfxCamVignetteCorrectionElement; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that defines Camera Vignette Correction Parameters. +*/ +typedef struct { + mfxCamVignetteCorrectionElement R; /*!< Red correction element.*/ + mfxCamVignetteCorrectionElement G0; /*!< Green top correction element.*/ + mfxCamVignetteCorrectionElement B; /*!< Blue Correction element.*/ + mfxCamVignetteCorrectionElement G1; /*!< Green bottom correction element.*/ + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxCamVignetteCorrectionParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + A hint structure that configures Camera Vignette Correction filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_VIGNETTE_CORRECTION. */ + mfxU32 Width; /*!< Width of Correction Map 2D buffer in mfxCamVignetteCorrectionParam elements. */ + mfxU32 Height; /*!< Height of Correction Map 2D buffer in mfxCamVignetteCorrectionParam elements. */ + mfxU32 Pitch; /*!< Pitch of Correction Map 2D buffer in mfxCamVignetteCorrectionParam elements. */ + mfxU32 reserved[7]; /*!< Reserved for future extension.*/ + + union { + mfxCamVignetteCorrectionParam* CorrectionMap; /*!< 2D buffer of mfxCamVignetteCorrectionParam elements.*/ + mfxU64 reserved1; /*!< Reserved for alignment on 32bit and 64bit.*/ + }; +} mfxExtCamVignetteCorrection; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Bayer denoise filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_BAYER_DENOISE. */ + mfxU16 Threshold; /*!< Level of denoise, legal values: [0:63].*/ + mfxU16 reserved[27]; /*!< Reserved for future extension.*/ +} mfxExtCamBayerDenoise; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures Camera Color correction filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_COLOR_CORRECTION_3X3. */ + mfxF32 CCM[3][3]; /*!< 3x3 dimension matrix providing RGB Color Correction coefficients.*/ + mfxU32 reserved[32]; /*!< Reserved for future extension.*/ +} mfxExtCamColorCorrection3x3; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Padding. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_PADDING. */ + mfxU16 Top; /*!< Specify number of padded columns respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU16 Bottom; /*!< Specify number of padded columns respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU16 Left; /*!< Specify number of padded rows respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU16 Right; /*!< Specify number of padded rows respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxExtCamPadding; +MFX_PACK_END() + +/*! + A enumeration that defines Bayer mode. +*/ +typedef enum { + /*! + Pixel Representation BG + GR. + */ + MFX_CAM_BAYER_BGGR = 0x0000, + /*! + Pixel Representation RG + GB. + */ + MFX_CAM_BAYER_RGGB = 0x0001, + /*! + Pixel Representation GB + RG. + */ + MFX_CAM_BAYER_GBRG = 0x0002, + /*! + Pixel Representation GR + BG. + */ + MFX_CAM_BAYER_GRBG = 0x0003 +} mfxCamBayerFormat; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures camera pipe control. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_PIPECONTROL. */ + mfxU16 RawFormat; /*!< Specifies one of the four Bayer patterns defined in mfxCamBayerFormat enumeration. */ + mfxU16 reserved1; /*!< Reserved for future extension.*/ + mfxU32 reserved[5]; /*!< Reserved for future extension.*/ +} mfxExtCamPipeControl; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that specifies forward gamma segment. +*/ +typedef struct { + mfxU16 Pixel; /*!< Pixel value.*/ + mfxU16 Red; /*!< Corrected Red value.*/ + mfxU16 Green; /*!< Corrected Green value.*/ + mfxU16 Blue; /*!< Corrected Blue value.*/ +} mfxCamFwdGammaSegment; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures Camera Forward Gamma Correction filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_FORWARD_GAMMA_CORRECTION. */ + + mfxU16 reserved[19]; /*!< Reserved for future extension.*/ + mfxU16 NumSegments; /*!< Number of Gamma segments.*/ + union { + mfxCamFwdGammaSegment* Segment; /*!< Pointer to Gamma segments array.*/ + mfxU64 reserved1; /*!< Reserved for future extension.*/ + }; +} mfxExtCamFwdGamma; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Lens Geometry Distortion and Chroma Aberration Correction filter. +*/ +typedef struct { + mfxExtBuffer + Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_LENS_GEOM_DIST_CORRECTION. */ + + mfxF32 a[3]; /*!< Polynomial coefficients a for R/G/B*/ + mfxF32 b[3]; /*!< Polynomial coefficients b for R/G/B*/ + mfxF32 c[3]; /*!< Polynomial coefficients c for R/G/B*/ + mfxF32 d[3]; /*!< Polynomial coefficients d for R/G/B*/ + mfxU16 reserved[36]; /*!< Reserved for future extension.*/ +} mfxExtCamLensGeomDistCorrection; +MFX_PACK_END() + +/*! + A enumeration that defines 3DLUT size. +*/ +enum { + MFX_CAM_3DLUT17_SIZE = (17 * 17 * 17), /*!< 17^3 LUT size*/ + MFX_CAM_3DLUT33_SIZE = (33 * 33 * 33), /*!< 33^3 LUT size*/ + MFX_CAM_3DLUT65_SIZE = (65 * 65 * 65) /*!< 65^3 LUT size*/ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that defines 3DLUT entry. +*/ +typedef struct { + mfxU16 R; /*!< R channel*/ + mfxU16 G; /*!< G channel*/ + mfxU16 B; /*!< B channel*/ + mfxU16 Reserved; /*!< Reserved for future extension.*/ +} mfxCam3DLutEntry; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures Camera 3DLUT filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_3DLUT. */ + + mfxU16 reserved[10]; /*!< Reserved for future extension.*/ + mfxU32 Size; /*!< LUT size, defined in MFX_CAM_3DLUT17/33/65_SIZE enumeration.*/ + union { + mfxCam3DLutEntry* Table; /*!< Pointer to mfxCam3DLutEntry, size of each dimension depends on LUT size, e.g. LUT[17][17][17] for 17x17x17 look up table.*/ + mfxU64 reserved1; /*!< Reserved for future extension.*/ + }; +} mfxExtCam3DLut; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MFXCAMERA_H__ \ No newline at end of file diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxcommon.h b/third-party/IntelVPL/arm64/include/vpl/mfxcommon.h new file mode 100644 index 000000000..1b3737d72 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxcommon.h @@ -0,0 +1,740 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXCOMMON_H__ +#define __MFXCOMMON_H__ +#include "mfxdefs.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define MFX_MAKEFOURCC(A,B,C,D) ((((int)A))+(((int)B)<<8)+(((int)C)<<16)+(((int)D)<<24)) + +/* Extended Configuration Header Structure */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The common header definition for external buffers and video + processing hints. */ +typedef struct { + mfxU32 BufferId; /*!< Identifier of the buffer content. See the ExtendedBufferID enumerator for a complete list of extended buffers. */ + mfxU32 BufferSz; /*!< Size of the buffer. */ +} mfxExtBuffer; +MFX_PACK_END() + + +#define MFX_REFINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure represents reference counted interface structure. + The memory is allocated and released by the implementation. +*/ +typedef struct mfxRefInterface { + mfxHDL Context; /*!< The context of the container interface. User should not touch (change, set, null) this pointer. */ + mfxStructVersion Version; /*!< The version of the structure. */ + /*! @brief + Increments the internal reference counter of the container. The container is not destroyed until the container + is released using the mfxRefInterface::Release function. + mfxRefInterface::AddRef should be used each time a new link to the container is created + (for example, copy structure) for proper management. + + @param[in] ref_interface Valid interface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxRefInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxRefInterface* ref_interface); + /*! @brief + Decrements the internal reference counter of the container. mfxRefInterface::Release should be called after using the + mfxRefInterface::AddRef function to add a container or when allocation logic requires it. + + @param[in] ref_interface Valid interface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxRefInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of container is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxRefInterface* ref_interface); + /*! @brief + Returns current reference counter of mfxRefInterface structure. + + @param[in] ref_interface Valid interface. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxRefInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(struct mfxRefInterface* ref_interface, mfxU32* counter); + mfxHDL reserved[4]; + +}mfxRefInterface; +MFX_PACK_END() + +/* Library initialization and deinitialization */ +/*! + This enumerator itemizes implementation types. + The implementation type is a bit OR'ed value of the base type and any decorative flags. + @note This enumerator is for legacy dispatcher compatibility only. The new dispatcher does not use it. + */ +typedef mfxI32 mfxIMPL; +/*! + The application can use the macro MFX_IMPL_BASETYPE(x) to obtain the base implementation type. +*/ +#define MFX_IMPL_BASETYPE(x) (0x00ff & (x)) + +enum { + MFX_IMPL_AUTO = 0x0000, /*!< Auto Selection/In or Not Supported/Out. */ + MFX_IMPL_SOFTWARE = 0x0001, /*!< Pure software implementation. */ + MFX_IMPL_HARDWARE = 0x0002, /*!< Hardware accelerated implementation (default device). */ + MFX_IMPL_AUTO_ANY = 0x0003, /*!< Auto selection of any hardware/software implementation. */ + MFX_IMPL_HARDWARE_ANY = 0x0004, /*!< Auto selection of any hardware implementation. */ + MFX_IMPL_HARDWARE2 = 0x0005, /*!< Hardware accelerated implementation (2nd device). */ + MFX_IMPL_HARDWARE3 = 0x0006, /*!< Hardware accelerated implementation (3rd device). */ + MFX_IMPL_HARDWARE4 = 0x0007, /*!< Hardware accelerated implementation (4th device). */ + MFX_IMPL_RUNTIME = 0x0008, /*!< This value cannot be used for session initialization. It may be returned by the MFXQueryIMPL + function to show that the session has been initialized in run-time mode. */ + MFX_IMPL_VIA_ANY = 0x0100, /*!< Hardware acceleration can go through any supported OS infrastructure. This is the default value. The default value + is used by the legacy Intel(r) Media SDK if none of the MFX_IMPL_VIA_xxx flags are specified by the application. */ + MFX_IMPL_VIA_D3D9 = 0x0200, /*!< Hardware acceleration goes through the Microsoft* Direct3D* 9 infrastructure. */ + MFX_IMPL_VIA_D3D11 = 0x0300, /*!< Hardware acceleration goes through the Microsoft* Direct3D* 11 infrastructure. */ + MFX_IMPL_VIA_VAAPI = 0x0400, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure. */ + MFX_IMPL_VIA_HDDLUNITE = 0x0500, /*!< Hardware acceleration goes through the HDDL* Unite*. */ + + MFX_IMPL_UNSUPPORTED = 0x0000 /*!< One of the MFXQueryIMPL returns. */ +}; + +/* Version Info */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The mfxVersion union describes the version of the implementation.*/ +typedef union { + /*! @brief Structure with Major and Minor fields. */ + /*! @struct Anonymous */ + struct { + /*! @{ + @name Major and Minor fields + Anonymous structure with Major and Minor fields. + */ + mfxU16 Minor; /*!< Minor number of the implementation. */ + mfxU16 Major; /*!< Major number of the implementation. */ + /*! @} */ + }; + mfxU32 Version; /*!< Implementation version number. */ +} mfxVersion; +MFX_PACK_END() + +/*! The mfxPriority enumerator describes the session priority. */ +typedef enum +{ + MFX_PRIORITY_LOW = 0, /*!< Low priority: the session operation halts when high priority tasks are executing and more than 75% of the CPU is being used for normal priority tasks.*/ + MFX_PRIORITY_NORMAL = 1, /*!< Normal priority: the session operation is halted if there are high priority tasks.*/ + MFX_PRIORITY_HIGH = 2 /*!< High priority: the session operation blocks other lower priority session operations.*/ + +} mfxPriority; + +typedef struct _mfxEncryptedData mfxEncryptedData; +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! Defines the buffer that holds compressed video data. */ +typedef struct { + /*! @internal :unnamed(union) @endinternal */ + union { + struct { + mfxEncryptedData* EncryptedData; /*!< Reserved and must be zero. */ + mfxExtBuffer **ExtParam; /*!< Array of extended buffers for additional bitstream configuration. See the ExtendedBufferID enumerator for a complete list of extended buffers. */ + mfxU16 NumExtParam; /*!< The number of extended buffers attached to this structure. */ + mfxU16 reserved1; /*!< Reserved for future use. */ + mfxU32 CodecId; /*!< Specifies the codec format identifier in the FourCC code. See the CodecFormatFourCC enumerator for details. This optional parameter is required for the simplified decode initialization. */ + + }; + mfxU32 reserved[6]; + }; + /*! Decode time stamp of the compressed bitstream in units of 90KHz. A value of MFX_TIMESTAMP_UNKNOWN indicates that there is no time stamp. + + This value is calculated by the encoder from the presentation time stamp provided by the application in the mfxFrameSurface1 structure and + from the frame rate provided by the application during the encoder initialization. */ + mfxI64 DecodeTimeStamp; + mfxU64 TimeStamp; /*!< Time stamp of the compressed bitstream in units of 90KHz. A value of MFX_TIMESTAMP_UNKNOWN indicates that there is no time stamp. */ + mfxU8* Data; /*!< Bitstream buffer pointer, 32-bytes aligned. */ + mfxU32 DataOffset; /*!< Next reading or writing position in the bitstream buffer. */ + mfxU32 DataLength; /*!< Size of the actual bitstream data in bytes. */ + mfxU32 MaxLength; /*!< Allocated bitstream buffer size in bytes. */ + + mfxU16 PicStruct; /*!< Type of the picture in the bitstream. Output parameter. */ + mfxU16 FrameType; /*!< Frame type of the picture in the bitstream. Output parameter. */ + mfxU16 DataFlag; /*!< Indicates additional bitstream properties. See the BitstreamDataFlag enumerator for details. */ + mfxU16 reserved2; /*!< Reserved for future use. */ +} mfxBitstream; +MFX_PACK_END() + +/*! Synchronization point object handle. */ +typedef struct _mfxSyncPoint *mfxSyncPoint; + +/*! The GPUCopy enumerator controls usage of GPU accelerated copying between video and system memory in the legacy Intel(r) Media SDK components. */ +enum { + MFX_GPUCOPY_DEFAULT = 0, /*!< Use default mode for the legacy Intel(r) Media SDK implementation. */ + MFX_GPUCOPY_ON = 1, /*!< The hint to enable GPU accelerated copying when it is supported by the library. + If the library doesn't support GPU accelerated copy the operation will be made by CPU. + Buffer caching usage decision is up to runtime to decide, for explicit hints please use MFX_GPUCOPY_SAFE or MFX_GPUCOPY_FAST */ + MFX_GPUCOPY_OFF = 2, /*!< Disable GPU accelerated copying. */ + MFX_GPUCOPY_SAFE = 3, /*!< The hint to disable buffer caching for GPU accelerated copying. Actual when GPU accelerated copying is supported by the library. */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_GPUCOPY_FAST = 4 /*!< The hint to enable buffer caching for GPU accelerated copying. Actual when GPU accelerated copying is supported by the library. */ +#endif +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Specifies advanced initialization parameters. + A zero value in any of the fields indicates that the corresponding field + is not explicitly specified. +*/ +typedef struct { + mfxIMPL Implementation; /*!< Enumerator that indicates the desired legacy Intel(r) Media SDK implementation. */ + mfxVersion Version; /*!< Structure which specifies minimum library version or zero, if not specified. */ + mfxU16 ExternalThreads; /*!< Desired threading mode. Value 0 means internal threading, 1 - external. */ + /*! @internal :unnamed(union) @endinternal */ + union { + struct { + mfxExtBuffer **ExtParam; /*!< Points to an array of pointers to the extra configuration structures; see the ExtendedBufferID enumerator for a list of extended configurations. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + }; + mfxU16 reserved2[5]; + }; + mfxU16 GPUCopy; /*!< Enables or disables GPU accelerated copying between video and system memory in legacy Intel(r) Media SDK components. See the GPUCopy enumerator for a list of valid values. */ + mfxU16 reserved[21]; +} mfxInitParam; +MFX_PACK_END() + +enum { + MFX_EXTBUFF_THREADS_PARAM = MFX_MAKEFOURCC('T','H','D','P') /*!< mfxExtThreadsParam buffer ID. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies options for threads created by this session. Attached to the + mfxInitParam structure during legacy Intel(r) Media SDK session initialization + or to mfxInitializationParam by the dispatcher in MFXCreateSession function. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_THREADS_PARAM. */ + + mfxU16 NumThread; /*!< The number of threads. */ + mfxI32 SchedulingType; /*!< Scheduling policy for all threads.*/ + mfxI32 Priority; /*!< Priority for all threads. */ + mfxU16 reserved[55]; /*!< Reserved for future use. */ +} mfxExtThreadsParam; +MFX_PACK_END() + +/*! Deprecated. */ +enum { + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_UNKNOWN) = 0, /*!< Unknown platform. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_SANDYBRIDGE) = 1, /*!< Intel(r) microarchitecture code name Sandy Bridge. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_IVYBRIDGE) = 2, /*!< Intel(r) microarchitecture code name Ivy Bridge. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_HASWELL) = 3, /*!< Code name Haswell. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_BAYTRAIL) = 4, /*!< Code name Bay Trail. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_BROADWELL) = 5, /*!< Intel(r) microarchitecture code name Broadwell. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_CHERRYTRAIL) = 6, /*!< Code name Cherry Trail. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_SKYLAKE) = 7, /*!< Intel(r) microarchitecture code name Skylake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_APOLLOLAKE) = 8, /*!< Code name Apollo Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_KABYLAKE) = 9, /*!< Code name Kaby Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_GEMINILAKE) = 10, /*!< Code name Gemini Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_COFFEELAKE) = 11, /*!< Code name Coffee Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_CANNONLAKE) = 20, /*!< Code name Cannon Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ICELAKE) = 30, /*!< Code name Ice Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_JASPERLAKE) = 32, /*!< Code name Jasper Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ELKHARTLAKE) = 33, /*!< Code name Elkhart Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_TIGERLAKE) = 40, /*!< Code name Tiger Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ROCKETLAKE) = 42, /*!< Code name Rocket Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ALDERLAKE_S) = 43, /*!< Code name Alder Lake S. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ALDERLAKE_P) = 44, /*!< Code name Alder Lake P. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ARCTICSOUND_P) = 45, + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_XEHP_SDV) = 45, /*!< Code name XeHP SDV. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_DG2) = 46, /*!< Code name DG2. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ATS_M) = 46, /*!< Code name ATS-M, same media functionality as DG2. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ALDERLAKE_N) = 55, /*!< Code name Alder Lake N. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_KEEMBAY) = 50, /*!< Code name Keem Bay. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_METEORLAKE) = 51, /*!< Code name Meteor Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_BATTLEMAGE) = 52, /*!< Code name Battlemage. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_LUNARLAKE) = 53, /*!< Code name Lunar Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ARROWLAKE) = 54, /*!< Code name Arrow Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_MAXIMUM) = 65535, /*!< General code name. */ +}; + +/*! The mfxMediaAdapterType enumerator itemizes types of graphics adapters. */ +typedef enum +{ + MFX_MEDIA_UNKNOWN = 0xffff, /*!< Unknown type. */ + MFX_MEDIA_INTEGRATED = 0, /*!< Integrated graphics adapter. */ + MFX_MEDIA_DISCRETE = 1 /*!< Discrete graphics adapter. */ +} mfxMediaAdapterType; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Contains information about hardware platform for the Legacy mode. */ +typedef struct { + MFX_DEPRECATED mfxU16 CodeName; /*!< Deprecated. */ + mfxU16 DeviceId; /*!< Unique identifier of graphics device. */ + mfxU16 MediaAdapterType; /*!< Description of graphics adapter type. See the mfxMediaAdapterType enumerator for a list of possible values. */ + mfxU16 reserved[13]; /*!< Reserved for future use. */ +} mfxPlatform; +MFX_PACK_END() + + +/*! The mfxResourceType enumerator specifies types of different native data frames and buffers. */ +typedef enum { + MFX_RESOURCE_SYSTEM_SURFACE = 1, /*!< System memory. */ + MFX_RESOURCE_VA_SURFACE_PTR = 2, /*!< Pointer to VA surface index. */ + MFX_RESOURCE_VA_SURFACE = MFX_RESOURCE_VA_SURFACE_PTR, /*!< Pointer to VA surface index. */ + MFX_RESOURCE_VA_BUFFER_PTR = 3, /*!< Pointer to VA buffer index. */ + MFX_RESOURCE_VA_BUFFER = MFX_RESOURCE_VA_BUFFER_PTR, /*!< Pointer to VA buffer index. */ + MFX_RESOURCE_DX9_SURFACE = 4, /*!< Pointer to IDirect3DSurface9. */ + MFX_RESOURCE_DX11_TEXTURE = 5, /*!< Pointer to ID3D11Texture2D. */ + MFX_RESOURCE_DX12_RESOURCE = 6, /*!< Pointer to ID3D12Resource. */ + MFX_RESOURCE_DMA_RESOURCE = 7, /*!< DMA resource. */ + MFX_RESOURCE_HDDLUNITE_REMOTE_MEMORY = 8, /*!< HDDL Unite Remote memory handle. */ +} mfxResourceType; + +/*! Maximum allowed length of the implementation name. */ +#define MFX_IMPL_NAME_LEN 32 +/*! Maximum allowed length of the implementation name. */ +#define MFX_STRFIELD_LEN 128 + +#ifdef ONEVPL_EXPERIMENTAL + +#define MFX_DECEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxDecExtDescription structure represents the extended description of a decoder. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[14]; /*!< Reserved for future use. */ + mfxU16 NumExtBufferIDs; /*!< Number of supported extended buffer IDs. */ + mfxU32* ExtBufferIDs; /*!< Pointer to the array of supported extended buffer IDs. */ +} mfxDecExtDescription; +MFX_PACK_END() + +#define MFX_DECMEMEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxDecMemExtDescription structure represents the extended description for decoder memory. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[13]; /*!< Reserved for future use. */ + mfxU16 MaxBitDepth; /*!< Maximum supported bit depth. */ + mfxU16 NumChromaSubsamplings; /*!< Number of supported output chroma subsamplings. */ + mfxU16* ChromaSubsamplings; /*!< Pointer to the array of supported output chroma subsamplings. */ +} mfxDecMemExtDescription; +MFX_PACK_END() + +#endif + +#ifdef ONEVPL_EXPERIMENTAL +#define MFX_DECODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 1) +#else +#define MFX_DECODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) +#endif + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxDecoderDescription structure represents the description of a decoder. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumCodecs; /*!< Number of supported decoders. */ + /*! This structure represents the decoder description. */ + struct decoder { + mfxU32 CodecID; /*!< Decoder ID in FourCC format. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 reserved[2]; /*!< Reserved for future use. */ + union { + mfxDecExtDescription* DecExtDesc; /*!< Pointer to the extended descriptions of the decoder. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved3[2]; /*!< Reserved for future use. */ +#else + mfxU16 reserved[8]; /*!< Reserved for future use. */ +#endif + mfxU16 MaxcodecLevel; /*!< Maximum supported codec level. See the CodecProfile enumerator for possible values. */ + mfxU16 NumProfiles; /*!< Number of supported profiles. */ + /*! This structure represents the codec profile description. */ + struct decprofile { + mfxU32 Profile; /*!< Profile ID. See the CodecProfile enumerator for possible values.*/ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumMemTypes; /*!< Number of supported memory types. */ + /*! This structure represents the underlying details of the memory type. */ + struct decmemdesc { + mfxResourceType MemHandleType; /*!< Memory handle type. */ + mfxRange32U Width; /*!< Range of supported image widths. */ + mfxRange32U Height; /*!< Range of supported image heights. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 reserved[2]; /*!< Reserved for future use. */ + union { + mfxDecMemExtDescription* MemExtDesc; /*!< Pointer to the extended descriptions for decoder memory. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved3; /*!< Reserved for future use. */ +#else + mfxU16 reserved[7]; /*!< Reserved for future use. */ +#endif + mfxU16 NumColorFormats; /*!< Number of supported output color formats. */ + mfxU32* ColorFormats; /*!< Pointer to the array of supported output color formats (in FOURCC). */ + } * MemDesc; /*!< Pointer to the array of memory types. */ + } * Profiles; /*!< Pointer to the array of profiles supported by the codec. */ + } * Codecs; /*!< Pointer to the array of decoders. */ +} mfxDecoderDescription; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL + +#define MFX_ENCEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxEncExtDescription structure represents the extended description of an encoder. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[10]; /*!< Reserved for future use. */ + mfxU16 NumRateControlMethods; /*!< Number of supported bitrate control methods. */ + mfxU16* RateControlMethods; /*!< Pointer to the array of supported bitrate control methods. */ + mfxU16 reserved2[11]; /*!< Reserved for future use. */ + mfxU16 NumExtBufferIDs; /*!< Number of supported extended buffer IDs. */ + mfxU32* ExtBufferIDs; /*!< Pointer to the array of supported extended buffer IDs. */ +} mfxEncExtDescription; +MFX_PACK_END() + +#define MFX_ENCMEMEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxEncMemExtDescription structure represents the extended description for encoder memory. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[13]; /*!< Reserved for future use. */ + mfxU16 TargetMaxBitDepth; /*!< Maximum supported bit depth. */ + mfxU16 NumTargetChromaSubsamplings; /*!< Number of supported target chroma subsamplings. */ + mfxU16* TargetChromaSubsamplings; /*!< Pointer to the array of supported target chroma subsamplings. */ +} mfxEncMemExtDescription; +MFX_PACK_END() + +#endif + +#ifdef ONEVPL_EXPERIMENTAL +#define MFX_ENCODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 1) +#else +#define MFX_ENCODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) +#endif + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents an encoder description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumCodecs; /*!< Number of supported encoders. */ + /*! This structure represents encoder description. */ + struct encoder { + mfxU32 CodecID; /*!< Encoder ID in FourCC format. */ + mfxU16 MaxcodecLevel; /*!< Maximum supported codec level. See the CodecProfile enumerator for possible values. */ + mfxU16 BiDirectionalPrediction; /*!< Indicates B-frames support. */ +#ifdef ONEVPL_EXPERIMENTAL + union { + mfxEncExtDescription* EncExtDesc; /*!< Pointer to the extended descriptions of the encoder. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved[3]; /*!< Reserved for future use. */ +#else + mfxU16 reserved[7]; /*!< Reserved for future use. */ +#endif + mfxU16 NumProfiles; /*!< Number of supported profiles. */ + /*! This structure represents the codec profile description. */ + struct encprofile { + mfxU32 Profile; /*!< Profile ID. See the CodecProfile enumerator for possible values.*/ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumMemTypes; /*!< Number of supported memory types. */ + /*! This structure represents the underlying details of the memory type. */ + struct encmemdesc { + mfxResourceType MemHandleType; /*!< Memory handle type. */ + mfxRange32U Width; /*!< Range of supported image widths. */ + mfxRange32U Height; /*!< Range of supported image heights. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 reserved[2]; /*!< Reserved for future use. */ + union { + mfxEncMemExtDescription* MemExtDesc; /*!< Pointer to the extended descriptions for encoder memory. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved3; /*!< Reserved for future use. */ +#else + mfxU16 reserved[7]; /*!< Reserved for future use. */ +#endif + mfxU16 NumColorFormats; /*!< Number of supported input color formats. */ + mfxU32* ColorFormats; /*!< Pointer to the array of supported input color formats (in FOURCC). */ + } * MemDesc; /*!< Pointer to the array of memory types. */ + } * Profiles; /*!< Pointer to the array of profiles supported by the codec. */ + } * Codecs; /*!< Pointer to the array of encoders. */ +} mfxEncoderDescription; +MFX_PACK_END() + +#define MFX_VPPDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents VPP description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumFilters; /*!< Number of supported VPP filters. */ + /*! This structure represents the VPP filters description. */ + struct filter { + mfxU32 FilterFourCC; /*!< Filter ID in FourCC format. */ + mfxU16 MaxDelayInFrames; /*!< Introduced output delay in frames. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumMemTypes; /*!< Number of supported memory types. */ + /*! This structure represents the underlying details of the memory type. */ + struct memdesc { + mfxResourceType MemHandleType; /*!< Memory handle type. */ + mfxRange32U Width; /*!< Range of supported image widths. */ + mfxRange32U Height; /*!< Range of supported image heights. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumInFormats; /*!< Number of supported input color formats. */ + /*! This structure represents the input color format description. */ + struct format { + mfxU32 InFormat; /*!< Input color in FourCC format. */ + mfxU16 reserved[5]; /*!< Reserved for future use. */ + mfxU16 NumOutFormat; /*!< Number of supported output color formats. */ + mfxU32* OutFormats; /*!< Pointer to the array of supported output color formats (in FOURCC). */ + } * Formats; /*!< Pointer to the array of supported formats. */ + } * MemDesc; /*!< Pointer to the array of memory types. */ + } * Filters; /*!< Pointer to the array of supported filters. */ +} mfxVPPDescription; +MFX_PACK_END() + +/*! The current version of mfxDeviceDescription structure. */ +#define MFX_DEVICEDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 1) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents device description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[6]; /*!< reserved for future use. */ + mfxU16 MediaAdapterType; /*!< Graphics adapter type. See the mfxMediaAdapterType enumerator for a list of possible values. */ + mfxChar DeviceID[MFX_STRFIELD_LEN]; /*!< Null terminated string with device ID. */ + mfxU16 NumSubDevices; /*!< Number of available uniform sub-devices. Pure software implementation can report 0. */ + /*! This structure represents sub-device description. */ + struct subdevices { + mfxU32 Index; /*!< Index of the sub-device, started from 0 and increased by 1.*/ + mfxChar SubDeviceID[MFX_STRFIELD_LEN]; /*!< Null terminated string with unique sub-device ID, mapped to the system ID. */ + mfxU32 reserved[7]; /*!< reserved for future use. */ + } * SubDevices; /*!< Pointer to the array of available sub-devices. */ +} mfxDeviceDescription; +MFX_PACK_END() + +/*! This enum itemizes implementation type. */ +typedef enum { + MFX_IMPL_TYPE_SOFTWARE = 0x0001, /*!< Pure Software Implementation. */ + MFX_IMPL_TYPE_HARDWARE = 0x0002, /*!< Hardware Accelerated Implementation. */ +} mfxImplType; + +/*! This enum itemizes hardware acceleration stack to use. */ +typedef enum { + MFX_ACCEL_MODE_NA = 0, /*!< Hardware acceleration is not applicable. */ + MFX_ACCEL_MODE_VIA_D3D9 = 0x0200, /*!< Hardware acceleration goes through the Microsoft* Direct3D9* infrastructure. */ + MFX_ACCEL_MODE_VIA_D3D11 = 0x0300, /*!< Hardware acceleration goes through the Microsoft* Direct3D11* infrastructure. */ + MFX_ACCEL_MODE_VIA_VAAPI = 0x0400, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure. */ + MFX_ACCEL_MODE_VIA_VAAPI_DRM_RENDER_NODE + = MFX_ACCEL_MODE_VIA_VAAPI, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with DRM RENDER MODE as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_DRM_MODESET = 0x0401, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with DRM MODESET as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_GLX = 0x0402, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with OpenGL Extension to the X Window System + as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_X11 = 0x0403, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with X11 as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_WAYLAND = 0x0404, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with Wayland as default acceleration access point. */ + 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() +/*! This structure represents acceleration modes description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[2]; /*!< reserved for future use. */ + mfxU16 NumAccelerationModes; /*!< Number of supported acceleration modes. */ + mfxAccelerationMode* Mode; /*!< Pointer to the array of supported acceleration modes. */ +} mfxAccelerationModeDescription; +MFX_PACK_END() + +/*! Specifies the surface pool allocation policies. */ + typedef enum { + /*! Recommends to limit max pool size by sum of requested surfaces asked by components. */ + MFX_ALLOCATION_OPTIMAL = 0, + + /*! Dynamic allocation with no limit. */ + MFX_ALLOCATION_UNLIMITED = 1, + + /*! Max pool size is limited by NumberToPreAllocate + DeltaToAllocateOnTheFly. */ + MFX_ALLOCATION_LIMITED = 2, + +} mfxPoolAllocationPolicy; + +/*! The current version of mfxPoolPolicyDescription structure. */ +#define MFX_POOLPOLICYDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents pool policy description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[2]; /*!< reserved for future use. */ + mfxU16 NumPoolPolicies; /*!< Number of supported pool policies. */ + mfxPoolAllocationPolicy* Policy; /*!< Pointer to the array of supported pool policies. */ +} mfxPoolPolicyDescription; +MFX_PACK_END() + +/*! The current version of mfxImplDescription structure. */ +#define MFX_IMPLDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 2) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents the implementation description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxImplType Impl; /*!< Impl type: software/hardware. */ + mfxAccelerationMode AccelerationMode; /*!< Default Hardware acceleration stack to use. OS dependent parameter. Use VA for Linux* and DX* for Windows*. */ + mfxVersion ApiVersion; /*!< Supported API version. */ + mfxChar ImplName[MFX_IMPL_NAME_LEN]; /*!< Null-terminated string with implementation name given by vendor. */ + mfxChar License[MFX_STRFIELD_LEN]; /*!< Null-terminated string with comma-separated list of license names of the implementation. */ + mfxChar Keywords[MFX_STRFIELD_LEN]; /*!< Null-terminated string with comma-separated list of keywords specific to this implementation that dispatcher can search for. */ + mfxU32 VendorID; /*!< Standard vendor ID 0x8086 - Intel. */ + mfxU32 VendorImplID; /*!< Vendor specific number with given implementation ID. */ + mfxDeviceDescription Dev; /*!< Supported device. */ + mfxDecoderDescription Dec; /*!< Decoder configuration. */ + mfxEncoderDescription Enc; /*!< Encoder configuration. */ + mfxVPPDescription VPP; /*!< VPP configuration. */ + union + { + mfxAccelerationModeDescription AccelerationModeDescription; /*!< Supported acceleration modes. */ + mfxU32 reserved3[4]; + }; + mfxPoolPolicyDescription PoolPolicies; /*!< Supported surface pool polices. */ + mfxU32 reserved[8]; /*!< Reserved for future use. */ + mfxU32 NumExtParam; /*!< Number of extension buffers. Reserved for future use. Must be 0. */ + union { + mfxExtBuffer **ExtParam; /*!< Array of extension buffers. */ + mfxU64 Reserved2; /*!< Reserved for future use. */ + } ExtParams; /*!< Extension buffers. Reserved for future. */ +} mfxImplDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents the list of names of implemented functions. */ +typedef struct { + mfxU16 NumFunctions; /*!< Number of function names in the FunctionsName array. */ + mfxChar** FunctionsName; /*!< Array of the null-terminated strings. Each string contains name of the implemented function. */ +} mfxImplementedFunctions; +MFX_PACK_END() + + +#define MFX_EXTENDEDDEVICEID_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies various physical device properties for device matching and identification outside of oneAPI Video Processing Library (oneVPL). */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 VendorID; /*!< PCI vendor ID. */ + mfxU16 DeviceID; /*!< PCI device ID. */ + mfxU32 PCIDomain; /*!< PCI bus domain. Equals to '0' if OS doesn't support it or + has sequential numbering of buses across domains. */ + mfxU32 PCIBus; /*!< The number of the bus that the physical device is located on. */ + mfxU32 PCIDevice; /*!< The index of the physical device on the bus. */ + mfxU32 PCIFunction; /*!< The function number of the device on the physical device. */ + mfxU8 DeviceLUID[8]; /*!< LUID of DXGI adapter. */ + mfxU32 LUIDDeviceNodeMask; /*!< Bitfield identifying the node within a linked + device adapter corresponding to the device. */ + mfxU32 LUIDValid; /*!< Boolean value that will be 1 if DeviceLUID contains a valid LUID + and LUIDDeviceNodeMask contains a valid node mask, + and 0 if they do not. */ + mfxU32 DRMRenderNodeNum; /*!< Number of the DRM render node from the path /dev/dri/RenderD\. + Value equals to 0 means that this field doesn't contain valid DRM Render + Node number.*/ + mfxU32 DRMPrimaryNodeNum; /*!< Number of the DRM primary node from the path /dev/dri/card\. + Value equals to 0x7FFFFFFF means that this field doesn't contain valid DRM Primary + Node number.*/ + mfxU16 RevisionID; /*!< PCI revision ID. The value contains microarchitecture version. */ + mfxU8 reserved1[18]; /*!< Reserved for future use. */ + mfxChar DeviceName[MFX_STRFIELD_LEN]; /*!< Null-terminated string in utf-8 with the name of the device. */ +} mfxExtendedDeviceId; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Cross domain structure to define device UUID. It is defined here to check backward compatibility.*/ +typedef struct { + mfxU16 vendor_id; /*!< PCI vendor ID. Same as mfxExtendedDeviceId::VendorID. */ + mfxU16 device_id; /*!< PCI device ID. Same as mfxExtendedDeviceId::DeviceID. */ + mfxU16 revision_id; /*!< PCI revision ID. Same as mfxExtendedDeviceId::RevisionID. */ + mfxU16 pci_domain; /*!< PCI bus domain. Same as mfxExtendedDeviceId::PCIDomain. */ + mfxU8 pci_bus; /*!< The number of the bus that the physical device is located on. Same as mfxExtendedDeviceId::PCIBus. */ + mfxU8 pci_dev; /*!< The index of the physical device on the bus. Same as mfxExtendedDeviceId::PCIDevice. */ + mfxU8 pci_func; /*!< The function number of the device on the physical device. Same as mfxExtendedDeviceId::PCIFunction. */ + mfxU8 reserved[4]; /*!< Reserved for future use. */ + mfxU8 sub_device_id; /*!< SubDevice ID.*/ +} extDeviceUUID; +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_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. */ + MFX_IMPLCAPS_DEVICE_ID_EXTENDED = 4, /*!< Deliver extended device ID information as mfxExtendedDeviceId + structure.*/ +#ifdef ONEVPL_EXPERIMENTAL + MFX_IMPLCAPS_SURFACE_TYPES = 5, /*!< Deliver capabilities as mfxSurfaceTypesSupported structure. */ +#endif +} mfxImplCapsDeliveryFormat; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Specifies initialization parameters for API version starting from 2.0. +*/ +typedef struct { + mfxAccelerationMode AccelerationMode; /*!< Hardware acceleration stack to use. OS dependent parameter. Use VA for Linux*, DX* for Windows* or HDDL. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 DeviceCopy; /*!< Enables or disables device's accelerated copying between device and + host. See the GPUCopy enumerator for a list of valid values. + This parameter is the equivalent of mfxInitParam::GPUCopy. */ + mfxU16 reserved[2]; /*!< Reserved for future use. */ +#else + mfxU16 reserved[3]; /*!< Reserved for future use. */ +#endif + 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 field from mfxImplDescription. */ + mfxU32 reserved2[3]; /*!< Reserved for future use. */ +} mfxInitializationParam; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Represents a name/value pair to indicate requested properties. For use with MFXQueryImplsProperties() */ +typedef struct { + mfxU8* PropName; /*!< Property name string to indicate the requested Property. */ + mfxVariant PropVar; /*!< Property value corresponding to the property name. */ +} mfxQueryProperty; +MFX_PACK_END() +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxdefs.h b/third-party/IntelVPL/arm64/include/vpl/mfxdefs.h new file mode 100644 index 000000000..5b9be9422 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxdefs.h @@ -0,0 +1,349 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXDEFS_H__ +#define __MFXDEFS_H__ + +#define MFX_VERSION_MAJOR 2 +#define MFX_VERSION_MINOR 16 + +// 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 + + +#if !defined(MFX_VERSION) + #define MFX_VERSION (MFX_VERSION_MAJOR * 1000 + MFX_VERSION_MINOR) +#else + #undef MFX_VERSION_MAJOR + #define MFX_VERSION_MAJOR ((MFX_VERSION) / 1000) + + #undef MFX_VERSION_MINOR + #define MFX_VERSION_MINOR ((MFX_VERSION) % 1000) +#endif + +/*! 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 1035 + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* In preprocessor syntax # symbol has stringize meaning, + so to expand some macro to preprocessor pragma we need to use + special compiler dependent construction */ + +#if defined(_MSC_VER) + #define MFX_PRAGMA_IMPL(x) __pragma(x) +#else + #define MFX_PRAGMA_IMPL(x) _Pragma(#x) +#endif + +#define MFX_PACK_BEGIN_X(x) MFX_PRAGMA_IMPL(pack(push, x)) +#define MFX_PACK_END() MFX_PRAGMA_IMPL(pack(pop)) + +/* The general rule for alignment is following: + - structures with pointers have 4/8 bytes alignment on 32/64 bit systems + - structures with fields of type mfxU64/mfxF64 (unsigned long long / double) + have alignment 8 bytes on 64 bit and 32 bit Windows, on Linux alignment is 4 bytes + - all the rest structures are 4 bytes aligned + - there are several exceptions: some structs which had 4-byte alignment were extended + with pointer / long type fields; such structs have 4-byte alignment to keep binary + compatibility with previously release API */ + +#define MFX_PACK_BEGIN_USUAL_STRUCT() MFX_PACK_BEGIN_X(4) + +/* 64-bit LP64 data model */ +#if defined(_WIN64) || defined(__LP64__) + #define MFX_PACK_BEGIN_STRUCT_W_PTR() MFX_PACK_BEGIN_X(8) + #define MFX_PACK_BEGIN_STRUCT_W_L_TYPE() MFX_PACK_BEGIN_X(8) +/* 32-bit ILP32 data model Windows* (Intel(r) architecture) */ +#elif defined(_WIN32) || defined(_M_IX86) && !defined(__linux__) + #define MFX_PACK_BEGIN_STRUCT_W_PTR() MFX_PACK_BEGIN_X(4) + #define MFX_PACK_BEGIN_STRUCT_W_L_TYPE() MFX_PACK_BEGIN_X(8) +/* 32-bit ILP32 data model Linux* */ +#elif defined(__ILP32__) || defined(__arm__) + #define MFX_PACK_BEGIN_STRUCT_W_PTR() MFX_PACK_BEGIN_X(4) + #define MFX_PACK_BEGIN_STRUCT_W_L_TYPE() MFX_PACK_BEGIN_X(4) +#else + #error Unknown packing +#endif + +#ifdef _WIN32 + #define MFX_CDECL __cdecl + #define MFX_STDCALL __stdcall +#else + #define MFX_CDECL + #define MFX_STDCALL +#endif /* _WIN32 */ + +#define MFX_INFINITE 0xFFFFFFFF + +#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 + +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. */ +typedef unsigned short mfxU16; /*!< Unsigned integer, 16 bit type. */ +typedef unsigned int mfxU32; /*!< Unsigned integer, 32 bit type. */ +typedef int mfxI32; /*!< Signed integer, 32 bit type. */ +#if defined( _WIN32 ) || defined ( _WIN64 ) +typedef unsigned long mfxUL32; /*!< Unsigned integer, 32 bit type. */ +typedef long mfxL32; /*!< Signed integer, 32 bit type. */ +#else +typedef unsigned int mfxUL32; /*!< Unsigned integer, 32 bit type. */ +typedef int mfxL32; /*!< Signed integer, 32 bit type. */ +#endif +typedef float mfxF32; /*!< Single-precision floating point, 32 bit type. */ +typedef double mfxF64; /*!< Double-precision floating point, 64 bit type. */ +typedef unsigned long long mfxU64; /*!< Unsigned integer, 64 bit type. */ +typedef long long mfxI64; /*!< Signed integer, 64 bit type. */ +typedef void* mfxHDL; /*!< Handle type. */ +typedef mfxHDL mfxMemId; /*!< Memory ID type. */ +typedef void* mfxThreadTask; /*!< Thread task type. */ +typedef char mfxChar; /*!< UTF-8 byte. */ +typedef unsigned short mfxFP16; /*!< Half precision floating point, 16 bit type. */ + +/* MFX structures version info */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Introduce the field Version for any structure. +Assumed that any structure changes are backward binary compatible. + mfxStructVersion starts from {1,0} for any new API structures. If mfxStructVersion is + added to the existent legacy structure (replacing reserved fields) it starts from {1, 1}. +*/ +typedef union { + /*! Structure with Major and Minor fields. */ + /*! @struct Anonymous */ + struct { + /*! @{ + @name Major and Minor fields + Anonymous structure with Major and Minor fields. Minor number is incremented when reserved fields are used. Major number is incremented when the size of structure is increased. */ + mfxU8 Minor; /*!< Minor number of the correspondent structure. */ + mfxU8 Major; /*!< Major number of the correspondent structure. */ + /*! @} */ + }; + mfxU16 Version; /*!< Structure version number. */ +} mfxStructVersion; +MFX_PACK_END() + +#define MFX_STRUCT_VERSION(MAJOR, MINOR) (256*(MAJOR) + (MINOR)) + +#define MFX_VARIANT_VERSION MFX_STRUCT_VERSION(1, 1) + +/*! 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. */ + MFX_DATA_TYPE_PTR, /*!< Generic type pointer. */ + MFX_DATA_TYPE_FP16, /*!< 16-bit half precision floating point. */ +}mfxDataType; + +/*! The mfxVariantType enumerator data types for mfxVariantType. */ +typedef enum { + 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 = MFX_DATA_TYPE_PTR, /*!< Generic type pointer. */ + MFX_VARIANT_TYPE_FP16 = MFX_DATA_TYPE_FP16, /*!< 16-bit half precision floating point. */ + +#ifdef ONEVPL_EXPERIMENTAL + MFX_VARIANT_TYPE_QUERY = 0x00000100, /*!< Bitmask to OR with other variant types when using property-based query API */ +#endif +} mfxVariantType; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxVariantType enumerator data types for mfxVariant type. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxVariantType Type; /*!< Value type. */ + /*! Value data holder. */ + union data { + mfxU8 U8; /*!< mfxU8 data. */ + mfxI8 I8; /*!< mfxI8 data. */ + mfxU16 U16; /*!< mfxU16 data. */ + mfxI16 I16; /*!< mfxI16 data. */ + mfxU32 U32; /*!< mfxU32 data. */ + mfxI32 I32; /*!< mfxI32 data. */ + mfxU64 U64; /*!< mfxU64 data. */ + mfxI64 I64; /*!< mfxI64 data. */ + mfxF32 F32; /*!< mfxF32 data. */ + mfxF64 F64; /*!< mfxF64 data. */ + mfxFP16 FP16; /*!< mfxFP16 data. */ + mfxHDL Ptr; /*!< Pointer. When this points to a string the string must be null terminated. */ + } Data; /*!< Value data member. */ +} mfxVariant; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Represents a range of unsigned values. */ +typedef struct { + mfxU32 Min; /*!< Minimal value of the range. */ + mfxU32 Max; /*!< Maximal value of the range. */ + mfxU32 Step; /*!< Value increment. */ +} mfxRange32U; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Represents a pair of numbers of type mfxI16. */ +typedef struct { + mfxI16 x; /*!< First number. */ + mfxI16 y; /*!< Second number. */ +} mfxI16Pair; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Represents pair of handles of type mfxHDL. */ +typedef struct { + mfxHDL first; /*!< First handle. */ + mfxHDL second; /*!< Second handle. */ +} mfxHDLPair; +MFX_PACK_END() + +/*********************************************************************************\ +Error message +\*********************************************************************************/ +/*! @enum mfxStatus Itemizes status codes returned by API functions. */ +typedef enum +{ + /* no error */ + MFX_ERR_NONE = 0, /*!< No error. */ + /* reserved for unexpected errors */ + MFX_ERR_UNKNOWN = -1, /*!< Unknown error. */ + + /* error codes <0 */ + MFX_ERR_NULL_PTR = -2, /*!< Null pointer. */ + MFX_ERR_UNSUPPORTED = -3, /*!< Unsupported feature. */ + MFX_ERR_MEMORY_ALLOC = -4, /*!< Failed to allocate memory. */ + MFX_ERR_NOT_ENOUGH_BUFFER = -5, /*!< Insufficient buffer at input/output. */ + MFX_ERR_INVALID_HANDLE = -6, /*!< Invalid handle. */ + MFX_ERR_LOCK_MEMORY = -7, /*!< Failed to lock the memory block. */ + MFX_ERR_NOT_INITIALIZED = -8, /*!< Member function called before initialization. */ + MFX_ERR_NOT_FOUND = -9, /*!< The specified object is not found. */ + MFX_ERR_MORE_DATA = -10, /*!< Expect more data at input. */ + MFX_ERR_MORE_SURFACE = -11, /*!< Expect more surface at output. */ + MFX_ERR_ABORTED = -12, /*!< Operation aborted. */ + MFX_ERR_DEVICE_LOST = -13, /*!< Lose the hardware acceleration device. */ + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM = -14, /*!< Incompatible video parameters. */ + MFX_ERR_INVALID_VIDEO_PARAM = -15, /*!< Invalid video parameters. */ + MFX_ERR_UNDEFINED_BEHAVIOR = -16, /*!< Undefined behavior. */ + MFX_ERR_DEVICE_FAILED = -17, /*!< Device operation failure. */ + MFX_ERR_MORE_BITSTREAM = -18, /*!< Expect more bitstream buffers at output. */ + MFX_ERR_GPU_HANG = -21, /*!< Device operation failure caused by GPU hang. */ + MFX_ERR_REALLOC_SURFACE = -22, /*!< Bigger output surface required. */ + MFX_ERR_RESOURCE_MAPPED = -23, /*!< Write access is already acquired and user requested + another write access, or read access with MFX_MEMORY_NO_WAIT flag. */ + MFX_ERR_NOT_IMPLEMENTED = -24, /*!< Feature or function not implemented. */ + MFX_ERR_MORE_EXTBUFFER = -25, /*!< Expect additional extended configuration buffer. */ + + /* warnings >0 */ + MFX_WRN_IN_EXECUTION = 1, /*!< The previous asynchronous operation is in execution. */ + MFX_WRN_DEVICE_BUSY = 2, /*!< The hardware acceleration device is busy. */ + MFX_WRN_VIDEO_PARAM_CHANGED = 3, /*!< The video parameters are changed during decoding. */ + MFX_WRN_PARTIAL_ACCELERATION = 4, /*!< Software acceleration is used. */ + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM = 5, /*!< Incompatible video parameters. */ + MFX_WRN_VALUE_NOT_CHANGED = 6, /*!< The value is saturated based on its valid range. */ + MFX_WRN_OUT_OF_RANGE = 7, /*!< The value is out of valid range. */ + MFX_WRN_FILTER_SKIPPED = 10, /*!< One of requested filters has been skipped. */ + /* low-delay partial output */ + MFX_ERR_NONE_PARTIAL_OUTPUT = 12, /*!< Frame is not ready, but bitstream contains partial output. */ + + MFX_WRN_ALLOC_TIMEOUT_EXPIRED = 13, /*!< Timeout expired for internal frame allocation. */ + + /* threading statuses */ + MFX_TASK_DONE = MFX_ERR_NONE, /*!< Task has been completed. */ + MFX_TASK_WORKING = 8, /*!< There is some more work to do. */ + MFX_TASK_BUSY = 9, /*!< Task is waiting for resources. */ + + /* plug-in statuses */ + MFX_ERR_MORE_DATA_SUBMIT_TASK = -10000, /*!< Return MFX_ERR_MORE_DATA but submit internal asynchronous task. */ + +} 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) + +#include "mfxdispatcherprefixedfunctions.h" + +#endif // MFX_DISPATCHER_EXPOSED_PREFIX + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MFXDEFS_H__ */ diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxdispatcher.h b/third-party/IntelVPL/arm64/include/vpl/mfxdispatcher.h new file mode 100644 index 000000000..df7d7ae3d --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxdispatcher.h @@ -0,0 +1,271 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXDISPATCHER_H__ +#define __MFXDISPATCHER_H__ + +#include "mfxdefs.h" +#include "mfxcommon.h" +#include "mfxsession.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! Loader handle. */ +typedef struct _mfxLoader *mfxLoader; + +/*! Config handle. */ +typedef struct _mfxConfig *mfxConfig; + +/*! + @brief Creates the loader. + @return Loader Loader handle or NULL if failed. + + @since This function is available since API version 2.0. +*/ +mfxLoader MFX_CDECL MFXLoad(void); + +/*! + @brief Destroys the dispatcher. + @param[in] loader Loader handle. + + @since This function is available since API version 2.0. +*/ +void MFX_CDECL MFXUnload(mfxLoader loader); + +/*! + @brief Creates dispatcher configuration. + @details Creates the dispatcher internal configuration, which is used to filter out available implementations. + This configuration is used to walk through selected implementations to gather more details and select the appropriate + implementation to load. The loader object remembers all created mfxConfig objects and destroys them during the mfxUnload + function call. + + Multiple configurations per single mfxLoader object are possible. + + Usage example: + @code + mfxLoader loader = MFXLoad(); + mfxConfig cfg = MFXCreateConfig(loader); + MFXCreateSession(loader,0,&session); + @endcode + @param[in] loader Loader handle. + @return Config handle or NULL pointer is failed. + + @since This function is available since API version 2.0. +*/ +mfxConfig MFX_CDECL MFXCreateConfig(mfxLoader loader); + +/*! + @brief Adds additional filter properties (any fields of the mfxImplDescription structure) to the configuration of the loader object. + @note Each new call with the same parameter name will overwrite the previously set value. This may invalidate other properties. + + @param[in] config Config handle. + @param[in] name Name of the parameter (see mfxImplDescription structure and example). + @param[in] value Value of the parameter. + @return + MFX_ERR_NONE The function completed successfully. + MFX_ERR_NULL_PTR If config is NULL. \n + MFX_ERR_NULL_PTR If name is NULL. \n + MFX_ERR_NOT_FOUND If name contains unknown parameter name. + MFX_ERR_UNSUPPORTED If value data type does not equal the parameter with provided name. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXSetConfigFilterProperty(mfxConfig config, const mfxU8* name, mfxVariant value); + +/*! + @brief Iterates over filtered out implementations to gather their details. This function allocates memory to store + a structure or string corresponding to the type specified by format. For example, if format is set to + MFX_IMPLCAPS_IMPLDESCSTRUCTURE, then idesc will return a pointer to a structure of type mfxImplDescription. + Use the MFXDispReleaseImplDescription function to free memory allocated to this structure or string. + @param[in] loader Loader handle. + @param[in] i Index of the implementation. + @param[in] format Format in which capabilities need to be delivered. See the mfxImplCapsDeliveryFormat enumerator for more details. + @param[out] idesc Pointer to the structure or string corresponding to the requested format. + @return + MFX_ERR_NONE The function completed successfully. The idesc contains valid information.\n + MFX_ERR_NULL_PTR If loader is NULL. \n + MFX_ERR_NULL_PTR If idesc is NULL. \n + MFX_ERR_NOT_FOUND Provided index is out of possible range. \n + MFX_ERR_UNSUPPORTED If requested format is not supported. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXEnumImplementations(mfxLoader loader, mfxU32 i, mfxImplCapsDeliveryFormat format, mfxHDL* idesc); + + +/*! + @brief Loads and initializes the implementation. + @code + mfxLoader loader = MFXLoad(); + int i=0; + while(1) { + mfxImplDescription *idesc; + MFXEnumImplementations(loader, i, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL*)&idesc); + if(is_good(idesc)) { + MFXCreateSession(loader, i,&session); + // ... + MFXDispReleaseImplDescription(loader, idesc); + } + else + { + MFXDispReleaseImplDescription(loader, idesc); + break; + } + } + @endcode + @param[in] loader Loader handle. + @param[in] i Index of the implementation. + @param[out] session Pointer to the session handle. + @return + MFX_ERR_NONE The function completed successfully. The session contains a pointer to the session handle.\n + MFX_ERR_NULL_PTR If loader is NULL. \n + MFX_ERR_NULL_PTR If session is NULL. \n + MFX_ERR_NOT_FOUND Provided index is out of possible range. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXCreateSession(mfxLoader loader, mfxU32 i, mfxSession* session); + +/*! + @brief + Destroys handle allocated by the MFXEnumImplementations function. + + @param[in] loader Loader handle. + @param[in] hdl Handle to destroy. Can be equal to NULL. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR If loader is NULL. \n + MFX_ERR_INVALID_HANDLE Provided hdl handle is not associated with this loader. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXDispReleaseImplDescription(mfxLoader loader, mfxHDL hdl); + +/*! + @brief + Macro help to return UUID in the common oneAPI format. + + @param[in] devinfo Handle to mfxExtendedDeviceId. + @param[in] sub_dev_num SubDevice number. Can be obtained from mfxDeviceDescription::SubDevices::Index. Set to zero if no SubDevices. + @param[out] uuid Pointer to UUID. + +*/ +#define MFX_UUID_COMPUTE_DEVICE_ID(devinfo, sub_dev_num, uuid) \ +{ \ + extDeviceUUID t_uuid = { 0 }; \ + extDeviceUUID* shared_uuid = (extDeviceUUID*)(uuid); \ + t_uuid.vendor_id = (devinfo)->VendorID; \ + t_uuid.device_id = (devinfo)->DeviceID; \ + t_uuid.revision_id = (devinfo)->RevisionID; \ + t_uuid.pci_domain = (devinfo)->PCIDomain; \ + t_uuid.pci_bus = (mfxU8)(devinfo)->PCIBus; \ + t_uuid.pci_dev = (mfxU8)(devinfo)->PCIDevice; \ + t_uuid.pci_func = (mfxU8)(devinfo)->PCIFunction; \ + t_uuid.sub_device_id = (mfxU8)(sub_dev_num); \ + *shared_uuid = t_uuid; \ +} + +/* Helper macro definitions to add config filter properties. */ + +/*! Adds single property of mfxU32 type. + @param[in] loader Valid mfxLoader object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_ADD_PROPERTY_U32(loader, name, value) \ +{ \ + mfxVariant impl_value; \ + mfxConfig cfg = MFXCreateConfig(loader); \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U32; \ + impl_value.Data.U32 = value; \ + MFXSetConfigFilterProperty(cfg, (mfxU8 *)name, impl_value); \ +} + +/*! Adds single property of mfxU16 type. + @param[in] loader Valid mfxLoader object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_ADD_PROPERTY_U16(loader, name, value) \ +{ \ + mfxVariant impl_value = { 0 }; \ + mfxConfig cfg = MFXCreateConfig(loader); \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U16; \ + impl_value.Data.U16 = value; \ + MFXSetConfigFilterProperty(cfg, (mfxU8 *)name, impl_value); \ +} + +/*! Adds single property of pointer type. + @param[in] loader Valid mfxLoader object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_ADD_PROPERTY_PTR(loader, name, value) \ +{ \ + mfxVariant impl_value = { 0 }; \ + mfxConfig cfg = MFXCreateConfig(loader); \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_PTR; \ + impl_value.Data.Ptr = (mfxHDL)value; \ + MFXSetConfigFilterProperty(cfg, (mfxU8 *)name, impl_value); \ +} + +/*! Update existing property of mfxU32 type. + @param[in] loader Valid mfxLoader object + @param[in] config Valid mfxConfig object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_UPDATE_PROPERTY_U32(loader, config, name, value) \ +{ \ + mfxVariant impl_value; \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U32; \ + impl_value.Data.U32 = value; \ + MFXSetConfigFilterProperty(config, (mfxU8 *)name, impl_value); \ +} + +/*! Update existing property of mfxU16 type. + @param[in] loader Valid mfxLoader object + @param[in] config Valid mfxConfig object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_UPDATE_PROPERTY_U16(loader, config, name, value) \ +{ \ + mfxVariant impl_value; \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U16; \ + impl_value.Data.U16 = value; \ + MFXSetConfigFilterProperty(config, (mfxU8 *)name, impl_value); \ +} + +/*! Update existing property of pointer type. + @param[in] loader Valid mfxLoader object + @param[in] config Valid mfxConfig object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_UPDATE_PROPERTY_PTR(loader, config, name, value) \ +{ \ + mfxVariant impl_value; \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_PTR; \ + impl_value.Data.Ptr = (mfxHDL)value; \ + MFXSetConfigFilterProperty(config, (mfxU8 *)name, impl_value); \ +} + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxdispatcherprefixedfunctions.h b/third-party/IntelVPL/arm64/include/vpl/mfxdispatcherprefixedfunctions.h new file mode 100644 index 000000000..38fe0cca7 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxdispatcherprefixedfunctions.h @@ -0,0 +1,154 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXDISPATCHERPREFIXEDFUNCTIONS_H__ +#define __MFXDISPATCHERPREFIXEDFUNCTIONS_H__ + +// API 1.0 functions +#define MFXInit disp_MFXInit +#define MFXClose disp_MFXClose +#define MFXQueryIMPL disp_MFXQueryIMPL +#define MFXQueryVersion disp_MFXQueryVersion + +#define MFXJoinSession disp_MFXJoinSession +#define MFXDisjoinSession disp_MFXDisjoinSession +#define MFXCloneSession disp_MFXCloneSession +#define MFXSetPriority disp_MFXSetPriority +#define MFXGetPriority disp_MFXGetPriority + +#define MFXVideoCORE_SetFrameAllocator disp_MFXVideoCORE_SetFrameAllocator +#define MFXVideoCORE_SetHandle disp_MFXVideoCORE_SetHandle +#define MFXVideoCORE_GetHandle disp_MFXVideoCORE_GetHandle +#define MFXVideoCORE_SyncOperation disp_MFXVideoCORE_SyncOperation + +#define MFXVideoENCODE_Query disp_MFXVideoENCODE_Query +#define MFXVideoENCODE_QueryIOSurf disp_MFXVideoENCODE_QueryIOSurf +#define MFXVideoENCODE_Init disp_MFXVideoENCODE_Init +#define MFXVideoENCODE_Reset disp_MFXVideoENCODE_Reset +#define MFXVideoENCODE_Close disp_MFXVideoENCODE_Close +#define MFXVideoENCODE_GetVideoParam disp_MFXVideoENCODE_GetVideoParam +#define MFXVideoENCODE_GetEncodeStat disp_MFXVideoENCODE_GetEncodeStat +#define MFXVideoENCODE_EncodeFrameAsync disp_MFXVideoENCODE_EncodeFrameAsync + +#define MFXVideoDECODE_Query disp_MFXVideoDECODE_Query +#define MFXVideoDECODE_DecodeHeader disp_MFXVideoDECODE_DecodeHeader +#define MFXVideoDECODE_QueryIOSurf disp_MFXVideoDECODE_QueryIOSurf +#define MFXVideoDECODE_Init disp_MFXVideoDECODE_Init +#define MFXVideoDECODE_Reset disp_MFXVideoDECODE_Reset +#define MFXVideoDECODE_Close disp_MFXVideoDECODE_Close +#define MFXVideoDECODE_GetVideoParam disp_MFXVideoDECODE_GetVideoParam +#define MFXVideoDECODE_GetDecodeStat disp_MFXVideoDECODE_GetDecodeStat +#define MFXVideoDECODE_SetSkipMode disp_MFXVideoDECODE_SetSkipMode +#define MFXVideoDECODE_GetPayload disp_MFXVideoDECODE_GetPayload +#define MFXVideoDECODE_DecodeFrameAsync disp_MFXVideoDECODE_DecodeFrameAsync + +#define MFXVideoVPP_Query disp_MFXVideoVPP_Query +#define MFXVideoVPP_QueryIOSurf disp_MFXVideoVPP_QueryIOSurf +#define MFXVideoVPP_Init disp_MFXVideoVPP_Init +#define MFXVideoVPP_Reset disp_MFXVideoVPP_Reset +#define MFXVideoVPP_Close disp_MFXVideoVPP_Close + +#define MFXVideoVPP_GetVideoParam disp_MFXVideoVPP_GetVideoParam +#define MFXVideoVPP_GetVPPStat disp_MFXVideoVPP_GetVPPStat +#define MFXVideoVPP_RunFrameVPPAsync disp_MFXVideoVPP_RunFrameVPPAsync + +// API 1.1 functions +#define MFXVideoUSER_Register disp_MFXVideoUSER_Register +#define MFXVideoUSER_Unregister disp_MFXVideoUSER_Unregister +#define MFXVideoUSER_ProcessFrameAsync disp_MFXVideoUSER_ProcessFrameAsync + +// API 1.10 functions + +#define MFXVideoENC_Query disp_MFXVideoENC_Query +#define MFXVideoENC_QueryIOSurf disp_MFXVideoENC_QueryIOSurf +#define MFXVideoENC_Init disp_MFXVideoENC_Init +#define MFXVideoENC_Reset disp_MFXVideoENC_Reset +#define MFXVideoENC_Close disp_MFXVideoENC_Close +#define MFXVideoENC_ProcessFrameAsync disp_MFXVideoENC_ProcessFrameAsync +#define MFXVideoVPP_RunFrameVPPAsyncEx disp_MFXVideoVPP_RunFrameVPPAsyncEx +#define MFXVideoUSER_Load disp_MFXVideoUSER_Load +#define MFXVideoUSER_UnLoad disp_MFXVideoUSER_UnLoad + +// API 1.11 functions + +#define MFXVideoPAK_Query disp_MFXVideoPAK_Query +#define MFXVideoPAK_QueryIOSurf disp_MFXVideoPAK_QueryIOSurf +#define MFXVideoPAK_Init disp_MFXVideoPAK_Init +#define MFXVideoPAK_Reset disp_MFXVideoPAK_Reset +#define MFXVideoPAK_Close disp_MFXVideoPAK_Close +#define MFXVideoPAK_ProcessFrameAsync disp_MFXVideoPAK_ProcessFrameAsync + +// API 1.13 functions + +#define MFXVideoUSER_LoadByPath disp_MFXVideoUSER_LoadByPath + +// API 1.14 functions +#define MFXInitEx disp_MFXInitEx + +// Audio library functions + +// API 1.8 functions + +#define MFXAudioCORE_SyncOperation disp_MFXAudioCORE_SyncOperation +#define MFXAudioENCODE_Query disp_MFXAudioENCODE_Query +#define MFXAudioENCODE_QueryIOSize disp_MFXAudioENCODE_QueryIOSize +#define MFXAudioENCODE_Init disp_MFXAudioENCODE_Init +#define MFXAudioENCODE_Reset disp_MFXAudioENCODE_Reset +#define MFXAudioENCODE_Close disp_MFXAudioENCODE_Close +#define MFXAudioENCODE_GetAudioParam disp_MFXAudioENCODE_GetAudioParam +#define MFXAudioENCODE_EncodeFrameAsync disp_MFXAudioENCODE_EncodeFrameAsync + +#define MFXAudioDECODE_Query disp_MFXAudioDECODE_Query +#define MFXAudioDECODE_DecodeHeader disp_MFXAudioDECODE_DecodeHeader +#define MFXAudioDECODE_Init disp_MFXAudioDECODE_Init +#define MFXAudioDECODE_Reset disp_MFXAudioDECODE_Reset +#define MFXAudioDECODE_Close disp_MFXAudioDECODE_Close +#define MFXAudioDECODE_QueryIOSize disp_MFXAudioDECODE_QueryIOSize +#define MFXAudioDECODE_GetAudioParam disp_MFXAudioDECODE_GetAudioParam +#define MFXAudioDECODE_DecodeFrameAsync disp_MFXAudioDECODE_DecodeFrameAsync + +// API 1.9 functions + +#define MFXAudioUSER_Register disp_MFXAudioUSER_Register +#define MFXAudioUSER_Unregister disp_MFXAudioUSER_Unregister +#define MFXAudioUSER_ProcessFrameAsync disp_MFXAudioUSER_ProcessFrameAsync +#define MFXAudioUSER_Load disp_MFXAudioUSER_Load +#define MFXAudioUSER_UnLoad disp_MFXAudioUSER_UnLoad + +// API 1.19 functions + +#define MFXVideoENC_GetVideoParam disp_MFXVideoENC_GetVideoParam +#define MFXVideoPAK_GetVideoParam disp_MFXVideoPAK_GetVideoParam +#define MFXVideoCORE_QueryPlatform disp_MFXVideoCORE_QueryPlatform +#define MFXVideoUSER_GetPlugin disp_MFXVideoUSER_GetPlugin + +// API 2.0 functions +#define MFXMemory_GetSurfaceForVPP disp_MFXMemory_GetSurfaceForVPP +#define MFXMemory_GetSurfaceForEncode disp_MFXMemory_GetSurfaceForEncode +#define MFXMemory_GetSurfaceForDecode disp_MFXMemory_GetSurfaceForDecode + +#define MFXQueryImplsDescription disp_MFXQueryImplsDescription +#define MFXReleaseImplDescription disp_MFXReleaseImplDescription + +#define MFXInitialize disp_MFXInitialize + +// API 2.1 functions +#define MFXMemory_GetSurfaceForVPPOut disp_MFXMemory_GetSurfaceForVPPOut + +#define MFXVideoDECODE_VPP_Init disp_MFXVideoDECODE_VPP_Init +#define MFXVideoDECODE_VPP_DecodeFrameAsync disp_MFXVideoDECODE_VPP_DecodeFrameAsync +#define MFXVideoDECODE_VPP_Reset disp_MFXVideoDECODE_VPP_Reset +#define MFXVideoDECODE_VPP_GetChannelParam disp_MFXVideoDECODE_VPP_GetChannelParam +#define MFXVideoDECODE_VPP_Close disp_MFXVideoDECODE_VPP_Close + +#define MFXVideoVPP_ProcessFrameAsync disp_MFXVideoVPP_ProcessFrameAsync + +// API 2.15 functions +#ifdef ONEVPL_EXPERIMENTAL +#define MFXQueryImplsProperties disp_MFXQueryImplsProperties +#endif + +#endif diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxencodestats.h b/third-party/IntelVPL/arm64/include/vpl/mfxencodestats.h new file mode 100644 index 000000000..940e94a8a --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxencodestats.h @@ -0,0 +1,458 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifdef ONEVPL_EXPERIMENTAL + + +#ifndef __MFXENCODESTATS_H__ +#define __MFXENCODESTATS_H__ +#include "mfxcommon.h" +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*!< The enum to specify memory layout for statistics. */ +typedef enum { + MFX_ENCODESTATS_MEMORY_LAYOUT_DEFAULT = 0, /*!< The default memory layout for statistics. */ +} mfxEncodeBlkStatsMemLayout; + +/*!< The enum to specify mode to gather statistics. */ +typedef enum { + MFX_ENCODESTATS_MODE_DEFAULT = 0, /*!< Encode mode is selected by the implementation. */ + MFX_ENCODESTATS_MODE_ENCODE = 1, /*!< Full encode mode. */ +} mfxEncodeStatsMode; + +/*!< Flags to specify what statistics will be reported by the implementation. */ +enum { + MFX_ENCODESTATS_LEVEL_BLK = 0x1, /*!< Block level statistics. */ + MFX_ENCODESTATS_LEVEL_SLICE = 0x2, /*!< Slice level statistics. */ + MFX_ENCODESTATS_LEVEL_TILE = 0x4, /*!< Tile level statistics. */ + MFX_ENCODESTATS_LEVEL_FRAME = 0x8, /*!< Frame level statistics. */ +}; + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*!< Specifies H.265 CTU header. */ +typedef struct { + union { + struct { + mfxU32 CUcountminus1 : 6; /*!< Number of CU per CTU. */ + mfxU32 MaxDepth : 2; /*!< Max quad-tree depth of CU in CTU. */ + mfxU32 reserved : 24; + } bitfields0; + mfxU32 dword0; + }; + mfxU16 CurrXAddr; /*!< Horizontal address of CTU. */ + mfxU16 CurrYAddr; /*!< Vertical address of CTU. */ + mfxU32 reserved1; +} mfxCTUHeader; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*!< Specifies H.265 CU info. */ +typedef struct { + union { + struct { + mfxU32 CU_Size : 2; /*!< indicates the CU size of the current CU. 0: 8x8 1: 16x16 2: 32x32 3: 64x64 */ + mfxU32 CU_pred_mode : 1; /*!< indicates the prediction mode for the current CU. 0: intra 1: inter */ + /*! + indicates the PU partition mode for the current CU. + 0: 2Nx2N + 1: 2NxN (inter) + 2: Nx2N (inter) + 3: NXN (intra only, CU Size=8x8 only. Luma Intra Mode indicates the intra prediction mode for 4x4_0. The additional prediction modes are overloaded on 4x4_1, 4x4_2, 4x4_3 below) + 4: 2NxnT (inter only) + 5: 2NxnB (inter only) + 6: nLx2N (inter only) + 7: nRx2N (inter only). + */ + mfxU32 CU_part_mode : 3; + mfxU32 InterPred_IDC_MV0 : 2; /*!< indicates the prediction direction for PU0 of the current CU. 0: L0 1: L1 2: Bi 3: reserved */ + mfxU32 InterPred_IDC_MV1 : 2; /*!< indicates the prediction direction for PU1 of the current CU. 0: L0 1: L1 2: Bi 3: reserved */ + /*! + Final explicit Luma Intra Mode 4x4_0 for NxN. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode : 6; + /*! + indicates the final explicit Luma Intra Mode for the CU. + 0: DM (use Luma mode, from block 0 if NxN) + 1: reserved + 2: Planar + 3: Vertical + 4: Horizontal + 5: DC */ + mfxU32 ChromaIntraMode : 3; + mfxU32 reserved : 13; + } bitfields0; + mfxU32 dword0; + }; + + union { + struct { + /*! + Final explicit Luma Intra Mode 4x4_1. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode4x4_1 : 6; + /*! + Final explicit Luma Intra Mode 4x4_2. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode4x4_2 : 6; + /*! + Final explicit Luma Intra Mode 4x4_3. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode4x4_3 : 6; + mfxU32 reserved1 : 14; + } bitfields1; + mfxU32 dword1; + }; + + mfxI8 QP; // signed QP value + mfxU8 reserved2[3]; + /*! distortion measure, approximation to SAD. + Will deviate significantly (pre, post reconstruction) and due to variation in algorithm. + */ + mfxU32 SAD; + + /*! + These parameters indicate motion vectors that are associated with the PU0/PU1 winners + range [-2048.00..2047.75]. + L0/PU0 - MV[0][0] + L0/PU1 - MV[0][1] + L1/PU0 - MV[1][0] + L1/PU1 - MV[1][1] + */ + mfxI16Pair MV[2][2]; + + union { + struct { + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L0_MV0.X and L0_MV0.Y fields. */ + mfxU32 L0_MV0_RefID : 4; + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L0_MV1.X and L0_MV1.Y fields. */ + mfxU32 L0_MV1_RefID : 4; + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L1_MV0.X and L1_MV0.Y fields. */ + mfxU32 L1_MV0_RefID : 4; + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L1_MV1.X and L1_MV1.Y fields. */ + mfxU32 L1_MV1_RefID : 4; + + mfxU32 reserved3 : 16; + } bitfields8; + mfxU32 dword8; + }; + mfxU32 reserved4[10]; +} mfxCUInfo; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*!< Specifies H.265 CTU. */ +typedef struct { + mfxCTUHeader CtuHeader; /*!< H.265 CTU header. */ + mfxCUInfo CuInfo[64]; /*!< Array of CU. */ + mfxU32 reserved; +} mfxCTUInfo; +MFX_PACK_END() + + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + The structure describes H.264 stats per MB. +*/ +typedef struct { + union { + struct { + /*! + Together with @p IntraMbFlag this parameter specifies macroblock type according to the + ISO\*\/IEC\* 14496-10 with the following difference - it stores either intra or inter + values according to @p IntraMbFlag, but not intra after inter. + Values for P-slices are mapped to B-slice values. For example P_16x8 is coded with + B_FWD_16x8 value. + */ + mfxU32 MBType : 5; + /*! + This field specifies inter macroblock mode and is ignored for intra MB. It is derived from @p MbType and has next values: + @li 0 - 16x16 mode + @li 1 - 16x8 mode + @li 2 - 8x16 mode + @li 3 - 8x8 mode + */ + mfxU32 InterMBMode : 2; + /*! + This field specifies intra macroblock mode and is ignored for inter MB. It is derived from @p MbType and has next values: + @li 0 - 16x16 mode + @li 1 - 8x8 mode + @li 2 - 4x4 mode + @li 3 - PCM + */ + mfxU32 IntraMBMode : 2; + /*! + This flag specifies intra/inter MB type and has next values: + 0 - Inter prediction MB type + 1 - Intra prediction MB type + */ + mfxU32 IntraMBFlag : 1; + /*! + This field specifies subblock shapes for the current MB. Each block is described by 2 bits starting from lower bits for block 0. + + @li 0 - 8x8 + @li 1 - 8x4 + @li 2 - 4x8 + @li 3 - 4x4 + */ + mfxU32 SubMBShapes : 8; + /*! + This field specifies prediction modes for the current MB partition blocks. Each block is described by 2 bits starting from lower bits for block 0. + @li 0 - Pred_L0 + @li 1 - Pred_L1 + @li 2 - BiPred + @li 3 - reserved + + Only one prediction value for partition is reported, the rest values are set to zero. For example: + @li 16x16 Pred_L1 - 0x01 (only 2 lower bits are used) + @li 16x8 Pred_L1 / BiPred - 0x09 (1001b) + @li 8x16 BiPred / BiPred - 0x0a (1010b) + + For P MBs this value is always zero. + */ + mfxU32 SubMBShapeMode : 8; + /*! + This value specifies chroma intra prediction mode. + @li 0 - DC + @li 1 - Horizontal + @li 2 - Vertical + @li 3 - Plane + */ + mfxU32 ChromaIntraPredMode : 2; + mfxU32 reserved : 4; + } bitfields0; + mfxU32 dword0; + } ; + /*! + Distortion measure, approximation to SAD. + Deviate significantly (pre, post reconstruction) and due to variation in algorithm. + */ + mfxU32 SAD; + mfxI8 Qp; /*!< MB QP. */ + mfxU8 reserved1[3]; + + /*! + These values specify luma intra prediction modes for current MB. Each element of the array + corresponds to 8x8 block and each holds prediction modes for four 4x4 subblocks. + Four bits per mode, lowest bits for left top subblock. + All 16 prediction modes are always specified. For 8x8 case, block prediction mode is + populated to all subblocks of the 8x8 block. For 16x16 case - to all subblocks of the MB. + + Prediction directions for 4x4 and 8x8 blocks: + @li 0 - Vertical + @li 1 - Horizontal + @li 2 - DC + @li 3 - Diagonal Down Left + @li 4 - Diagonal Down Right + @li 5 - Vertical Right + @li 6 - Horizontal Down + @li 7 - Vertical Left + @li 8 - Horizontal Up + + Prediction directions for 16x16 blocks: + @li 0 - Vertical + @li 1 - Horizontal + @li 2 - DC + @li 3 - Plane + */ + mfxU16 LumaIntraMode[4]; + + mfxU32 reserved2; +} mfxMBInfo; +MFX_PACK_END() + +/*! + The enum specifies block size. +*/ +typedef enum { + MFX_BLOCK_4X4 = 0, /*!< 4x4 block size. */ + MFX_BLOCK_16X16 = 1, /*!< 16x16 block size. */ +} mfxBlockSize; + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + The structure describes H.264 and H.265 stats per MB or CTUs. +*/ +typedef struct { + union { + mfxU32 NumMB; /*!< Number of MBs per frame for H.264. */ + mfxU32 NumCTU; /*!< number of CTUs per frame for H.265. */ + }; + union { + mfxCTUInfo *HEVCCTUArray; /*!< Array of CTU statistics. */ + mfxMBInfo *AVCMBArray; /*!< Array of MB statistics. */ + }; + mfxU32 reserved[8]; + +} mfxEncodeBlkStats; +MFX_PACK_END() + + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + The structure describes H.264/H.265 frame/slice/tile level statistics. +*/ +typedef struct { + mfxF32 PSNRLuma; /*!< PSNR for LUMA samples. */ + mfxF32 PSNRCb; /*!< PSNR for Chroma (Cb) samples. */ + mfxF32 PSNRCr; /*!< PSNR for Chroma (Cr) samples. */ + /*! distortion measure, approximation to SAD. + Will deviate significantly (pre, post reconstruction) and due to variation in algorithm. + */ + mfxU64 SADLuma; + mfxF32 Qp; /*!< average frame QP, may have fractional part in case of MBQP. */ + + union { + mfxU32 NumMB; /*!< Number of MBs per frame for H.264. */ + mfxU32 NumCTU; /*!< number of CTUs per frame for H.265. */ + }; + + mfxBlockSize BlockSize; /*! For H.264 it is always 16x16 corresponding to MB size. + In H.265 it's normalized to 4x4, so for each CU we calculate number of 4x4 which belongs to the block. */ + + mfxU32 NumIntraBlock; /*! Number of intra blocks in the frame. The size of block is defined by BlockSize. + For H.265 it can be more than number of intra CU. */ + mfxU32 NumInterBlock; /*! Number of inter blocks in the frame. The size of block is defined by BlockSize. + For H.265 it can be more than number of inter CU. */ + mfxU32 NumSkippedBlock; /*! Number of skipped blocks in the frame. The size of block is defined by BlockSize. + For H.265 it can be more than number of skipped CU. */ + + mfxU32 reserved[8]; + +} mfxEncodeHighLevelStats; +MFX_PACK_END() + +/*! + Alias for the structure to describe H.264 and H.265 frame level stats. +*/ +typedef mfxEncodeHighLevelStats mfxEncodeFrameStats; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + The structure describes H.264 and H.265 stats per Slice or Tile. +*/ +typedef struct { + mfxU32 NumElements; /*!< Number of Slices or Tiles per frame for H.264/H.265. */ + mfxEncodeHighLevelStats *HighLevelStatsArray; /*!< Array of CTU statistics. */ + mfxU32 reserved[8]; + +} mfxEncodeSliceStats; +MFX_PACK_END() + +/*! + Alias for the structure to describe H.264 and H.265 tile level stats. +*/ +typedef mfxEncodeSliceStats mfxEncodeTileStats; + + +#define MFX_ENCODESTATSCONTAINER_VERSION MFX_STRUCT_VERSION(1, 0) + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure represents reference counted container for output after encoding operation which includes statistics + and synchronization primitive for compressed bitstream. + The memory is allocated and released by the library. +*/ +typedef struct mfxEncodeStatsContainer { + mfxStructVersion Version; /*!< The version of the structure. */ + mfxRefInterface RefInterface; /*! < Reference counting interface. */ + /*! @brief + Guarantees readiness of the statistics after a function completes. + Instead of MFXVideoCORE_SyncOperation which leads to the synchronization of all output objects, + users may directly call the mfxEncodeStatsContainer::SynchronizeStatistics function to get output statistics. + + + @param[in] ref_interface Valid interface. + @param[out] wait Wait time in milliseconds. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of container is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the container is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *SynchronizeStatistics)(mfxRefInterface* ref_interface, mfxU32 wait); + /*! @brief + Guarantees readiness of associated compressed bitstream after a function completes. + Instead of MFXVideoCORE_SyncOperation which leads to the synchronization of all output objects, + users may directly call the mfxEncodeStatsContainer::SynchronizeStatistics function to get output bitstream. + + + @param[in] ref_interface Valid interface. + @param[out] wait Wait time in milliseconds. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of container is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the container is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *SynchronizeBitstream)(mfxRefInterface* ref_interface, mfxU32 wait); + mfxHDL reserved[4]; + mfxU32 reserved1[2]; + mfxU32 DisplayOrder; /*!< To which frame number statistics belong. */ + mfxEncodeBlkStatsMemLayout MemLayout; /*!< Memory layout for statistics. */ + mfxEncodeBlkStats *EncodeBlkStats; /*!< Block level statistics. */ + mfxEncodeSliceStats *EncodeSliceStats; /*!< Slice level statistics. */ + mfxEncodeTileStats *EncodeTileStats; /*!< Tile level statistics. */ + mfxEncodeFrameStats *EncodeFrameStats; /*!< Frame level statistics. */ + mfxU32 reserved2[8]; +}mfxEncodeStatsContainer; +MFX_PACK_END() + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The extension buffer which should be attached by application for mfxBitstream buffer before + encode operation. As result the encoder will allocate memory for statistics and fill appropriate structures. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODESTATS_BLK. */ + mfxU16 EncodeStatsFlags; /*!< What statistics is required: block/slice/tile/frame level or any combinations. + In case of slice or tile output statistics for one slice or tile will be available only.*/ + mfxEncodeStatsMode Mode; /*!< What encoding mode should be used to gather statistics. */ + mfxEncodeStatsContainer *EncodeStatsContainer; /*!< encode output, filled by the implementation. */ + mfxU32 reserved[8]; +} mfxExtEncodeStatsOutput; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + +#endif \ No newline at end of file diff --git a/third-party/IntelVPL/arm64/include/vpl/mfximplcaps.h b/third-party/IntelVPL/arm64/include/vpl/mfximplcaps.h new file mode 100644 index 000000000..b78b0be69 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfximplcaps.h @@ -0,0 +1,78 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#include "mfxdefs.h" + +#ifndef __MFXIMPLCAPS_H__ +#define __MFXIMPLCAPS_H__ + +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + @brief + Delivers implementation capabilities in the requested format according to the format value. Calling this + function directly is not recommended. Instead, applications must call the MFXEnumImplementations function. + + @param[in] format Format in which capabilities must be delivered. See mfxImplCapsDeliveryFormat for more details. + @param[out] num_impls Number of the implementations. + + @return + Array of handles to the capability report or NULL in case of unsupported format or NULL num_impls pointer. + Length of array is equal to num_impls. + + @since This function is available since API version 2.0. +*/ +mfxHDL* MFX_CDECL MFXQueryImplsDescription(mfxImplCapsDeliveryFormat format, mfxU32* num_impls); + +/*! + @brief + Destroys the handle allocated by the MFXQueryImplsDescription function or the MFXQueryImplsProperties 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. Calling this function directly is not recommended. Instead, applications must call + the MFXDispReleaseImplDescription function. + + @param[in] hdl Handle to destroy. Can be equal to NULL. + + @return + MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXReleaseImplDescription(mfxHDL hdl); + +#ifdef ONEVPL_EXPERIMENTAL +/*! + @brief + Delivers implementation capabilities for configured properties. + The returned capability report will be sparsely filled out, with only properties available which + were set via MFXSetConfigFilterProperty(). Calling this function directly is not recommended. + Instead, applications must call the MFXEnumImplementations function. + + + @param[in] properties Array of property name/value pairs indicating which properties to populate in the capability report. + @param[in] num_properties Number of property name/value pairs. + @param[out] num_impls Number of the implementations. + + @return + Array of handles to the capability report or NULL in case of NULL properties pointer or zero num_properties or NULL num_impls pointer. + Length of array is equal to num_impls. + + @since This function is available since API version 2.15. +*/ +mfxHDL* MFX_CDECL MFXQueryImplsProperties(mfxQueryProperty** properties, mfxU32 num_properties, mfxU32* num_impls); +#endif + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MFXIMPLCAPS_H__ diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxjpeg.h b/third-party/IntelVPL/arm64/include/vpl/mfxjpeg.h new file mode 100644 index 000000000..fe9d5421a --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxjpeg.h @@ -0,0 +1,136 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFX_JPEG_H__ +#define __MFX_JPEG_H__ + +#include "mfxdefs.h" +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* CodecId */ +enum { + MFX_CODEC_JPEG = MFX_MAKEFOURCC('J','P','E','G') /*!< JPEG codec */ +}; + +/* CodecProfile, CodecLevel */ +enum +{ + MFX_PROFILE_JPEG_BASELINE = 1 /*!< Baseline JPEG profile. */ +}; + +/*! The Rotation enumerator itemizes the JPEG rotation options. */ +enum +{ + MFX_ROTATION_0 = 0, /*!< No rotation. */ + MFX_ROTATION_90 = 1, /*!< 90 degree rotation. */ + MFX_ROTATION_180 = 2, /*!< 180 degree rotation. */ + MFX_ROTATION_270 = 3 /*!< 270 degree rotation. */ +}; + +enum { + MFX_EXTBUFF_JPEG_QT = MFX_MAKEFOURCC('J','P','G','Q'), /*!< This extended buffer defines quantization tables for JPEG encoder. */ + MFX_EXTBUFF_JPEG_HUFFMAN = MFX_MAKEFOURCC('J','P','G','H') /*!< This extended buffer defines Huffman tables for JPEG encoder. */ +}; + +/*! The JPEGColorFormat enumerator itemizes the JPEG color format options. */ +enum { + MFX_JPEG_COLORFORMAT_UNKNOWN = 0, /*! Unknown color format. The decoder tries to determine color format from available in bitstream information. + If such information is not present, then MFX_JPEG_COLORFORMAT_YCbCr color format is assumed. */ + MFX_JPEG_COLORFORMAT_YCbCr = 1, /*! Bitstream contains Y, Cb and Cr components. */ + MFX_JPEG_COLORFORMAT_RGB = 2 /*! Bitstream contains R, G and B components. */ +}; + +/*! The JPEGScanType enumerator itemizes the JPEG scan types. */ +enum { + MFX_SCANTYPE_UNKNOWN = 0, /*!< Unknown scan type. */ + MFX_SCANTYPE_INTERLEAVED = 1, /*!< Interleaved scan. */ + MFX_SCANTYPE_NONINTERLEAVED = 2 /*!< Non-interleaved scan. */ +}; + +enum { + MFX_CHROMAFORMAT_JPEG_SAMPLING = 6 /*!< Color sampling specified via mfxInfoMFX::SamplingFactorH and SamplingFactorV. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies quantization tables. The application may specify up to 4 quantization tables. The encoder assigns an ID to each table. + That ID is equal to the table index in the Qm array. Table "0" is used for encoding of the Y component, table "1" for the U component, and table "2" + for the V component. The application may specify fewer tables than the number of components in the image. If two tables are specified, + then table "1" is used for both U and V components. If only one table is specified then it is used for all components in the image. + The following table illustrates this behavior. + + @internal + +------------------+---------+------+---+ + | Table ID | 0 | 1 | 2 | + +------------------+---------+------+---+ + | Number of tables | | | | + +==================+=========+======+===+ + | 0 | Y, U, V | | | + +------------------+---------+------+---+ + | 1 | Y | U, V | | + +------------------+---------+------+---+ + | 2 | Y | U | V | + +------------------+---------+------+---+ + @endinternal +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_JPEG_QT. */ + + mfxU16 reserved[7]; + mfxU16 NumTable; /*!< Number of quantization tables defined in Qm array. */ + + mfxU16 Qm[4][64]; /*!< Quantization table values. */ +} mfxExtJPEGQuantTables; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies Huffman tables. The application may specify up to 2 quantization table pairs for baseline process. The encoder + assigns an ID to each table. That ID is equal to the table index in the DCTables and ACTables arrays. Table "0" is used for encoding of the Y component and + table "1" is used for encoding of the U and V component. The application may specify only one table, in which case the table will be used for all components in the image. + The following table illustrates this behavior. + + @internal + +------------------+---------+------+ + | Table ID | 0 | 1 | + +------------------+---------+------+ + | Number of tables | | | + +==================+=========+======+ + | 0 | Y, U, V | | + +------------------+---------+------+ + | 1 | Y | U, V | + +------------------+---------+------+ + @endinternal +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_JPEG_HUFFMAN. */ + + mfxU16 reserved[2]; + mfxU16 NumDCTable; /*!< Number of DC quantization table in DCTables array. */ + mfxU16 NumACTable; /*!< Number of AC quantization table in ACTables array. */ + + struct { + mfxU8 Bits[16]; /*!< Number of codes for each code length. */ + mfxU8 Values[12]; /*!< List of the 8-bit symbol values. */ + } DCTables[4]; /*!< Array of DC tables. */ + + struct { + mfxU8 Bits[16]; /*!< Number of codes for each code length. */ + mfxU8 Values[162]; /*!< Array of AC tables. */ + } ACTables[4]; /*!< List of the 8-bit symbol values. */ +} mfxExtJPEGHuffmanTables; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif // __MFX_JPEG_H__ diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxmemory.h b/third-party/IntelVPL/arm64/include/vpl/mfxmemory.h new file mode 100644 index 000000000..5a7ceeb12 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxmemory.h @@ -0,0 +1,322 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXMEMORY_H__ +#define __MFXMEMORY_H__ +#include "mfxsession.h" +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + @brief + Returns surface which can be used as input for VPP. + + VPP should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0. + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR If double-pointer to the @p surface is NULL. \n + MFX_ERR_INVALID_HANDLE If @p session was not initialized. \n + MFX_ERR_NOT_INITIALIZED If VPP was not initialized (allocator needs to know surface size from somewhere). \n + MFX_ERR_MEMORY_ALLOC In case of any other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.0. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForVPP(mfxSession session, mfxFrameSurface1** surface); + +/*! + @brief + Returns surface which can be used as output of VPP. + + VPP should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0. + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR If double-pointer to the @p surface is NULL. \n + MFX_ERR_INVALID_HANDLE If @p session was not initialized. \n + MFX_ERR_NOT_INITIALIZED If VPP was not initialized (allocator needs to know surface size from somewhere). \n + MFX_ERR_MEMORY_ALLOC In case of any other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.1. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForVPPOut(mfxSession session, mfxFrameSurface1** surface); + +/*! Alias for MFXMemory_GetSurfaceForVPP function. */ +#define MFXMemory_GetSurfaceForVPPIn MFXMemory_GetSurfaceForVPP + +/*! + @brief + Returns a surface which can be used as input for the encoder. + + Encoder should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0. + + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully.\n + MFX_ERR_NULL_PTR If surface is NULL.\n + MFX_ERR_INVALID_HANDLE If session was not initialized.\n + MFX_ERR_NOT_INITIALIZED If the encoder was not initialized (allocator needs to know surface size from somewhere).\n + MFX_ERR_MEMORY_ALLOC In case of any other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.0. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForEncode(mfxSession session, mfxFrameSurface1** surface); + +/*! + @brief + Returns a surface which can be used as output of the decoder. + + Decoder should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0.' + + @note This function was added to simplify transition from legacy surface management to the proposed internal allocation approach. + Previously, the user allocated surfaces for the working pool and fed them to the decoder using DecodeFrameAsync calls. With MFXMemory_GetSurfaceForDecode + it is possible to change the existing pipeline by just changing the source of work surfaces. + Newly developed applications should prefer direct usage of DecodeFrameAsync with internal allocation. + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully.\n + MFX_ERR_NULL_PTR If surface is NULL.\n + MFX_ERR_INVALID_HANDLE If session was not initialized.\n + MFX_ERR_NOT_INITIALIZED If the decoder was not initialized (allocator needs to know surface size from somewhere).\n + MFX_ERR_MEMORY_ALLOC Other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.0. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForDecode(mfxSession session, mfxFrameSurface1** surface); + +#ifdef ONEVPL_EXPERIMENTAL + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL texture2D; /*!< Pointer to texture, type ID3D11Texture2D* */ + mfxHDL reserved[7]; +} mfxSurfaceD3D11Tex2D; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL vaDisplay; /*!< Object of type VADisplay. */ + mfxU32 vaSurfaceID; /*!< Object of type VASurfaceID. */ + mfxU32 reserved1; + + mfxHDL reserved[6]; +} mfxSurfaceVAAPI; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Optional extension buffer, which can be attached to mfxSurfaceHeader::ExtParam + (second parameter of mfxFrameSurfaceInterface::Export) in order to pass OCL parameters + during mfxFrameSurface1 exporting to OCL surface. + If buffer is not provided all resources will be created by oneAPI Video Processing Library (oneVPL) RT internally. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_EXPORT_SHARING_DESC_OCL. */ + + mfxHDL ocl_context; /*!< Object of type cl_context (OpenCL context). */ + mfxHDL ocl_command_queue; /*!< Object of type cl_command_queue (OpenCL command queue). */ + + mfxHDL reserved[8]; +} mfxExtSurfaceOpenCLImg2DExportDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL ocl_context; /*!< Object of type cl_context (OpenCL context). */ + mfxHDL ocl_command_queue; /*!< Object of type cl_command_queue (OpenCL command queue). */ + + mfxHDL ocl_image[4]; /*!< Object of type cl_mem[4] (array of 4 OpenCL 2D images). */ + mfxU32 ocl_image_num; /*!< Number of valid images (planes), depends on color format. */ + + mfxHDL reserved[8]; +} mfxSurfaceOpenCLImg2D; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Optional extension buffer, which can be attached to mfxSurfaceHeader::ExtParam + (second parameter of mfxFrameSurfaceInterface::Export) in order to pass D3D12 parameters + during mfxFrameSurface1 exporting to D3D12 resource. + If buffer is not provided all resources will be created by oneAPI Video Processing Library (oneVPL) RT internally. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_EXPORT_SHARING_DESC_D3D12. */ + + mfxHDL d3d12Device; /*!< Pointer to D3D12 Device, type ID3D12Device*. */ + + mfxHDL reserved[9]; +} mfxExtSurfaceD3D12Tex2DExportDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL texture2D; /*!< Pointer to D3D12 resource, type ID3D12Resource*. */ + + mfxHDL reserved[7]; +} mfxSurfaceD3D12Tex2D; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Optional extension buffer, which can be attached to mfxSurfaceHeader::ExtParam + (second parameter of mfxFrameSurfaceInterface::Export) in order to pass Vulkan parameters + during mfxFrameSurface1 exporting to Vulkan surface. + If buffer is not provided all resources will be created by oneAPI Video Processing Library (oneVPL) RT internally. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_EXPORT_SHARING_DESC_VULKAN. */ + + mfxHDL instance; /*!< Object of type VkInstance (Vulkan instance). */ + mfxHDL physicalDevice; /*!< Object of type VkPhysicalDevice (Vulkan physical device). */ + mfxHDL device; /*!< Object of type VkDevice (Vulkan device). */ + + mfxHDL reserved[7]; +} mfxExtSurfaceVulkanImg2DExportDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL instance; /*!< Object of type VkInstance (Vulkan instance). */ + mfxHDL physicalDevice; /*!< Object of type VkPhysicalDevice (Vulkan physical device). */ + mfxHDL device; /*!< Object of type VkDevice (Vulkan device). */ + + mfxHDL image2D; /*!< Object of type VkImage (Vulkan 2D images). */ + mfxHDL image2DMemory; /*!< Object of type VkDeviceMemory (Vulkan device memory). */ + + mfxHDL reserved[10]; +} mfxSurfaceVulkanImg2D; +MFX_PACK_END() + +/*! The mfxSurfaceComponent enumerator specifies the internal surface pool to use when importing surfaces. */ +typedef enum { + MFX_SURFACE_COMPONENT_UNKNOWN = 0, /*!< Unknown surface component. */ + + MFX_SURFACE_COMPONENT_ENCODE = 1, /*!< Shared surface for encoding. */ + MFX_SURFACE_COMPONENT_DECODE = 2, /*!< Shared surface for decoding. */ + MFX_SURFACE_COMPONENT_VPP_INPUT = 3, /*!< Shared surface for VPP input. */ + MFX_SURFACE_COMPONENT_VPP_OUTPUT = 4, /*!< Shared surface for VPP output. */ +} mfxSurfaceComponent; + +/*! The current version of mfxSurfaceTypesSupported structure. */ +#define MFX_SURFACETYPESSUPPORTED_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure describes the supported surface types and modes. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + + mfxU16 NumSurfaceTypes; /*!< Number of supported surface types. */ + struct surftype { + mfxSurfaceType SurfaceType; /*!< Supported surface type. */ + mfxU32 reserved[6]; /*!< Reserved for future use. */ + mfxU16 NumSurfaceComponents; /*!< Number of supported surface components. */ + struct surfcomp { + mfxSurfaceComponent SurfaceComponent; /*!< Supported surface component. */ + mfxU32 SurfaceFlags; /*!< Supported surface flags for this component (may be OR'd). */ + mfxU32 reserved[7]; /*!< Reserved for future use. */ + } *SurfaceComponents; + } *SurfaceTypes; + + mfxU32 reserved[4]; /*!< Reserved for future use. */ +} mfxSurfaceTypesSupported; +MFX_PACK_END() + +#define MFX_MEMORYINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/* Specifies memory interface. */ +typedef struct mfxMemoryInterface { + mfxHDL Context; /*!< The context of the memory interface. User should not touch (change, set, null) this pointer. */ + mfxStructVersion Version; /*!< The version of the structure. */ + + /*! + @brief + Imports an application-provided surface into mfxFrameSurface1 which may be used as input for encoding or video processing. + + @param[in] memory_interface Valid memory interface. + @param[in] surf_component Surface component type. Required for allocating new surfaces from the appropriate pool. + @param[in,out] external_surface Pointer to the mfxSurfaceXXX object describing the surface to be imported. All fields in + mfxSurfaceHeader must be set by the application. mfxSurfaceHeader::SurfaceType is + read by oneVPL runtime to determine which particular mfxSurfaceXXX structure is supplied. + For example, if mfxSurfaceXXX::SurfaceType == MFX_SURFACE_TYPE_D3D11_TEX2D, then the handle + will be interpreted as an object of type mfxSurfaceD3D11Tex2D. The application should + set or clear other fields as specified in the corresponding structure description. + After successful import, the value of mfxSurfaceHeader::SurfaceFlags will be replaced with the actual + import type. It can be used to determine which import type (with or without copy) took place in the case + of initial default setting, or if multiple import flags were OR'ed. + All external sync operations on the ext_surface must be completed before calling this function. + @param[out] imported_surface Pointer to a valid mfxFrameSurface1 object containing the imported frame. + imported_surface may be passed as an input to Encode or VPP processing operations. + + @return + MFX_ERR_NONE The function completed successfully.\n + MFX_ERR_NULL_PTR If ext_surface or imported_surface are NULL.\n + MFX_ERR_INVALID_HANDLE If the corresponding session was not initialized.\n + MFX_ERR_UNSUPPORTED If surf_component is not one of [MFX_SURFACE_COMPONENT_ENCODE, MFX_SURFACE_COMPONENT_VPP_INPUT], or if + mfxSurfaceHeader::SurfaceType is not supported by oneVPL runtime for this operation.\n + + @since This function is available since API version 2.10. + */ + + /* For reference with Export flow please search for mfxFrameSurfaceInterface::Export. */ + mfxStatus (MFX_CDECL *ImportFrameSurface)(struct mfxMemoryInterface* memory_interface, mfxSurfaceComponent surf_component, mfxSurfaceHeader* external_surface, mfxFrameSurface1** imported_surface); + + mfxHDL reserved[16]; +} mfxMemoryInterface; +MFX_PACK_END() + +/*! Alias for returning interface of type mfxMemoryInterface. */ +#define MFXGetMemoryInterface(session, piface) MFXVideoCORE_GetHandle((session), MFX_HANDLE_MEMORY_INTERFACE, (mfxHDL *)(piface)) + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxmvc.h b/third-party/IntelVPL/arm64/include/vpl/mfxmvc.h new file mode 100644 index 000000000..5e5a3413e --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxmvc.h @@ -0,0 +1,105 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXMVC_H__ +#define __MFXMVC_H__ + +#include "mfxdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* CodecProfile, CodecLevel */ +enum { + /* MVC profiles */ + MFX_PROFILE_AVC_MULTIVIEW_HIGH = 118, /*!< Multi-view high profile. The encoding of VDEnc or LowPower ON is not supported. */ + MFX_PROFILE_AVC_STEREO_HIGH = 128 /*!< Stereo high profile. The encoding of VDEnc or LowPower ON is not supported. */ +}; + +/* Extended Buffer Ids */ +enum { + MFX_EXTBUFF_MVC_SEQ_DESC = MFX_MAKEFOURCC('M','V','C','D'), /*!< This extended buffer describes the MVC stream information of view dependencies, view identifiers, and operation points. See the ITU*-T H.264 specification chapter H.7.3.2.1.4 for details. */ + MFX_EXTBUFF_MVC_TARGET_VIEWS = MFX_MAKEFOURCC('M','V','C','T') /*!< This extended buffer defines target views at the decoder output.*/ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Describes MVC view dependencies. +*/ +typedef struct { + mfxU16 ViewId; /*!< View identifier of this dependency structure. */ + + mfxU16 NumAnchorRefsL0; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList0 for anchor view components. */ + mfxU16 NumAnchorRefsL1; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList1 for anchor view components. */ + mfxU16 AnchorRefL0[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList0 for anchor view components. */ + mfxU16 AnchorRefL1[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList1 for anchor view components. */ + + mfxU16 NumNonAnchorRefsL0; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList0 for non-anchor view components. */ + mfxU16 NumNonAnchorRefsL1; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList1 for non-anchor view components. */ + mfxU16 NonAnchorRefL0[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList0 for non-anchor view components. */ + mfxU16 NonAnchorRefL1[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList0 for non-anchor view components. */ +} mfxMVCViewDependency; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the MVC operation point. +*/ +typedef struct { + mfxU16 TemporalId; /*!< Temporal identifier of the operation point. */ + mfxU16 LevelIdc; /*!< Level value signaled for the operation point. */ + + mfxU16 NumViews; /*!< Number of views required for decoding the target output views that correspond to the operation point. */ + mfxU16 NumTargetViews; /*!< Number of target output views for the operation point. */ + mfxU16 *TargetViewId; /*!< Target output view identifiers for operation point. */ +} mfxMVCOperationPoint; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the MVC stream information of view dependencies, view identifiers, and operation points. See the ITU*-T H.264 specification chapter H.7.3.2.1.4 for details. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MVC_SEQUENCE_DESCRIPTION. */ + + mfxU32 NumView; /*!< Number of views. */ + mfxU32 NumViewAlloc; /*!< The allocated view dependency array size. */ + mfxMVCViewDependency *View; /*!< Pointer to a list of the mfxMVCViewDependency. */ + + mfxU32 NumViewId; /*!< Number of view identifiers. */ + mfxU32 NumViewIdAlloc; /*!< The allocated view identifier array size. */ + mfxU16 *ViewId; /*!< Pointer to the list of view identifier. */ + + mfxU32 NumOP; /*!< Number of operation points. */ + mfxU32 NumOPAlloc; /*!< The allocated operation point array size. */ + mfxMVCOperationPoint *OP; /*!< Pointer to a list of the mfxMVCOperationPoint structure. */ + + mfxU16 NumRefsTotal; /*!< Total number of reference frames in all views required to decode the stream. This value is returned from the MFXVideoDECODE_Decodeheader function. Do not modify this value. */ + mfxU32 Reserved[16]; + +} mfxExtMVCSeqDesc; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures views for the decoding output. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MVC_TARGET_VIEWS. */ + + mfxU16 TemporalId; /*!< The temporal identifier to be decoded. */ + mfxU32 NumView; /*!< The number of views to be decoded. */ + mfxU16 ViewId[1024]; /*!< List of view identifiers to be decoded. */ +} mfxExtMVCTargetViews ; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxpcp.h b/third-party/IntelVPL/arm64/include/vpl/mfxpcp.h new file mode 100644 index 000000000..a55c0e404 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxpcp.h @@ -0,0 +1,45 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXPCP_H__ +#define __MFXPCP_H__ +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! The Protected enumerator describes the protection schemes. */ +enum { + MFX_PROTECTION_CENC_WV_CLASSIC = 0x0004, /*!< The protection scheme is based on the Widevine* DRM from Google*. */ + MFX_PROTECTION_CENC_WV_GOOGLE_DASH = 0x0005, /*!< The protection scheme is based on the Widevine* Modular DRM* from Google*. */ +}; + +/* Extended Buffer Ids */ +enum { + MFX_EXTBUFF_CENC_PARAM = MFX_MAKEFOURCC('C','E','N','P') /*!< This structure is used to pass decryption status report index for Common + Encryption usage model. See the mfxExtCencParam structure for more details. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to pass the decryption status report index for the Common Encryption usage model. The application can + attach this extended buffer to the mfxBitstream structure at runtime. +*/ +typedef struct _mfxExtCencParam{ + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CENC_PARAM. */ + + mfxU32 StatusReportIndex; /*!< Decryption status report index. */ + mfxU32 reserved[15]; +} mfxExtCencParam; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxsession.h b/third-party/IntelVPL/arm64/include/vpl/mfxsession.h new file mode 100644 index 000000000..d68ff1a72 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxsession.h @@ -0,0 +1,234 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXSESSION_H__ +#define __MFXSESSION_H__ +#include "mfxcommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Global Functions */ + +/*! Session handle. */ +typedef struct _mfxSession *mfxSession; + +/*! + @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. + + Call this function before calling + any other API function. If the desired implementation specified by ``impl`` is MFX_IMPL_AUTO, + the function will search for the platform-specific implementation. + If the function cannot find the platform-specific implementation, it will use the software implementation instead. + + The ``ver`` argument indicates the desired version of the library implementation. + The loaded implementation will have an API version compatible to the specified version (equal in + the major version number, and no less in the minor version number.) If the desired version + is not specified, the default is to use the API version from the library release with + which an application is built. + + Production applications should always specify the minimum API version that meets the + functional requirements. 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. + + @param[in] impl mfxIMPL enumerator that indicates the desired legacy Intel(r) Media SDK implementation. + @param[in] ver Pointer to the minimum library version or zero, if not specified. + @param[out] session Pointer to the legacy Intel(r) Media SDK session handle. + + @return + MFX_ERR_NONE The function completed successfully. The output parameter contains the handle of the session.\n + 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); + +/*! + @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. + + 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 + the platform-specific implementation. If the function cannot find the platform-specific implementation, it will use the software implementation instead. + + The argument ``par.Version`` indicates the desired version of the implementation. The loaded implementation will have an API + version compatible to the specified version (equal in the major version number, and no less in the minor version number.) + If the desired version is not specified, the default is to use the API version from the library release with + which an application is built. + + Production applications should always specify the minimum API version that meets the functional requirements. + 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). + + @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. + + @return + MFX_ERR_NONE The function completed successfully. The output parameter contains the handle of the session.\n + 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); + +/*! + @brief + Creates and initializes a session starting from API version 2.0. This function is used by the dispatcher. + The dispatcher creates and fills the mfxInitializationParam structure according to mfxConfig values set by an application. + Calling this function directly is not recommended. Instead, applications must call the MFXCreateSession function. + + + @param[in] par mfxInitializationParam structure that indicates the minimum library version and acceleration type. + @param[out] session Pointer to the session handle. + + @return + MFX_ERR_NONE The function completed successfully. The output parameter contains the handle of the session.\n + MFX_ERR_UNSUPPORTED The function cannot find the desired implementation or version. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXInitialize(mfxInitializationParam par, mfxSession *session); + +/*! + @brief Completes and deinitializes a session. Any active tasks in execution or + in queue are aborted. The application cannot call any API function after calling this function. + + All child sessions must be disjoined before closing a parent session. + @param[in] session session handle. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXClose(mfxSession session); + +/*! + @brief Returns the implementation type of a given session. + + @param[in] session Session handle. + @param[out] impl Pointer to the implementation type + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXQueryIMPL(mfxSession session, mfxIMPL *impl); + +/*! + @brief Returns the implementation version. + + @param[in] session Session handle. + @param[out] version Pointer to the returned implementation version. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXQueryVersion(mfxSession session, mfxVersion *version); + +/*! + @brief Joins the child session to the current session. + + After joining, the two sessions share thread and resource scheduling for asynchronous + operations. However, each session still maintains its own device manager and buffer/frame + allocator. Therefore, the application must use a compatible device manager and buffer/frame + allocator to share data between two joined sessions. + + The application can join multiple sessions by calling this function multiple times. When joining + the first two sessions, the current session becomes the parent responsible for thread and + resource scheduling of any later joined sessions. + + Joining of two parent sessions is not supported. + + @param[in,out] session The current session handle. + @param[in] child The child session handle to be joined + + @return MFX_ERR_NONE The function completed successfully. \n + MFX_WRN_IN_EXECUTION Active tasks are executing or in queue in one of the + sessions. Call this function again after all tasks are completed. \n + MFX_ERR_UNSUPPORTED The child session cannot be joined with the current session. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXJoinSession(mfxSession session, mfxSession child); + +/*! + @brief Removes the joined state of the current session. + + After disjoining, the current session becomes independent. The application must ensure there is no active task running in the session before calling this API function. + + @param[in,out] session The current session handle. + + @return MFX_ERR_NONE The function completed successfully. \n + MFX_WRN_IN_EXECUTION Active tasks are executing or in queue in one of the + sessions. Call this function again after all tasks are completed. \n + MFX_ERR_UNDEFINED_BEHAVIOR The session is independent, or this session is the parent of all joined sessions. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXDisjoinSession(mfxSession session); + +/*! + @brief Creates a clean copy of the current session. + + The cloned session is an independent session and does not inherit any user-defined buffer, frame allocator, or device manager handles from the current session. + This function is a light-weight equivalent of MFXJoinSession after MFXInit. + + @param[in] session The current session handle. + @param[out] clone Pointer to the cloned session handle. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXCloneSession(mfxSession session, mfxSession *clone); + +/*! + @brief Sets the current session priority. + + @param[in] session The current session handle. + @param[in] priority Priority value. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXSetPriority(mfxSession session, mfxPriority priority); + +/*! + @brief Returns the current session priority. + + @param[in] session The current session handle. + @param[out] priority Pointer to the priority value. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXGetPriority(mfxSession session, mfxPriority *priority); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxstructures.h b/third-party/IntelVPL/arm64/include/vpl/mfxstructures.h new file mode 100644 index 000000000..3ee64fe12 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxstructures.h @@ -0,0 +1,5399 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXSTRUCTURES_H__ +#define __MFXSTRUCTURES_H__ +#include "mfxcommon.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Frame ID for MVC */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Describes the view and layer of a frame picture. */ +typedef struct { + mfxU16 TemporalId; /*!< The temporal identifier as defined in the annex H of the ITU*-T H.264 specification. */ + mfxU16 PriorityId; /*!< Reserved and must be zero. */ + union { + struct { + mfxU16 DependencyId; /*!< Reserved for future use. */ + mfxU16 QualityId; /*!< Reserved for future use. */ + }; + struct { + mfxU16 ViewId; /*!< The view identifier as defined in the annex H of the ITU-T H.264 specification. */ + }; + }; +} mfxFrameId; +MFX_PACK_END() + +/* This struct has 4-byte alignment for binary compatibility with previously released versions of API. */ +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 + zero. It's allowed to skip setting of decoder's parameters for simplified decoding procedure */ + 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; + /*! Number of bits used to represent chroma samples. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU16 BitDepthChroma; + /*! The Shift flag indicates whether the values of luma and chroma samples are shifted. For the decoding process, the recommended value + is specified by the DecodeHeader or GetVideoParam API. A value of one indicates that the luma and chroma sample values are shifted, + while a value of zero indicates that there is no shift. Please refer to the example data alignment provided below. + + @note Not all codecs and implementations support this flag. Use the Query API function to check if this feature is supported. + AVC and HEVC allow users to set the Shift flag to either 0 or 1. However, setting the Shift flag to a value different from the + recommended one may lead to increased CPU utilization. For other codecs, attempting to set the Shift flag to a value other than + the recommended one will result in an error status. + */ + mfxU16 Shift; + mfxFrameId FrameId; /*!< Describes the view and layer of a frame picture. */ + mfxU32 FourCC; /*!< FourCC code of the color format. See the ColorFourCC enumerator for details. */ + union { + struct { /* Frame parameters */ + /*! Width of the video frame in pixels. Must be a multiple of 16. + In case of fused operation of decode plus VPP it can be set to zero to signalize that scaling operation is not requested. */ + mfxU16 Width; + /*! Height of the video frame in pixels. Must be a multiple of 16 for progressive frame sequence and a multiple of 32 otherwise. + In case of fused operation of decode plus VPP it can be set to zero to signalize that scaling operation is not requested. */ + mfxU16 Height; + + /*! @{ + @name ROI + The region of interest of the frame. Specify the display width and height in mfxVideoParam. */ + /*! X coordinate. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropX; + /*! Y coordinate. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropY; + /*! Width in pixels. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropW; + /*! Height in pixels. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropH; + /*! @} */ + }; + struct { /* Buffer parameters (for plain formats like P8) */ + mfxU64 BufferSize; /*!< Size of frame buffer in bytes. Valid only for plain formats (when FourCC is P8). In this case, Width, Height, and crop values are invalid. */ + mfxU32 reserved5; + }; + }; + + /*! @{ + @name FrameRate + Specify the frame rate with the following formula: FrameRateExtN / FrameRateExtD. + + For encoding, frame rate must be specified. For decoding, frame rate may be unspecified (FrameRateExtN and FrameRateExtD + are all zeros.) In this case, the frame rate is defaulted to 0 frames per second, and timestamp will be calculated by 30fps in SDK. + + In decoding process: + + If there is frame rate information in bitstream, MFXVideoDECODE_DecodeHeader will carry actual frame rate in FrameRateExtN and FrameRateExtD parameters. + MFXVideoDECODE_Init, MFXVideoDECODE_Query, MFXVideoDECODE_DecodeFrameAsync and MFXVideoDECODE_GetVideoParam will also carry these values for frame rate. + Timestamp will be calculated by the actual frame rate. + + If there is no frame rate information in bitstream, MFXVideoDECODE_DecodeHeader will assign 0 for frame rate in FrameRateExtN and FrameRateExtD parameters. + MFXVideoDECODE_Init, MFXVideoDECODE_Query, MFXVideoDECODE_DecodeFrameAsync and MFXVideoDECODE_GetVideoParam will also assign 0 for frame rate. Timestamp will be calculated by 30fps. + + If these two parameters are modified through MFXVideoDECODE_Init, then the modified values for frame rate will be used in + MFXVideoDECODE_Query, MFXVideoDECODE_DecodeFrameAsync and MFXVideoDECODE_GetVideoParam. Timestamps will be calculated using the modified values. + */ + mfxU32 FrameRateExtN; /*!< Frame rate numerator. */ + mfxU32 FrameRateExtD; /*!< Frame rate denominator. */ + /*! @} */ + mfxU16 reserved3; + + /*! @{ + @name AspectRatio + AspectRatioW and AspectRatioH are used to specify the sample aspect ratio. If sample aspect ratio is explicitly defined by the standards (see + Table 6-3 in the MPEG-2 specification or Table E-1 in the H.264 specification), AspectRatioW and AspectRatioH should be the defined values. + Otherwise, the sample aspect ratio can be derived as follows: + + @li @c AspectRatioW=display_aspect_ratio_width*display_height + + @li @c AspectRatioH=display_aspect_ratio_height*display_width + + For MPEG-2, the above display aspect ratio must be one of the defined values in Table 6-3 in the MPEG-2 specification. For H.264, there is no restriction + on display aspect ratio values. + + If both parameters are zero, the encoder uses the default value of sample aspect ratio. + */ + mfxU16 AspectRatioW; /*!< Aspect Ratio for width. */ + mfxU16 AspectRatioH; /*!< Aspect Ratio for height. */ + /*! @} */ + + mfxU16 PicStruct; /*!< Picture type as specified in the PicStruct enumerator. */ + mfxU16 ChromaFormat; /*!< Color sampling method. Value is the same as that of ChromaFormatIdc. + ChromaFormat is not defined if FourCC is zero.*/ + mfxU16 reserved2; +} mfxFrameInfo; +MFX_PACK_END() + +/*! The ColorFourCC enumerator itemizes color formats. */ +enum { + MFX_FOURCC_NV12 = MFX_MAKEFOURCC('N','V','1','2'), /*!< NV12 color planes. Native format for 4:2:0/8b Gen hardware implementation. */ + MFX_FOURCC_YV12 = MFX_MAKEFOURCC('Y','V','1','2'), /*!< YV12 color planes. */ + MFX_FOURCC_NV16 = MFX_MAKEFOURCC('N','V','1','6'), /*!< 4:2:2 color format with similar to NV12 layout. */ + MFX_FOURCC_YUY2 = MFX_MAKEFOURCC('Y','U','Y','2'), /*!< YUY2 color planes. */ + MFX_FOURCC_RGB565 = MFX_MAKEFOURCC('R','G','B','2'), /*!< 2 bytes per pixel, uint16 in little-endian format, where 0-4 bits are blue, bits 5-10 are green and bits 11-15 are red. */ + /*! RGB 24 bit planar layout (3 separate channels, 8-bits per sample each). This format should be mapped to D3DFMT_R8G8B8 or VA_FOURCC_RGBP. */ + MFX_FOURCC_RGBP = MFX_MAKEFOURCC('R','G','B','P'), + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_FOURCC_RGB3) = MFX_MAKEFOURCC('R','G','B','3'), /* Deprecated. */ + MFX_FOURCC_RGB4 = MFX_MAKEFOURCC('R','G','B','4'), /*!< RGB4 (RGB32) color planes. BGRA is the order, 'B' is 8 LSBs in 32-bit unit, then 8 bits for 'G' channel, then 'R' and 'A' channels. */ + /*! + Internal color format. The application should use the following functions to create a surface that corresponds to the Direct3D* version in use. + + For Direct3D* 9: IDirectXVideoDecoderService::CreateSurface() + + For Direct3D* 11: ID3D11Device::CreateBuffer() + */ + MFX_FOURCC_P8 = 41, + /*! + Internal color format. The application should use the following functions to create a surface that corresponds to the Direct3D* version in use. + + For Direct3D 9: IDirectXVideoDecoderService::CreateSurface() + + For Direct3D 11: ID3D11Device::CreateTexture2D() + */ + MFX_FOURCC_P8_TEXTURE = MFX_MAKEFOURCC('P','8','M','B'), + MFX_FOURCC_P010 = MFX_MAKEFOURCC('P','0','1','0'), /*!< P010 color format. This is 10 bit per sample format with similar to NV12 layout. This format should be mapped to DXGI_FORMAT_P010. */ + MFX_FOURCC_P016 = MFX_MAKEFOURCC('P','0','1','6'), /*!< P016 color format. This is 16 bit per sample format with similar to NV12 layout. This format should be mapped to DXGI_FORMAT_P016. */ + MFX_FOURCC_P210 = MFX_MAKEFOURCC('P','2','1','0'), /*!< 10 bit per sample 4:2:2 color format with similar to NV12 layout. */ + MFX_FOURCC_BGR4 = MFX_MAKEFOURCC('B','G','R','4'), /*!< RGBA color format. It is similar to MFX_FOURCC_RGB4 but with different order of channels. 'R' is 8 LSBs in 32-bit unit, then 8 bits for 'G' channel, then 'B' and 'A' channels. */ + MFX_FOURCC_A2RGB10 = MFX_MAKEFOURCC('R','G','1','0'), /*!< 10 bits ARGB color format packed in 32 bits. 'A' channel is two MSBs, then 'R', then 'G' and then 'B' channels. This format should be mapped to DXGI_FORMAT_R10G10B10A2_UNORM or D3DFMT_A2R10G10B10. */ + MFX_FOURCC_ARGB16 = MFX_MAKEFOURCC('R','G','1','6'), /*!< 16 bits ARGB color format packed in 64 bits. 'A' channel is 16 MSBs, then 'R', then 'G' and then 'B' channels. This format should be mapped to DXGI_FORMAT_R16G16B16A16_UNORM or D3DFMT_A16B16G16R16 formats. */ + MFX_FOURCC_ABGR16 = MFX_MAKEFOURCC('B','G','1','6'), /*!< 16 bits ABGR color format packed in 64 bits. 'A' channel is 16 MSBs, then 'B', then 'G' and then 'R' channels. This format should be mapped to DXGI_FORMAT_R16G16B16A16_UNORM or D3DFMT_A16B16G16R16 formats. */ + MFX_FOURCC_R16 = MFX_MAKEFOURCC('R','1','6','U'), /*!< 16 bits single channel color format. This format should be mapped to DXGI_FORMAT_R16_TYPELESS or D3DFMT_R16F. */ + MFX_FOURCC_AYUV = MFX_MAKEFOURCC('A','Y','U','V'), /*!< YUV 4:4:4, AYUV color format. This format should be mapped to DXGI_FORMAT_AYUV. */ + MFX_FOURCC_AYUV_RGB4 = MFX_MAKEFOURCC('A','V','U','Y'), /*!< RGB4 stored in AYUV surface. This format should be mapped to DXGI_FORMAT_AYUV. */ + MFX_FOURCC_UYVY = MFX_MAKEFOURCC('U','Y','V','Y'), /*!< UYVY color planes. Same as YUY2 except the byte order is reversed. */ + MFX_FOURCC_Y210 = MFX_MAKEFOURCC('Y','2','1','0'), /*!< 10 bit per sample 4:2:2 packed color format with similar to YUY2 layout. This format should be mapped to DXGI_FORMAT_Y210. */ + MFX_FOURCC_Y410 = MFX_MAKEFOURCC('Y','4','1','0'), /*!< 10 bit per sample 4:4:4 packed color format. This format should be mapped to DXGI_FORMAT_Y410. */ + MFX_FOURCC_Y216 = MFX_MAKEFOURCC('Y','2','1','6'), /*!< 16 bit per sample 4:2:2 packed color format with similar to YUY2 layout. This format should be mapped to DXGI_FORMAT_Y216. */ + MFX_FOURCC_Y416 = MFX_MAKEFOURCC('Y','4','1','6'), /*!< 16 bit per sample 4:4:4 packed color format. This format should be mapped to DXGI_FORMAT_Y416. */ + MFX_FOURCC_NV21 = MFX_MAKEFOURCC('N', 'V', '2', '1'), /*!< Same as NV12 but with weaved V and U values. */ + MFX_FOURCC_IYUV = MFX_MAKEFOURCC('I', 'Y', 'U', 'V'), /*!< Same as YV12 except that the U and V plane order is reversed. */ + MFX_FOURCC_I010 = MFX_MAKEFOURCC('I', '0', '1', '0'), /*!< 10-bit YUV 4:2:0, each component has its own plane. */ + MFX_FOURCC_I210 = MFX_MAKEFOURCC('I', '2', '1', '0'), /*!< 10-bit YUV 4:2:2, each component has its own plane. */ + MFX_FOURCC_I420 = MFX_FOURCC_IYUV, /*!< Alias for the IYUV color format. */ + MFX_FOURCC_I422 = MFX_MAKEFOURCC('I', '4', '2', '2'), /*!< Same as YV16 except that the U and V plane order is reversed */ + 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'), + /*! 8bit per sample 4:4:4 format packed in 32 bits, X=unused/undefined, 'X' channel is 8 MSBs, then 'Y', then 'U', and then 'V' channels. This format should be mapped to VA_FOURCC_XYUV. */ + MFX_FOURCC_XYUV = MFX_MAKEFOURCC('X','Y','U','V'), + MFX_FOURCC_ABGR16F = MFX_MAKEFOURCC('B', 'G', 'R', 'F'), /*!< 16 bits float point ABGR color format packed in 64 bits. 'A' channel is 16 MSBs, then 'B', then 'G' and then 'R' channels. This format should be mapped to DXGI_FORMAT_R16G16B16A16_FLOAT or D3DFMT_A16B16G16R16F formats.. */ +}; + +/* PicStruct */ +enum { + MFX_PICSTRUCT_UNKNOWN =0x00, /*!< Unspecified or mixed progressive/interlaced/field pictures. */ + MFX_PICSTRUCT_PROGRESSIVE =0x01, /*!< Progressive picture. */ + MFX_PICSTRUCT_FIELD_TFF =0x02, /*!< Top field in first interlaced picture. */ + MFX_PICSTRUCT_FIELD_BFF =0x04, /*!< Bottom field in first interlaced picture. */ + + MFX_PICSTRUCT_FIELD_REPEATED=0x10, /*!< First field repeated: pic_struct=5 or 6 in H.264. */ + MFX_PICSTRUCT_FRAME_DOUBLING=0x20, /*!< Double the frame for display: pic_struct=7 in H.264. */ + MFX_PICSTRUCT_FRAME_TRIPLING=0x40, /*!< Triple the frame for display: pic_struct=8 in H.264. */ + + MFX_PICSTRUCT_FIELD_SINGLE =0x100, /*!< Single field in a picture. */ + MFX_PICSTRUCT_FIELD_TOP =MFX_PICSTRUCT_FIELD_SINGLE | MFX_PICSTRUCT_FIELD_TFF, /*!< Top field in a picture: pic_struct = 1 in H.265. */ + MFX_PICSTRUCT_FIELD_BOTTOM =MFX_PICSTRUCT_FIELD_SINGLE | MFX_PICSTRUCT_FIELD_BFF, /*!< Bottom field in a picture: pic_struct = 2 in H.265. */ + MFX_PICSTRUCT_FIELD_PAIRED_PREV =0x200, /*!< Paired with previous field: pic_struct = 9 or 10 in H.265. */ + MFX_PICSTRUCT_FIELD_PAIRED_NEXT =0x400, /*!< Paired with next field: pic_struct = 11 or 12 in H.265 */ +}; + +/*! The ChromaFormatIdc enumerator itemizes color-sampling formats. */ +enum { + MFX_CHROMAFORMAT_MONOCHROME =0, /*!< Monochrome. */ + MFX_CHROMAFORMAT_YUV420 =1, /*!< 4:2:0 color. */ + MFX_CHROMAFORMAT_YUV422 =2, /*!< 4:2:2 color. */ + MFX_CHROMAFORMAT_YUV444 =3, /*!< 4:4:4 color. */ + MFX_CHROMAFORMAT_YUV400 = MFX_CHROMAFORMAT_MONOCHROME, /*!< Equal to monochrome. */ + MFX_CHROMAFORMAT_YUV411 = 4, /*!< 4:1:1 color. */ + MFX_CHROMAFORMAT_YUV422H = MFX_CHROMAFORMAT_YUV422, /*!< 4:2:2 color, horizontal sub-sampling. It is equal to 4:2:2 color. */ + MFX_CHROMAFORMAT_YUV422V = 5, /*!< 4:2:2 color, vertical sub-sampling. */ + MFX_CHROMAFORMAT_RESERVED1 = 6 /*!< Reserved. */ +}; + +enum { + MFX_TIMESTAMP_UNKNOWN = -1 /*!< Indicates that time stamp is unknown for this frame/bitstream portion. */ +}; + +enum { + MFX_FRAMEORDER_UNKNOWN = -1 /*!< Unused entry or API functions that generate the frame output do not use this frame. */ +}; + +/*! The FrameDataFlag enumerator itemizes DataFlag value in mfxFrameData. */ +enum { + MFX_FRAMEDATA_TIMESTAMP_UNKNOWN = 0x0000,/*!< Indicates the time stamp of this frame is unknown and will be calculated by SDK. */ + MFX_FRAMEDATA_ORIGINAL_TIMESTAMP = 0x0001 /*!< Indicates the time stamp of this frame is not calculated and is a pass-through of the original time stamp. */ +}; + +/*! Corrupted in mfxFrameData */ +enum { + MFX_CORRUPTION_NO = 0x0000, /*!< No corruption. */ + MFX_CORRUPTION_MINOR = 0x0001, /*!< Minor corruption in decoding certain macro-blocks. */ + MFX_CORRUPTION_MAJOR = 0x0002, /*!< Major corruption in decoding the frame - incomplete data, for example. */ + MFX_CORRUPTION_ABSENT_TOP_FIELD = 0x0004, /*!< Top field of frame is absent in bitstream. Only bottom field has been decoded. */ + MFX_CORRUPTION_ABSENT_BOTTOM_FIELD = 0x0008, /*!< Bottom field of frame is absent in bitstream. Only top filed has been decoded. */ + MFX_CORRUPTION_REFERENCE_FRAME = 0x0010, /*!< Decoding used a corrupted reference frame. A corrupted reference frame was used for decoding this + frame. For example, if the frame uses a reference frame that was decoded with minor/major corruption flag, then this + frame is also marked with a reference corruption flag. */ + MFX_CORRUPTION_REFERENCE_LIST = 0x0020, /*!< The reference list information of this frame does not match what is specified in the Reference Picture Marking + Repetition SEI message. (ITU-T H.264 D.1.8 dec_ref_pic_marking_repetition) */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_CORRUPTION_HW_RESET = 0x0040 /*!< The hardware reset is reported from media driver. */ +#endif +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in Y410 color format. */ +typedef struct +{ + mfxU32 U : 10; /*!< U component. */ + mfxU32 Y : 10; /*!< Y component. */ + mfxU32 V : 10; /*!< V component. */ + mfxU32 A : 2; /*!< A component. */ +} mfxY410; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in Y416 color format. */ +typedef struct +{ + mfxU32 U : 16; /*!< U component. */ + mfxU32 Y : 16; /*!< Y component. */ + mfxU32 V : 16; /*!< V component. */ + mfxU32 A : 16; /*!< A component. */ +} mfxY416; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in A2RGB10 color format */ +typedef struct +{ + mfxU32 B : 10; /*!< B component. */ + mfxU32 G : 10; /*!< G component. */ + mfxU32 R : 10; /*!< R component. */ + mfxU32 A : 2; /*!< A component. */ +} mfxA2RGB10; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in ABGR 16 bit half float point color format */ +typedef struct +{ + mfxFP16 R; /*!< R component. */ + mfxFP16 G; /*!< G component. */ + mfxFP16 B; /*!< B component. */ + mfxFP16 A; /*!< A component. */ +} mfxABGR16FP; +MFX_PACK_END() + +/*! Describes frame buffer pointers. */ +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +typedef struct { + /*! @name Extension Buffers */ + /*! @{ */ + union { + mfxExtBuffer **ExtParam; /*!< Points to an array of pointers to the extra configuration structures. See the ExtendedBufferID + enumerator for a list of extended configurations. */ + mfxU64 reserved2; + }; + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + /*! @} */ + + /*! @name General members */ + /*! @{ */ + mfxU16 reserved[9]; /*!< Reserved for future use. */ + mfxU16 MemType; /*!< Allocated memory type. See the ExtMemFrameType enumerator for details. Used for better integration of + 3rd party plugins into the pipeline. */ + mfxU16 PitchHigh; /*!< Distance in bytes between the start of two consecutive rows in a frame. */ + + mfxU64 TimeStamp; /*!< Time stamp of the video frame in units of 90KHz. Divide TimeStamp by 90,000 (90 KHz) to obtain the time in seconds. + A value of MFX_TIMESTAMP_UNKNOWN indicates that there is no time stamp. */ + mfxU32 FrameOrder; /*!< Current frame counter for the top field of the current frame. An invalid value of MFX_FRAMEORDER_UNKNOWN indicates that + API functions that generate the frame output do not use this frame. */ + mfxU16 Locked; /*!< Counter flag for the application. If Locked is greater than zero then the application locks the frame or field pair. + Do not move, alter or delete the frame. */ + union{ + mfxU16 Pitch; + mfxU16 PitchLow; /*!< Distance in bytes between the start of two consecutive rows in a frame. */ + }; + /*! @} */ + + /*! + @name Color Planes + Data pointers to corresponding color channels (planes). The frame buffer pointers must be 16-byte aligned. The application has to specify pointers to + all color channels even for packed formats. For example, for YUY2 format the application must specify Y, U, and V pointers. + For RGB32 format, the application must specify R, G, B, and A pointers. + */ + /*! @{ */ + union { + mfxU8 *Y; /*!< Y channel. */ + mfxU16 *Y16; /*!< Y16 channel. */ + mfxU8 *R; /*!< R channel. */ + }; + union { + mfxU8 *UV; /*!< UV channel for UV merged formats. */ + mfxU8 *VU; /*!< YU channel for VU merged formats. */ + mfxU8 *CbCr; /*!< CbCr channel for CbCr merged formats. */ + mfxU8 *CrCb; /*!< CrCb channel for CrCb merged formats. */ + mfxU8 *Cb; /*!< Cb channel. */ + mfxU8 *U; /*!< U channel. */ + mfxU16 *U16; /*!< U16 channel. */ + mfxU8 *G; /*!< G channel. */ + mfxY410 *Y410; /*!< T410 channel for Y410 format (merged AVYU). */ + mfxY416 *Y416; /*!< This format is a packed 16-bit representation that includes 16 bits of alpha. */ + }; + union { + mfxU8 *Cr; /*!< Cr channel. */ + mfxU8 *V; /*!< V channel. */ + mfxU16 *V16; /*!< V16 channel. */ + mfxU8 *B; /*!< B channel. */ + mfxA2RGB10 *A2RGB10; /*!< A2RGB10 channel for A2RGB10 format (merged ARGB). */ + mfxABGR16FP* ABGRFP16; /*!< ABGRFP16 channel for half float ARGB format (use this merged one due to no separate FP16 Alpha Channel). */ + }; + mfxU8 *A; /*!< A channel. */ + mfxMemId MemId; /*!< Memory ID of the data buffers. Ignored if any of the preceding data pointers is non-zero. */ + /*! @} */ + + /*! + @name Additional Flags + */ + /*! @{ */ + mfxU16 Corrupted; /*!< Some part of the frame or field pair is corrupted. See the Corruption enumerator for details. */ + mfxU16 DataFlag; /*!< Additional flags to indicate frame data properties. See the FrameDataFlag enumerator for details. */ + /*! @} */ +} mfxFrameData; +MFX_PACK_END() + +/*! The mfxHandleType enumerator itemizes system handle types that implementations might use. */ +typedef enum { + MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 = 1, /*!< Pointer to the IDirect3DDeviceManager9 interface. See Working with Microsoft* DirectX* Applications for more details on how to use this handle. */ + MFX_HANDLE_D3D9_DEVICE_MANAGER = MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9, /*!< Pointer to the IDirect3DDeviceManager9 interface. See Working with Microsoft* DirectX* Applications for more details on how to use this handle. */ + MFX_HANDLE_RESERVED1 = 2, /* Reserved. */ + MFX_HANDLE_D3D11_DEVICE = 3, /*!< Pointer to the ID3D11Device interface. See Working with Microsoft* DirectX* Applications for more details on how to use this handle. */ + MFX_HANDLE_VA_DISPLAY = 4, /*!< VADisplay interface. See Working with VA-API Applications for more details on how to use this handle. */ + MFX_HANDLE_RESERVED3 = 5, /* Reserved. */ + MFX_HANDLE_VA_CONFIG_ID = 6, /*!< Pointer to VAConfigID interface. It represents external VA config for Common Encryption usage model. */ + MFX_HANDLE_VA_CONTEXT_ID = 7, /*!< Pointer to VAContextID interface. It represents external VA context for Common Encryption usage model. */ + MFX_HANDLE_CM_DEVICE = 8, /*!< Pointer to CmDevice interface ( Intel(r) C for Metal Runtime ). */ + MFX_HANDLE_HDDLUNITE_WORKLOADCONTEXT = 9, /*!< Pointer to HddlUnite::WorkloadContext interface. */ + MFX_HANDLE_PXP_CONTEXT = 10, /*!< Pointer to PXP context for protected content support. */ + + MFX_HANDLE_CONFIG_INTERFACE = 1000, /*!< Pointer to interface of type mfxConfigInterface. */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_HANDLE_MEMORY_INTERFACE = 1001, /*!< Pointer to interface of type mfxMemoryInterface. */ +#endif +} mfxHandleType; + +/*! The mfxMemoryFlags enumerator specifies memory access mode. */ +typedef enum +{ + MFX_MAP_READ = 0x1, /*!< The surface is mapped for reading. */ + MFX_MAP_WRITE = 0x2, /*!< The surface is mapped for writing. */ + MFX_MAP_READ_WRITE = MFX_MAP_READ|MFX_MAP_WRITE, /*!< The surface is mapped for reading and writing. */ + /*! + * The mapping would be done immediately without any implicit synchronizations. + * \attention This flag is optional. + */ + MFX_MAP_NOWAIT = 0x10 +} mfxMemoryFlags; + +#define MFX_FRAMESURFACE1_VERSION MFX_STRUCT_VERSION(1, 1) + +/* Frame Surface */ +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! Defines the uncompressed frames surface information and data buffers. + The frame surface is in the frame or complementary field pairs of pixels up to four color-channels, in two parts: + mfxFrameInfo and mfxFrameData. +*/ +typedef struct { + union + { + struct mfxFrameSurfaceInterface* FrameInterface; /*!< Specifies interface to work with surface. */ + mfxU32 reserved[2]; + }; + mfxStructVersion Version; /*!< Specifies version of mfxFrameSurface1 structure. */ + mfxU16 reserved1[3]; + mfxFrameInfo Info; /*!< Specifies surface properties. */ + mfxFrameData Data; /*!< Describes the actual frame buffer. */ +} mfxFrameSurface1; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL + +/*! The mfxSurfaceType enumerator specifies the surface type described by mfxSurfaceHeader. */ +typedef enum { + MFX_SURFACE_TYPE_UNKNOWN = 0, /*!< Unknown surface type. */ + + MFX_SURFACE_TYPE_D3D11_TEX2D = 2, /*!< D3D11 surface of type ID3D11Texture2D. */ + MFX_SURFACE_TYPE_VAAPI = 3, /*!< VA-API surface. */ + MFX_SURFACE_TYPE_OPENCL_IMG2D = 4, /*!< OpenCL 2D image (cl_mem). */ + MFX_SURFACE_TYPE_D3D12_TEX2D = 5, /*!< D3D12 surface of type ID3D12Resource with 2D texture type. */ + MFX_SURFACE_TYPE_VULKAN_IMG2D = 6, /*!< Vulkan 2D image (VkImage). */ +} mfxSurfaceType; + +/*! This enumerator specifies the sharing modes which are allowed for importing or exporting shared surfaces. */ +enum { + MFX_SURFACE_FLAG_DEFAULT = 0x0000, /*!< Default is SHARED import or export. */ + + MFX_SURFACE_FLAG_IMPORT_SHARED = 0x0010, /*!< Import frames directly by mapping a shared native handle from an application-provided surface to an internally-allocated surface. */ + MFX_SURFACE_FLAG_IMPORT_COPY = 0x0020, /*!< Import frames by copying data from an application-provided surface to an internally-allocated surface. */ + + MFX_SURFACE_FLAG_EXPORT_SHARED = 0x0100, /*!< Export frames directly by mapping a shared native handle from an internally-allocated surface to an application-provided surface. */ + MFX_SURFACE_FLAG_EXPORT_COPY = 0x0200, /*!< Export frames by copying data from an internally-allocated surface to an application-provided surface. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceType SurfaceType; /*!< Set to the MFX_SURFACE_TYPE enum corresponding to the specific structure. */ + mfxU32 SurfaceFlags; /*!< Set to the MFX_SURFACE_FLAG enum (or combination) corresponding to the allowed import / export mode(s). Multiple flags may be combined with OR. + Upon a successful Import or Export operation, this field will indicate the actual mode used.*/ + + mfxU32 StructSize; /*!< Size in bytes of the complete mfxSurfaceXXX structure. */ + + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to the 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 reserved[6]; +} mfxSurfaceHeader; +MFX_PACK_END() + + +#define MFX_SURFACEINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +/*! + Contains mfxSurfaceHeader and the callback functions AddRef, Release and GetRefCounter + that the application may use to manage access to exported surfaces. + These interfaces are only valid for surfaces obtained by mfxFrameSurfaceInterface::Export. + They are not used for surface descriptions passed to function mfxMemoryInterface::ImportFrameSurface. +*/ +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct mfxSurfaceInterface { + mfxSurfaceHeader Header; /*!< Exported surface header. Contains description of current surface. */ + + mfxStructVersion Version; /*!< The version of the structure. */ + + mfxHDL Context; /*!< The context of the exported surface interface. User should not touch (change, set, null) this pointer. */ + + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the mfxSurfaceInterface::Release function. + mfxSurfaceInterface::AddRef should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxSurfaceInterface* surface); + + /*! @brief + Decrements the internal reference counter of the surface. mfxSurfaceInterface::Release should be called after using the + mfxSurfaceInterface::AddRef function to add a surface or when allocation logic requires it. For example, call + mfxSurfaceInterface::Release to release a surface obtained with the mfxFrameSurfaceInterface::Export function. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxSurfaceInterface* surface); + + /*! @brief + Returns current reference counter of exported surface. + + @param[in] surface Valid surface. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(struct mfxSurfaceInterface* surface, mfxU32* counter); + + /*! @brief + This function is only valuable for surfaces which were exported in sharing mode (without a copy). + Guarantees readiness of both the data (pixels) and any original mfxFrameSurface1 frame's meta information (for example corruption flags) after a function completes. + + Instead of MFXVideoCORE_SyncOperation, users may directly call the mfxSurfaceInterface::Synchronize function after the corresponding + Decode or VPP function calls (MFXVideoDECODE_DecodeFrameAsync or MFXVideoVPP_RunFrameVPPAsync). + The prerequisites to call the functions are: + + @li The main processing functions return MFX_ERR_NONE. + @li A valid surface object. + + @param[in] surface Valid surface. + @param[out] wait Wait time in milliseconds. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the surface is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Synchronize)(struct mfxSurfaceInterface* surface, mfxU32 wait); + + mfxHDL reserved[11]; +} mfxSurfaceInterface; +MFX_PACK_END() + +#endif + +#ifdef ONEVPL_EXPERIMENTAL +#define MFX_FRAMESURFACEINTERFACE_VERSION MFX_STRUCT_VERSION(1, 1) +#else +#define MFX_FRAMESURFACEINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) +#endif + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! Specifies frame surface interface. */ +typedef struct mfxFrameSurfaceInterface { + 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 reserved1[3]; + + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the mfxFrameSurfaceInterface::Release function. + mfxFrameSurfaceInterface::AddRef should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(mfxFrameSurface1* surface); + + /*! @brief + Decrements the internal reference counter of the surface. mfxFrameSurfaceInterface::Release should be called after using the + mfxFrameSurfaceInterface::AddRef function to add a surface or when allocation logic requires it. For example, call + mfxFrameSurfaceInterface::Release to release a surface obtained with the GetSurfaceForXXX function. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(mfxFrameSurface1* surface); + + /*! @brief + Returns current reference counter of mfxFrameSurface1 structure. + + @param[in] surface Valid surface. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(mfxFrameSurface1* surface, mfxU32* counter); + + /*! @brief + Sets pointers of surface->Info.Data to actual pixel data, providing read-write access. + + In case of video memory, the surface with data in video memory becomes mapped to system memory. + An application can map a surface for read access with any value of mfxFrameSurface1::Data::Locked, but can map a surface for write access only when mfxFrameSurface1::Data::Locked equals to 0. + + Note: A surface allows shared read access, but exclusive write access. Consider the following cases: + @li Map with Write or Read|Write flags. A request during active another read or write access returns MFX_ERR_LOCK_MEMORY error immediately, without waiting. + MFX_MAP_NOWAIT does not impact behavior. This type of request does not lead to any implicit synchronizations. + @li Map with Read flag. A request during active write access will wait for resource to become free, + or exits immediately with error if MFX_MAP_NOWAIT flag was set. This request may lead to the implicit synchronization (with same logic as Synchronize call) + waiting for surface to become ready to use (all dependencies should be resolved and upstream components finished writing to this surface). + + It is guaranteed that read access will be acquired right after synchronization without allowing another thread to acquire this surface for writing. + + If MFX_MAP_NOWAIT was set and the surface is not ready yet (for example the surface has unresolved data dependencies or active processing), the read access request exits immediately with error. + + Read-write access with MFX_MAP_READ_WRITE provides exclusive simultaneous reading and writing access. + + @note Bitwise copying of mfxFrameSurface1 object between map / unmap calls may result in having dangling data pointers in copies. + + @param[in] surface Valid surface. + @param[out] flags Specify mapping mode. + @param[out] surface->Info.Data Pointers set to actual pixel data. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNSUPPORTED If flags are invalid. \n + MFX_ERR_LOCK_MEMORY If user wants to map the surface for write and surface->Data.Locked does not equal to 0. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Map)(mfxFrameSurface1* surface, mfxU32 flags); + + /*! @brief + Invalidates pointers of surface->Info.Data and sets them to NULL. + In case of video memory, the underlying texture becomes unmapped after last reader or writer unmap. + + + @param[in] surface Valid surface. + @param[out] surface->Info.Data Pointers set to NULL. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNSUPPORTED If surface is already unmapped. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Unmap)(mfxFrameSurface1* surface); + + /*! @brief + Returns a native resource's handle and type. The handle is returned *as-is*, meaning that the reference counter of base resources is not incremented. + The native resource is not detached from surface and the library still owns the resource. User must not destroy + the native resource or assume that the resource will be alive after mfxFrameSurfaceInterface::Release. + + + + @param[in] surface Valid surface. + @param[out] resource Pointer is set to the native handle of the resource. + @param[out] resource_type Type of native resource. See mfxResourceType enumeration). + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If any of surface, resource or resource_type is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface, resource or resource_type is not valid object (no native resource was allocated). \n + MFX_ERR_UNSUPPORTED If surface is in system memory. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetNativeHandle)(mfxFrameSurface1* surface, mfxHDL* resource, mfxResourceType* resource_type); + + /*! @brief + Returns a device abstraction that was used to create that resource. + The handle is returned *as-is*, meaning that the reference counter for the device abstraction is not incremented. + The native resource is not detached from the surface and the library still has a reference to the resource. + User must not destroy the device or assume that the device will be alive after mfxFrameSurfaceInterface::Release. + + + @param[in] surface Valid surface. + @param[out] device_handle Pointer is set to the device which created the resource + @param[out] device_type Type of device (see mfxHandleType enumeration). + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If any of surface, device_handle or device_type is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface, resource or resource_type is not valid object (no native resource was allocated). \n + MFX_ERR_UNSUPPORTED If surface is in system memory. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetDeviceHandle)(mfxFrameSurface1* surface, mfxHDL* device_handle, mfxHandleType* device_type); + + /*! @brief + Guarantees readiness of both the data (pixels) and any frame's meta information (for example corruption flags) after a function completes. + + Instead of MFXVideoCORE_SyncOperation, users may directly call the mfxFrameSurfaceInterface::Synchronize function after the corresponding + Decode or VPP function calls (MFXVideoDECODE_DecodeFrameAsync or MFXVideoVPP_RunFrameVPPAsync). + The prerequisites to call the functions are: + + @li The main processing functions return MFX_ERR_NONE. + @li A valid mfxFrameSurface1 object. + + + + @param[in] surface Valid surface. + @param[out] wait Wait time in milliseconds. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the surface is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + 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. + + @note The library calls this callback only when this surface is used as the output surface. + + 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); + + /*! @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); + +#ifdef ONEVPL_EXPERIMENTAL + /*! @brief + If successful returns an exported surface, which is a refcounted object allocated by runtime. It could be exported with or without copy, depending + on export flags and the possibility of such export. Exported surface is valid throughout the session, as long as the original mfxFrameSurface1 + object is not closed and the refcount of exported surface is not zero. + + @param[in] surface Valid surface. + @param[in] export_header Description of export: caller should fill in SurfaceType (type to export to) and SurfaceFlags (allowed export modes). + @param[out] exported_surface Exported surface, allocated by runtime, user needs to decrement refcount after usage for object release. + After successful export, the value of mfxSurfaceHeader::SurfaceFlags will contain the actual export mode. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If export surface or surface is NULL. \n + MFX_ERR_UNSUPPORTED If requested export is not supported. \n + MFX_ERR_NOT_IMPLEMENTED If requested export is not implemented. \n + MFX_ERR_UNKNOWN Any internal error. + */ + + /* For reference with Import flow please search for mfxMemoryInterface::ImportFrameSurface. */ + mfxStatus (MFX_CDECL *Export)(mfxFrameSurface1* surface, mfxSurfaceHeader export_header, mfxSurfaceHeader** exported_surface); + + mfxHDL reserved2[1]; +#else + mfxHDL reserved2[2]; +#endif +} mfxFrameSurfaceInterface; +MFX_PACK_END() + +/*! The TimeStampCalc enumerator itemizes time-stamp calculation methods. */ +enum { + /*! The time stamp calculation is based on the input frame rate if time stamp is not explicitly specified. */ + MFX_TIMESTAMPCALC_UNKNOWN = 0, + /*! Adjust time stamp to 29.97fps on 24fps progressively encoded sequences if telecine attributes are available in the bitstream and + time stamp is not explicitly specified. The input frame rate must be specified. */ + MFX_TIMESTAMPCALC_TELECINE = 1, +}; + +/* Transcoding Info */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies configurations for decoding, encoding, and transcoding processes. + A zero value in any of these fields indicates that the field is not explicitly specified. */ +typedef struct { + mfxU32 reserved[7]; /*!< Reserved for future use. */ + + /*! Hint to enable low power consumption mode for encoders. See the CodingOptionValue enumerator for values + of this option. Use the Query API function to check if this feature is supported. */ + mfxU16 LowPower; + /*! Specifies a multiplier for bitrate control parameters. Affects the following variables: InitialDelayInKB, BufferSizeInKB, + TargetKbps, MaxKbps, WinBRCMaxAvgKbps. If this value is not equal to zero, the encoder calculates BRC parameters as ``value * BRCParamMultiplier``. */ + mfxU16 BRCParamMultiplier; + + mfxFrameInfo FrameInfo; /*!< mfxFrameInfo structure that specifies frame parameters. */ + mfxU32 CodecId; /*!< Specifies the codec format identifier in the FourCC code; see the CodecFormatFourCC enumerator for details. + This is a mandated input parameter for the QueryIOSurf and Init API functions. */ + mfxU16 CodecProfile; /*!< Specifies the codec profile; see the CodecProfile enumerator for details. Specify the codec profile explicitly or the API functions will determine + the correct profile from other sources, such as resolution and bitrate. */ + mfxU16 CodecLevel; /*!< Codec level; see the CodecLevel enumerator for details. Specify the codec level explicitly or the functions will determine the correct level from other sources, + such as resolution and bitrate. */ + mfxU16 NumThread; + + union { + struct { /* Encoding Options */ + mfxU16 TargetUsage; /*!< Target usage model that guides the encoding process; see the TargetUsage enumerator for details. */ + + /*! Number of pictures within the current GOP (Group of Pictures); if GopPicSize = 0, then the GOP size is unspecified. If GopPicSize = 1, only I-frames are used. + The following pseudo-code that shows how the library uses this parameter: + @code + mfxU16 get_gop_sequence (...) { + pos=display_frame_order; + if (pos == 0) + return MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF; + + If (GopPicSize == 1) // Only I-frames + return MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; + + if (GopPicSize == 0) + frameInGOP = pos; //Unlimited GOP + else + frameInGOP = pos%GopPicSize; + + if (frameInGOP == 0) + return MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; + + if (GopRefDist == 1 || GopRefDist == 0) // Only I,P frames + return MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF; + + frameInPattern = (frameInGOP-1)%GopRefDist; + if (frameInPattern == GopRefDist - 1) + return MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF; + + return MFX_FRAMETYPE_B; + } + @endcode */ + mfxU16 GopPicSize; + /*! Distance between I- or P (or GPB) - key frames; if it is zero, the GOP structure is unspecified. Note: If GopRefDist = 1, + there are no regular B-frames used (only P or GPB); if mfxExtCodingOption3::GPB is ON, GPB frames (B without backward + references) are used instead of P. */ + mfxU16 GopRefDist; + /*! ORs of the GopOptFlag enumerator indicate the additional flags for the GOP specification. */ + mfxU16 GopOptFlag; + /*! For H.264, specifies IDR-frame interval in terms of I-frames. + For example: + @li If IdrInterval = 0, then every I-frame is an IDR-frame. + @li If IdrInterval = 1, then every other I-frame is an IDR-frame. + + For HEVC, if IdrInterval = 0, then only first I-frame is an IDR-frame. For example: + @li If IdrInterval = 1, then every I-frame is an IDR-frame. + @li If IdrInterval = 2, then every other I-frame is an IDR-frame. + + For MPEG2, IdrInterval defines sequence header interval in terms of I-frames. For example: + @li If IdrInterval = 0 (default), then the sequence header is inserted once at the beginning of the stream. + @li If IdrInterval = N, then the sequence header is inserted before every Nth I-frame. + + + If GopPicSize or GopRefDist is zero, IdrInterval is undefined. */ + mfxU16 IdrInterval; + + mfxU16 RateControlMethod; /*! Rate control method; see the RateControlMethod enumerator for details. */ + union { + /*! Initial size of the Video Buffering Verifier (VBV) buffer. + @note In this context, KB is 1000 bytes and Kbps is 1000 bps. */ + mfxU16 InitialDelayInKB; + /*! Quantization Parameter (QP) for I-frames for constant QP mode (CQP). Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPI range. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted QPI value = QPI - (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we minus (6*(10-8)=12) on our side and continue. + @note In av1 design, valid range is 0 to 255 inclusive, and if QPI=QPP=QPB=0, the encoder is in lossless mode. + @note In vp9 design, valid range is 1 to 255 inclusive, and zero QP that the default value is assigned by the library. + @note Default QPI value is implementation dependent and subject to change without additional notice in this document. */ + mfxU16 QPI; + mfxU16 Accuracy; /*!< Specifies accuracy range in the unit of tenth of percent. */ + }; + mfxU16 BufferSizeInKB; /*!< Represents the maximum possible size of any compressed frames. */ + union { + /*! Constant bitrate TargetKbps. Used to estimate the targeted frame size by dividing the frame rate by the bitrate. */ + mfxU16 TargetKbps; + /*! Quantization Parameter (QP) for P-frames for constant QP mode (CQP). Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPP might be clipped to supported QPI range. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted QPP value = QPP - (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we minus (6*(10-8)=12) on our side and continue. + @note In av1 design, valid range is 0 to 255 inclusive, and if QPI=QPP=QPB=0, the encoder is in lossless mode. + @note In vp9 design, valid range is 1 to 255 inclusive, and zero QP that the default value is assigned by the library. + @note Default QPP value is implementation dependent and subject to change without additional notice in this document. */ + mfxU16 QPP; + mfxU16 ICQQuality; /*!< Used by the Intelligent Constant Quality (ICQ) bitrate control algorithm. Values are in the 1 to 51 range, where 1 corresponds the best quality. */ + }; + union { + /*! The maximum bitrate at which the encoded data enters the Video Buffering Verifier (VBV) buffer. */ + mfxU16 MaxKbps; + /*! Quantization Parameter (QP) for B-frames for constant QP mode (CQP). Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPB range. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted QPB value = QPB - (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we minus (6*(10-8)=12) on our side and continue. + @note In av1 design, valid range is 0 to 255 inclusive, and if QPI=QPP=QPB=0, the encoder is in lossless mode. + @note Default QPB value is implementation dependent and subject to change without additional notice in this document. */ + mfxU16 QPB; + mfxU16 Convergence; /*!< Convergence period in the unit of 100 frames. */ + }; + + /*! Number of slices in each video frame. Each slice contains one or more macro-block rows. If NumSlice equals zero, the encoder may choose any slice partitioning + allowed by the codec standard. See also mfxExtCodingOption2::NumMbPerSlice. */ + mfxU16 NumSlice; + /*! Max number of all available reference frames (for AVC/HEVC, NumRefFrame defines DPB size). If NumRefFrame = 0, this parameter is not specified. + See also NumRefActiveP, NumRefActiveBL0, and NumRefActiveBL1 in the mfxExtCodingOption3 structure, which set a number of active references. */ + mfxU16 NumRefFrame; + /*! If not zero, specifies that ENCODE takes the input surfaces in the encoded order and uses explicit frame type control. + The application must still provide GopRefDist and mfxExtCodingOption2::BRefType so the library can pack headers and build reference + lists correctly. */ + mfxU16 EncodedOrder; + }; + struct { /* Decoding Options */ + /*! For AVC and HEVC, used to instruct the decoder to return output frames in the decoded order. Must be zero for all other decoders. + When enabled, correctness of mfxFrameData::TimeStamp and FrameOrder for output surface is not guaranteed, the application should ignore them. */ + mfxU16 DecodedOrder; + /*! Instructs DECODE to output extended picture structure values for additional display attributes. See the PicStruct description for details. */ + mfxU16 ExtendedPicStruct; + /*! Time stamp calculation method. See the TimeStampCalc description for details. */ + mfxU16 TimeStampCalc; + /*! Nonzero value indicates that slice groups are present in the bitstream. Used only by AVC decoder. */ + mfxU16 SliceGroupsPresent; + /*! Nonzero value specifies the maximum required size of the decoded picture buffer in frames for AVC and HEVC decoders. */ + mfxU16 MaxDecFrameBuffering; + /*! For decoders supporting dynamic resolution change (VP9), set this option to ON to allow MFXVideoDECODE_DecodeFrameAsync + 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 + 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). + 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 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 reserved2[4]; + }; + struct { /* JPEG Decoding Options */ + /*! Specify the chroma sampling format that has been used to encode a JPEG picture. See the ChromaFormat enumerator for details. */ + mfxU16 JPEGChromaFormat; + /*! Rotation option of the output JPEG picture. See the Rotation enumerator for details. */ + mfxU16 Rotation; + /*! Specify the color format that has been used to encode a JPEG picture. See the JPEGColorFormat enumerator for details. */ + mfxU16 JPEGColorFormat; + /*! Specify JPEG scan type for decoder. See the JPEGScanType enumerator for details. */ + mfxU16 InterleavedDec; + mfxU8 SamplingFactorH[4]; /*!< Horizontal sampling factor. */ + mfxU8 SamplingFactorV[4]; /*!< Vertical sampling factor. */ + mfxU16 reserved3[5]; + }; + struct { /* JPEG Encoding Options */ + /*! Specify interleaved or non-interleaved scans. If it is equal to MFX_SCANTYPE_INTERLEAVED then the image is encoded as interleaved, + all components are encoded in one scan. See the JPEG Scan Type enumerator for details. */ + mfxU16 Interleaved; + /*! Specifies the image quality if the application does not specified quantization table. + The value is from 1 to 100 inclusive. "100" is the best quality. */ + mfxU16 Quality; + /*! Specifies the number of MCU in the restart interval. "0" means no restart interval. */ + mfxU16 RestartInterval; + mfxU16 reserved5[10]; + }; + }; +} mfxInfoMFX; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies configurations for video processing. A zero value in any of the fields indicates + that the corresponding field is not explicitly specified. */ +typedef struct { + mfxU32 reserved[8]; + mfxFrameInfo In; /*!< Input format for video processing. */ + mfxFrameInfo Out; /*!< Output format for video processing. */ +} mfxInfoVPP; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Configuration parameters for encoding, decoding, transcoding, and video processing. */ +typedef struct { + /*! Unique component ID that will be passed by the library to mfxFrameAllocRequest. Useful in pipelines where several + components of the same type share the same allocator. */ + mfxU32 AllocId; + mfxU32 reserved[2]; + mfxU16 reserved3; + /*! Specifies how many asynchronous operations an application performs before the application explicitly synchronizes the result. + If zero, the value is not specified. */ + mfxU16 AsyncDepth; + + union { + mfxInfoMFX mfx; /*!< Configurations related to encoding, decoding, and transcoding. See the definition of the mfxInfoMFX structure for details. */ + mfxInfoVPP vpp; /*!< Configurations related to video processing. See the definition of the mfxInfoVPP structure for details. */ + }; + /*! Specifies the content protection mechanism. See the Protected enumerator for a list of supported protection schemes. */ + mfxU16 Protected; + /*! Input and output memory access types for functions. See the enumerator IOPattern for details. + The Query API functions return the natively supported IOPattern if the Query input argument is NULL. + This parameter is a mandated input for QueryIOSurf and Init API functions. The output pattern must be specified for DECODE. + The input pattern must be specified for ENCODE. Both input and output pattern must be specified for VPP. */ + mfxU16 IOPattern; + mfxExtBuffer** ExtParam; /*!< Points to an array of pointers to the extra configuration structures. See the ExtendedBufferID enumerator + for a list of extended configurations. + The list of extended buffers should not contain duplicated entries, such as entries of the same type. + If the mfxVideoParam structure is used to query library capability, then the list of extended buffers attached to the input + and output mfxVideoParam structure should be equal, that is, it should contain the same number of extended + buffers of the same type. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + mfxU16 reserved2; +} mfxVideoParam; +MFX_PACK_END() + +/*! The IOPattern enumerator itemizes memory access patterns for API functions. Use bit-ORed values to specify an input access + pattern and an output access pattern. */ +enum { + MFX_IOPATTERN_IN_VIDEO_MEMORY = 0x01, /*!< Input to functions is a video memory surface. */ + MFX_IOPATTERN_IN_SYSTEM_MEMORY = 0x02, /*!< Input to functions is a linear buffer directly in system memory or in system memory through an external allocator. */ + MFX_IOPATTERN_OUT_VIDEO_MEMORY = 0x10, /*!< Output to functions is a video memory surface. */ + MFX_IOPATTERN_OUT_SYSTEM_MEMORY = 0x20 /*!< Output to functions is a linear buffer directly in system memory or in system memory through an external allocator. */ +}; + +/*! The CodecFormatFourCC enumerator itemizes codecs in the FourCC format. */ +enum { + MFX_CODEC_AVC =MFX_MAKEFOURCC('A','V','C',' '), /*!< AVC, H.264, or MPEG-4, part 10 codec. */ + MFX_CODEC_HEVC =MFX_MAKEFOURCC('H','E','V','C'), /*!< HEVC codec. */ + MFX_CODEC_MPEG2 =MFX_MAKEFOURCC('M','P','G','2'), /*!< MPEG-2 codec. */ + MFX_CODEC_VC1 =MFX_MAKEFOURCC('V','C','1',' '), /*!< VC-1 codec. */ + MFX_CODEC_CAPTURE =MFX_MAKEFOURCC('C','A','P','T'), /*!< */ + MFX_CODEC_VP9 =MFX_MAKEFOURCC('V','P','9',' '), /*!< VP9 codec. */ + MFX_CODEC_AV1 =MFX_MAKEFOURCC('A','V','1',' '), /*!< AV1 codec. */ + MFX_CODEC_VVC =MFX_MAKEFOURCC('V','V','C',' ') /*!< VVC codec. */ +}; + +/*! +The CodecProfile enumerator itemizes codec profiles for all codecs. +CodecLevel +*/ +enum { + MFX_PROFILE_UNKNOWN =0, /*!< Unspecified profile. */ + MFX_LEVEL_UNKNOWN =0, /*!< Unspecified level. */ + + /*! @{ */ + /* Combined with H.264 profile these flags impose additional constrains. See H.264 specification for the list of constrains. */ + MFX_PROFILE_AVC_CONSTRAINT_SET0 = (0x100 << 0), + MFX_PROFILE_AVC_CONSTRAINT_SET1 = (0x100 << 1), + MFX_PROFILE_AVC_CONSTRAINT_SET2 = (0x100 << 2), + MFX_PROFILE_AVC_CONSTRAINT_SET3 = (0x100 << 3), + MFX_PROFILE_AVC_CONSTRAINT_SET4 = (0x100 << 4), + MFX_PROFILE_AVC_CONSTRAINT_SET5 = (0x100 << 5), + /*! @} */ + + /*! @{ */ + /* H.264 Profiles. */ + MFX_PROFILE_AVC_BASELINE =66, + MFX_PROFILE_AVC_MAIN =77, + MFX_PROFILE_AVC_EXTENDED =88, + MFX_PROFILE_AVC_HIGH =100, + MFX_PROFILE_AVC_HIGH10 =110, + MFX_PROFILE_AVC_HIGH_422 =122, + MFX_PROFILE_AVC_CONSTRAINED_BASELINE =MFX_PROFILE_AVC_BASELINE + MFX_PROFILE_AVC_CONSTRAINT_SET1, + MFX_PROFILE_AVC_CONSTRAINED_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4 + + MFX_PROFILE_AVC_CONSTRAINT_SET5, + MFX_PROFILE_AVC_PROGRESSIVE_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4, + /*! @} */ + + /*! @{ */ + /* H.264 level 1-1.3 */ + MFX_LEVEL_AVC_1 =10, + MFX_LEVEL_AVC_1b =9, + MFX_LEVEL_AVC_11 =11, + MFX_LEVEL_AVC_12 =12, + MFX_LEVEL_AVC_13 =13, + /*! @} */ + /*! @{ */ + /* H.264 level 2-2.2 */ + MFX_LEVEL_AVC_2 =20, + MFX_LEVEL_AVC_21 =21, + MFX_LEVEL_AVC_22 =22, + /*! @} */ + /*! @{ */ + /* H.264 level 3-3.2 */ + MFX_LEVEL_AVC_3 =30, + MFX_LEVEL_AVC_31 =31, + MFX_LEVEL_AVC_32 =32, + /*! @} */ + /*! @{ */ + /* H.264 level 4-4.2 */ + MFX_LEVEL_AVC_4 =40, + MFX_LEVEL_AVC_41 =41, + MFX_LEVEL_AVC_42 =42, + /*! @} */ + /*! @{ */ + /* H.264 level 5-5.2 */ + MFX_LEVEL_AVC_5 =50, + MFX_LEVEL_AVC_51 =51, + MFX_LEVEL_AVC_52 =52, + /*! @} */ + /*! @{ */ + /* H.264 level 6-6.2 */ + MFX_LEVEL_AVC_6 =60, + MFX_LEVEL_AVC_61 =61, + MFX_LEVEL_AVC_62 =62, + /*! @} */ + + /*! @{ */ + /* MPEG2 Profiles. */ + MFX_PROFILE_MPEG2_SIMPLE =0x50, + MFX_PROFILE_MPEG2_MAIN =0x40, + MFX_PROFILE_MPEG2_HIGH =0x10, + /*! @} */ + + /*! @{ */ + /* MPEG2 Levels. */ + MFX_LEVEL_MPEG2_LOW =0xA, + MFX_LEVEL_MPEG2_MAIN =0x8, + MFX_LEVEL_MPEG2_HIGH =0x4, + MFX_LEVEL_MPEG2_HIGH1440 =0x6, + /*! @} */ + + /*! @{ */ + /* VC-1 Profiles. */ + MFX_PROFILE_VC1_SIMPLE =(0+1), + MFX_PROFILE_VC1_MAIN =(4+1), + MFX_PROFILE_VC1_ADVANCED =(12+1), + /*! @} */ + + /*! @{ */ + /* VC-1 Level Low (simple & main profiles) */ + MFX_LEVEL_VC1_LOW =(0+1), + MFX_LEVEL_VC1_MEDIAN =(2+1), + MFX_LEVEL_VC1_HIGH =(4+1), + /*! @} */ + + /*! @{ */ + /* VC-1 advanced profile levels */ + MFX_LEVEL_VC1_0 =(0x00+1), + MFX_LEVEL_VC1_1 =(0x01+1), + MFX_LEVEL_VC1_2 =(0x02+1), + MFX_LEVEL_VC1_3 =(0x03+1), + MFX_LEVEL_VC1_4 =(0x04+1), + /*! @} */ + + /*! @{ */ + /* HEVC profiles */ + MFX_PROFILE_HEVC_MAIN =1, + MFX_PROFILE_HEVC_MAIN10 =2, + MFX_PROFILE_HEVC_MAINSP =3, + MFX_PROFILE_HEVC_REXT =4, + MFX_PROFILE_HEVC_SCC =9, + /*! @} */ + + /*! @{ */ + /* HEVC levels */ + MFX_LEVEL_HEVC_1 = 10, + MFX_LEVEL_HEVC_2 = 20, + MFX_LEVEL_HEVC_21 = 21, + MFX_LEVEL_HEVC_3 = 30, + MFX_LEVEL_HEVC_31 = 31, + MFX_LEVEL_HEVC_4 = 40, + MFX_LEVEL_HEVC_41 = 41, + MFX_LEVEL_HEVC_5 = 50, + MFX_LEVEL_HEVC_51 = 51, + MFX_LEVEL_HEVC_52 = 52, + MFX_LEVEL_HEVC_6 = 60, + MFX_LEVEL_HEVC_61 = 61, + MFX_LEVEL_HEVC_62 = 62, + MFX_LEVEL_HEVC_85 = 85, + /*! @} */ + + /*! @{ */ + /* HEVC tiers */ + MFX_TIER_HEVC_MAIN = 0, + MFX_TIER_HEVC_HIGH = 0x100, + /*! @} */ + + /*! @{ */ + /* VP9 Profiles */ + MFX_PROFILE_VP9_0 = 1, + MFX_PROFILE_VP9_1 = 2, + MFX_PROFILE_VP9_2 = 3, + MFX_PROFILE_VP9_3 = 4, + /*! @} */ + + /*! @{ */ + /* AV1 Profiles */ + MFX_PROFILE_AV1_MAIN = 1, + MFX_PROFILE_AV1_HIGH = 2, + MFX_PROFILE_AV1_PRO = 3, + /*! @} */ + + /*! @{ */ + /* AV1 Levels */ + MFX_LEVEL_AV1_2 = 20, + MFX_LEVEL_AV1_21 = 21, + MFX_LEVEL_AV1_22 = 22, + MFX_LEVEL_AV1_23 = 23, + MFX_LEVEL_AV1_3 = 30, + MFX_LEVEL_AV1_31 = 31, + MFX_LEVEL_AV1_32 = 32, + MFX_LEVEL_AV1_33 = 33, + MFX_LEVEL_AV1_4 = 40, + MFX_LEVEL_AV1_41 = 41, + MFX_LEVEL_AV1_42 = 42, + MFX_LEVEL_AV1_43 = 43, + MFX_LEVEL_AV1_5 = 50, + MFX_LEVEL_AV1_51 = 51, + MFX_LEVEL_AV1_52 = 52, + MFX_LEVEL_AV1_53 = 53, + MFX_LEVEL_AV1_6 = 60, + MFX_LEVEL_AV1_61 = 61, + MFX_LEVEL_AV1_62 = 62, + MFX_LEVEL_AV1_63 = 63, + MFX_LEVEL_AV1_7 = 70, + MFX_LEVEL_AV1_71 = 71, + MFX_LEVEL_AV1_72 = 72, + MFX_LEVEL_AV1_73 = 73, + /*! @} */ + + /*! @{ */ + /* VVC Profiles */ + MFX_PROFILE_VVC_MAIN10 = 1, + MFX_PROFILE_VVC_MAIN10_STILL_PICTURE = 65, + /*! @} */ + + /*! @{ */ + /* VVC Levels */ + MFX_LEVEL_VVC_1 = 16, + MFX_LEVEL_VVC_2 = 32, + MFX_LEVEL_VVC_21 = 35, + MFX_LEVEL_VVC_3 = 48, + MFX_LEVEL_VVC_31 = 51, + MFX_LEVEL_VVC_4 = 64, + MFX_LEVEL_VVC_41 = 67, + MFX_LEVEL_VVC_5 = 80, + MFX_LEVEL_VVC_51 = 83, + MFX_LEVEL_VVC_52 = 86, + MFX_LEVEL_VVC_6 = 96, + MFX_LEVEL_VVC_61 = 99, + MFX_LEVEL_VVC_62 = 102, + MFX_LEVEL_VVC_63 = 105, + MFX_LEVEL_VVC_155 = 255, + /*! @} */ + + /*! @{ */ + /* VVC tiers */ + MFX_TIER_VVC_MAIN = 0, + MFX_TIER_VVC_HIGH = 0x100, + /*! @} */ +}; + +/*! The GopOptFlag enumerator itemizes special properties in the GOP (Group of Pictures) sequence. */ +enum { + /*! + The encoder generates closed GOP if this flag is set. Frames in this GOP do not use frames in previous GOP as reference. + + The encoder generates open GOP if this flag is not set. In this GOP frames prior to the first frame of GOP in display order may use + frames from previous GOP as reference. Frames subsequent to the first frame of GOP in display order do not use frames from previous + GOP as reference. + + The AVC encoder ignores this flag if IdrInterval in mfxInfoMFX structure is set to 0, i.e. if every GOP starts from IDR frame. + In this case, GOP is encoded as closed. + + This flag does not affect long-term reference frames. + */ + MFX_GOP_CLOSED =1, + /*! + The encoder must strictly follow the given GOP structure as defined by parameter GopPicSize, GopRefDist etc in the mfxVideoParam structure. + Otherwise, the encoder can adapt the GOP structure for better efficiency, whose range is constrained by parameter GopPicSize and + GopRefDist etc. See also description of AdaptiveI and AdaptiveB fields in the mfxExtCodingOption2 structure. + */ + MFX_GOP_STRICT =2 +}; + +/*! The TargetUsage enumerator itemizes a range of numbers from MFX_TARGETUSAGE_1, best quality, to MFX_TARGETUSAGE_7, best speed. + It indicates trade-offs between quality and speed. The application can use any number in the range. The actual number of supported + target usages depends on implementation. If specified target usage is not supported, the encoder will use the closest supported value. */ +enum { + MFX_TARGETUSAGE_1 =1, /*!< Best quality */ + MFX_TARGETUSAGE_2 =2, + MFX_TARGETUSAGE_3 =3, + MFX_TARGETUSAGE_4 =4, /*!< Balanced quality and speed. */ + MFX_TARGETUSAGE_5 =5, + MFX_TARGETUSAGE_6 =6, + MFX_TARGETUSAGE_7 =7, /*!< Best speed */ + + MFX_TARGETUSAGE_UNKNOWN =0, /*!< Unspecified target usage. */ + MFX_TARGETUSAGE_BEST_QUALITY =MFX_TARGETUSAGE_1, /*!< Best quality. */ + MFX_TARGETUSAGE_BALANCED =MFX_TARGETUSAGE_4, /*!< Balanced quality and speed. */ + MFX_TARGETUSAGE_BEST_SPEED =MFX_TARGETUSAGE_7 /*!< Best speed. */ +}; + +/*! The RateControlMethod enumerator itemizes bitrate control methods. */ +enum { + MFX_RATECONTROL_CBR =1, /*!< Use the constant bitrate control algorithm. */ + MFX_RATECONTROL_VBR =2, /*!< Use the variable bitrate control algorithm. */ + MFX_RATECONTROL_CQP =3, /*!< Use the constant quantization parameter algorithm. */ + MFX_RATECONTROL_AVBR =4, /*!< Use the average variable bitrate control algorithm. */ + MFX_RATECONTROL_RESERVED1 =5, + MFX_RATECONTROL_RESERVED2 =6, + MFX_RATECONTROL_RESERVED3 =100, + MFX_RATECONTROL_RESERVED4 =7, + /*! + Use the VBR algorithm with look ahead. It is a special bitrate control mode in the AVC encoder that has been designed + to improve encoding quality. It works by performing extensive analysis of several dozen frames before the actual encoding and as a side + effect significantly increases encoding delay and memory consumption. + + The only available rate control parameter in this mode is mfxInfoMFX::TargetKbps. Two other parameters, MaxKbps and InitialDelayInKB, + are ignored. To control LA depth the application can use mfxExtCodingOption2::LookAheadDepth parameter. + + This method is not HRD compliant. + */ + MFX_RATECONTROL_LA =8, + /*! + Use the Intelligent Constant Quality algorithm. This algorithm improves subjective video quality of encoded stream. Depending on content, + it may or may not decrease objective video quality. Only one control parameter is used - quality factor, specified by mfxInfoMFX::ICQQuality. + */ + MFX_RATECONTROL_ICQ =9, + /*! + Use the Video Conferencing Mode algorithm. This algorithm is similar to the VBR and uses the same set of parameters mfxInfoMFX::InitialDelayInKB, + TargetKbpsandMaxKbps. It is tuned for IPPP GOP pattern and streams with strong temporal correlation between frames. + It produces better objective and subjective video quality in these conditions than other bitrate control algorithms. + It does not support interlaced content, B-frames and produced stream is not HRD compliant. + */ + MFX_RATECONTROL_VCM =10, + /*! + Use Intelligent Constant Quality algorithm with look ahead. Quality factor is specified by mfxInfoMFX::ICQQuality. + To control LA depth the application can use mfxExtCodingOption2::LookAheadDepth parameter. + + This method is not HRD compliant. + */ + MFX_RATECONTROL_LA_ICQ =11, + /*! + MFX_RATECONTROL_LA_EXT has been removed + */ + + /*! Use HRD compliant look ahead rate control algorithm. */ + MFX_RATECONTROL_LA_HRD =13, + /*! + Use the variable bitrate control algorithm with constant quality. This algorithm trying to achieve the target subjective quality with + the minimum number of bits, while the bitrate constraint and HRD compliance are satisfied. It uses the same set of parameters + as VBR and quality factor specified by mfxExtCodingOption3::QVBRQuality. + */ + MFX_RATECONTROL_QVBR =14, +}; + +/*! + The TrellisControl enumerator is used to control trellis quantization in AVC encoder. The application can turn it on + or off for any combination of I-, P- and B-frames by combining different enumerator values. For example, MFX_TRELLIS_I | MFX_TRELLIS_B + turns it on for I- and B-frames. + + @note Due to performance reason on some target usages trellis quantization is always turned off and this control is ignored by the encoder. +*/ +enum { + MFX_TRELLIS_UNKNOWN =0, /*!< Default value, it is up to the encoder to turn trellis quantization on or off. */ + MFX_TRELLIS_OFF =0x01, /*!< Turn trellis quantization off for all frame types. */ + MFX_TRELLIS_I =0x02, /*!< Turn trellis quantization on for I-frames. */ + MFX_TRELLIS_P =0x04, /*!< Turn trellis quantization on for P-frames. */ + MFX_TRELLIS_B =0x08 /*!< Turn trellis quantization on for B-frames. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies additional options for encoding. + + The application can attach this extended buffer to the mfxVideoParam structure to configure initialization. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION. */ + + mfxU16 reserved1; + mfxU16 RateDistortionOpt; /*!< Set this flag if rate distortion optimization is needed. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 MECostType; /*!< Motion estimation cost type. This value is reserved and must be zero. */ + mfxU16 MESearchType; /*!< Motion estimation search algorithm. This value is reserved and must be zero. */ + mfxI16Pair MVSearchWindow; /*!< Rectangular size of the search window for motion estimation. This parameter is reserved and must be (0, 0). */ + MFX_DEPRECATED mfxU16 EndOfSequence; /* Deprecated */ + mfxU16 FramePicture; /*!< Set this flag to encode interlaced fields as interlaced frames. This flag does not affect progressive input frames. See the CodingOptionValue enumerator for values of this option. */ + + mfxU16 CAVLC; /*!< If set, CAVLC is used; if unset, CABAC is used for encoding. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 reserved2[2]; + /*! + Set this flag to insert the recovery point SEI message at the beginning of every intra refresh cycle. See the description of + IntRefType in mfxExtCodingOption2 structure for details on how to enable and configure intra refresh. + + If intra refresh is not enabled then this flag is ignored. + + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 RecoveryPointSEI; + /*! + Set this flag to instruct the MVC encoder to output each view in separate bitstream buffer. See the CodingOptionValue enumerator + for values of this option and the Multi-View Video Coding section for more details about usage of this flag. + */ + mfxU16 ViewOutput; + /*! + If this option is turned ON, then AVC encoder produces an HRD conformant bitstream. If it is turned OFF, then the AVC encoder may (but not necessarily) violate HRD conformance. That is, this option can force the encoder to produce an HRD conformant stream, but + cannot force it to produce a non-conformant stream. + + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 NalHrdConformance; + /*! + If set, encoder puts all SEI messages in the singe NAL unit. It includes messages provided by application and created + by encoder. It is a three-states option. See CodingOptionValue enumerator for values of this option. The three states are: + + @li UNKNOWN Put each SEI in its own NAL unit. + + @li ON Put all SEI messages in the same NAL unit. + + @li OFF The same as unknown. + */ + mfxU16 SingleSeiNalUnit; + /*! + If set and VBR rate control method is used, then VCL HRD parameters are written in bitstream with values identical to the values of the NAL HRD parameters. + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 VuiVclHrdParameters; + + mfxU16 RefPicListReordering; /*!< Set this flag to activate reference picture list reordering. This value is reserved and must be zero. */ + mfxU16 ResetRefList; /*!< Set this flag to reset the reference list to non-IDR I-frames of a GOP sequence. See the CodingOptionValue enumerator for values of this option. */ + /*! + Set this flag to write the reference picture marking repetition SEI message into the output bitstream. + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 RefPicMarkRep; + /*! + Set this flag to instruct the AVC encoder to output bitstreams immediately after the encoder encodes a field, + in the field-encoding mode. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 FieldOutput; + + mfxU16 IntraPredBlockSize; /*!< Minimum block size of intra-prediction. This value is reserved and must be zero. */ + mfxU16 InterPredBlockSize; /*!< Minimum block size of inter-prediction. This value is reserved and must be zero. */ + mfxU16 MVPrecision; /*!< Specify the motion estimation precision. This parameter is reserved and must be zero. */ + mfxU16 MaxDecFrameBuffering; /*!< Specifies the maximum number of frames buffered in a DPB. A value of zero means unspecified. */ + + mfxU16 AUDelimiter; /*!< Set this flag to insert the Access Unit Delimiter NAL. See the CodingOptionValue enumerator for values of this option. */ + MFX_DEPRECATED mfxU16 EndOfStream; /* Deprecated */ + /*! + Set this flag to insert the picture timing SEI with pic_struct syntax element. See sub-clauses D.1.2 and D.2.2 of the ISO/IEC 14496-10 + specification for the definition of this syntax element. See the CodingOptionValue enumerator for values of this option. + The default value is ON. + */ + mfxU16 PicTimingSEI; + mfxU16 VuiNalHrdParameters; /*!< Set this flag to insert NAL HRD parameters in the VUI header. See the CodingOptionValue enumerator for values of this option. */ +} mfxExtCodingOption; +MFX_PACK_END() + +/*! The BRefControl enumerator is used to control usage of B-frames as reference in AVC encoder. */ +enum { + MFX_B_REF_UNKNOWN = 0, /*!< Default value, it is up to the encoder to use B-frames as reference. */ + MFX_B_REF_OFF = 1, /*!< Do not use B-frames as reference. */ + MFX_B_REF_PYRAMID = 2 /*!< Arrange B-frames in so-called "B pyramid" reference structure. */ +}; + +/*! The LookAheadDownSampling enumerator is used to control down sampling in look ahead bitrate control mode in AVC encoder. */ +enum { + MFX_LOOKAHEAD_DS_UNKNOWN = 0, /*!< Default value, it is up to the encoder what down sampling value to use. */ + MFX_LOOKAHEAD_DS_OFF = 1, /*!< Do not use down sampling, perform estimation on original size frames. This is the slowest setting that produces the best quality. */ + MFX_LOOKAHEAD_DS_2x = 2, /*!< Down sample frames two times before estimation. */ + MFX_LOOKAHEAD_DS_4x = 3 /*!< Down sample frames four times before estimation. This option may significantly degrade quality. */ +}; + +/*! The BPSEIControl enumerator is used to control insertion of buffering period SEI in the encoded bitstream. */ +enum { + MFX_BPSEI_DEFAULT = 0x00, /*!< encoder decides when to insert BP SEI. */ + MFX_BPSEI_IFRAME = 0x01 /*!< BP SEI should be inserted with every I-frame */ +}; + +/*! The SkipFrame enumerator is used to define usage of mfxEncodeCtrl::SkipFrame parameter. */ +enum { + MFX_SKIPFRAME_NO_SKIP = 0, /*!< Frame skipping is disabled, mfxEncodeCtrl::SkipFrame is ignored. */ + MFX_SKIPFRAME_INSERT_DUMMY = 1, /*!< Skipping is allowed, when mfxEncodeCtrl::SkipFrame is set encoder inserts into bitstream frame + where all macroblocks are encoded as skipped. Only non-reference P- and B-frames can be skipped. + If GopRefDist = 1 and mfxEncodeCtrl::SkipFrame is set for reference P-frame, it will be encoded + as non-reference. */ + MFX_SKIPFRAME_INSERT_NOTHING = 2, /*!< Similar to MFX_SKIPFRAME_INSERT_DUMMY, but when mfxEncodeCtrl::SkipFrame is set encoder inserts nothing into bitstream. */ + MFX_SKIPFRAME_BRC_ONLY = 3, /*!< mfxEncodeCtrl::SkipFrame indicates number of missed frames before the current frame. Affects only BRC, current frame will be encoded as usual. */ +}; + +/*! The IntraRefreshTypes enumerator itemizes types of intra refresh. */ +enum { + MFX_REFRESH_NO = 0, /*!< Encode without refresh. */ + MFX_REFRESH_VERTICAL = 1, /*!< Vertical refresh, by column of MBs. */ + MFX_REFRESH_HORIZONTAL = 2, /*!< Horizontal refresh, by rows of MBs. */ + MFX_REFRESH_SLICE = 3 /*!< Horizontal refresh by slices without overlapping. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used with the mfxExtCodingOption structure to specify additional options for encoding. + + The application can attach this extended buffer to the mfxVideoParam structure to configure initialization and to the mfxEncodeCtrl during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION2. */ + + /*! + Specifies intra refresh type. See the IntraRefreshTypes. The major goal of intra refresh is improvement of error resilience without + significant impact on encoded bitstream size caused by I-frames. The encoder achieves this by encoding part of each frame in the refresh + cycle using intra MBs. + + This parameter is valid during initialization and + runtime. When used with temporal scalability, intra refresh applied only to base layer. + + MFX_REFRESH_NO No refresh. + + MFX_REFRESH_VERTICAL Vertical refresh, by column of MBs. + + MFX_REFRESH_HORIZONTAL Horizontal refresh, by rows of MBs. + + MFX_REFRESH_SLICE Horizontal refresh by slices without overlapping. + + MFX_REFRESH_SLICE Library ignores IntRefCycleSize (size of refresh cycle equals number slices). + */ + mfxU16 IntRefType; + /*! + Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are invalid values. This parameter is valid only during initialization. + */ + mfxU16 IntRefCycleSize; + /*! + Specifies QP difference for inserted intra MBs. Signed values are in the -51 to 51 range. This parameter is valid during initialization and runtime. + */ + mfxI16 IntRefQPDelta; + + /*! + Specify maximum encoded frame size in byte. This parameter is used in VBR based bitrate control modes and ignored in others. + The encoder tries to keep frame size below specified limit but minor overshoots are possible to preserve visual quality. + This parameter is valid during initialization and runtime. It is recommended to set MaxFrameSize to 5x-10x target frame size + ((TargetKbps*1000)/(8* FrameRateExtN/FrameRateExtD)) for I-frames and 2x-4x target frame size for P- and B-frames. + */ + mfxU32 MaxFrameSize; + /*! + Specify maximum slice size in bytes. If this parameter is specified other controls over number of slices are ignored. + + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU32 MaxSliceSize; + + /*! + Modifies bitrate to be in the range imposed by the encoder. The default value is ON, that is, bitrate is limited. Setting this flag to OFF may lead to violation of HRD conformance.Specifying bitrate below the encoder range might significantly affect quality. + + If set to ON, this option takes effect in non CQP modes: + if TargetKbps is not in the range imposed by the encoder, it will be changed to be in the range. + + This parameter is valid only during initialization. Flag works with MFX_CODEC_AVC only, it is ignored with other codecs. + See the CodingOptionValue + enumerator for values of this option. + + @deprecated Deprecated in API version 2.9 + */ + MFX_DEPRECATED mfxU16 BitrateLimit; /* Deprecated */ + /*! + Setting this flag enables macroblock level bitrate control that generally improves subjective visual quality. Enabling this flag may + have negative impact on performance and objective visual quality metric. See the CodingOptionValue enumerator for values of this option. + The default value depends on target usage settings. + */ + mfxU16 MBBRC; + /*! + Set this option to ON to enable external BRC. See the CodingOptionValue enumerator for values of this option. + Use the Query API function to check if this feature is supported. + */ + mfxU16 ExtBRC; + /*! + Specifies the depth of the look ahead rate control algorithm. The depth value is the number of frames that the encoder analyzes before encoding. Values are in the 10 to 100 range, inclusive. + To instruct the encoder to use the default value the application should zero this field. + */ + mfxU16 LookAheadDepth; + /*! + Used to control trellis quantization in AVC encoder. See TrellisControl enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 Trellis; + /*! + Controls picture parameter set repetition in AVC encoder. Set this flag to ON to repeat PPS with each frame. + See the CodingOptionValue enumerator for values of this option. The default value is ON. This parameter is valid only during initialization. + */ + mfxU16 RepeatPPS; + /*! + Controls usage of B-frames as reference. See BRefControl enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 BRefType; + /*! + Controls insertion of I-frames by the encoder. Set this flag to ON to allow changing of frame type from P and B to I. + This option is ignored if GopOptFlag in mfxInfoMFX structure is equal to MFX_GOP_STRICT. See the CodingOptionValue enumerator + for values of this option. This parameter is valid only during initialization. + */ + mfxU16 AdaptiveI; + /*! + Controls changing of frame type from B to P. Set this flag to ON enable changing of frame type from B to P. This option is ignored if + GopOptFlag in mfxInfoMFX structure is equal to MFX_GOP_STRICT. See the CodingOptionValue enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 AdaptiveB; + /*! + Controls down sampling in look ahead bitrate control mode. See LookAheadDownSampling enumerator for values + of this option. This parameter is valid only during initialization. + */ + mfxU16 LookAheadDS; + /*! + Specifies suggested slice size in number of macroblocks. The library can adjust this number based on platform capability. + If this option is specified, that is, if it is not equal to zero, the library ignores mfxInfoMFX::NumSlice parameter. + */ + mfxU16 NumMbPerSlice; + /*! + Enables usage of mfxEncodeCtrl::SkipFrame parameter. See the SkipFrame enumerator for values of this option. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 SkipFrame; + mfxU8 MinQPI; /*!< Minimum allowed QP value for I-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MaxQPI; /*!< Maximum allowed QP value for I-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted MaxQPI value = 51 + (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we add (6*(10-8)=12) on our side for MaxQPI will reach 63. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MinQPP; /*!< Minimum allowed QP value for P-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MaxQPP; /*!< Maximum allowed QP value for P-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted MaxQPP value = 51 + (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we add (6*(10-8)=12) on our side for MaxQPP will reach 63. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MinQPB; /*!< Minimum allowed QP value for B-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MaxQPB; /*!< Maximum allowed QP value for B-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted MaxQPB value = 51 + (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we add (6*(10-8)=12) on our side for MaxQPB will reach 63. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + /*! + Sets fixed_frame_rate_flag in VUI. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 FixedFrameRate; + /*! Disables deblocking. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 DisableDeblockingIdc; + /*! + Completely disables VUI in the output bitstream. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 DisableVUI; + /*! + Controls insertion of buffering period SEI in the encoded bitstream. It should be one of the following values: + + MFX_BPSEI_DEFAULT Encoder decides when to insert BP SEI, + + MFX_BPSEI_IFRAME BP SEI should be inserted with every I-frame. + */ + mfxU16 BufferingPeriodSEI; + /*! + Set this flag to ON to enable per-frame reporting of Mean Absolute Difference. This parameter is valid only during initialization. + */ + mfxU16 EnableMAD; + /*! + Set this flag to ON to use raw frames for reference instead of reconstructed frames. This parameter is valid during + initialization and runtime (only if was turned ON during initialization). + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 UseRawRef; +} mfxExtCodingOption2; +MFX_PACK_END() + +/*! The WeightedPred enumerator itemizes weighted prediction modes. */ +enum { + MFX_WEIGHTED_PRED_UNKNOWN = 0, /*!< Allow encoder to decide. */ + MFX_WEIGHTED_PRED_DEFAULT = 1, /*!< Use default weighted prediction. */ + MFX_WEIGHTED_PRED_EXPLICIT = 2, /*!< Use explicit weighted prediction. */ + MFX_WEIGHTED_PRED_IMPLICIT = 3 /*!< Use implicit weighted prediction (for B-frames only). */ +}; + +/*! The ScenarioInfo enumerator itemizes scenarios for the encoding session. */ +enum { + MFX_SCENARIO_UNKNOWN = 0, + MFX_SCENARIO_DISPLAY_REMOTING = 1, + MFX_SCENARIO_VIDEO_CONFERENCE = 2, + MFX_SCENARIO_ARCHIVE = 3, + MFX_SCENARIO_LIVE_STREAMING = 4, + MFX_SCENARIO_CAMERA_CAPTURE = 5, + MFX_SCENARIO_VIDEO_SURVEILLANCE = 6, + MFX_SCENARIO_GAME_STREAMING = 7, + MFX_SCENARIO_REMOTE_GAMING = 8 +}; + +/*! The ContentInfo enumerator itemizes content types for the encoding session. */ +enum { + MFX_CONTENT_UNKNOWN = 0, + MFX_CONTENT_FULL_SCREEN_VIDEO = 1, + MFX_CONTENT_NON_VIDEO_SCREEN = 2, + MFX_CONTENT_NOISY_VIDEO = 3 +}; + +/*! The PRefType enumerator itemizes models of reference list construction and DPB management when GopRefDist=1. */ +enum { + MFX_P_REF_DEFAULT = 0, /*!< Allow encoder to decide. */ + MFX_P_REF_SIMPLE = 1, /*!< Regular sliding window used for DPB removal process. */ + MFX_P_REF_PYRAMID = 2 /*!< Let N be the max reference list's size. Encoder treats each N's frame as a 'strong' + reference and the others as 'weak' references. The encoder uses a 'weak' reference only for + prediction of the next frame and removes it from DPB immediately after use. 'Strong' references are removed from + DPB by a sliding window. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used with mfxExtCodingOption and mfxExtCodingOption2 structures to specify additional options for encoding. + The application can attach this extended buffer to the mfxVideoParam structure to configure initialization and to the mfxEncodeCtrl during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION3. */ + + mfxU16 NumSliceI; /*!< The number of slices for I-frames. + @note Not all codecs and implementations support these values. Use the Query API function to check if this feature is supported */ + mfxU16 NumSliceP; /*!< The number of slices for P-frames. + @note Not all codecs and implementations support these values. Use the Query API function to check if this feature is supported */ + mfxU16 NumSliceB; /*!< The number of slices for B-frames. + @note Not all codecs and implementations support these values. Use the Query API function to check if this feature is supported */ + + /*! + When rate control method is MFX_RATECONTROL_CBR, MFX_RATECONTROL_VBR, MFX_RATECONTROL_LA, MFX_RATECONTROL_LA_HRD, or MFX_RATECONTROL_QVBR + this parameter specifies the maximum bitrate averaged over a sliding window specified by WinBRCSize. + */ + mfxU16 WinBRCMaxAvgKbps; + /*! + When rate control method is MFX_RATECONTROL_CBR, MFX_RATECONTROL_VBR, MFX_RATECONTROL_LA, MFX_RATECONTROL_LA_HRD, or MFX_RATECONTROL_QVBR + this parameter specifies sliding window size in frames. Set WinBRCMaxAvgKbps and WinBRCSize to zero to disable sliding window. + */ + 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. + */ + mfxU16 QVBRQuality; + /*! + Set this flag to ON to enable per-macroblock QP control. Rate control method must be MFX_RATECONTROL_CQP. See the CodingOptionValue + enumerator for values of this option. This parameter is valid only during initialization. + */ + mfxU16 EnableMBQP; + /*! + Distance between the beginnings of the intra-refresh cycles in frames. Zero means no distance between cycles. + */ + mfxU16 IntRefCycleDist; + /*! + Set this flag to ON to enable the ENC mode decision algorithm to bias to fewer B Direct/Skip types. Applies only to B-frames, + all other frames will ignore this setting. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 DirectBiasAdjustment; + /*! + Enables global motion bias. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 GlobalMotionBiasAdjustment; + /*! + Values are: + + @li 0: Set MV cost to be 0. + + @li 1: Scale MV cost to be 1/2 of the default value. + + @li 2: Scale MV cost to be 1/4 of the default value. + + @li 3: Scale MV cost to be 1/8 of the default value. + */ + mfxU16 MVCostScalingFactor; + /*! + Set this flag to ON to enable usage of mfxExtMBDisableSkipMap. See the CodingOptionValue enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 MBDisableSkipMap; + + mfxU16 WeightedPred; /*!< Weighted prediction mode. See the WeightedPred enumerator for values of these options. */ + mfxU16 WeightedBiPred; /*!< Weighted prediction mode. See the WeightedPred enumerator for values of these options. */ + + /*! + Instructs encoder whether aspect ratio info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 AspectRatioInfoPresent; + /*! + Instructs encoder whether overscan info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 OverscanInfoPresent; + /*! + ON indicates that the cropped decoded pictures output are suitable for display using overscan. OFF indicates that the cropped decoded + pictures output contain visually important information in the entire region out to the edges of the cropping rectangle of the picture. + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 OverscanAppropriate; + /*! + Instructs encoder whether frame rate info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 TimingInfoPresent; + /*! + Instructs encoder whether bitstream restriction info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 BitstreamRestriction; + /*! + Corresponds to AVC syntax element low_delay_hrd_flag (VUI). See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 LowDelayHrd; + /*! + When set to OFF, no sample outside the picture boundaries and no sample at a fractional sample position for which the sample value + is derived using one or more samples outside the picture boundaries is used for inter prediction of any sample. + + When set to ON, one or more samples outside picture boundaries may be used in inter prediction. + + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 MotionVectorsOverPicBoundaries; + mfxU16 reserved1[2]; + + mfxU16 ScenarioInfo; /*!< Provides a hint to encoder about the scenario for the encoding session. See the ScenarioInfo enumerator for values of this option. */ + mfxU16 ContentInfo; /*!< Provides a hint to encoder about the content for the encoding session. See the ContentInfo enumerator for values of this option. */ + + mfxU16 PRefType; /*!< When GopRefDist=1, specifies the model of reference list construction and DPB management. See the PRefType enumerator for values of this option. */ + /*! + Instructs encoder whether internal fade detection algorithm should be used for calculation of weigh/offset values for pred_weight_table + unless application provided mfxExtPredWeightTable for this frame. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 FadeDetection; + mfxU16 reserved2[2]; + /*! + Set this flag to OFF to make HEVC encoder use regular P-frames instead of GPB. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 GPB; + + /*! + Same as mfxExtCodingOption2::MaxFrameSize but affects only I-frames. MaxFrameSizeI must be set if MaxFrameSizeP is set. + If MaxFrameSizeI is not specified or greater than spec limitation, spec limitation will be applied to the sizes of I-frames. + */ + mfxU32 MaxFrameSizeI; + /*! + Same as mfxExtCodingOption2::MaxFrameSize but affects only P/B-frames. If MaxFrameSizeP equals 0, the library sets MaxFrameSizeP + equal to MaxFrameSizeI. If MaxFrameSizeP is not specified or greater than spec limitation, spec limitation will be applied to the + sizes of P/B-frames. + */ + mfxU32 MaxFrameSizeP; + mfxU32 reserved3[3]; + + /*! + Enables QPOffset control. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 EnableQPOffset; + /*! + Specifies QP offset per pyramid layer when EnableQPOffset is set to ON and RateControlMethod is CQP. + + For B-pyramid, B-frame QP = QPB + QPOffset[layer]. + + For P-pyramid, P-frame QP = QPP + QPOffset[layer]. + */ + mfxI16 QPOffset[8]; /* FrameQP = QPX + QPOffset[pyramid_layer]; QPX = QPB for B-pyramid, QPP for P-pyramid */ + + + mfxU16 NumRefActiveP[8]; /*!< Max number of active references for P-frames. Array index is pyramid layer. */ + mfxU16 NumRefActiveBL0[8]; /*!< Max number of active references for B-frames in reference picture list 0. Array index is pyramid layer. */ + mfxU16 NumRefActiveBL1[8]; /*!< Max number of active references for B-frames in reference picture list 1. Array index is pyramid layer. */ + + mfxU16 reserved6; + /*! + For HEVC if this option is turned ON, the transform_skip_enabled_flag will be set to 1 in PPS. OFF specifies that transform_skip_enabled_flag will be set to 0. + */ + mfxU16 TransformSkip; + /*! + Minus 1 specifies target encoding chroma format (see ChromaFormatIdc enumerator). May differ from the source format. + TargetChromaFormatPlus1 = 0 specifies the default target chroma format which is equal to source (mfxVideoParam::mfx::FrameInfo::ChromaFormat + 1), + except RGB4 source format. In case of RGB4 source format default target , chroma format is 4:2:0 (instead of 4:4:4) + for the purpose of backward compatibility. + */ + mfxU16 TargetChromaFormatPlus1; + /*! + Target encoding bit-depth for luma samples. May differ from source bit-depth. 0 specifies a default target bit-depth that is equal to + source (mfxVideoParam::mfx::FrameInfo::BitDepthLuma). + */ + mfxU16 TargetBitDepthLuma; + /*! + Target encoding bit-depth for chroma samples. May differ from source bit-depth. 0 specifies a default target bit-depth that is equal to + source (mfxVideoParam::mfx::FrameInfo::BitDepthChroma). + */ + mfxU16 TargetBitDepthChroma; + mfxU16 BRCPanicMode; /*!< Controls panic mode in AVC and MPEG2 encoders. */ + + /*! + When rate control method is MFX_RATECONTROL_VBR, MFX_RATECONTROL_QVBR or MFX_RATECONTROL_VCM this parameter specifies frame size + tolerance. Set this parameter to MFX_CODINGOPTION_ON to allow strictly obey average frame size set by MaxKbps, for example cases when + MaxFrameSize == (MaxKbps*1000)/(8* FrameRateExtN/FrameRateExtD). Also MaxFrameSizeI and MaxFrameSizeP can be set separately. + */ + mfxU16 LowDelayBRC; + /*! + Set this flag to ON to enable usage of mfxExtMBForceIntra for AVC encoder. See the CodingOptionValue enumerator + for values of this option. This parameter is valid only during initialization. + */ + mfxU16 EnableMBForceIntra; + /*! + If this flag is set to ON, BRC may decide a larger P- or B-frame size than what MaxFrameSizeP dictates when the scene change is detected. + It may benefit the video quality. AdaptiveMaxFrameSize feature is not supported with LowPower ON or if the value of MaxFrameSizeP = 0. + */ + mfxU16 AdaptiveMaxFrameSize; + + /*! + Controls AVC encoder attempts to predict from small partitions. Default value allows encoder to choose preferred mode. + MFX_CODINGOPTION_ON forces encoder to favor quality and MFX_CODINGOPTION_OFF forces encoder to favor performance. + */ + mfxU16 RepartitionCheckEnable; + mfxU16 reserved5[3]; + mfxU16 EncodedUnitsInfo; /*!< Set this flag to ON to make encoded units info available in mfxExtEncodedUnitsInfo. */ + /*! + If this flag is set to ON, the HEVC encoder uses the NAL unit type provided by the application in the mfxEncodeCtrl::MfxNalUnitType field. + This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 EnableNalUnitType; + + union { + MFX_DEPRECATED 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. + Their number and definitions are API implementation specific. + If this flag is set to OFF, default quantization matrix is used for all frames. + This parameter is valid only during initialization. + */ + mfxU16 AdaptiveCQM; + /*! + If this flag is set to ON, encoder adaptively selects list of reference frames to improve 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() + +/*! IntraPredBlockSize/InterPredBlockSize specifies the minimum block size of inter-prediction. */ +enum { + MFX_BLOCKSIZE_UNKNOWN = 0, /*!< Unspecified. */ + MFX_BLOCKSIZE_MIN_16X16 = 1, /*!< 16x16 minimum block size. */ + MFX_BLOCKSIZE_MIN_8X8 = 2, /*!< 8x8 minimum block size. May be 16x16 or 8x8. */ + MFX_BLOCKSIZE_MIN_4X4 = 3 /*!< 4x4 minimum block size. May be 16x16, 8x8, or 4x4. */ +}; + +/*! The MVPrecision enumerator specifies the motion estimation precision. */ +enum { + MFX_MVPRECISION_UNKNOWN = 0, + MFX_MVPRECISION_INTEGER = (1 << 0), + MFX_MVPRECISION_HALFPEL = (1 << 1), + MFX_MVPRECISION_QUARTERPEL = (1 << 2) +}; + +/*! The CodingOptionValue enumerator defines a three-state coding option setting. */ +enum { + MFX_CODINGOPTION_UNKNOWN =0, /*!< Unspecified. */ + MFX_CODINGOPTION_ON =0x10, /*!< Coding option set. */ + MFX_CODINGOPTION_OFF =0x20, /*!< Coding option not set. */ + MFX_CODINGOPTION_ADAPTIVE =0x30 /*!< Reserved. */ +}; + +/*! The BitstreamDataFlag enumerator uses bit-ORed values to itemize additional information about the bitstream buffer. */ +enum { + MFX_BITSTREAM_NO_FLAG = 0x0000, /*!< The bitstream doesn't contain any flags. */ + /*! + The bitstream buffer contains a complete frame or complementary field pair of data for the bitstream. For decoding, this means + that the decoder can proceed with this buffer without waiting for the start of the next frame, which effectively reduces decoding latency. + If this flag is set, but the bitstream buffer contains incomplete frame or pair of field, then decoder will produce corrupted output. + */ + MFX_BITSTREAM_COMPLETE_FRAME = 0x0001, + /*! + The bitstream buffer contains the end of the stream. For decoding, + this means that the application does not have any additional bitstream data to send to decoder. + */ + MFX_BITSTREAM_EOS = 0x0002 +}; +/*! The ExtendedBufferID enumerator itemizes and defines identifiers (BufferId) for extended buffers or video processing algorithm identifiers. */ +enum { + /*! + This extended buffer defines additional encoding controls. See the mfxExtCodingOption structure for details. + The application can attach this buffer to the structure for encoding initialization. + */ + MFX_EXTBUFF_CODING_OPTION = MFX_MAKEFOURCC('C','D','O','P'), + /*! + This extended buffer defines sequence header and picture header for encoders and decoders. See the mfxExtCodingOptionSPSPPS + structure for details. The application can attach this buffer to the mfxVideoParam structure for encoding initialization, + and for obtaining raw headers from the decoders and encoders. + */ + MFX_EXTBUFF_CODING_OPTION_SPSPPS = MFX_MAKEFOURCC('C','O','S','P'), + /*! + This extended buffer defines a list of VPP algorithms that applications should not use. See the mfxExtVPPDoNotUse structure + for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DONOTUSE = MFX_MAKEFOURCC('N','U','S','E'), + /*! + This extended buffer defines auxiliary information at the VPP output. See the mfxExtVppAuxData structure for details. The application + can attach this buffer to the mfxEncodeCtrl structure for per-frame encoding control. + */ + MFX_EXTBUFF_VPP_AUXDATA = MFX_MAKEFOURCC('A','U','X','D'), + /*! + The extended buffer defines control parameters for the VPP denoise filter algorithm. See the mfxExtVPPDenoise2 structure for details. + The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DENOISE2 = MFX_MAKEFOURCC('D','N','I','2'), + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_EXTBUFF_VPP_DENOISE) = MFX_MAKEFOURCC('D','N','I','S'), /*!< Deprecated in 2.2 API version.*/ + MFX_EXTBUFF_VPP_SCENE_ANALYSIS = MFX_MAKEFOURCC('S','C','L','Y'), /*!< Reserved for future use. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_EXTBUFF_VPP_SCENE_CHANGE) = MFX_EXTBUFF_VPP_SCENE_ANALYSIS, /* Deprecated. */ + /*! + The extended buffer defines control parameters for the VPP ProcAmp filter algorithm. See the mfxExtVPPProcAmp structure for details. + The application can attach this buffer to the mfxVideoParam structure for video processing initialization or to the mfxFrameData + structure in the mfxFrameSurface1 structure of output surface for per-frame processing configuration. + */ + MFX_EXTBUFF_VPP_PROCAMP = MFX_MAKEFOURCC('P','A','M','P'), + /*! + The extended buffer defines control parameters for the VPP detail filter algorithm. See the mfxExtVPPDetail structure for details. + The application can attach this buffer to the structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DETAIL = MFX_MAKEFOURCC('D','E','T',' '), + /*! + This extended buffer defines video signal type. See the mfxExtVideoSignalInfo structure for details. The application can attach this + buffer to the mfxVideoParam structure for encoding initialization, and for retrieving such information from the decoders. If video + signal info changes per frame, the application can attach this buffer to the mfxFrameData structure for video processing. + */ + MFX_EXTBUFF_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','S','I','N'), + /*! + This extended buffer defines video signal type. See the mfxExtVideoSignalInfo structure for details. The application can attach this + buffer to the mfxVideoParam structure for the input of video processing if the input video signal information changes in sequence + base. + */ + MFX_EXTBUFF_VIDEO_SIGNAL_INFO_IN = MFX_MAKEFOURCC('V','S','I','I'), + /*! + This extended buffer defines video signal type. See the mfxExtVideoSignalInfo structure for details. The application can attach this + buffer to the mfxVideoParam structure for the output of video processing if the output video signal information changes in sequence + base. + */ + MFX_EXTBUFF_VIDEO_SIGNAL_INFO_OUT = MFX_MAKEFOURCC('V','S','I','O'), + /*! + This extended buffer defines a list of VPP algorithms that applications should use. See the mfxExtVPPDoUse structure for details. + The application can attach this buffer to the structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DOUSE = MFX_MAKEFOURCC('D','U','S','E'), + /*! + This extended buffer defines additional encoding controls for reference list. See the mfxExtAVCRefListCtrl structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding & decoding initialization, or the mfxEncodeCtrl + structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_AVC_REFLIST_CTRL = MFX_MAKEFOURCC('R','L','S','T'), + /*! + This extended buffer defines control parameters for the VPP frame rate conversion algorithm. See the mfxExtVPPFrameRateConversion structure + for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION = MFX_MAKEFOURCC('F','R','C',' '), + /*! + This extended buffer configures the H.264 picture timing SEI message. See the mfxExtPictureTimingSEI structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization, or the mfxEncodeCtrl structure + for per-frame encoding configuration. + */ + MFX_EXTBUFF_PICTURE_TIMING_SEI = MFX_MAKEFOURCC('P','T','S','E'), + /*! + This extended buffer configures the structure of temporal layers inside the encoded H.264 bitstream. See the mfxExtAvcTemporalLayers + structure for details. The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_AVC_TEMPORAL_LAYERS = MFX_MAKEFOURCC('A','T','M','L'), + /*! + This extended buffer defines additional encoding controls. See the mfxExtCodingOption2 structure for details. + The application can attach this buffer to the structure for encoding initialization. + */ + MFX_EXTBUFF_CODING_OPTION2 = MFX_MAKEFOURCC('C','D','O','2'), + /*! + This extended buffer defines control parameters for the VPP image stabilization filter algorithm. See the mfxExtVPPImageStab structure + for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_IMAGE_STABILIZATION = MFX_MAKEFOURCC('I','S','T','B'), + /*! + This extended buffer is used to retrieve encoder capability. See the mfxExtEncoderCapability structure for details. + The application can attach this buffer to the mfxVideoParam structure before calling MFXVideoENCODE_Query function. + */ + MFX_EXTBUFF_ENCODER_CAPABILITY = MFX_MAKEFOURCC('E','N','C','P'), + /*! + This extended buffer is used to control encoder reset behavior and also to query possible encoder reset outcome. + See the mfxExtEncoderResetOption structure for details. The application can attach this buffer to the mfxVideoParam structure + before calling MFXVideoENCODE_Query or MFXVideoENCODE_Reset functions. + */ + MFX_EXTBUFF_ENCODER_RESET_OPTION = MFX_MAKEFOURCC('E','N','R','O'), + /*! + This extended buffer is used by the encoder to report additional information about encoded picture. + See the mfxExtAVCEncodedFrameInfo structure for details. The application can attach this buffer to the mfxBitstream structure + before calling MFXVideoENCODE_EncodeFrameAsync function. + */ + MFX_EXTBUFF_ENCODED_FRAME_INFO = MFX_MAKEFOURCC('E','N','F','I'), + /*! + This extended buffer is used to control composition of several input surfaces in the one output. In this mode, + the VPP skips any other filters. The VPP returns error if any mandatory filter is specified and filter skipped warning + for optional filter. The only supported filters are deinterlacing and interlaced scaling. + */ + MFX_EXTBUFF_VPP_COMPOSITE = MFX_MAKEFOURCC('V','C','M','P'), + /*! + This extended buffer is used to control transfer matrix and nominal range of YUV frames. + The application should provide it during initialization. + */ + MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','V','S','I'), + /*! + This extended buffer is used by the application to specify different Region Of Interests during encoding. + The application should provide it at initialization or at runtime. + */ + MFX_EXTBUFF_ENCODER_ROI = MFX_MAKEFOURCC('E','R','O','I'), + /*! + This extended buffer is used by the application to specify different deinterlacing algorithms. + */ + MFX_EXTBUFF_VPP_DEINTERLACING = MFX_MAKEFOURCC('V','P','D','I'), + /*! + This extended buffer specifies reference lists for the encoder. + */ + MFX_EXTBUFF_AVC_REFLISTS = MFX_MAKEFOURCC('R','L','T','S'), + /*! + See the mfxExtDecVideoProcessing structure for details. + */ + MFX_EXTBUFF_DEC_VIDEO_PROCESSING = MFX_MAKEFOURCC('D','E','C','V'), + /*! + The extended buffer defines control parameters for the VPP field-processing algorithm. See the mfxExtVPPFieldProcessing + structure for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization + or to the mfxFrameData structure during runtime. + */ + MFX_EXTBUFF_VPP_FIELD_PROCESSING = MFX_MAKEFOURCC('F','P','R','O'), + /*! + This extended buffer defines additional encoding controls. See the mfxExtCodingOption3 structure for details. + The application can attach this buffer to the structure for encoding initialization. + */ + MFX_EXTBUFF_CODING_OPTION3 = MFX_MAKEFOURCC('C','D','O','3'), + /*! + This extended buffer defines chroma samples location information. See the mfxExtChromaLocInfo structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_CHROMA_LOC_INFO = MFX_MAKEFOURCC('C','L','I','N'), + /*! + This extended buffer defines per-macroblock QP. See the mfxExtMBQP structure for details. + The application can attach this buffer to the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_MBQP = MFX_MAKEFOURCC('M','B','Q','P'), + /*! + This extended buffer defines per-macroblock force intra flag. See the mfxExtMBForceIntra structure for details. + The application can attach this buffer to the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_MB_FORCE_INTRA = MFX_MAKEFOURCC('M','B','F','I'), + /*! + This extended buffer defines additional encoding controls for HEVC tiles. See the mfxExtHEVCTiles structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_HEVC_TILES = MFX_MAKEFOURCC('2','6','5','T'), + /*! + This extended buffer defines macroblock map for current frame which forces specified macroblocks to be non skip. See the + mfxExtMBDisableSkipMap structure for details. The application can attach this buffer to the mfxEncodeCtrl structure for + per-frame encoding configuration. + */ + MFX_EXTBUFF_MB_DISABLE_SKIP_MAP = MFX_MAKEFOURCC('M','D','S','M'), + /*! + See the mfxExtHEVCParam structure for details. + */ + MFX_EXTBUFF_HEVC_PARAM = MFX_MAKEFOURCC('2','6','5','P'), + /*! + This extended buffer is used by decoders to report additional information about decoded frame. See the + mfxExtDecodedFrameInfo structure for more details. + */ + MFX_EXTBUFF_DECODED_FRAME_INFO = MFX_MAKEFOURCC('D','E','F','I'), + /*! + See the mfxExtTimeCode structure for more details. + */ + MFX_EXTBUFF_TIME_CODE = MFX_MAKEFOURCC('T','M','C','D'), + /*! + This extended buffer specifies the region to encode. The application can attach this buffer to the + mfxVideoParam structure during HEVC encoder initialization. + */ + MFX_EXTBUFF_HEVC_REGION = MFX_MAKEFOURCC('2','6','5','R'), + /*! + See the mfxExtPredWeightTable structure for details. + */ + MFX_EXTBUFF_PRED_WEIGHT_TABLE = MFX_MAKEFOURCC('E','P','W','T'), + /*! + See the mfxExtDirtyRect structure for details. + */ + MFX_EXTBUFF_DIRTY_RECTANGLES = MFX_MAKEFOURCC('D','R','O','I'), + /*! + See the mfxExtMoveRect structure for details. + */ + MFX_EXTBUFF_MOVING_RECTANGLES = MFX_MAKEFOURCC('M','R','O','I'), + /*! + See the mfxExtCodingOptionVPS structure for details. + */ + MFX_EXTBUFF_CODING_OPTION_VPS = MFX_MAKEFOURCC('C','O','V','P'), + /*! + See the mfxExtVPPRotation structure for details. + */ + MFX_EXTBUFF_VPP_ROTATION = MFX_MAKEFOURCC('R','O','T',' '), + /*! + See the mfxExtEncodedSlicesInfo structure for details. + */ + MFX_EXTBUFF_ENCODED_SLICES_INFO = MFX_MAKEFOURCC('E','N','S','I'), + /*! + See the mfxExtVPPScaling structure for details. + */ + MFX_EXTBUFF_VPP_SCALING = MFX_MAKEFOURCC('V','S','C','L'), + /*! + This extended buffer defines additional encoding controls for reference list. See the mfxExtAVCRefListCtrl structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding & decoding initialization, or + the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_HEVC_REFLIST_CTRL = MFX_EXTBUFF_AVC_REFLIST_CTRL, + /*! + This extended buffer specifies reference lists for the encoder. + */ + MFX_EXTBUFF_HEVC_REFLISTS = MFX_EXTBUFF_AVC_REFLISTS, + /*! + This extended buffer configures the structure of temporal layers inside the encoded H.265 bitstream. See the mfxExtHEVCTemporalLayers + structure for details. The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_HEVC_TEMPORAL_LAYERS = MFX_EXTBUFF_AVC_TEMPORAL_LAYERS, + /*! + See the mfxExtVPPMirroring structure for details. + */ + MFX_EXTBUFF_VPP_MIRRORING = MFX_MAKEFOURCC('M','I','R','R'), + /*! + See the mfxExtMVOverPicBoundaries structure for details. + */ + MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES = MFX_MAKEFOURCC('M','V','P','B'), + /*! + See the mfxExtVPPColorFill structure for details. + */ + MFX_EXTBUFF_VPP_COLORFILL = MFX_MAKEFOURCC('V','C','L','F'), + /*! + This extended buffer is used by decoders to report error information before frames get decoded. + See the mfxExtDecodeErrorReport structure for more details. + */ + MFX_EXTBUFF_DECODE_ERROR_REPORT = MFX_MAKEFOURCC('D', 'E', 'R', 'R'), + /*! + See the mfxExtColorConversion structure for details. + */ + MFX_EXTBUFF_VPP_COLOR_CONVERSION = MFX_MAKEFOURCC('V', 'C', 'S', 'C'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtContentLightLevelInfo structure for details. + */ + MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO = MFX_MAKEFOURCC('L', 'L', 'I', 'S'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtMasteringDisplayColourVolume structure for details. If color volume changes + per frame, the application can attach this buffer to the mfxFrameData structure for video processing. + */ + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME = MFX_MAKEFOURCC('D', 'C', 'V', 'S'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtMasteringDisplayColourVolume structure for details. The application can + attach this buffer to the mfxVideoParam structure for the input of video processing if the mastering display color volume changes per + sequence. In this case, this buffer should be together with MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO to indicate the light level and mastering + color volume of the input of video processing. If color Volume changes per frame instead of per sequence, the application can attach + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME to mfxFrameData for frame based processing. + */ + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME_IN = MFX_MAKEFOURCC('D', 'C', 'V', 'I'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtMasteringDisplayColourVolume structure for details. The application can + attach this buffer to the mfxVideoParam structure for the output of video processing if the mastering display color volume changes per + sequence. If color volume changes per frame instead of per sequence, the application can attach the buffer with MFX_EXTBUFF_MASTERING_ + DISPLAY_COLOUR_VOLUME to mfxFrameData for frame based processing. + */ + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME_OUT = MFX_MAKEFOURCC('D', 'C', 'V', 'O'), + /*! + See the mfxExtEncodedUnitsInfo structure for details. + */ + MFX_EXTBUFF_ENCODED_UNITS_INFO = MFX_MAKEFOURCC('E', 'N', 'U', 'I'), + /*! + This video processing algorithm identifier is used to enable MCTF via mfxExtVPPDoUse and together with mfxExtVppMctf + */ + MFX_EXTBUFF_VPP_MCTF = MFX_MAKEFOURCC('M', 'C', 'T', 'F'), + /*! + Extends mfxVideoParam structure with VP9 segmentation parameters. See the mfxExtVP9Segmentation structure for details. + */ + MFX_EXTBUFF_VP9_SEGMENTATION = MFX_MAKEFOURCC('9', 'S', 'E', 'G'), + /*! + Extends mfxVideoParam structure with parameters for VP9 temporal scalability. See the mfxExtVP9TemporalLayers structure for details. + */ + MFX_EXTBUFF_VP9_TEMPORAL_LAYERS = MFX_MAKEFOURCC('9', 'T', 'M', 'L'), + /*! + Extends mfxVideoParam structure with VP9-specific parameters. See the mfxExtVP9Param structure for details. + */ + MFX_EXTBUFF_VP9_PARAM = MFX_MAKEFOURCC('9', 'P', 'A', 'R'), + /*! + See the mfxExtAVCRoundingOffset structure for details. + */ + MFX_EXTBUFF_AVC_ROUNDING_OFFSET = MFX_MAKEFOURCC('R','N','D','O'), + /*! + See the mfxExtPartialBitstreamParam structure for details. + */ + MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM = MFX_MAKEFOURCC('P','B','O','P'), + + /*! + See the mfxExtEncoderIPCMArea structure for details. + */ + MFX_EXTBUFF_ENCODER_IPCM_AREA = MFX_MAKEFOURCC('P', 'C', 'M', 'R'), + /*! + See the mfxExtInsertHeaders structure for details. + */ + MFX_EXTBUFF_INSERT_HEADERS = MFX_MAKEFOURCC('S', 'P', 'R', 'E'), + + /*! + See the mfxExtDeviceAffinityMask structure for details. + */ + MFX_EXTBUFF_DEVICE_AFFINITY_MASK = MFX_MAKEFOURCC('D', 'A', 'F', 'M'), + + /*! + See the mfxExtInCrops structure for details. + */ + MFX_EXTBUFF_CROPS = MFX_MAKEFOURCC('C', 'R', 'O', 'P'), + + /*! + See the mfxExtAV1BitstreamParam structure for more details. + */ + MFX_EXTBUFF_AV1_BITSTREAM_PARAM = MFX_MAKEFOURCC('A', '1', 'B', 'S'), + + /*! + See the mfxExtAV1ResolutionParam structure for more details. + */ + MFX_EXTBUFF_AV1_RESOLUTION_PARAM = MFX_MAKEFOURCC('A', '1', 'R', 'S'), + + /*! + See the mfxExtAV1TileParam structure for more details. + */ + MFX_EXTBUFF_AV1_TILE_PARAM = MFX_MAKEFOURCC('A', '1', 'T', 'L'), + + /*! + See the mfxExtAV1Segmentation structure for more details. + */ + MFX_EXTBUFF_AV1_SEGMENTATION = MFX_MAKEFOURCC('1', 'S', 'E', 'G'), + + /*! + See the mfxExtAV1FilmGrainParam structure for more details. + */ + 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 mfxExtTemporalLayers structure for more details. + */ + MFX_EXTBUFF_UNIVERSAL_TEMPORAL_LAYERS = MFX_MAKEFOURCC('U', 'T', 'M', 'P'), + /*! + This extended buffer defines additional encoding controls for reference list. See the mfxExtRefListCtrl structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding & decoding initialization, or + the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_UNIVERSAL_REFLIST_CTRL = MFX_EXTBUFF_AVC_REFLIST_CTRL, +#ifdef ONEVPL_EXPERIMENTAL + /*! + See the mfxExtEncodeStats structure for details. + */ + MFX_EXTBUFF_ENCODESTATS = MFX_MAKEFOURCC('E','N','S','B'), +#endif + /*! + See the mfxExtVPP3DLut structure for more details. + */ + MFX_EXTBUFF_VPP_3DLUT = MFX_MAKEFOURCC('T','D','L','T'), + + /*! + See the mfxExtAllocationHints structure for more details. + */ + MFX_EXTBUFF_ALLOCATION_HINTS = MFX_MAKEFOURCC('A','L','C','H'), + +#ifdef ONEVPL_EXPERIMENTAL + /*! + See the mfxExtVPPPercEncPrefilter structure for details. + */ + MFX_EXTBUFF_VPP_PERC_ENC_PREFILTER = MFX_MAKEFOURCC('V','P','E','F'), + /*! + See the mfxExtTuneEncodeQuality structure for details. + */ + MFX_EXTBUFF_TUNE_ENCODE_QUALITY = MFX_MAKEFOURCC('T','U','N','E'), + /*! + See the mfxExtSurfaceOpenCLImg2DExportDescription structure for more details. + */ + MFX_EXTBUFF_EXPORT_SHARING_DESC_OCL = MFX_MAKEFOURCC('E', 'O', 'C', 'L'), + /*! + See the mfxExtSurfaceD3D12Tex2DExportDescription structure for more details. + */ + MFX_EXTBUFF_EXPORT_SHARING_DESC_D3D12 = MFX_MAKEFOURCC('E', 'D', '1', '2'), + /*! + See the mfxExtSurfaceVulkanImg2DExportDescription structure for more details. + */ + MFX_EXTBUFF_EXPORT_SHARING_DESC_VULKAN = MFX_MAKEFOURCC('E', 'V', 'U', 'L'), +#endif + /*! + See the mfxExtVPPAISuperResolution structure for details. + */ + MFX_EXTBUFF_VPP_AI_SUPER_RESOLUTION = MFX_MAKEFOURCC('V','A','S','R'), + /*! + See the mfxExtVPPAIFrameInterpolation structure for details. + */ + MFX_EXTBUFF_VPP_AI_FRAME_INTERPOLATION = MFX_MAKEFOURCC('V', 'A', 'F', 'I'), + /*! + See the mfxExtQualityInfoMode structure for details. + */ + MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE = MFX_MAKEFOURCC('E', 'N', 'Q', 'M'), + /*! + See the mfxExtQualityInfoOutput structure for details. + */ + MFX_EXTBUFF_ENCODED_QUALITY_INFO_OUTPUT = MFX_MAKEFOURCC('E', 'N', 'Q', 'O'), + /*! + See the mfxExtAV1ScreenContentTools structure for details. + */ + MFX_EXTBUFF_AV1_SCREEN_CONTENT_TOOLS = MFX_MAKEFOURCC('1', 'S', 'C', 'C'), + /*! + See the mfxExtAlphaChannelEncCtrl structure for more details. + */ + MFX_EXTBUFF_ALPHA_CHANNEL_ENC_CTRL = MFX_MAKEFOURCC('A', 'C', 'E', 'C'), + /*! + See the mfxExtAlphaChannelSurface structure for more details. + */ + MFX_EXTBUFF_ALPHA_CHANNEL_SURFACE = MFX_MAKEFOURCC('A', 'C', 'S', 'F'), +#ifdef ONEVPL_EXPERIMENTAL + /*! + See the mfxExtAIEncCtrl structure for more details. + */ + MFX_EXTBUFF_AI_ENC_CTRL = MFX_MAKEFOURCC('A', 'I', 'E', 'C'), +#endif +}; + +/* VPP Conf: Do not use certain algorithms */ +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Tells the VPP not to use certain filters in pipeline. See "Configurable VPP filters" table for complete + list of configurable filters. The user can attach this structure to the mfxVideoParam structure when initializing video processing. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DONOTUSE. */ + mfxU32 NumAlg; /*!< Number of filters (algorithms) not to use */ + mfxU32* AlgList; /*!< Pointer to a list of filters (algorithms) not to use */ +} mfxExtVPPDoNotUse; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP denoise filter algorithm. + @deprecated Deprecated in API version 2.5. Use mfxExtVPPDenoise2 instead. +*/ +MFX_DEPRECATED typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DENOISE. */ + mfxU16 DenoiseFactor; /*!< Indicates the level of noise to remove. Value range of 0 to 100 (inclusive). */ +} mfxExtVPPDenoise; +MFX_PACK_END() + +/*! The mfxDenoiseMode enumerator specifies the mode of denoise. */ +typedef enum { + MFX_DENOISE_MODE_DEFAULT = 0, /*!< Default denoise mode. The library selects the most appropriate denoise mode. */ + MFX_DENOISE_MODE_VENDOR = 1000, /*!< The enumeration to separate common denoise mode above and vendor specific. */ + + MFX_DENOISE_MODE_INTEL_HVS_AUTO_BDRATE = MFX_DENOISE_MODE_VENDOR + 1, /*!< Indicates auto BD rate improvement in pre-processing before video encoding, + ignore Strength.*/ + MFX_DENOISE_MODE_INTEL_HVS_AUTO_SUBJECTIVE = MFX_DENOISE_MODE_VENDOR + 2, /*!< Indicates auto subjective quality improvement in pre-processing before video encoding, + ignore Strength.*/ + MFX_DENOISE_MODE_INTEL_HVS_AUTO_ADJUST = MFX_DENOISE_MODE_VENDOR + 3, /*!< Indicates auto adjust subjective quality in post-processing (after decoding) for video playback, + ignore Strength.*/ + MFX_DENOISE_MODE_INTEL_HVS_PRE_MANUAL = MFX_DENOISE_MODE_VENDOR + 4, /*!< Indicates manual mode for pre-processing before video encoding, + allow to adjust the denoise strength manually.*/ + MFX_DENOISE_MODE_INTEL_HVS_POST_MANUAL = MFX_DENOISE_MODE_VENDOR + 5, /*!< Indicates manual mode for post-processing for video playback, + allow to adjust the denoise strength manually.*/ +} mfxDenoiseMode; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP denoise filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DENOISE2. */ + mfxDenoiseMode Mode; /*!< Indicates the mode of denoise. mfxDenoiseMode enumerator. */ + mfxU16 Strength; /*!< Denoise strength in manual mode. Value of 0-100 (inclusive) indicates the strength of denoise. + The strength of denoise controls degree of possible changes of pixel values; the bigger the strength + the larger the change is. */ + mfxU16 reserved[15]; +} 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() + +#ifdef ONEVPL_EXPERIMENTAL +/*! The mfx3DLutInterpolationMethod enumerator specifies the 3DLUT interpolation method. */ +typedef enum { + MFX_3DLUT_INTERPOLATION_DEFAULT = 0, /*!< Default 3DLUT interpolation Method. The library selects the most appropriate 3DLUT interpolation method. */ + MFX_3DLUT_INTERPOLATION_TRILINEAR = 1, /*!< 3DLUT Trilinear interpolation method. */ + MFX_3DLUT_INTERPOLATION_TETRAHEDRAL = 2, /*!< 3DLUT Tetrahedral interpolation method. */ +} mfx3DLutInterpolationMethod; +#endif + +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.*/ + }; +#ifdef ONEVPL_EXPERIMENTAL + mfx3DLutInterpolationMethod InterpolationMethod; /*!< Indicates 3DLUT Interpolation Method. mfx3DLutInterpolationMethod enumerator.*/ + mfxU32 reserved[3]; /*!< Reserved for future extension.*/ +#else + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +#endif +} mfxExtVPP3DLut; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP detail/edge enhancement filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DETAIL. */ + mfxU16 DetailFactor; /*!< Indicates the level of details to be enhanced. Value range of 0 to 100 (inclusive). */ +} mfxExtVPPDetail; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures the VPP ProcAmp filter algorithm. + The structure parameters will be clipped to their corresponding range and rounded by their corresponding increment. + @note There are no default values for fields in this structure, all settings must be explicitly specified every time this + buffer is submitted for processing. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_PROCAMP. */ + mfxF64 Brightness; /*!< The brightness parameter is in the range of -100.0F to 100.0F, in increments of 0.1F. + Setting this field to 0.0F will disable brightness adjustment. */ + mfxF64 Contrast; /*!< The contrast parameter in the range of 0.0F to 10.0F, in increments of 0.01F, is used for manual + contrast adjustment. Setting this field to 1.0F will disable contrast adjustment. If the parameter + is negative, contrast will be adjusted automatically. */ + mfxF64 Hue; /*!< The hue parameter is in the range of -180F to 180F, in increments of 0.1F. Setting this field to 0.0F + will disable hue adjustment. */ + mfxF64 Saturation; /*!< The saturation parameter is in the range of 0.0F to 10.0F, in increments of 0.01F. + Setting this field to 1.0F will disable saturation adjustment. */ +} mfxExtVPPProcAmp; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Returns statistics collected during encoding. +*/ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; /*!< Number of encoded frames. */ + mfxU64 NumBit; /*!< Number of bits for all encoded frames. */ + mfxU32 NumCachedFrame; /*!< Number of internally cached frames. */ +} mfxEncodeStat; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Returns statistics collected during decoding. +*/ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; /*!< Number of total decoded frames. */ + mfxU32 NumSkippedFrame; /*!< Number of skipped frames. */ + mfxU32 NumError; /*!< Number of errors recovered. */ + mfxU32 NumCachedFrame; /*!< Number of internally cached frames. */ +} mfxDecodeStat; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Returns statistics collected during video processing. +*/ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; /*!< Total number of frames processed. */ + mfxU32 NumCachedFrame; /*!< Number of internally cached frames. */ +} mfxVPPStat; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Returns auxiliary data generated by the video processing pipeline. + The encoding process may use the auxiliary data by attaching this structure to the mfxEncodeCtrl structure. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_AUXDATA. */ + + union{ + struct{ + MFX_DEPRECATED mfxU32 SpatialComplexity; /* Deprecated */ + MFX_DEPRECATED mfxU32 TemporalComplexity; /* Deprecated */ + }; + struct{ + /*! + Detected picture structure - top field first, bottom field first, progressive or unknown if video processor cannot + detect picture structure. See the PicStruct enumerator for definition of these values. + + */ + mfxU16 PicStruct; + mfxU16 reserved[3]; + }; + }; + MFX_DEPRECATED mfxU16 SceneChangeRate; /* Deprecated */ + mfxU16 RepeatedFrame; /*!< The flag signalizes that the frame is identical to the previous one. */ +} mfxExtVppAuxData; +MFX_PACK_END() + +/*! The PayloadCtrlFlags enumerator itemizes additional payload properties. */ +enum { + MFX_PAYLOAD_CTRL_SUFFIX = 0x00000001 /*!< Insert this payload into HEVC Suffix SEI NAL-unit. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes user data payload in MPEG-2 or SEI message payload in H.264. + + For encoding, these payloads can be + inserted into the bitstream. The payload buffer must contain a valid formatted payload. + + For H.264, this is the sei_message() as + specified in the section 7.3.2.3.1 'Supplemental enhancement information message syntax' of the ISO/IEC 14496-10 specification. + + For MPEG-2, + this is the section 6.2.2.2.2 'User data' of the ISO/IEC 13818-2 specification, excluding the user data start_code. + + For decoding, + these payloads can be retrieved as the decoder parses the bitstream and caches them in an internal buffer. + + @internal + +-----------+-------------------------------------------+ + | **Codec** | **Supported Types** | + +===========+===========================================+ + | MPEG2 | 0x01B2 //User Data | + +-----------+-------------------------------------------+ + | AVC | 02 //pan_scan_rect | + | | 03 //filler_payload | + | | 04 //user_data_registered_itu_t_t35 | + | | 05 //user_data_unregistered | + | | 06 //recovery_point | + | | 09 //scene_info | + | | 13 //full_frame_freeze | + | | 14 //full_frame_freeze_release | + | | 15 //full_frame_snapshot | + | | 16 //progressive_refinement_segment_start | + | | 17 //progressive_refinement_segment_end | + | | 19 //film_grain_characteristics | + | | 20 //deblocking_filter_display_preference | + | | 21 //stereo_video_info | + | | 45 //frame_packing_arrangement | + +-----------+-------------------------------------------+ + | HEVC | All | + +-----------+-------------------------------------------+ + @endinternal + +*/ +typedef struct { + mfxU32 CtrlFlags; /*!< Additional payload properties. See the PayloadCtrlFlags enumerator for details. */ + mfxU32 reserved[3]; + mfxU8 *Data; /*!< Pointer to the actual payload data buffer. */ + mfxU32 NumBit; /*!< Number of bits in the payload data */ + mfxU16 Type; /*!< MPEG-2 user data start code or H.264 SEI message type. */ + mfxU16 BufSize; /*!< Payload buffer size in bytes. */ +} mfxPayload; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains parameters for per-frame based encoding control. +*/ +typedef struct { + mfxExtBuffer Header; /*!< This extension buffer doesn't have assigned buffer ID. Ignored. */ + mfxU32 reserved[4]; + mfxU16 reserved1; + /*! + Type of NAL unit that contains encoding frame. All supported values are defined by MfxNalUnitType enumerator. Other values + defined in ITU-T H.265 specification are not supported. + + The encoder uses this field only if application sets mfxExtCodingOption3::EnableNalUnitType option to ON during encoder initialization. + + @note Only encoded order is supported. If application specifies this value in display order or uses value inappropriate for current frame or + invalid value, then the encoder silently ignores it. + */ + mfxU16 MfxNalUnitType; + mfxU16 SkipFrame; /*!< Indicates that current frame should be skipped or the number of missed frames before the current frame. See mfxExtCodingOption2::SkipFrame for details. */ + + mfxU16 QP; /*!< If nonzero, this value overwrites the global QP value for the current frame in the constant QP mode. */ + + /*! + Encoding frame type. See the FrameType enumerator for details. If the encoder works in the encoded order, the application must + specify the frame type. If the encoder works in the display order, only key frames are enforceable. + */ + mfxU16 FrameType; + mfxU16 NumExtParam; /*!< Number of extra control buffers. */ + mfxU16 NumPayload; /*!< Number of payload records to insert into the bitstream. */ + mfxU16 reserved2; + + /*! + Pointer to an array of pointers to external buffers that provide additional information or control to the encoder for this + frame or field pair. A typical use is to pass the VPP auxiliary data generated by the video processing pipeline to the encoder. + See the ExtendedBufferID for the list of extended buffers. + */ + mfxExtBuffer **ExtParam; + /*! + Pointer to an array of pointers to user data (MPEG-2) or SEI messages (H.264) for insertion into the bitstream. For field pictures, + odd payloads are associated with the first field and even payloads are associated with the second field. See the mfxPayload structure + for payload definitions. + */ + mfxPayload **Payload; +} mfxEncodeCtrl; +MFX_PACK_END() + +/*! The ExtMemBufferType enumerator specifies the buffer type. It is a bit-ORed value of the following. */ +enum { + MFX_MEMTYPE_PERSISTENT_MEMORY =0x0002 /*!< Memory page for persistent use. */ +}; + +/* Frame Memory Types */ +#define MFX_MEMTYPE_BASE(x) (0x90ff & (x)) + +/*! + The ExtMemFrameType enumerator specifies the memory type of frame. It is a bit-ORed value of the following. + \verbatim embed:rst + For information on working with video memory surfaces, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim +*/ +enum { + MFX_MEMTYPE_DXVA2_DECODER_TARGET =0x0010, /*!< Frames are in video memory and belong to video decoder render targets. */ + MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET =0x0020, /*!< Frames are in video memory and belong to video processor render targets. */ + MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET = MFX_MEMTYPE_DXVA2_DECODER_TARGET, /*!< Frames are in video memory and belong to video decoder render targets. */ + MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET = MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET,/*!< Frames are in video memory and belong to video processor render targets. */ + MFX_MEMTYPE_SYSTEM_MEMORY =0x0040, /*!< The frames are in system memory. */ + MFX_MEMTYPE_RESERVED1 =0x0080, /*!< */ + + MFX_MEMTYPE_FROM_ENCODE = 0x0100, /*!< Allocation request comes from an ENCODE function */ + MFX_MEMTYPE_FROM_DECODE = 0x0200, /*!< Allocation request comes from a DECODE function */ + MFX_MEMTYPE_FROM_VPPIN = 0x0400, /*!< Allocation request comes from a VPP function for input frame allocation */ + MFX_MEMTYPE_FROM_VPPOUT = 0x0800, /*!< Allocation request comes from a VPP function for output frame allocation */ + MFX_MEMTYPE_FROM_ENC = 0x2000, /*!< Allocation request comes from an ENC function */ + MFX_MEMTYPE_FROM_PAK = 0x4000, /* Reserved */ + + MFX_MEMTYPE_INTERNAL_FRAME = 0x0001, /*!< Allocation request for internal frames */ + MFX_MEMTYPE_EXTERNAL_FRAME = 0x0002, /*!< Allocation request for I/O frames */ + MFX_MEMTYPE_EXPORT_FRAME = 0x0008, /*!< Application requests frame handle export to some associated object. For Linux frame handle can be + considered to be exported to DRM Prime FD, DRM FLink or DRM FrameBuffer Handle. Specifics of export + types and export procedure depends on external frame allocator implementation */ + MFX_MEMTYPE_SHARED_RESOURCE = MFX_MEMTYPE_EXPORT_FRAME, /*!< For DX11 allocation use shared resource bind flag. */ + MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET = 0x1000, /*!< Frames are in video memory and belong to video encoder render targets. */ + + MFX_MEMTYPE_VIDEO_MEMORY_UNORDERED_ACCESS = 0x8000 /*!< Frames are in video memory and used as an unordered access resource. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Describes multiple frame allocations when initializing encoders, decoders, and video preprocessors. + A range specifies the number of video frames. Applications are free to allocate additional frames. In all cases, the minimum number of + frames must be at least NumFrameMin or the called API function will return an error. +*/ +typedef struct { + union { + mfxU32 AllocId; /*!< Unique (within the session) ID of component requested the allocation. */ + mfxU32 reserved[1]; + }; + mfxU32 reserved3[3]; + mfxFrameInfo Info; /*!< Describes the properties of allocated frames. */ + mfxU16 Type; /*!< Allocated memory type. See the ExtMemFrameType enumerator for details. */ + mfxU16 NumFrameMin; /*!< Minimum number of allocated frames. */ + mfxU16 NumFrameSuggested; /*!< Suggested number of allocated frames. */ + mfxU16 reserved2; +} mfxFrameAllocRequest; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the response to multiple frame allocations. The calling API function returns the number of + video frames actually allocated and pointers to their memory IDs. +*/ +typedef struct { + mfxU32 AllocId; /*!< Unique (within the session) ID of component requested the allocation. */ + mfxU32 reserved[3]; + mfxMemId *mids; /*!< Pointer to the array of the returned memory IDs. The application allocates or frees this array. */ + mfxU16 NumFrameActual; /*!< Number of frames actually allocated. */ + mfxU16 reserved2; +} mfxFrameAllocResponse; +MFX_PACK_END() + +/*! The FrameType enumerator itemizes frame types. Use bit-ORed values to specify all that apply. */ +enum { + MFX_FRAMETYPE_UNKNOWN =0x0000, /*!< Frame type is unspecified. */ + + MFX_FRAMETYPE_I =0x0001, /*!< This frame or the first field is encoded as an I-frame/field. */ + MFX_FRAMETYPE_P =0x0002, /*!< This frame or the first field is encoded as an P-frame/field. */ + MFX_FRAMETYPE_B =0x0004, /*!< This frame or the first field is encoded as an B-frame/field. */ + MFX_FRAMETYPE_S =0x0008, /*!< This frame or the first field is either an SI- or SP-frame/field. */ + + MFX_FRAMETYPE_REF =0x0040, /*!< This frame or the first field is encoded as a reference. */ + MFX_FRAMETYPE_IDR =0x0080, /*!< This frame or the first field is encoded as an IDR. */ + + MFX_FRAMETYPE_xI =0x0100, /*!< The second field is encoded as an I-field. */ + MFX_FRAMETYPE_xP =0x0200, /*!< The second field is encoded as an P-field. */ + MFX_FRAMETYPE_xB =0x0400, /*!< The second field is encoded as an S-field. */ + MFX_FRAMETYPE_xS =0x0800, /*!< The second field is an SI- or SP-field. */ + + MFX_FRAMETYPE_xREF =0x4000, /*!< The second field is encoded as a reference. */ + MFX_FRAMETYPE_xIDR =0x8000 /*!< The second field is encoded as an IDR. */ +}; + +/*! + The MfxNalUnitType enumerator specifies NAL unit types supported by the HEVC encoder. +*/ +enum { + MFX_HEVC_NALU_TYPE_UNKNOWN = 0, /*!< The encoder will decide what NAL unit type to use. */ + MFX_HEVC_NALU_TYPE_TRAIL_N = ( 0+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_TRAIL_R = ( 1+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RADL_N = ( 6+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RADL_R = ( 7+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RASL_N = ( 8+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RASL_R = ( 9+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_IDR_W_RADL = (19+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_IDR_N_LP = (20+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_CRA_NUT = (21+1) /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ +}; + +/*! The mfxSkipMode enumerator describes the decoder skip-mode options. */ +typedef enum { + MFX_SKIPMODE_NOSKIP=0, /*! Do not skip any frames. */ + MFX_SKIPMODE_MORE=1, /*! Skip more frames. */ + MFX_SKIPMODE_LESS=2 /*! Skip less frames. */ +} mfxSkipMode; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Attach this structure as part of the extended buffers to configure the encoder during MFXVideoENCODE_Init. The sequence or picture + parameters specified by this structure overwrite any parameters specified by the structure or any other attached extended buffers attached. + + For H.264, SPSBuffer and PPSBuffer must point to valid bitstreams that contain the sequence parameter set and picture parameter set, + respectively. + + For MPEG-2, SPSBuffer must point to valid bitstreams that contain the sequence header followed by any sequence header extension. The PPSBuffer pointer is ignored. + + The encoder imports parameters from these buffers. If the encoder does not support the specified parameters, + the encoder does not initialize and returns the status code MFX_ERR_INCOMPATIBLE_VIDEO_PARAM. + + Check with the MFXVideoENCODE_Query function for the support of this multiple segment encoding feature. If this feature is not supported, + the query returns MFX_ERR_UNSUPPORTED. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION_SPSPPS. */ + mfxU8 *SPSBuffer; /*!< Pointer to a valid bitstream that contains the SPS (sequence parameter set for H.264 or sequence header + followed by any sequence header extension for MPEG-2) buffer. Can be NULL to skip specifying the SPS. */ + mfxU8 *PPSBuffer; /*!< Pointer to a valid bitstream that contains the PPS (picture parameter set for H.264 or picture header + followed by any picture header extension for MPEG-2) buffer. Can be NULL to skip specifying the PPS. */ + mfxU16 SPSBufSize; /*!< Size of the SPS in bytes. */ + mfxU16 PPSBufSize; /*!< Size of the PPS in bytes. */ + mfxU16 SPSId; /*!< SPS identifier. The value is reserved and must be zero. */ + mfxU16 PPSId; /*!< PPS identifier. The value is reserved and must be zero. */ +} mfxExtCodingOptionSPSPPS; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Attach this structure as part of the extended buffers to configure the encoder during MFXVideoENCODE_Init. The sequence or picture + parameters specified by this structure overwrite any parameters specified by the structure or any other attached extended buffers attached. + + If the encoder does not support the specified parameters, the encoder does not initialize and returns the status code + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM. + + Check with the MFXVideoENCODE_Query function for the support of this multiple segment encoding feature. If this feature is not supported, + the query returns MFX_ERR_UNSUPPORTED. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION_VPS. */ + + union { + mfxU8 *VPSBuffer; /*!< Pointer to a valid bitstream that contains the VPS (video parameter set for HEVC) buffer. */ + mfxU64 reserved1; + }; + mfxU16 VPSBufSize; /*!< Size of the VPS in bytes. */ + mfxU16 VPSId; /*!< VPS identifier; the value is reserved and must be zero. */ + + mfxU16 reserved[6]; +} mfxExtCodingOptionVPS; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Defines the video signal information. + + For H.264, see Annex E of the ISO/IEC 14496-10 specification for the definition of these parameters. + + For MPEG-2, see section 6.3.6 of the ITU* H.262 specification for the definition of these parameters. The field VideoFullRange is ignored. + + For VC-1, see section 6.1.14.5 of the SMPTE* 421M specification. The fields VideoFormat and VideoFullRange are ignored. + + @note If ColourDescriptionPresent is zero, the color description information (including ColourPrimaries, TransferCharacteristics, + and MatrixCoefficients) does not present in the bitstream. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VIDEO_SIGNAL_INFO. */ + mfxU16 VideoFormat; + mfxU16 VideoFullRange; + mfxU16 ColourDescriptionPresent; + mfxU16 ColourPrimaries; + mfxU16 TransferCharacteristics; + mfxU16 MatrixCoefficients; +} mfxExtVideoSignalInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Tells the VPP to include certain filters in the pipeline. + + 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. + + @li Attaching a filter configuration structure directly to the mfxVideoParam structure. + 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. + + The user can attach this structure to the mfxVideoParam structure when initializing video processing. + + @note MFX_EXTBUFF_VPP_COMPOSITE cannot be enabled using mfxExtVPPDoUse because default parameters are undefined for this filter. + The application must attach the appropriate filter configuration structure directly to the mfxVideoParam structure to enable it. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DOUSE. */ + mfxU32 NumAlg; /*!< Number of filters (algorithms) to use */ + mfxU32 *AlgList; /*!< Pointer to a list of filters (algorithms) to use */ +} mfxExtVPPDoUse; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures reference frame options for the H.264 encoder. + \verbatim embed:rst + See the :ref:`Reference List Selection ` and :ref:`Long Term Reference Frame ` sections for more details. + \endverbatim + + + @note Not all implementations of the encoder support LongTermIdx and ApplyLongTermIdx fields in this structure. The application must use + query mode 1 to determine if such functionality is supported. To do this, the application must attach this extended buffer to the + mfxVideoParam structure and call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE and these fields were set to non-zero value, + then the functionality is supported. If the function fails or sets fields to zero, then the functionality is not supported. + +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_REFLIST_CTRL. */ + mfxU16 NumRefIdxL0Active; /*!< Specify the number of reference frames in the active reference list L0. This number should be less or equal to the NumRefFrame parameter from encoding initialization. */ + mfxU16 NumRefIdxL1Active; /*!< Specify the number of reference frames in the active reference list L1. This number should be less or equal to the NumRefFrame parameter from encoding initialization. */ + + struct { + /*! @{ + @name Reference Lists + The following structure members are used by the reference lists contained in the parent structure. */ + mfxU32 FrameOrder; /*!< Together FrameOrder and PicStruct fields are used to identify reference picture. Use FrameOrder = MFX_FRAMEORDER_UNKNOWN to mark unused entry. */ + mfxU16 PicStruct; /*!< Together FrameOrder and PicStruct fields are used to identify reference picture. Use FrameOrder = MFX_FRAMEORDER_UNKNOWN to mark unused entry. */ + mfxU16 ViewId; /*!< Reserved and must be zero. */ + mfxU16 LongTermIdx; /*!< Index that should be used by the encoder to mark long-term reference frame. */ + mfxU16 reserved[3]; /*!< Reserved */ + /*! @} */ + } PreferredRefList[32], /*!< Reference list that specifies the list of frames that should be used to predict the current frame. */ + RejectedRefList[16], /*!< Reference list that specifies the list of frames that should not be used for prediction. */ + LongTermRefList[16]; /*!< Reference list that specifies the list of frames that should be marked as long-term reference frame. */ + + mfxU16 ApplyLongTermIdx;/*!< If it is equal to zero, the encoder assigns long-term index according to internal algorithm. + If it is equal to one, the encoder uses LongTermIdx value as long-term index. */ + mfxU16 reserved[15]; +} mfxExtAVCRefListCtrl; +MFX_PACK_END() + +/*! The FrcAlgm enumerator itemizes frame rate conversion algorithms. See description of mfxExtVPPFrameRateConversion structure for more details. */ +enum { + MFX_FRCALGM_PRESERVE_TIMESTAMP = 0x0001, /*!< Frame dropping/repetition based frame rate conversion algorithm with preserved original + time stamps. Any inserted frames will carry MFX_TIMESTAMP_UNKNOWN. */ + MFX_FRCALGM_DISTRIBUTED_TIMESTAMP = 0x0002, /*!< Frame dropping/repetition based frame rate conversion algorithm with distributed time stamps. + The algorithm distributes output time stamps evenly according to the output frame rate. */ + MFX_FRCALGM_FRAME_INTERPOLATION = 0x0004, /*!< Frame rate conversion algorithm based on frame interpolation. This flag may be combined with + MFX_FRCALGM_PRESERVE_TIMESTAMP or MFX_FRCALGM_DISTRIBUTED_TIMESTAMP flags. */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_FRCALGM_AI_FRAME_INTERPOLATION = 0x0008 /*!< Frame rate conversion algorithm based on AI powered frame interpolation. This flag may be combined with + MFX_FRCALGM_PRESERVE_TIMESTAMP or MFX_FRCALGM_DISTRIBUTED_TIMESTAMP flags. This flag can not be combined + with MFX_FRCALGM_FRAME_INTERPOLATION. If application sets this flag, the application needs to attach + MFX_EXTBUFF_VPP_AI_FRAME_INTERPOLATION for the details of frame interpolation to mfxVideoParam. Refer to + mfxExtVPPAIFrameInterpolation for more details.*/ +#endif +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP frame rate conversion filter. The user can attach this structure to the + mfxVideoParam structure when initializing, resetting, or querying capability of video processing. + + On some platforms the advanced frame rate conversion algorithm (the algorithm based on frame interpolation) is not supported. To query its support, + the application should add the MFX_FRCALGM_FRAME_INTERPOLATION flag to the Algorithm value in the mfxExtVPPFrameRateConversion structure, attach it to the + structure, and call the MFXVideoVPP_Query function. If the filter is supported, the function returns a MFX_ERR_NONE status and copies the content of the + input structure to the output structure. If an advanced filter is not supported, then a simple filter will be used and the function returns + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, copies content of the input structure to the output structure, and corrects the Algorithm value. + + If advanced FRC algorithm is not supported, both MFXVideoVPP_Init and MFXVideoVPP_Reset functions return the MFX_WRN_INCOMPATIBLE_VIDEO_PARAM status. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION. */ + mfxU16 Algorithm; /*!< See the FrcAlgm enumerator for a list of frame rate conversion algorithms. */ + mfxU16 reserved; + mfxU32 reserved2[15]; +} mfxExtVPPFrameRateConversion; +MFX_PACK_END() + +/*! The ImageStabMode enumerator itemizes image stabilization modes. See description of mfxExtVPPImageStab structure for more details. */ +enum { + MFX_IMAGESTAB_MODE_UPSCALE = 0x0001, /*!< Upscale mode. */ + MFX_IMAGESTAB_MODE_BOXING = 0x0002 /*!< Boxing mode. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP image stabilization filter. + + 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. + + 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 + filter from the mfxExtVPPDoUse structure, and zeroes the mfxExtVPPImageStab structure. + + If the image stabilization filter is not supported, both MFXVideoVPP_Init and MFXVideoVPP_Reset functions return a MFX_WRN_FILTER_SKIPPED status. + + The application can retrieve the list of active filters by attaching the mfxExtVPPDoUse structure to the mfxVideoParam structure and calling the + MFXVideoVPP_GetVideoParam function. The application must allocate enough memory for the filter list. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_IMAGE_STABILIZATION. */ + mfxU16 Mode; /*!< Image stabilization mode. See ImageStabMode enumerator for values. */ + mfxU16 reserved[11]; +} mfxExtVPPImageStab; +MFX_PACK_END() + + +/*! + The InsertHDRPayload enumerator itemizes HDR payloads insertion rules in the encoder, + and indicates if there is valid HDR information in the clip in the decoder. +*/ +enum { + MFX_PAYLOAD_OFF = 0, /*!< Do not insert payload when encoding; + Clip does not have valid HDR information when decoding. */ + MFX_PAYLOAD_IDR = 1 /*!< Insert payload on IDR frames when encoding; + Clip has valid HDR information when decoding. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Handle the HDR information. + + During encoding: If the application attaches this structure to the mfxEncodeCtrl structure at runtime, + the encoder inserts the HDR information 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 information based on InsertPayloadToggle. + + During video processing: If the application attaches this structure for video processing, InsertPayloadToggle will be ignored. + And DisplayPrimariesX[3], DisplayPrimariesY[3] specify the color primaries where 0,1,2 specifies Red, Green, Blue respectively. + + During decoding: If the application attaches this structure to the mfxFrameSurface1 structure at runtime + which will seed to the MFXVideoDECODE_DecodeFrameAsync() as surface_work parameter, + the decoder will parse the HDR information if the bitstream include HDR information per frame. + The parsed HDR information will be attached to the ExtendBuffer of surface_out parameter of MFXVideoDECODE_DecodeFrameAsync() + with flag `InsertPayloadToggle` to indicate if there is valid HDR information in the clip. + `InsertPayloadToggle` will be set to `MFX_PAYLOAD_IDR` if oneAPI Video Processing Library (oneVPL) gets valid HDR information, otherwise it will be set + to `MFX_PAYLOAD_OFF`. + This function is support for HEVC and AV1 only now. + + Encoding or Decoding, Field semantics are defined in ITU-T* H.265 Annex D, AV1 6.7.4 Metadata OBU semantics. + + Video processing, `DisplayPrimariesX[3]` and `WhitePointX` are in increments of 0.00002, in the range of [5, 37000]. `DisplayPrimariesY[3]` + and `WhitePointY` are in increments of 0.00002, in the range of [5, 42000]. `MaxDisplayMasteringLuminance` is in units of 1 candela per square meter. + `MinDisplayMasteringLuminance` is in units of 0.0001 candela per square meter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME. */ + mfxU16 reserved[15]; + + mfxU16 InsertPayloadToggle; /*!< InsertHDRPayload enumerator value. */ + mfxU16 DisplayPrimariesX[3]; /*!< Color primaries for a video source. Consist of RGB x coordinates and + define how to convert colors from RGB color space to CIE XYZ color space. */ + mfxU16 DisplayPrimariesY[3]; /*!< Color primaries for a video source. Consists of RGB y coordinates and + defines how to convert colors from RGB color space to CIE XYZ color space.*/ + mfxU16 WhitePointX; /*!< White point X coordinate. */ + mfxU16 WhitePointY; /*!< White point Y coordinate. */ + mfxU32 MaxDisplayMasteringLuminance; /*!< Specify maximum luminance of the display on which the content was authored.*/ + mfxU32 MinDisplayMasteringLuminance; /*!< Specify minimum luminance of the display on which the content was authored. */ +} mfxExtMasteringDisplayColourVolume; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Handle the HDR information. + + During encoding: If the application attaches this structure to the mfxEncodeCtrl structure at runtime, + the encoder inserts the HDR information 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 information based on InsertPayloadToggle. + + During video processing: If the application attaches this structure for video processing, InsertPayloadToggle will be ignored. + + During decoding: If the application attaches this structure to the mfxFrameSurface1 structure at runtime + which will seed to the MFXVideoDECODE_DecodeFrameAsync() as surface_work parameter, + the decoder will parse the HDR information if the bitstream include HDR information per frame. + The parsed HDR information will be attached to the ExtendBuffer of surface_out parameter of MFXVideoDECODE_DecodeFrameAsync() + with flag `InsertPayloadToggle` to indicate if there is valid HDR information in the clip. + `InsertPayloadToggle` will be set to `MFX_PAYLOAD_IDR` if oneVPL gets valid HDR information, otherwise it will be set to `MFX_PAYLOAD_OFF`. + This function is support for HEVC and AV1 only now. + + Field semantics are defined in ITU-T* H.265 Annex D, AV1 6.7.3 Metadata high dynamic range content light level semantics. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to EXTBUFF_CONTENT_LIGHT_LEVEL_INFO. */ + mfxU16 reserved[9]; + + mfxU16 InsertPayloadToggle; /*!< InsertHDRPayload enumerator value. */ + mfxU16 MaxContentLightLevel; /*!< Maximum luminance level of the content. Field range is 1 to 65535. */ + mfxU16 MaxPicAverageLightLevel; /*!< Maximum average per-frame luminance level of the content. Field range is 1 to 65535. */ +} mfxExtContentLightLevelInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the H.264 picture timing SEI message. The encoder ignores it if HRD information in + the stream is absent and the PicTimingSEI option in the mfxExtCodingOption structure is turned off. See mfxExtCodingOption for details. + + If the application attaches this structure to the mfxVideoParam structure during initialization, the encoder inserts the picture timing + SEI message based on provided template in every access unit of coded bitstream. + + If application attaches this structure to the mfxEncodeCtrl structure at runtime, the encoder inserts the picture timing SEI message + based on provided template in access unit that represents current frame. + + These parameters define the picture timing information. An invalid value of 0xFFFF indicates that application does not set the value and + encoder must calculate it. + + See Annex D of the ISO*\/IEC* 14496-10 specification for the definition of these parameters. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_PICTURE_TIMING_SEI. */ + mfxU32 reserved[14]; + + struct { + mfxU16 ClockTimestampFlag; + mfxU16 CtType; + mfxU16 NuitFieldBasedFlag; + mfxU16 CountingType; + mfxU16 FullTimestampFlag; + mfxU16 DiscontinuityFlag; + mfxU16 CntDroppedFlag; + mfxU16 NFrames; + mfxU16 SecondsFlag; + mfxU16 MinutesFlag; + mfxU16 HoursFlag; + mfxU16 SecondsValue; + mfxU16 MinutesValue; + mfxU16 HoursValue; + mfxU32 TimeOffset; + } TimeStamp[3]; +} mfxExtPictureTimingSEI; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the H.264 temporal layers hierarchy. + + If the application attaches it to the mfxVideoParam + structure during initialization, the encoder generates the temporal layers and inserts the prefix NAL unit before each slice to + indicate the temporal and priority IDs of the layer. + + This structure can be used with the display-order encoding mode only. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_TEMPORAL_LAYERS. */ + mfxU32 reserved1[4]; + mfxU16 reserved2; + mfxU16 BaseLayerPID; /*!< The priority ID of the base layer. The encoder increases the ID for each temporal layer and writes to the prefix NAL unit. */ + + struct { + mfxU16 Scale; /*!< The ratio between the frame rates of the current temporal layer and the base layer. */ + mfxU16 reserved[3]; + }Layer[8]; +} mfxExtAvcTemporalLayers; /*!< The array of temporal layers; Use Scale=0 to specify absent layers. */ +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to retrieve encoder capability. See the description of mode 4 of the MFXVideoENCODE_Query function + for details on how to use this structure. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine + if the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_CAPABILITY. */ + + mfxU32 MBPerSec; /*!< Specify the maximum processing rate in macro blocks per second. */ + mfxU16 reserved[58]; +} mfxExtEncoderCapability; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to control the encoder behavior during reset. By using this structure, the application + instructs the encoder to start a new coded sequence after reset or to continue encoding of the current sequence. + + This structure is also used in mode 3 of the MFXVideoENCODE_Query function to check for reset outcome before actual reset. The application + should set StartNewSequence to the required behavior and call the query function. If the query fails (see status codes below), then reset is not + possible in current encoder state. If the application sets StartNewSequence to MFX_CODINGOPTION_UNKNOWN, then the query function replaces the coding option with the + actual reset type: MFX_CODINGOPTION_ON if the encoder will begin a new sequence after reset or MFX_CODINGOPTION_OFF if the encoder will continue the current sequence. + + Using this structure may cause one of the following status codes from the MFXVideoENCODE_Reset and MFXVideoENCODE_Queryfunctions: + + @li MFX_ERR_INVALID_VIDEO_PARAM If a reset is not possible. For example, the application sets StartNewSequence to off and requests resolution change. + + @li MFX_ERR_INCOMPATIBLE_VIDEO_PARAM If the application requests change that leads to memory allocation. For example, the application sets StartNewSequence to on and + requests resolution change to greater than the initialization value. + + @li MFX_ERR_NONE If reset is possible. + + The following limited list of parameters can be changed without starting a new coded sequence: + + @li The bitrate parameters, TargetKbps and MaxKbps, in the mfxInfoMFX structure. + + @li The number of slices, NumSlice, in the mfxInfoMFX structure. Number of slices should be equal to or less than the number of slices during initialization. + + @li The number of temporal layers in the mfxExtAvcTemporalLayers structure. Reset should be called immediately before encoding of frame from base layer and + number of reference frames should be large enough for the new temporal layers structure. + + @li The quantization parameters, QPI, QPP and QPB, in the mfxInfoMFX structure. + + The application should retrieve all cached frames before calling reset. When the Query API function + checks for reset outcome, it expects that this requirement be satisfied. If it is not true and there are some cached frames inside the + encoder, then the query result may differ from the reset result, because the encoder may insert an IDR frame to produce valid coded sequence. + \verbatim embed:rst + See the :ref:`Configuration Change ` section for more information. + \endverbatim + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if the + functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and call the + MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE, then the functionality is supported. + + \verbatim embed:rst + See the :ref:`Streaming and Video Conferencing Features ` section for more information. + \endverbatim + +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_RESET_OPTION. */ + + /*! + Instructs encoder to start new sequence after reset. Use one of the CodingOptionValue options: + + @li MFX_CODINGOPTION_ON The encoder completely reset internal state and begins new coded sequence after reset, including + insertion of IDR frame, sequence, and picture headers. + + @li MFX_CODINGOPTION_OFF The encoder continues encoding of current coded sequence after reset, without insertion of IDR frame. + + @li MFX_CODINGOPTION_UNKNOWN Depending on the current encoder state and changes in configuration parameters, the encoder may or may not + start new coded sequence. This value is also used to query reset outcome. + */ + mfxU16 StartNewSequence; + mfxU16 reserved[11]; +} mfxExtEncoderResetOption; +MFX_PACK_END() + +/*! The LongTermIdx specifies long term index of picture control. */ +enum { + MFX_LONGTERM_IDX_NO_IDX = 0xFFFF /*!< Long term index of picture is undefined. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to report additional information about the encoded picture. The application can attach + this buffer to the mfxBitstream structure before calling MFXVideoENCODE_EncodeFrameAsync function. For interlaced content the encoder + requires two such structures. They correspond to fields in encoded order. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_FRAME_INFO. */ + + mfxU32 FrameOrder; /*!< Frame order of encoded picture. */ + mfxU16 PicStruct; /*!< Picture structure of encoded picture. */ + mfxU16 LongTermIdx; /*!< Long term index of encoded picture if applicable. */ + mfxU32 MAD; /*!< Mean Absolute Difference between original pixels of the frame and motion compensated (for inter macroblocks) or + spatially predicted (for intra macroblocks) pixels. Only luma component, Y plane, is used in calculation. */ + mfxU16 BRCPanicMode; /*!< Bitrate control was not able to allocate enough bits for this frame. Frame quality may be unacceptably low. */ + mfxU16 QP; /*!< Luma QP. */ + mfxU32 SecondFieldOffset; /*!< Offset to second field. Second field starts at mfxBitstream::Data + mfxBitstream::DataOffset + mfxExtAVCEncodedFrameInfo::SecondFieldOffset. */ + mfxU16 reserved[2]; + + struct { + /*! @{ + @name Reference Lists + The following structure members are used by the reference lists contained in the parent structure. */ + mfxU32 FrameOrder; /*!< Frame order of reference picture. */ + mfxU16 PicStruct; /*!< Picture structure of reference picture. */ + mfxU16 LongTermIdx; /*!< Long term index of reference picture if applicable. */ + mfxU16 reserved[4]; + /*! @} */ + } UsedRefListL0[32], /*!< Reference list that has been used to encode picture. */ + UsedRefListL1[32]; /*!< Reference list that has been used to encode picture. */ +} mfxExtAVCEncodedFrameInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to specify input stream details for composition of several input surfaces in the one output. +*/ +typedef struct mfxVPPCompInputStream { + mfxU32 DstX; /*!< X coordinate of location of input stream in output surface. */ + mfxU32 DstY; /*!< Y coordinate of location of input stream in output surface. */ + mfxU32 DstW; /*!< Width of of location of input stream in output surface.*/ + mfxU32 DstH; /*!< Height of of location of input stream in output surface.*/ + + mfxU16 LumaKeyEnable; /*!< Non-zero value enables luma keying for the input stream. Luma keying is used to mark some of the areas + of the frame with specified luma values as transparent. It may, for example, be used for closed captioning. */ + mfxU16 LumaKeyMin; /*!< Minimum value of luma key, inclusive. Pixels whose luma values fit in this range are rendered transparent. */ + mfxU16 LumaKeyMax; /*!< Maximum value of luma key, inclusive. Pixels whose luma values fit in this range are rendered transparent. */ + + mfxU16 GlobalAlphaEnable; /*!< Non-zero value enables global alpha blending for this input stream. */ + mfxU16 GlobalAlpha; /*!< Alpha value for this stream. Should be in the range of 0 to 255, where 0 is transparent and 255 is opaque. */ + mfxU16 PixelAlphaEnable; /*!< Non-zero value enables per pixel alpha blending for this input stream. The stream should have RGB color format. */ + + mfxU16 TileId; /*!< Specify the tile this video stream is assigned to. Should be in the range of 0 to NumTiles. Valid only if NumTiles > 0. */ + + mfxU16 reserved2[17]; +} mfxVPPCompInputStream; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Used to control composition of several input surfaces in one output. In this mode, the VPP skips + any other filters. The VPP returns an error if any mandatory filter is specified and returns the filter skipped warning if an optional filter is specified. The only + supported filters are deinterlacing and interlaced scaling. The only supported combinations of input and output color formats are: + + - RGB to RGB, + + - NV12 to NV12, + + - RGB and NV12 to NV12, for per the pixel alpha blending use case. + + The VPP returns MFX_ERR_MORE_DATA for additional input until an output is ready. When the output is ready, the VPP returns MFX_ERR_NONE. + The application must process the output frame after synchronization. + + The composition process is controlled by: + + - mfxFrameInfo::CropXYWH in the input surface defines the location of the picture in the input frame. + + - InputStream[i].DstXYWH defines the location of the cropped input picture in the output frame. + + - mfxFrameInfo::CropXYWH in the output surface defines the actual part of the output frame. All pixels in the output frame outside this region will be filled by the specified color. + + If the application uses the composition process on video streams with different frame sizes, the application should provide maximum frame size in the + mfxVideoParam structure during the initialization, reset, or query operations. + + If the application uses the composition process, the MFXVideoVPP_QueryIOSurf function returns the cumulative number of input surfaces, that is, the number + required to process all input video streams. The function sets the frame size in the mfxFrameAllocRequest equal to the size provided by the + application in the mfxVideoParam structure. + + The composition process supports all types of surfaces. + + All input surfaces should have the same type and color format, except for the per pixel alpha blending case, where it is allowable to mix NV12 and RGB + surfaces. + + There are three different blending use cases: + + - Luma keying. All input surfaces should have the NV12 color format specified during VPP initialization. Part of each surface, including the + first one, may be rendered transparent by using LumaKeyEnable, LumaKeyMin, and LumaKeyMax values. + + - Global alpha blending. All input surfaces should have the same color format, NV12 or RGB, specified during VPP initialization. Each input surface, including the first one, can be blended with underlying surfaces by using GlobalAlphaEnable and + GlobalAlpha values. + + - Per-pixel alpha blending. It is allowed to mix NV12 and RGB input surfaces. Each RGB input surface, including the first one, + can be blended with underlying surfaces by using PixelAlphaEnable value. + + It is not allowed to mix different blending use cases in the same function call. + + In the special case where the destination region of the output surface defined by output crops is fully covered with destination sub-regions of the + surfaces, the fast compositing mode can be enabled. The main use case for this mode is a video-wall scenario with a fixed destination surface + partition into sub-regions of potentially different size. + + In order to trigger this mode, the application must cluster input surfaces into tiles, defining at least one tile by setting the NumTiles + field to be greater than 0, and assigning surfaces to the corresponding tiles by setting the TileId field to the value within the 0 to NumTiles range per + input surface. Tiles should also satisfy the following additional constraints: + + - Each tile should not have more than 8 surfaces assigned to it. + + - Tile bounding boxes, as defined by the enclosing rectangles of a union of a surfaces assigned to this tile, should not intersect. + + Background color may be changed dynamically through Reset. There is no default value. YUV black is (0;128;128) or (16;128;128) depending + on the sample range. The library uses a YUV or RGB triple depending on output color format. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_COMPOSITE. */ + + /* background color*/ + union { + mfxU16 Y; /*!< Y value of the background color. */ + mfxU16 R; /*!< R value of the background color. */ + }; + union { + mfxU16 U; /*!< U value of the background color. */ + mfxU16 G; /*!< G value of the background color. */ + }; + union { + mfxU16 V; /*!< V value of the background color. */ + mfxU16 B; /*!< B value of the background color. */ + }; + mfxU16 NumTiles; /*!< Number of input surface clusters grouped together to enable fast compositing. May be changed dynamically + at runtime through Reset. */ + mfxU16 reserved1[23]; + + mfxU16 NumInputStream; /*!< Number of input surfaces to compose one output. May be changed dynamically at runtime through Reset. Number of surfaces + can be decreased or increased, but should not exceed the number specified during initialization. Query mode 2 should be used + to find the maximum supported number. */ + mfxVPPCompInputStream *InputStream; /*!< An array of mfxVPPCompInputStream structures that describe composition of input video streams. It should consist of exactly NumInputStream elements. */ +} mfxExtVPPComposite; +MFX_PACK_END() + +/*! The TransferMatrix enumerator itemizes color transfer matrices. */ +enum { + MFX_TRANSFERMATRIX_UNKNOWN = 0, /*!< Transfer matrix is not specified */ + MFX_TRANSFERMATRIX_BT709 = 1, /*!< Transfer matrix from ITU-R BT.709 standard. */ + MFX_TRANSFERMATRIX_BT601 = 2 /*!< Transfer matrix from ITU-R BT.601 standard. */ +}; + +/*! The NominalRange enumerator itemizes pixel's value nominal range. */ +enum { + MFX_NOMINALRANGE_UNKNOWN = 0, /*!< Range is not defined. */ + MFX_NOMINALRANGE_0_255 = 1, /*!< Range is from 0 to 255. */ + MFX_NOMINALRANGE_16_235 = 2 /*!< Range is from 16 to 235. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to control transfer matrix and nominal range of YUV frames. The application + should provide this during initialization. Supported for multiple conversions, for example YUV to YUV, YUV to RGB, and RGB to YUV. + + @note This structure is used by VPP only and is not compatible with mfxExtVideoSignalInfo. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO. */ + mfxU16 reserved1[4]; + + union { + struct { // Init + struct { + mfxU16 TransferMatrix; /*!< Transfer matrix. */ + mfxU16 NominalRange; /*!< Nominal range. */ + mfxU16 reserved2[6]; + } In, Out; + }; + struct { // Runtime< + mfxU16 TransferMatrix; /*!< Transfer matrix. */ + mfxU16 NominalRange; /*!< Nominal range. */ + mfxU16 reserved3[14]; + }; + }; +} mfxExtVPPVideoSignalInfo; +MFX_PACK_END() + +/*! The ROImode enumerator itemizes QP adjustment mode for ROIs. */ +enum { + MFX_ROI_MODE_PRIORITY = 0, /*!< Priority mode. */ + MFX_ROI_MODE_QP_DELTA = 1, /*!< QP mode */ + MFX_ROI_MODE_QP_VALUE = 2 /*!< Absolute QP */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify different Region Of Interests during encoding. It may be used at + initialization or at runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_ROI. */ + + mfxU16 NumROI; /*!< Number of ROI descriptions in array. The Query API function mode 2 returns maximum supported value (set it to 256 and + query will update it to maximum supported value). */ + mfxU16 ROIMode; /*!< QP adjustment mode for ROIs. Defines if Priority or DeltaQP is used during encoding. */ + mfxU16 reserved1[10]; + + struct { + /*! @{ + @name ROI location rectangle + The ROI rectangle definition uses end-point exclusive notation. In other words, the pixel with (Right, Bottom) + coordinates lies immediately outside of the ROI. Left, Top, Right, Bottom should be aligned by codec-specific block boundaries + (should be dividable by 16 for AVC, or by 32 for HEVC). Every ROI with unaligned coordinates will be expanded by the library to minimal-area + block-aligned ROI, enclosing the original one. For example (5, 5, 15, 31) ROI will be expanded to (0, 0, 16, 32) for AVC encoder, + or to (0, 0, 32, 32) for HEVC. + */ + mfxU32 Left; /*!< Left ROI's coordinate. */ + mfxU32 Top; /*!< Top ROI's coordinate. */ + mfxU32 Right; /*!< Right ROI's coordinate. */ + mfxU32 Bottom; /*!< Bottom ROI's coordinate. */ + union { + /*! Priority of ROI. Used if ROIMode = MFX_ROI_MODE_PRIORITY.This is an absolute value in the range of -3 to 3, + which will be added to the MB QP. Priority is deprecated mode and is used only for backward compatibility. + Bigger value produces better quality. */ + mfxI16 Priority; + /*! Delta QP of ROI. Used if ROIMode = MFX_ROI_MODE_QP_DELTA. This is an absolute value in the range of -51 to 51, + which will be added to the MB QP. Lesser value produces better quality. */ + mfxI16 DeltaQP; + }; + mfxU16 reserved2[7]; + /*! @} */ + } ROI[256]; /*!< Array of ROIs. Different ROI may overlap each other. If macroblock belongs to several ROI, + Priority from ROI with lowest index is used. */ +} mfxExtEncoderROI; +MFX_PACK_END() + +/*! The DeinterlacingMode enumerator itemizes VPP deinterlacing modes. */ +enum { + MFX_DEINTERLACING_BOB = 1, /*!< BOB deinterlacing mode. */ + MFX_DEINTERLACING_ADVANCED = 2, /*!< Advanced deinterlacing mode. */ + MFX_DEINTERLACING_AUTO_DOUBLE = 3, /*!< Auto mode with deinterlacing double frame rate output. */ + MFX_DEINTERLACING_AUTO_SINGLE = 4, /*!< Auto mode with deinterlacing single frame rate output. */ + MFX_DEINTERLACING_FULL_FR_OUT = 5, /*!< Deinterlace only mode with full frame rate output. */ + MFX_DEINTERLACING_HALF_FR_OUT = 6, /*!< Deinterlace only Mode with half frame rate output. */ + MFX_DEINTERLACING_24FPS_OUT = 7, /*!< 24 fps fixed output mode. */ + MFX_DEINTERLACING_FIXED_TELECINE_PATTERN = 8, /*!< Fixed telecine pattern removal mode. */ + MFX_DEINTERLACING_30FPS_OUT = 9, /*!< 30 fps fixed output mode. */ + MFX_DEINTERLACING_DETECT_INTERLACE = 10, /*!< Only interlace detection. */ + MFX_DEINTERLACING_ADVANCED_NOREF = 11, /*!< Advanced deinterlacing mode without using of reference frames. */ + MFX_DEINTERLACING_ADVANCED_SCD = 12, /*!< Advanced deinterlacing mode with scene change detection. */ + MFX_DEINTERLACING_FIELD_WEAVING = 13 /*!< Field weaving. */ +}; + +/*! The TelecinePattern enumerator itemizes telecine patterns. */ +enum { + MFX_TELECINE_PATTERN_32 = 0, /*!< 3:2 telecine. */ + MFX_TELECINE_PATTERN_2332 = 1, /*!< 2:3:3:2 telecine. */ + MFX_TELECINE_PATTERN_FRAME_REPEAT = 2, /*!< One frame repeat telecine. */ + MFX_TELECINE_PATTERN_41 = 3, /*!< 4:1 telecine. */ + MFX_TELECINE_POSITION_PROVIDED = 4 /*!< User must provide position inside a sequence of 5 frames where the artifacts start. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify different deinterlacing algorithms. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DEINTERLACING. */ + mfxU16 Mode; /*!< Deinterlacing algorithm. See the DeinterlacingMode enumerator for details. */ + mfxU16 TelecinePattern; /*!< Specifies telecine pattern when Mode = MFX_DEINTERLACING_FIXED_TELECINE_PATTERN. See the TelecinePattern enumerator for details.*/ + mfxU16 TelecineLocation; /*!< Specifies position inside a sequence of 5 frames where the artifacts start when TelecinePattern = MFX_TELECINE_POSITION_PROVIDED*/ + mfxU16 reserved[9]; /*!< Reserved for future use. */ +} mfxExtVPPDeinterlacing; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies reference lists for the encoder. It may be used together with the mfxExtAVCRefListCtrl + structure to create customized reference lists. If both structures are used together, then the encoder takes reference lists from the + mfxExtAVCRefLists structure and modifies them according to the mfxExtAVCRefListCtrl instructions. In case of interlaced coding, + the first mfxExtAVCRefLists structure affects TOP field and the second - BOTTOM field. + + @note Not all implementations of the encoder support this structure. The application must use the Query API function to determine if it is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_REFLISTS. */ + mfxU16 NumRefIdxL0Active; /*!< Specify the number of reference frames in the active reference list L0. This number should be less than or + equal to the NumRefFrame parameter from encoding initialization. */ + mfxU16 NumRefIdxL1Active; /*!< Specify the number of reference frames in the active reference list L1. This number should be less than or + equal to the NumRefFrame parameter from encoding initialization. */ + mfxU16 reserved[2]; + + /*! Used by the reference lists contained in the parent structure. Together these fields are used to identify reference picture. */ + struct mfxRefPic{ + mfxU32 FrameOrder; /*!< Use FrameOrder = MFX_FRAMEORDER_UNKNOWN to mark + unused entry. */ + mfxU16 PicStruct; /*!< Use PicStruct = MFX_PICSTRUCT_FIELD_TFF for TOP field, PicStruct = MFX_PICSTRUCT_FIELD_BFF for + BOTTOM field. */ + mfxU16 reserved[5]; + } RefPicList0[32], /*!< Specify L0 reference list. */ + RefPicList1[32]; /*!< Specify L1 reference list. */ + +}mfxExtAVCRefLists; +MFX_PACK_END() + +/*! The VPPFieldProcessingMode enumerator is used to control VPP field processing algorithm. */ +enum { + MFX_VPP_COPY_FRAME =0x01, /*!< Copy the whole frame. */ + MFX_VPP_COPY_FIELD =0x02, /*!< Copy only one field. */ + MFX_VPP_SWAP_FIELDS =0x03 /*!< Swap top and bottom fields. */ +}; + +/*! The PicType enumerator itemizes picture type. */ +enum { + MFX_PICTYPE_UNKNOWN =0x00, /*!< Picture type is unknown. */ + MFX_PICTYPE_FRAME =0x01, /*!< Picture is a frame. */ + MFX_PICTYPE_TOPFIELD =0x02, /*!< Picture is a top field. */ + MFX_PICTYPE_BOTTOMFIELD =0x04 /*!< Picture is a bottom field. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP field processing algorithm. The application can attach this extended buffer to + the mfxVideoParam structure to configure initialization and/or to the mfxFrameData during runtime. Runtime configuration has priority + over initialization configuration. If the field processing algorithm was activated via the mfxExtVPPDoUse structure and the mfxExtVPPFieldProcessing + extended buffer was not provided during initialization, this buffer must be attached to the mfxFrameData structure of each input surface. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_FIELD_PROCESSING. */ + + mfxU16 Mode; /*!< Specifies the mode of the field processing algorithm. See the VPPFieldProcessingMode enumerator for values of this option. */ + mfxU16 InField; /*!< When Mode is MFX_VPP_COPY_FIELD, specifies input field. See the PicType enumerator for values of this parameter. */ + mfxU16 OutField; /*!< When Mode is MFX_VPP_COPY_FIELD, specifies output field. See the PicType enumerator for values of this parameter. */ + mfxU16 reserved[25]; +} mfxExtVPPFieldProcessing; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + If attached to the mfxVideoParam structure during the Init stage, this buffer will instruct the decoder to resize output frames via the + fixed function resize engine (if supported by hardware), utilizing direct pipe connection and bypassing intermediate memory operations. + The main benefits of this mode of pipeline operation are offloading resize operation to a dedicated engine, thus reducing power + consumption and memory traffic. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DEC_VIDEO_PROCESSING. */ + + /*! Input surface description. */ + struct mfxIn{ + mfxU16 CropX; /*!< X coordinate of region of interest of the input surface. */ + mfxU16 CropY; /*!< Y coordinate of region of interest of the input surface. */ + mfxU16 CropW; /*!< Width coordinate of region of interest of the input surface. */ + mfxU16 CropH; /*!< Height coordinate of region of interest of the input surface. */ + mfxU16 reserved[12]; + }In; /*!< Input surface description. */ + + /*! Output surface description. */ + struct mfxOut{ + mfxU32 FourCC; /*!< FourCC of output surface Note: Should be MFX_FOURCC_NV12. */ + mfxU16 ChromaFormat; /*!< Chroma Format of output surface. + @note Should be MFX_CHROMAFORMAT_YUV420 */ + mfxU16 reserved1; + + mfxU16 Width; /*!< Width of output surface. */ + mfxU16 Height; /*!< Height of output surface. */ + + mfxU16 CropX; /*!< X coordinate of region of interest of the output surface. */ + mfxU16 CropY; /*!< Y coordinate of region of interest of the output surface. */ + mfxU16 CropW; /*!< Width coordinate of region of interest of the output surface. */ + mfxU16 CropH; /*!< Height coordinate of region of interest of the output surface. */ + mfxU16 reserved[22]; + }Out; /*!< Output surface description. */ + + mfxU16 reserved[13]; +} mfxExtDecVideoProcessing; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Members of this structure define the location of chroma samples information. + + See Annex E of the ISO*\/IEC* 14496-10 specification for the definition of these parameters. + + @note Not all implementations of the encoder support this structure. The application must use the Query API function to determine if it is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CHROMA_LOC_INFO. */ + + mfxU16 ChromaLocInfoPresentFlag; + mfxU16 ChromaSampleLocTypeTopField; + mfxU16 ChromaSampleLocTypeBottomField; + mfxU16 reserved[9]; +} mfxExtChromaLocInfo; +MFX_PACK_END() + +/*! The MBQPMode enumerator itemizes QP update modes. */ +enum { + MFX_MBQP_MODE_QP_VALUE = 0, /*!< QP array contains QP values. */ + MFX_MBQP_MODE_QP_DELTA = 1, /*!< QP array contains deltas for QP. */ + MFX_MBQP_MODE_QP_ADAPTIVE = 2 /*!< QP array contains deltas for QP or absolute QP values. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies per-MB or per-CU mode and QP or DeltaQP value depending on the mode type. + */ +typedef struct{ + union { + /*! + QP for MB or CU. Valid when Mode = MFX_MBQP_MODE_QP_VALUE. + + For AVC, the valid range is 1 to 51. + + For HEVC, the valid range is 1 to 51. The application's provided QP values should be valid, otherwise invalid QP values may cause undefined behavior. + + MBQP map should be aligned for 16x16 block size. The align rule is: (width +15 /16) && (height +15 /16). + + For MPEG2, the valid range is 1 to 112. QP corresponds to quantizer_scale of the ISO*\/IEC* 13818-2 specification. + */ + mfxU8 QP; + /*! + Per-macroblock QP delta. Valid when Mode = MFX_MBQP_MODE_QP_DELTA. + */ + mfxI8 DeltaQP; + }; + mfxU16 Mode; /*!< Defines QP update mode. Can be equal to MFX_MBQP_MODE_QP_VALUE or MFX_MBQP_MODE_QP_DELTA. */ +} mfxQPandMode; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Specifies per-macroblock QP for current frame if mfxExtCodingOption3::EnableMBQP was turned ON during + encoder initialization. The application can attach this extended buffer to the mfxEncodeCtrl structure during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MBQP. */ + + mfxU32 reserved[9]; + mfxU32 Pitch; /*!< Distance in bytes between the start of two consecutive rows in the QP array. */ + mfxU16 Mode; /*!< Defines QP update mode. See MBQPMode enumerator for more details. */ + mfxU16 BlockSize; /*!< QP block size, valid for HEVC only during Init and Runtime. */ + mfxU32 NumQPAlloc; /*!< Size of allocated by application QP or DeltaQP array. */ + union { + /*! + Pointer to a list of per-macroblock QP in raster scan order. In case of interlaced encoding the first half of QP array affects the top + field and the second half of QP array affects the bottom field. Valid when Mode = MFX_MBQP_MODE_QP_VALUE. + + For AVC, the valid range is 1 to 51. + + For HEVC, the valid range is 1 to 51. Application's provided QP values should be valid. Otherwise invalid QP values may cause undefined behavior. + MBQP map should be aligned for 16x16 block size. The alignment rule is (width +15 /16) && (height +15 /16). + + For MPEG2, QP corresponds to quantizer_scale of the ISO*\/IEC* 13818-2 specification and has a valid range of 1 to 112. + */ + mfxU8 *QP; + mfxI8 *DeltaQP; /*!< Pointer to a list of per-macroblock QP deltas in raster scan order. + For block i: QP[i] = BrcQP[i] + DeltaQP[i]. Valid when Mode = MFX_MBQP_MODE_QP_DELTA. */ + mfxQPandMode *QPmode; /*!< Block-granularity modes when MFX_MBQP_MODE_QP_ADAPTIVE is set. */ + + mfxU64 reserved2; + }; +} mfxExtMBQP; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Runtime ctrl buffer for SPS/PPS insertion with current encoding frame. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_INSERT_HEADERS. */ + mfxU16 SPS; /*!< Tri-state option to insert SPS. */ + mfxU16 PPS; /*!< Tri-state option to insert PPS. */ + mfxU16 reserved[8]; +} mfxExtInsertHeaders; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Specifies rectangle areas for IPCM coding mode. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_IPCM_AREA. */ + mfxU16 reserve1[10]; + + mfxU16 NumArea; /*! Number of areas */ + struct area { + + mfxU32 Left; /*!< Left area coordinate. */ + mfxU32 Top; /*!< Top area coordinate. */ + mfxU32 Right; /*!< Right area coordinate. */ + mfxU32 Bottom; /*!< Bottom area coordinate. */ + + mfxU16 reserved2[8]; + + } * Areas; /*!< Array of areas. */ +} mfxExtEncoderIPCMArea; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Specifies macroblock map for current frame which forces specified macroblocks to be encoded as intra + if mfxExtCodingOption3::EnableMBForceIntra was turned ON during encoder initialization. The application can attach this extended + buffer to the mfxEncodeCtrl structure during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MB_FORCE_INTRA. */ + + mfxU32 reserved[11]; + mfxU32 MapSize; /*!< Macroblock map size. */ + union { + mfxU8 *Map; /*!< Pointer to a list of force intra macroblock flags in raster scan order. Each flag is one byte in map. Set flag to 1 + to force corresponding macroblock to be encoded as intra. In case of interlaced encoding, the first half of map + affects top field and the second half of map affects the bottom field. */ + mfxU64 reserved2; + }; +} mfxExtMBForceIntra; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures tiles options for the HEVC encoder. The application can attach this extended buffer to the + mfxVideoParam structure to configure initialization. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_HEVC_TILES. */ + + mfxU16 NumTileRows; /*!< Number of tile rows. */ + mfxU16 NumTileColumns; /*!< Number of tile columns. */ + mfxU16 reserved[74]; +}mfxExtHEVCTiles; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Specifies macroblock map for current frame which forces specified macroblocks to be non-skip if + mfxExtCodingOption3::MBDisableSkipMap was turned ON during encoder initialization. The application can attach this + extended buffer to the mfxEncodeCtrl structure during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MB_DISABLE_SKIP_MAP. */ + + mfxU32 reserved[11]; + mfxU32 MapSize; /*!< Macroblock map size. */ + union { + mfxU8 *Map; /*!< Pointer to a list of non-skip macroblock flags in raster scan order. Each flag is one byte in map. Set flag to 1 to force + corresponding macroblock to be non-skip. In case of interlaced encoding, the first half of map affects + the top field and the second half of map affects the bottom field. */ + mfxU64 reserved2; + }; +} mfxExtMBDisableSkipMap; +MFX_PACK_END() + +/*! The GeneralConstraintFlags enumerator uses bit-ORed values to itemize HEVC bitstream indications for specific profiles. Each value + indicates for format range extensions profiles. + To specify HEVC Main 10 Still Picture profile applications have to set mfxInfoMFX::CodecProfile == MFX_PROFILE_HEVC_MAIN10 and + mfxExtHEVCParam::GeneralConstraintFlags == MFX_HEVC_CONSTR_REXT_ONE_PICTURE_ONLY. */ +enum { + /* REXT Profile constraint flags*/ + MFX_HEVC_CONSTR_REXT_MAX_12BIT = (1 << 0), + MFX_HEVC_CONSTR_REXT_MAX_10BIT = (1 << 1), + MFX_HEVC_CONSTR_REXT_MAX_8BIT = (1 << 2), + MFX_HEVC_CONSTR_REXT_MAX_422CHROMA = (1 << 3), + MFX_HEVC_CONSTR_REXT_MAX_420CHROMA = (1 << 4), + MFX_HEVC_CONSTR_REXT_MAX_MONOCHROME = (1 << 5), + MFX_HEVC_CONSTR_REXT_INTRA = (1 << 6), + MFX_HEVC_CONSTR_REXT_ONE_PICTURE_ONLY = (1 << 7), + MFX_HEVC_CONSTR_REXT_LOWER_BIT_RATE = (1 << 8) +}; + + +/*! The SampleAdaptiveOffset enumerator uses bit-ORed values to itemize corresponding HEVC encoding feature. */ +enum { + MFX_SAO_UNKNOWN = 0x00, /*!< Use default value for platform/TargetUsage. */ + MFX_SAO_DISABLE = 0x01, /*!< Disable SAO. If set during Init leads to SPS sample_adaptive_offset_enabled_flag = 0. + If set during Runtime, leads to to slice_sao_luma_flag = 0 and slice_sao_chroma_flag = 0 + for current frame. */ + MFX_SAO_ENABLE_LUMA = 0x02, /*!< Enable SAO for luma (slice_sao_luma_flag = 1). */ + MFX_SAO_ENABLE_CHROMA = 0x04 /*!< Enable SAO for chroma (slice_sao_chroma_flag = 1). */ +}; + + +/* This struct has 4-byte alignment for binary compatibility with previously released versions of API */ +MFX_PACK_BEGIN_USUAL_STRUCT() +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_HEVC_PARAM. */ + + mfxU16 PicWidthInLumaSamples; /*!< Specifies the width of each coded picture in units of luma samples. */ + mfxU16 PicHeightInLumaSamples; /*!< Specifies the height of each coded picture in units of luma samples. */ + mfxU64 GeneralConstraintFlags; /*!< Additional flags to specify exact profile and constraints. See the GeneralConstraintFlags enumerator for values of this field. */ + mfxU16 SampleAdaptiveOffset; /*!< Controls SampleAdaptiveOffset encoding feature. See the SampleAdaptiveOffset enumerator for supported values + (bit-ORed). Valid during encoder Init and Runtime. */ + mfxU16 LCUSize; /*!< Specifies largest coding unit size (max luma coding block). Valid during encoder Init. */ + mfxU16 reserved[116]; +} mfxExtHEVCParam; +MFX_PACK_END() + +/*! The ErrorTypes enumerator uses bit-ORed values to itemize bitstream error types. */ +enum { + MFX_ERROR_NO = 0, /*!< No error in bitstream. */ + MFX_ERROR_PPS = (1 << 0), /*!< Invalid/corrupted PPS. */ + MFX_ERROR_SPS = (1 << 1), /*!< Invalid/corrupted SPS. */ + MFX_ERROR_SLICEHEADER = (1 << 2), /*!< Invalid/corrupted slice header. */ + MFX_ERROR_SLICEDATA = (1 << 3), /*!< Invalid/corrupted slice data. */ + MFX_ERROR_FRAME_GAP = (1 << 4), /*!< Missed frames. */ + MFX_ERROR_JPEG_APP0_MARKER = (1 << 5), /*!< Invalid/corrupted APP0 marker. */ + MFX_ERROR_JPEG_APP1_MARKER = (1 << 6), /*!< Invalid/corrupted APP1 marker. */ + MFX_ERROR_JPEG_APP2_MARKER = (1 << 7), /*!< Invalid/corrupted APP2 marker. */ + MFX_ERROR_JPEG_APP3_MARKER = (1 << 8), /*!< Invalid/corrupted APP3 marker. */ + MFX_ERROR_JPEG_APP4_MARKER = (1 << 9), /*!< Invalid/corrupted APP4 marker. */ + MFX_ERROR_JPEG_APP5_MARKER = (1 << 10), /*!< Invalid/corrupted APP5 marker. */ + MFX_ERROR_JPEG_APP6_MARKER = (1 << 11), /*!< Invalid/corrupted APP6 marker. */ + MFX_ERROR_JPEG_APP7_MARKER = (1 << 12), /*!< Invalid/corrupted APP7 marker. */ + MFX_ERROR_JPEG_APP8_MARKER = (1 << 13), /*!< Invalid/corrupted APP8 marker. */ + MFX_ERROR_JPEG_APP9_MARKER = (1 << 14), /*!< Invalid/corrupted APP9 marker. */ + MFX_ERROR_JPEG_APP10_MARKER = (1 << 15), /*!< Invalid/corrupted APP10 marker. */ + MFX_ERROR_JPEG_APP11_MARKER = (1 << 16), /*!< Invalid/corrupted APP11 marker. */ + MFX_ERROR_JPEG_APP12_MARKER = (1 << 17), /*!< Invalid/corrupted APP12 marker. */ + MFX_ERROR_JPEG_APP13_MARKER = (1 << 18), /*!< Invalid/corrupted APP13 marker. */ + MFX_ERROR_JPEG_APP14_MARKER = (1 << 19), /*!< Invalid/corrupted APP14 marker. */ + MFX_ERROR_JPEG_DQT_MARKER = (1 << 20), /*!< Invalid/corrupted DQT marker. */ + MFX_ERROR_JPEG_SOF0_MARKER = (1 << 21), /*!< Invalid/corrupted SOF0 marker. */ + MFX_ERROR_JPEG_DHT_MARKER = (1 << 22), /*!< Invalid/corrupted DHT marker. */ + MFX_ERROR_JPEG_DRI_MARKER = (1 << 23), /*!< Invalid/corrupted DRI marker. */ + MFX_ERROR_JPEG_SOS_MARKER = (1 << 24), /*!< Invalid/corrupted SOS marker. */ + MFX_ERROR_JPEG_UNKNOWN_MARKER = (1 << 25), /*!< Unknown Marker. */ +}; + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the decoders to report bitstream error information right after DecodeHeader or DecodeFrameAsync. + The application can attach this extended buffer to the mfxBitstream structure at runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DECODE_ERROR_REPORT. */ + + mfxU32 ErrorTypes; /*!< Bitstream error types (bit-ORed values). See ErrorTypes enumerator for the list of types. */ + mfxU16 reserved[10]; +} mfxExtDecodeErrorReport; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the decoders to report additional information about a decoded frame. The application can attach this + extended buffer to the mfxFrameSurface1::mfxFrameData structure at runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DECODED_FRAME_INFO. */ + + mfxU16 FrameType; /*!< Frame type. See FrameType enumerator for the list of types. */ + mfxU16 reserved[59]; +} mfxExtDecodedFrameInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the library to pass MPEG 2 specific timing information. + + See ISO/IEC 13818-2 and ITU-T H.262, MPEG-2 Part 2 for the definition of these parameters. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_TIME_CODE. */ + + mfxU16 DropFrameFlag; /*!< Indicated dropped frame. */ + mfxU16 TimeCodeHours; /*!< Hours. */ + mfxU16 TimeCodeMinutes; /*!< Minutes. */ + mfxU16 TimeCodeSeconds; /*!< Seconds. */ + mfxU16 TimeCodePictures; /*!< Pictures. */ + mfxU16 reserved[7]; +} mfxExtTimeCode; +MFX_PACK_END() + +/*! The HEVCRegionType enumerator itemizes type of HEVC region. */ +enum { + MFX_HEVC_REGION_SLICE = 0 /*!< Slice type. */ +}; + +/*! The HEVCRegionEncoding enumerator itemizes HEVC region's encoding. */ +enum { + MFX_HEVC_REGION_ENCODING_ON = 0, + MFX_HEVC_REGION_ENCODING_OFF = 1 +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Attached to the mfxVideoParam structure during HEVC encoder initialization. Specifies the region to encode. + + @note Not all implementations of the encoder support this structure. The application must use the Query API function to determine if it is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_HEVC_REGION. */ + + mfxU32 RegionId; /*!< ID of region. */ + mfxU16 RegionType; /*!< Type of region. See HEVCRegionType enumerator for the list of types. */ + mfxU16 RegionEncoding; /*!< Set to MFX_HEVC_REGION_ENCODING_ON to encode only specified region. */ + mfxU16 reserved[24]; +} mfxExtHEVCRegion; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies weighted prediction table for current frame when all of the following conditions are met: + + @li mfxExtCodingOption3::WeightedPred was set to explicit during encoder Init or Reset . + + @li The current frame is P-frame or mfxExtCodingOption3::WeightedBiPred was set to explicit during encoder Init or Reset. + + @li The current frame is B-frame and is attached to the mfxEncodeCtrl structure. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_PRED_WEIGHT_TABLE. */ + + mfxU16 LumaLog2WeightDenom; /*!< Base 2 logarithm of the denominator for all luma weighting factors. Value must be in the range of 0 to 7, inclusive. */ + mfxU16 ChromaLog2WeightDenom; /*!< Base 2 logarithm of the denominator for all chroma weighting factors. Value must be in the range of 0 to 7, inclusive. */ + mfxU16 LumaWeightFlag[2][32]; /*!< LumaWeightFlag[L][R] equal to 1 specifies that the weighting factors for the luma component are specified for R's entry of RefPicList L. */ + mfxU16 ChromaWeightFlag[2][32]; /*!< ChromaWeightFlag[L][R] equal to 1 specifies that the weighting factors for the chroma component are specified for R's entry of RefPicList L. */ + mfxI16 Weights[2][32][3][2]; /*!< The values of the weights and offsets used in the encoding processing. The value of Weights[i][j][k][m] is + interpreted as: i refers to reference picture list 0 or 1; j refers to reference list entry 0-31; + k refers to data for the luma component when it is 0, the Cb chroma component when it is 1 and + the Cr chroma component when it is 2; m refers to weight when it is 0 and offset when it is 1 */ + mfxU16 reserved[58]; +} mfxExtPredWeightTable; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by encoders to set rounding offset parameters for quantization. It is per-frame based encoding control, + and can be attached to some frames and skipped for others. When the extension buffer is set the application can attach it to the mfxEncodeCtrl + during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_ROUNDING_OFFSET. */ + + mfxU16 EnableRoundingIntra; /*!< Enable rounding offset for intra blocks. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 RoundingOffsetIntra; /*!< Intra rounding offset. Value must be in the range of 0 to 7, inclusive. */ + mfxU16 EnableRoundingInter; /*!< Enable rounding offset for inter blocks. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 RoundingOffsetInter; /*!< Inter rounding offset. Value must be in the range of 0 to 7, inclusive. */ + + mfxU16 reserved[24]; +} mfxExtAVCRoundingOffset; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify dirty regions within a frame during encoding. It may be used at initialization or at runtime. + + Dirty rectangle definition is using end-point exclusive notation. In other words, the pixel with (Right, Bottom) coordinates lies + immediately outside of the dirty rectangle. Left, Top, Right, Bottom should be aligned by codec-specific block boundaries (should be + dividable by 16 for AVC, or by block size (8, 16, 32 or 64, depends on platform) for HEVC). + + Every dirty rectangle with unaligned + coordinates will be expanded to a minimal-area block-aligned dirty rectangle, enclosing the original one. + For example, a (5, 5, 15, 31) dirty rectangle will be expanded to (0, 0, 16, 32) for AVC encoder, or to (0, 0, 32, 32) for HEVC, + if block size is 32. + + Dirty rectangle (0, 0, 0, 0) is a valid dirty rectangle and means that the frame is not changed. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DIRTY_RECTANGLES. */ + + mfxU16 NumRect; /*!< Number of dirty rectangles. */ + mfxU16 reserved1[11]; + + struct { + /*! @{ + @name Dirty rectangle coordinates + The following structure members are used by the Rect array contained in the parent structure. + + */ + mfxU32 Left; /*!< Dirty region left coordinate. */ + mfxU32 Top; /*!< Dirty region top coordinate. */ + mfxU32 Right; /*!< Dirty region right coordinate. */ + mfxU32 Bottom; /*!< Dirty region bottom coordinate. */ + + mfxU16 reserved2[8]; + /*! @} */ + } Rect[256]; /*!< Array of dirty rectangles. */ +} mfxExtDirtyRect; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify moving regions within a frame during encoding. + + Destination rectangle location should be aligned to MB boundaries (should be dividable by 16). If not, the encoder + truncates it to MB boundaries, for example, both 17 and 31 will be truncated to 16. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MOVING_RECTANGLE. */ + + mfxU16 NumRect; /*!< Number of moving rectangles. */ + mfxU16 reserved1[11]; + + struct { + /*! @{ + @name Destination and source rectangle location + The following structure members are used by the Rect array contained in the parent structure. + */ + mfxU32 DestLeft; /*!< Destination rectangle location. */ + mfxU32 DestTop; /*!< Destination rectangle location. */ + mfxU32 DestRight; /*!< Destination rectangle location. */ + mfxU32 DestBottom; /*!< Destination rectangle location. */ + + mfxU32 SourceLeft; /*!< Source rectangle location. */ + mfxU32 SourceTop; /*!< Source rectangle location. */ + mfxU16 reserved2[4]; + /*! @} */ + } Rect[256]; /*!< Array of moving rectangles. */ +} mfxExtMoveRect; +MFX_PACK_END() + +/*! The Angle enumerator itemizes valid rotation angles. */ +enum { + MFX_ANGLE_0 = 0, /*!< 0 degrees. */ + MFX_ANGLE_90 = 90, /*!< 90 degrees. */ + MFX_ANGLE_180 = 180, /*!< 180 degrees. */ + MFX_ANGLE_270 = 270 /*!< 270 degrees. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP Rotation filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_ROTATION. */ + + mfxU16 Angle; /*!< Rotation angle. See Angle enumerator for supported values. */ + mfxU16 reserved[11]; +} mfxExtVPPRotation; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Used by the encoder to report additional information about encoded slices. The application can attach this + buffer to the mfxBitstream structure before calling the MFXVideoENCODE_EncodeFrameAsync function. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if the + functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and call the + MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE, then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_SLICES_INFO. */ + + mfxU16 SliceSizeOverflow; /*!< When mfxExtCodingOption2::MaxSliceSize is used, indicates the requested slice size was not met for one or more generated slices. */ + mfxU16 NumSliceNonCopliant; /*!< When mfxExtCodingOption2::MaxSliceSize is used, indicates the number of generated slices exceeds specification limits. */ + mfxU16 NumEncodedSlice; /*!< Number of encoded slices. */ + mfxU16 NumSliceSizeAlloc; /*!< SliceSize array allocation size. Must be specified by application. */ + union { + mfxU16 *SliceSize; /*!< Slice size in bytes. Array must be allocated by application. */ + mfxU64 reserved1; + }; + + mfxU16 reserved[20]; +} mfxExtEncodedSlicesInfo; +MFX_PACK_END() + +/*! The ScalingMode enumerator itemizes variants of scaling filter implementation. */ +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_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 Engines). 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). */ +}; + +/*! The InterpolationMode enumerator specifies type of interpolation method used by VPP scaling filter. */ +enum { + MFX_INTERPOLATION_DEFAULT = 0, /*!< Default interpolation mode for scaling. Library selects the most appropriate + scaling method. */ + MFX_INTERPOLATION_NEAREST_NEIGHBOR = 1, /*!< Nearest neighbor interpolation method. */ + MFX_INTERPOLATION_BILINEAR = 2, /*!< Bilinear interpolation method. */ + MFX_INTERPOLATION_ADVANCED = 3 /*!< Advanced interpolation method is defined by each implementation and usually gives best quality. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP Scaling filter algorithm. + Not all combinations of ScalingMode and InterpolationMethod are supported in the library. The application must use the Query API function to determine if a combination is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_SCALING. */ + + mfxU16 ScalingMode; /*!< Scaling mode. See ScalingMode for values. */ + mfxU16 InterpolationMethod; /*!< Interpolation mode for scaling algorithm. See InterpolationMode for values. */ + mfxU16 reserved[10]; +} mfxExtVPPScaling; +MFX_PACK_END() + +typedef mfxExtAVCRefListCtrl mfxExtHEVCRefListCtrl; +typedef mfxExtAVCRefLists mfxExtHEVCRefLists; +typedef mfxExtAvcTemporalLayers mfxExtHEVCTemporalLayers; + +typedef mfxExtAVCRefListCtrl mfxExtRefListCtrl; +typedef mfxExtAVCEncodedFrameInfo mfxExtEncodedFrameInfo; + +/* The MirroringType enumerator itemizes mirroring types. */ +enum +{ + MFX_MIRRORING_DISABLED = 0, + MFX_MIRRORING_HORIZONTAL = 1, + MFX_MIRRORING_VERTICAL = 2 +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP Mirroring filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_MIRRORING. */ + + mfxU16 Type; /*!< Mirroring type. See MirroringType for values. */ + mfxU16 reserved[11]; +} mfxExtVPPMirroring; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Instructs encoder to use or not use samples over specified picture border for inter prediction. Attached to the mfxVideoParam structure. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES. */ + + mfxU16 StickTop; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 StickBottom; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 StickLeft; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 StickRight; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 reserved[8]; +} mfxExtMVOverPicBoundaries; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP ColorFill filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_COLORFILL. */ + + mfxU16 Enable; /*!< Set to ON makes VPP fill the area between Width/Height and Crop borders. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 reserved[11]; +} mfxExtVPPColorFill; +MFX_PACK_END() + + +/*! The ChromaSiting enumerator defines chroma location. Use bit-OR'ed values to specify the desired location. */ +enum { + MFX_CHROMA_SITING_UNKNOWN = 0x0000, /*!< Unspecified. */ + MFX_CHROMA_SITING_VERTICAL_TOP = 0x0001, /*!< Chroma samples are co-sited vertically on the top with the luma samples. */ + MFX_CHROMA_SITING_VERTICAL_CENTER = 0x0002, /*!< Chroma samples are not co-sited vertically with the luma samples. */ + MFX_CHROMA_SITING_VERTICAL_BOTTOM = 0x0004, /*!< Chroma samples are co-sited vertically on the bottom with the luma samples. */ + MFX_CHROMA_SITING_HORIZONTAL_LEFT = 0x0010, /*!< Chroma samples are co-sited horizontally on the left with the luma samples. */ + MFX_CHROMA_SITING_HORIZONTAL_CENTER = 0x0020 /*!< Chroma samples are not co-sited horizontally with the luma samples. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that tunes the VPP Color Conversion algorithm when + attached to the mfxVideoParam structure during VPP Init. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_COLOR_CONVERSION. */ + + mfxU16 ChromaSiting; /*!< See ChromaSiting enumerator for details. */ + mfxU16 reserved[27]; +} mfxExtColorConversion; +MFX_PACK_END() + + +/*! The VP9ReferenceFrame enumerator itemizes reference frame type by mfxVP9SegmentParam::ReferenceFrame parameter. */ +enum { + MFX_VP9_REF_INTRA = 0, /*!< Intra. */ + MFX_VP9_REF_LAST = 1, /*!< Last. */ + MFX_VP9_REF_GOLDEN = 2, /*!< Golden. */ + MFX_VP9_REF_ALTREF = 3 /*!< Alternative reference. */ +}; + +/*! + The SegmentIdBlockSize enumerator indicates the block size represented by each segment_id in segmentation map. + These values are used with the mfxExtVP9Segmentation::SegmentIdBlockSize parameter. +*/ +enum { + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_UNKNOWN = 0, /*!< Unspecified block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_8x8 = 8, /*!< 8x8 block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_16x16 = 16, /*!< 16x16 block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_32x32 = 32, /*!< 32x32 block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_64x64 = 64, /*!< 64x64 block size. */ +}; + +/*! + The SegmentFeature enumerator indicates features enabled for the segment. + These values are used with the mfxVP9SegmentParam::FeatureEnabled parameter. +*/ +enum { + MFX_VP9_SEGMENT_FEATURE_QINDEX = 0x0001, /*!< Quantization index delta. */ + MFX_VP9_SEGMENT_FEATURE_LOOP_FILTER = 0x0002, /*!< Loop filter level delta. */ + MFX_VP9_SEGMENT_FEATURE_REFERENCE = 0x0004, /*!< Reference frame. */ + MFX_VP9_SEGMENT_FEATURE_SKIP = 0x0008 /*!< Skip. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Contains features and parameters for the segment. +*/ +typedef struct { + mfxU16 FeatureEnabled; /*!< Indicates which features are enabled for the segment. See the SegmentFeature enumerator for values for this + option. Values from the enumerator can be bit-OR'ed. Support of a particular feature depends on underlying + hardware platform. Application can check which features are supported by calling Query. */ + mfxI16 QIndexDelta; /*!< Quantization index delta for the segment. Ignored if MFX_VP9_SEGMENT_FEATURE_QINDEX isn't set in FeatureEnabled. + Valid range for this parameter is [-255, 255]. If QIndexDelta is out of this range, it will be ignored. + If QIndexDelta is within valid range, but sum of base quantization index and QIndexDelta is out of [0, 255], + QIndexDelta will be clamped. */ + mfxI16 LoopFilterLevelDelta; /*!< Loop filter level delta for the segment. Ignored if MFX_VP9_SEGMENT_FEATURE_LOOP_FILTER is not set in + FeatureEnabled. Valid range for this parameter is [-63, 63]. If LoopFilterLevelDelta is out of this range, + it will be ignored. If LoopFilterLevelDelta is within valid range, but sum of base loop filter level and + LoopFilterLevelDelta is out of [0, 63], LoopFilterLevelDelta will be clamped. */ + mfxU16 ReferenceFrame; /*!< Reference frame for the segment. See VP9ReferenceFrame enumerator for values for this option. Ignored + if MFX_VP9_SEGMENT_FEATURE_REFERENCE isn't set in FeatureEnabled. */ + mfxU16 reserved[12]; +} mfxVP9SegmentParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + In the VP9 encoder it is possible to divide a frame into up to 8 segments and apply particular features (like delta for quantization index or for + loop filter level) on a per-segment basis. "Uncompressed header" of every frame indicates if segmentation is enabled for the current frame, + and (if segmentation enabled) contains full information about features applied to every segment. Every "Mode info block" of a coded + frame has segment_id in the range of 0 to 7. + + To enable Segmentation, the mfxExtVP9Segmentation structure with correct settings should be passed to the encoder. It can be attached to the + mfxVideoParam structure during initialization or the MFXVideoENCODE_Reset call (static configuration). If the mfxExtVP9Segmentation buffer isn't + attached during initialization, segmentation is disabled for static configuration. If the buffer isn't attached for the Reset call, the encoder + continues to use static configuration for segmentation which was the default before this Reset call. If the mfxExtVP9Segmentation buffer with + NumSegments=0 is provided during initialization or Reset call, segmentation becomes disabled for static configuration. + + The buffer can be attached to the mfxEncodeCtrl structure during runtime (dynamic configuration). Dynamic configuration is applied to the + current frame only. After encoding of the current frame, the encoder will switch to the next dynamic configuration or to static configuration if dynamic configuration + is not provided for next frame). + + The SegmentIdBlockSize, NumSegmentIdAlloc, and SegmentId parameters represent a segmentation map. Here, the segmentation map is an array of segment_ids (one + byte per segment_id) for blocks of size NxN in raster scan order. The size NxN is specified by the application and is constant for the whole frame. + If mfxExtVP9Segmentation is attached during initialization and/or during runtime, all three parameters should be set to proper values that do not + conflict with each other and with NumSegments. If any of the parameters are not set or any conflict or error in these parameters is detected by the library, the segmentation + map will be discarded. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP9_SEGMENTATION. */ + mfxU16 NumSegments; /*!< Number of segments for frame. Value 0 means that segmentation is disabled. Sending 0 for a + particular frame will disable segmentation for this frame only. Sending 0 to the Reset API function will + disable segmentation permanently. Segmentation can be enabled again by a subsequent Reset call. */ + mfxVP9SegmentParam Segment[8]; /*!< Array of mfxVP9SegmentParam structures containing features and parameters for every segment. + Entries with indexes bigger than NumSegments-1 are ignored. See the mfxVP9SegmentParam structure for + definitions of segment features and their parameters. */ + mfxU16 SegmentIdBlockSize; /*!< Size of block (NxN) for segmentation map. See SegmentIdBlockSize enumerator for values for this + option. An encoded block that is bigger than SegmentIdBlockSize uses segment_id taken from it's + top-left sub-block from the segmentation map. The application can check if a particular block size is + supported by calling Query. */ + mfxU32 NumSegmentIdAlloc; /*!< Size of buffer allocated for segmentation map (in bytes). Application must assure that + NumSegmentIdAlloc is large enough to cover frame resolution with blocks of size SegmentIdBlockSize. + Otherwise the segmentation map will be discarded. */ + union { + mfxU8 *SegmentId; /*!< Pointer to the segmentation map buffer which holds the array of segment_ids in raster scan order. The application + is responsible for allocation and release of this memory. The buffer pointed to by SegmentId, provided during + initialization or Reset call should be considered in use until another SegmentId is provided via Reset + call (if any), or until MFXVideoENCODE_Close is called. The buffer pointed to by SegmentId provided with + mfxEncodeCtrl should be considered in use while the input surface is locked by the library. Every segment_id in the + map should be in the range of 0 to NumSegments-1. If some segment_id is out of valid range, the + segmentation map cannot be applied. If the mfxExtVP9Segmentation buffer is attached to the mfxEncodeCtrl structure in + runtime, SegmentId can be zero. In this case, the segmentation map from static configuration will be used. */ + mfxU64 reserved1; + }; + mfxU16 reserved[52]; +} mfxExtVP9Segmentation; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies temporal layer. +*/ +typedef struct { + mfxU16 FrameRateScale; /*!< The ratio between the frame rates of the current temporal layer and the base layer. The library treats a particular + temporal layer as "defined" if it has FrameRateScale > 0. If the base layer is defined, it must have FrameRateScale = 1. FrameRateScale of each subsequent layer (if defined) must be a multiple of and greater than the + FrameRateScale value of previous layer. */ + mfxU16 TargetKbps; /*!< Target bitrate for the current temporal layer. Ignored if RateControlMethod is CQP. If RateControlMethod is not CQP, the + application must provide TargetKbps for every defined temporal layer. TargetKbps of each subsequent layer (if defined) + must be greater than the TargetKbps value of the previous layer. */ + mfxU16 reserved[14]; +} mfxVP9TemporalLayer; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + API allows the encoding of VP9 bitstreams that contain several subset bitstreams that differ in frame rates, also called "temporal layers". + + When decoding, each temporal layer can be extracted from the coded stream and decoded separately. The mfxExtVP9TemporalLayers structure + configures the temporal layers for the VP9 encoder. It can be attached to the mfxVideoParam structure during initialization or the + MFXVideoENCODE_Reset call. If the mfxExtVP9TemporalLayers buffer isn't attached during initialization, temporal scalability is disabled. If the buffer isn't attached for the Reset call, the encoder continues to use the temporal scalability configuration that was defined before the Reset call. + + In the API, temporal layers are ordered by their frame rates in ascending order. Temporal layer 0 (having the lowest frame rate) is called the base layer. + Each subsequent temporal layer includes all previous layers. + + The temporal scalability feature requires a minimum number of allocated reference + frames (controlled by the NumRefFrame parameter). If the NumRefFrame value set by the application isn't enough to build the reference structure for the requested + number of temporal layers, the library corrects the NumRefFrame value. The temporal layer structure is reset (re-started) after key-frames. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP9_TEMPORAL_LAYERS. */ + /*! + The array of temporal layers. Layer[0] specifies the base layer. + + The library reads layers from the array when they are defined (FrameRateScale > 0). + All layers starting from first layer with FrameRateScale = 0 are ignored. The last layer that is not ignored is considered the "highest layer". + + The frame rate of the highest layer is specified in the mfxVideoParam structure. Frame rates of lower layers are calculated using their FrameRateScale. + + TargetKbps of the highest layer should be equal to the TargetKbps value specified in the mfxVideoParam structure. If it is not true, TargetKbps of highest temporal layers has priority. + + If there are no defined layers in the Layer array, the temporal scalability feature is disabled. For example, to disable temporal scalability in runtime, the application should + pass mfxExtVP9TemporalLayers buffer to Reset with all FrameRateScales set to 0. + */ + mfxVP9TemporalLayer Layer[8]; + mfxU16 reserved[60]; +} mfxExtVP9TemporalLayers; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Structure attached to the mfxVideoParam structure. Extends the mfxVideoParam structure with VP9-specific parameters. Used by both decoder and encoder. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP9_PARAM. */ + + mfxU16 FrameWidth; /*!< Width of the coded frame in pixels. */ + mfxU16 FrameHeight; /*!< Height of the coded frame in pixels. */ + + mfxU16 WriteIVFHeaders; /*!< Set this option to ON to make the encoder insert IVF container headers to the output stream. The NumFrame field of the IVF + sequence header will be zero. It is the responsibility of the application to update the NumFrame field with the correct value. See the + CodingOptionValue enumerator for values of this option. */ + + mfxI16 reserved1[6]; + mfxI16 QIndexDeltaLumaDC; /*!< Specifies an offset for a particular quantization parameter. */ + mfxI16 QIndexDeltaChromaAC; /*!< Specifies an offset for a particular quantization parameter. */ + mfxI16 QIndexDeltaChromaDC; /*!< Specifies an offset for a particular quantization parameter. */ + /*! + Number of tile rows. Should be power of two. The maximum number of tile rows is 4, per the VP9 specification. In addition, the maximum supported number + of tile rows may depend on the underlying library implementation. + + Use the Query API function to check if a particular pair of values (NumTileRows, NumTileColumns) + is supported. In VP9, tile rows have dependencies and cannot be encoded or decoded in parallel. Therefore, tile rows are always encoded by the library in + serial mode (one-by-one). + */ + mfxU16 NumTileRows; + /*! + Number of tile columns. Should be power of two. Restricted with maximum and minimum tile width in luma pixels, as defined in the VP9 + specification (4096 and 256 respectively). In addition, the maximum supported number of tile columns may depend on the underlying library + implementation. + + Use the Query API function to check if a particular pair of values (NumTileRows, NumTileColumns) is supported. In VP9, tile columns do not have + dependencies and can be encoded/decoded in parallel. Therefore, tile columns can be encoded by the library in both parallel and serial modes. + + Parallel mode is automatically utilized by the library when NumTileColumns exceeds 1 and does not exceed the number of tile coding engines on the + platform. In other cases, serial mode is used. Parallel mode is capable of encoding more than 1 tile row (within limitations provided by VP9 + specification and particular platform). Serial mode supports only tile grids 1xN and Nx1. + */ + mfxU16 NumTileColumns; + mfxU16 reserved[110]; +} mfxExtVP9Param; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to report encoded unit information. +*/ +typedef struct { + mfxU16 Type; /*!< Codec-dependent coding unit type (NALU type for AVC/HEVC, start_code for MPEG2 etc). */ + mfxU16 reserved1; + mfxU32 Offset; /*!< Offset relative to the associated mfxBitstream::DataOffset. */ + mfxU32 Size; /*!< Unit size, including delimiter. */ + mfxU32 reserved[5]; +} mfxEncodedUnitInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + If mfxExtCodingOption3::EncodedUnitsInfo was set to MFX_CODINGOPTION_ON during encoder initialization, the mfxExtEncodedUnitsInfo structure is + attached to the mfxBitstream structure during encoding. It is used to report information about coding units in the resulting bitstream. + + The number of filled items in UnitInfo is min(NumUnitsEncoded, NumUnitsAlloc). + + For counting a minimal amount of encoded units you can use the following algorithm: + @code + nSEI = amountOfApplicationDefinedSEI; + if (CodingOption3.NumSlice[IPB] != 0 || mfxVideoParam.mfx.NumSlice != 0) + ExpectedAmount = 10 + nSEI + Max(CodingOption3.NumSlice[IPB], mfxVideoParam.mfx.NumSlice); + else if (CodingOption2.NumMBPerSlice != 0) + ExpectedAmount = 10 + nSEI + (FrameWidth * FrameHeight) / (256 * CodingOption2.NumMBPerSlice); + else if (CodingOption2.MaxSliceSize != 0) + ExpectedAmount = 10 + nSEI + Round(MaxBitrate / (FrameRate*CodingOption2.MaxSliceSize)); + else + ExpectedAmount = 10 + nSEI; + + if (mfxFrameInfo.PictStruct != MFX_PICSTRUCT_PROGRESSIVE) + ExpectedAmount = ExpectedAmount * 2; + + if (temporalScaleabilityEnabled) + ExpectedAmount = ExpectedAmount * 2; + @endcode + @note Only supported by the AVC encoder. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_UNITS_INFO. */ + + union { + mfxEncodedUnitInfo *UnitInfo; /*!< Pointer to an array of mfxEncodedUnitsInfo structures whose size is equal to or greater than NumUnitsAlloc. */ + mfxU64 reserved1; + }; + mfxU16 NumUnitsAlloc; /*!< UnitInfo array size. */ + mfxU16 NumUnitsEncoded; /*!< Output field. Number of coding units to report. If NumUnitsEncoded is greater than NumUnitsAlloc, the UnitInfo + array will contain information only for the first NumUnitsAlloc units. User may consider reallocating the + UnitInfo array to avoid this for subsequent frames. */ + + mfxU16 reserved[22]; +} mfxExtEncodedUnitsInfo; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Provides setup for the Motion-Compensated Temporal Filter (MCTF) during the VPP initialization and for control + parameters at runtime. By default, MCTF is off. An application may enable it by adding MFX_EXTBUFF_VPP_MCTF to the mfxExtVPPDoUse buffer or by + attaching mfxExtVppMctf to the mfxVideoParam structure during initialization or reset. +*/ +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. + + 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; +MFX_PACK_END() + +/*! Describes type of workload passed to MFXQueryAdapters. */ +typedef enum +{ + MFX_COMPONENT_ENCODE = 1, /*!< Encode workload. */ + MFX_COMPONENT_DECODE = 2, /*!< Decode workload. */ + MFX_COMPONENT_VPP = 3 /*!< VPP workload. */ +} mfxComponentType; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains workload description, which is accepted by MFXQueryAdapters function. +*/ +typedef struct +{ + mfxComponentType Type; /*!< Type of workload: Encode, Decode, VPP. See mfxComponentType enumerator for values. */ + mfxVideoParam Requirements; /*!< Detailed description of workload. See mfxVideoParam for details. */ + + mfxU16 reserved[4]; +} mfxComponentInfo; +MFX_PACK_END() + +/* Adapter description */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Contains a description of the graphics adapter for the Legacy mode. +*/ +typedef struct +{ + mfxPlatform Platform; /*!< Platform type description. See mfxPlatform for details. */ + mfxU32 Number; /*!< Value which uniquely characterizes media adapter. On Windows* this number can be used for initialization through + DXVA interface (see example). */ + + mfxU16 reserved[14]; +} mfxAdapterInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains description of all graphics adapters available on the current system. +*/ +typedef struct +{ + mfxAdapterInfo * Adapters; /*!< Pointer to array of mfxAdapterInfo structs allocated by user. */ + mfxU32 NumAlloc; /*!< Length of Adapters array. */ + mfxU32 NumActual; /*!< Number of Adapters entries filled by MFXQueryAdapters. */ + + mfxU16 reserved[4]; +} mfxAdaptersInfo; +MFX_PACK_END() + + +/*! The PartialBitstreamOutput enumerator indicates flags of partial bitstream output type. */ +enum { + MFX_PARTIAL_BITSTREAM_NONE = 0, /*!< Do not use partial output */ + MFX_PARTIAL_BITSTREAM_SLICE = 1, /*!< Partial bitstream output will be aligned to slice granularity */ + MFX_PARTIAL_BITSTREAM_BLOCK = 2, /*!< Partial bitstream output will be aligned to user-defined block size granularity */ + MFX_PARTIAL_BITSTREAM_ANY = 3 /*!< Partial bitstream output will be return any coded data available at the end of SyncOperation timeout */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by an encoder to output parts of the bitstream as soon as they are ready. The application can attach this extended buffer to the + mfxVideoParam structure at initialization. If this option is turned ON (Granularity != MFX_PARTIAL_BITSTREAM_NONE), then the encoder can output + bitstream by part based on the required granularity. + + This parameter is valid only during initialization and reset. Absence of this buffer means default or previously configured bitstream output + behavior. + + @note Not all codecs and implementations support this feature. Use the Query API function to check if this feature is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM. */ + mfxU32 BlockSize; /*!< Output block granularity for PartialBitstreamGranularity. Valid only for MFX_PARTIAL_BITSTREAM_BLOCK. */ + mfxU16 Granularity; /*!< Granularity of the partial bitstream: slice/block/any, all types of granularity state in PartialBitstreamOutput enum. */ + mfxU16 reserved[8]; +} mfxExtPartialBitstreamParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + The mfxExtDeviceAffinityMask structure is used by the application to specify + affinity mask for the device with given device ID. See mfxDeviceDescription + for the device ID definition and sub device indexes. If the implementation + manages CPU threads for some purpose, the user can set the CPU thread affinity + mask by using this structure with DeviceID set to "CPU". +*/ +typedef struct { + /*! Extension buffer header. Header.BufferId must be equal to + MFX_EXTBUFF_DEVICE_AFFINITY_MASK. */ + mfxExtBuffer Header; + /*! Null terminated string with device ID. In case of CPU affinity mask + it must be equal to "CPU". */ + mfxChar DeviceID[MFX_STRFIELD_LEN]; + /*! Number of sub devices or threads in case of CPU in the mask. */ + mfxU32 NumSubDevices; + /*! Mask array. Every bit represents sub-device (or thread for CPU). + "1" means execution is allowed. "0" means that execution is prohibited on + this sub-device (or thread). Length of the array is equal to the: + "NumSubDevices / 8" and rounded to the closest (from the right) integer. + Bits order within each entry of the mask array is LSB: bit 0 holds data + for sub device with index 0 and bit 8 for sub device with index 8. + Index of sub device is defined by the mfxDeviceDescription structure. */ + mfxU8 *Mask; + mfxU32 reserved[4]; /*! Reserved for future use. */ +} mfxExtDeviceAffinityMask; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used by AV1 encoder with more parameter control to encode frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_BITSTREAM_PARAM. */ + + mfxU16 WriteIVFHeaders; /*!< Tri-state option to control IVF headers insertion, default is ON. + Writing IVF headers is enabled in the encoder when mfxExtAV1BitstreamParam is attached and its value is ON or zero. + Writing IVF headers is disabled by default in the encoder when mfxExtAV1BitstreamParam is not attached. */ + + mfxU16 reserved[31]; +} mfxExtAV1BitstreamParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used by AV1 encoder with more parameter control to encode frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_RESOLUTION_PARAM. */ + + mfxU32 FrameWidth; /*!< Width of the coded frame in pixels, default value is from mfxFrameInfo. */ + mfxU32 FrameHeight; /*!< Height of the coded frame in pixels, default value is from mfxFrameInfo. */ + + mfxU32 reserved[6]; +} mfxExtAV1ResolutionParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() + /*! The structure is used by AV1 encoder with more parameter control to encode frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_TILE_PARAM. */ + + mfxU16 NumTileRows; /*!< Number of tile rows, default value is 1. */ + mfxU16 NumTileColumns; /*!< Number of tile columns, default value is 1. */ + mfxU16 NumTileGroups; /*!< Number of tile groups, it will be ignored if the tile groups num is invalid, default value is 1. */ + + mfxU16 reserved[5]; +} mfxExtAV1TileParam; +MFX_PACK_END() + +/*! + The AV1 SegmentIdBlockSize enumerator indicates the block size represented by each segment_id in segmentation map. + These values are used with the mfxExtAV1Segmentation::SegmentIdBlockSize parameter. +*/ +typedef enum { + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_UNSPECIFIED = 0, /*!< Unspecified block size. */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_4x4 = 4, /*!< block size 4x4 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_8x8 = 8, /*!< block size 8x8 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_16x16 = 16, /*!< block size 16x16 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_32x32 = 32, /*!< block size 32x32 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_64x64 = 64, /*!< block size 64x64 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_128x128 = 128 /*!< block size 128x128 */ +} mfxAV1SegmentIdBlockSize; + +/*! + The AV1 SegmentFeature enumerator indicates features enabled for the segment. + These values are used with the mfxAV1SegmentParam::FeatureEnabled parameter. +*/ +enum { + MFX_AV1_SEGMENT_FEATURE_ALT_QINDEX = 0x0001, /*!< use alternate Quantizer. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_Y_VERT = 0x0002, /*!< use alternate loop filter value on y plane vertical. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_Y_HORZ = 0x0004, /*!< use alternate loop filter value on y plane horizontal. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_U = 0x0008, /*!< use alternate loop filter value on u plane. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_V = 0x0010, /*!< use alternate loop filter value on v plane. */ + MFX_AV1_SEGMENT_FEATURE_REFERENCE = 0x0020, /*!< use segment reference frame. */ + MFX_AV1_SEGMENT_FEATURE_SKIP = 0x0040, /*!< use segment (0,0) + skip mode. */ + MFX_AV1_SEGMENT_FEATURE_GLOBALMV = 0x0080 /*!< use global motion vector. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Contains features and parameters for the segment. +*/ +typedef struct { + mfxU16 FeatureEnabled; /*!< Indicates which features are enabled for the segment. See the AV1 SegmentFeature enumerator for values for + this option. Values from the enumerator can be bit-OR'ed. Support of a particular feature depends on underlying + hardware platform. Application can check which features are supported by calling Query. */ + mfxI16 AltQIndex; /*!< Quantization index delta for the segment. Ignored if MFX_AV1_SEGMENT_FEATURE_ALT_QINDEX isn't set in FeatureEnabled. + Valid range for this parameter is [-255, 255]. If AltQIndex is out of this range, it will be ignored. If AltQIndex + is within valid range, but sum of base quantization index and AltQIndex is out of [0, 255], AltQIndex will be clamped. */ + mfxU16 reserved[30]; +} mfxAV1SegmentParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + In the AV1 encoder it is possible to divide a frame into up to 8 segments and apply particular features (like delta for quantization index or for + loop filter level) on a per-segment basis. "Uncompressed header" of every frame indicates if segmentation is enabled for the current frame, + and (if segmentation enabled) contains full information about features applied to every segment. Every "Mode info block" of a coded + frame has segment_id in the range of 0 to 7. + To enable Segmentation, the mfxExtAV1Segmentation structure with correct settings should be passed to the encoder. It can be attached to the + mfxVideoParam structure during initialization or the MFXVideoENCODE_Reset call (static configuration). If the mfxExtAV1Segmentation buffer isn't + attached during initialization, segmentation is disabled for static configuration. If the buffer isn't attached for the Reset call, the encoder + continues to use static configuration for segmentation which was the default before this Reset call. If the mfxExtAV1Segmentation buffer with + NumSegments=0 is provided during initialization or Reset call, segmentation becomes disabled for static configuration. + The buffer can be attached to the mfxEncodeCtrl structure during runtime (dynamic configuration). Dynamic configuration is applied to the + current frame only. After encoding of the current frame, the encoder will switch to the next dynamic configuration or to static configuration if + dynamic configuration is not provided for next frame). + The SegmentIdBlockSize, NumSegmentIdAlloc, and SegmentId parameters represent a segmentation map. Here, the segmentation map is an array of + segment_ids (one byte per segment_id) for blocks of size NxN in raster scan order. The size NxN is specified by the application and is constant + for the whole frame. + If mfxExtAV1Segmentation is attached during initialization and/or during runtime, all three parameters should be set to proper values that do not + conflict with each other and with NumSegments. If any of the parameters are not set or any conflict or error in these parameters is detected by + the library, the segmentation map will be discarded. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_SEGMENTATION. */ + mfxU8 NumSegments; /*!< Number of segments for frame. Value 0 means that segmentation is disabled. Sending 0 for a + particular frame will disable segmentation for this frame only. Sending 0 to the Reset API function will + disable segmentation permanently. Segmentation can be enabled again by a subsequent Reset call. */ + mfxU8 reserved1[3]; + mfxAV1SegmentParam Segment[8]; /*!< Array of mfxAV1SegmentParam structures containing features and parameters for every segment. + Entries with indexes bigger than NumSegments-1 are ignored. See the mfxAV1SegmentParam structure for + definitions of segment features and their parameters. */ + mfxU16 SegmentIdBlockSize;/*!< Size of block (NxN) for segmentation map. See AV1 SegmentIdBlockSize enumerator for values for this + option. An encoded block that is bigger than AV1 SegmentIdBlockSize uses segment_id taken from it's + top-left sub-block from the segmentation map. The application can check if a particular block size is + supported by calling Query. */ + mfxU16 reserved2; + mfxU32 NumSegmentIdAlloc; /*!< Size of buffer allocated for segmentation map (in bytes). Application must assure that + NumSegmentIdAlloc is large enough to cover frame resolution with blocks of size SegmentIdBlockSize. + Otherwise the segmentation map will be discarded. */ + mfxU8 * SegmentIds; /*!< Pointer to the segmentation map buffer which holds the array of segment_ids in raster scan order. The application + is responsible for allocation and release of this memory. The buffer pointed to by SegmentId, provided during + initialization or Reset call should be considered in use until another SegmentId is provided via Reset + call (if any), or until MFXVideoENCODE_Close is called. The buffer pointed to by SegmentId provided with + mfxEncodeCtrl should be considered in use while the input surface is locked by the library. Every segment_id in the + map should be in the range of 0 to NumSegments-1. If some segment_id is out of valid range, the + segmentation map cannot be applied. If the mfxExtAV1Segmentation buffer is attached to the mfxEncodeCtrl structure in + runtime, SegmentId can be zero. In this case, the segmentation map from static configuration will be used. */ + mfxU16 reserved[36]; +} mfxExtAV1Segmentation; +MFX_PACK_END() + +/*! 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. */ + MFX_FILM_GRAIN_APPLY = (1 << 0), /*!< Film grain is added to this frame. */ + MFX_FILM_GRAIN_UPDATE = (1 << 1), /*!< New set of film grain parameters is sent for this frame. */ + MFX_FILM_GRAIN_CHROMA_SCALING_FROM_LUMA = (1 << 2), /*!< Chroma scaling is inferred from luma scaling. */ + MFX_FILM_GRAIN_OVERLAP = (1 << 3), /*!< Overlap between film grain blocks is applied. */ + MFX_FILM_GRAIN_CLIP_TO_RESTRICTED_RANGE = (1 << 4) /*!< Clipping to the restricted (studio) range is applied after adding the film grain. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Defines film grain point. */ +typedef struct { + mfxU8 Value; /*!< The x coordinate for the i-th point of the piece-wise linear scaling function for luma/Cb/Cr component. */ + mfxU8 Scaling; /*!< The scaling (output) value for the i-th point of the piecewise linear scaling function for luma/Cb/Cr component. */ +} mfxAV1FilmGrainPoint; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used by AV-1 decoder to report film grain parameters for decoded frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM. */ + + mfxU16 FilmGrainFlags; /*!< Bit map with bit-ORed flags from FilmGrainFlags enum. */ + mfxU16 GrainSeed; /*!< Starting value for pseudo-random numbers used during film grain synthesis. */ + + mfxU8 RefIdx; /*!< Indicate which reference frame contains the film grain parameters to be used for this frame. */ + mfxU8 NumYPoints; /*!< The number of points for the piece-wise linear scaling function of the luma component. */ + mfxU8 NumCbPoints; /*!< The number of points for the piece-wise linear scaling function of the Cb component. */ + mfxU8 NumCrPoints; /*!< The number of points for the piece-wise linear scaling function of the Cr component.*/ + + mfxAV1FilmGrainPoint PointY[14]; /*!< The array of points for luma component. */ + 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 + 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.*/ + + mfxU8 ArCoeffsYPlus128[24]; /*!< Auto-regressive coefficients used for the Y plane. */ + 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 + [-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 .*/ + + mfxU8 CbMult; /*!< The multiplier for the Cb component used in derivation of the input index to the Cb component scaling function.*/ + mfxU8 CbLumaMult; /*!< The multiplier for the average luma component used in derivation of the input index to the Cb component scaling function. */ + mfxU16 CbOffset; /*!< The offset used in derivation of the input index to the Cb component scaling function.*/ + + mfxU8 CrMult; /*!< The multiplier for the Cr component used in derivation of the input index to the Cr component scaling function.*/ + mfxU8 CrLumaMult; /*!< The multiplier for the average luma component used in derivation of the input index to the Cr component scaling function.*/ + mfxU16 CrOffset; /*!< The offset used in derivation of the input index to the Cr component scaling function.*/ + + mfxU16 reserved[43]; +} mfxExtAV1FilmGrainParam; +MFX_PACK_END() + +#define MFX_SURFACEARRAY_VERSION MFX_STRUCT_VERSION(1, 0) + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure is reference counted object to return array of surfaces allocated and processed by the library. */ +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]; + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the mfxSurfaceArray::Release function. + mfxSurfaceArray::AddRef should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + + @param[in] surface Valid mfxSurfaceArray. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxSurfaceArray* surface_array); + /*! @brief + Decrements the internal reference counter of the surface. mfxSurfaceArray::Release should be called after + using the mfxSurfaceArray::AddRef function to add a surface or when allocation logic requires it. + + @param[in] surface_array Valid mfxSurfaceArray. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxSurfaceArray* surface_array); + + /*! @brief + Returns current reference counter of mfxSurfaceArray structure. + + @param[in] surface Valid surface_array. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + 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 (MFX_CDECL *GetRefCounter)(struct mfxSurfaceArray* surface_array, mfxU32* counter); + + mfxFrameSurface1** Surfaces; /*!< The array of pointers to mfxFrameSurface1. mfxFrameSurface1 surfaces are allocated by the same + agent who allocates mfxSurfaceArray. */ + mfxU32 NumSurfaces; /*! 0. If the base layer is defined, it must have FrameRateScale = 1. + FrameRateScale of each subsequent layer (if defined) must be a multiple of and greater than the + FrameRateScale value of previous layer. */ + mfxU16 reserved[3]; /*!< Reserved for future use. */ + + union { + /*!< Type of bitrate controls is currently the same across all temporal layers and inherits from common parameters. */ + struct { + mfxU32 InitialDelayInKB;/*!< Initial size of the Video Buffering Verifier (VBV) buffer for the current temporal layer. + @note In this context, KB is 1000 bytes and Kbps is 1000 bps. */ + mfxU32 BufferSizeInKB; /*!< Represents the maximum possible size of any compressed frames for the current temporal layer. */ + mfxU32 TargetKbps; /*!< Target bitrate for the current temporal layer. If RateControlMethod is not CQP, the + application can provide TargetKbps for every defined temporal layer. If TargetKbps per temporal layer is not set then + encoder doesn't apply any special bitrate limitations for the layer. */ + mfxU32 MaxKbps; /*!< The maximum bitrate at which the encoded data enters the Video Buffering Verifier (VBV) buffer for the current temporal layer. */ + + mfxU32 reserved1[16]; /*!< Reserved for future use. */ + + }; + struct { + mfxI32 QPI; /*!< Quantization Parameter (QP) for I-frames for constant QP mode (CQP) for the current temporal layer. Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPI range. + @note Default QPI value is implementation dependent and subject to change without additional notice in this document. */ + mfxI32 QPP; /*!< Quantization Parameter (QP) for P-frames for constant QP mode (CQP) for the current temporal layer. Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPP might be clipped to supported QPI range. + @note Default QPP value is implementation dependent and subject to change without additional notice in this document. */ + mfxI32 QPB; /*!< Quantization Parameter (QP) for B-frames for constant QP mode (CQP) for the current temporal layer. Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPB range. + @note Default QPB value is implementation dependent and subject to change without additional notice in this document. */ + }; + }; + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + +} mfxTemporalLayer; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure is used for universal temporal layers description. */ +typedef struct { + mfxExtBuffer Header; /*! Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_UNIVERSAL_TEMPORAL_LAYERS. */ + mfxU16 NumLayers; /*!< The number of temporal layers. */ + mfxU16 BaseLayerPID; /*!< The priority ID of the base layer. The encoder increases the ID for each temporal layer and writes to the prefix NAL unit for AVC and HEVC. */ + mfxU16 reserved[2]; /*!< Reserved for future use. */ + mfxTemporalLayer *Layers; /*!< The array of temporal layers. */ + + mfxU16 reserved1[8]; /*!< Reserved for future use. */ +} mfxExtTemporalLayers; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used to configure perceptual encoding prefilter in VPP. */ +typedef struct { + mfxExtBuffer Header; /*! Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_PERC_ENC_PREFILTER. */ + mfxU16 reserved[252]; +} mfxExtVPPPercEncPrefilter; +MFX_PACK_END() +#endif + +#ifdef ONEVPL_EXPERIMENTAL +/*! The TuneQuality enumerator specifies tuning option for encode. Multiple tuning options can be combined using bit mask. */ +enum { + MFX_ENCODE_TUNE_OFF = 0, /*!< Tuning quality is disabled. */ + MFX_ENCODE_TUNE_PSNR = 0x1, /*!< The encoder optimizes quality according to Peak Signal-to-Noise Ratio (PSNR) metric. */ + MFX_ENCODE_TUNE_SSIM = 0x2, /*!< The encoder optimizes quality according to Structural Similarity Index Measure (SSIM) metric. */ + MFX_ENCODE_TUNE_MS_SSIM = 0x4, /*!< The encoder optimizes quality according to Multi-Scale Structural Similarity Index Measure (MS-SSIM) metric. */ + MFX_ENCODE_TUNE_VMAF = 0x8, /*!< The encoder optimizes quality according to Video Multi-Method Assessment Fusion (VMAF) metric. */ + MFX_ENCODE_TUNE_PERCEPTUAL = 0x10, /*!< The encoder makes perceptual quality optimization. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure specifies type of quality optimization used by the encoder. The buffer can also be attached for VPP functions to make correspondent pre-filtering. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_TUNE_ENCODE_QUALITY. */ + mfxU32 TuneQuality; /*!< The control to specify type of encode quality metric(s) to optimize; See correspondent enum. */ + mfxExtBuffer** ExtParam; /*!< Points to an array of pointers to the extra configuration structures; see the ExtendedBufferID enumerator for a list of extended configurations. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to the structure. */ + mfxU16 reserved[11]; +} mfxExtTuneEncodeQuality; +MFX_PACK_END() +#endif + +/*! The mfxAISuperResolutionMode enumerator specifies the mode of AI based super resolution. */ +typedef enum { + MFX_AI_SUPER_RESOLUTION_MODE_DISABLED = 0, /*!< Super Resolution is disabled.*/ + MFX_AI_SUPER_RESOLUTION_MODE_DEFAULT = 1, /*!< Default super resolution mode. The library selects the most appropriate super resolution mode.*/ +#ifdef ONEVPL_EXPERIMENTAL + MFX_AI_SUPER_RESOLUTION_MODE_SHARPEN = 2, /*!< In this mode, super Resolution is optimized or trained to have high sharpness level. This mode is recommended to be used in video conference(camera + noise) or similar usage scenario.*/ + MFX_AI_SUPER_RESOLUTION_MODE_ARTIFACTREMOVAL= 3, /*!< In this mode, Super Resolution is optimized or trained to remove encoding artifacts with medium sharpness level. This mode is recommended to be used in + video surveillance or similar usage scenarios which may have camera noise and encoding artifacts due to limited network bandwidth.*/ +#endif +} mfxAISuperResolutionMode; + +#ifdef ONEVPL_EXPERIMENTAL +typedef enum { + MFX_AI_SUPER_RESOLUTION_ALGORITHM_DEFAULT = 0, /*!< Super Resolution algorithm by default. The library selects the most appropriate super resolution algorithm.*/ + MFX_AI_SUPER_RESOLUTION_ALGORITHM_1 = 1, /*!< Super Resolution algorithm1.*/ + MFX_AI_SUPER_RESOLUTION_ALGORITHM_2 = 2, /*!< Super Resolution algorithm2, MFX_AI_SUPER_RESOLUTION_ALGORITHM_2 video quality is expected to be better than MFX_AI_SUPER_RESOLUTION_ALGORITHM_1.*/ +} mfxAISuperResolutionAlgorithm; +#endif + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + A hint structure that configures AI based super resolution VPP filter. + Super resolution is an AI-powered upscaling feature which converts a low-resolution to high-resolution. + 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 mfxExtVPPAISuperResolution structure directly to the mfxVideoParam structure and + calling the Query API function. If the filter is supported, the function returns a MFX_ERR_NONE status; otherwise, the function returns MFX_ERR_UNSUPPORTED. + If both mfxExtVPPAISuperResolution and mfxExtVPPScaling are attached during initialization, the function will return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM; if both + of them are attached during runtime, the mfxExtVPPAISuperResolution will override the upscaling mode and use super resolution. + If the application needs to switch on and off, the application can set the MFX_AI_SUPER_RESOLUTION_MODE_DISABLED to switch off, MFX_AI_SUPER_RESOLUTION_MODE_DEFAULT + to switch on. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_AI_SUPER_RESOLUTION.*/ + mfxAISuperResolutionMode SRMode; /*!< Indicates Super Resolution Mode. mfxAISuperResolutionMode enumerator.*/ +#ifdef ONEVPL_EXPERIMENTAL + mfxAISuperResolutionAlgorithm SRAlgorithm; /*!< Indicates Super Resolution Algorithm. mfxAISuperResolutionAlgorithm enumerator.*/ + mfxU32 reserved1[15]; /*!< Reserved for future use. */ +#else + mfxU32 reserved1[16]; /*!< Reserved for future use. */ +#endif + mfxHDL reserved2[4]; /*!< Reserved for future use. */ +} mfxExtVPPAISuperResolution; +MFX_PACK_END() + +/* The mfxAIFrameInterpolationMode enumerator specifies the mode of AI based frame interpolation. */ +typedef enum { + MFX_AI_FRAME_INTERPOLATION_MODE_DISABLE = 0, /*!< AI based frame interpolation is disabled. The library duplicates the frame if AI frame interpolation is disabled.*/ + MFX_AI_FRAME_INTERPOLATION_MODE_DEFAULT = 1, /*!< Default AI based frame interpolation mode. The library selects the most appropriate AI based frame interpolation mode.*/ + +#ifdef ONEVPL_EXPERIMENTAL + MFX_AI_FRAME_INTERPOLATION_MODE_BEST_SPEED = 2, /*!< AI based frame interpolation in best speed.*/ + MFX_AI_FRAME_INTERPOLATION_MODE_BEST_QUALITY = 3, /*!< AI based frame interpolation in best quality.*/ +#endif +} mfxAIFrameInterpolationMode; + +/*! + A hint structure that configures AI based frame interpolation VPP filter. + AI powered frame interpolation feature can reconstruct one or more intermediate frames between two consecutive frames by AI method. + 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: + Attaching the mfxExtVPPAIFrameInterpolation structure directly to the mfxVideoParam structure and setting the frame rate of input and output (FrameRateExtN and FrameRateExtD), + then calling the Query API function. If the filter is supported, the Query function returns a MFX_ERR_NONE status; otherwise, the function returns MFX_ERR_UNSUPPORTED. + As a new method of frame interpolation, the application can attach mfxExtVPPAIFrameInterpolation to mfxVideoParam during initialization for frame interpolation, or attach both + mfxExtVPPAIFrameInterpolation and mfxExtVPPFrameRateConversion to mfxVideoParam and use which mfxExtVPPAIFrameInterpolation is regarded as a new algorithm of mfxExtVPPFrameRateConversion + (MFX_FRCALGM_AI_FRAME_INTERPOLATION). + The applications should follow video processing procedures and call the API mfxStatus MFXVideoVPP_RunFrameVPPAsync(Session, Input, Output, Auxdata, Syncp) to process the frames one by one. + The below is detailed explanation of video processing procedures in this AI frame interpolation case. If the application does not follow the below input/output sequence, the application could + get the unexpected output and get an error return value. + Input: Frame0 Frame1 Frame2 Frame3 FrameN + Output: Frame0 Frame0.5 Frame1 Frame1.5 Frame2 Frame2.5 Frame3 FrameX.5 FrameN + #0 API call: Input Frame0, Output Frame0, Return MFX_ERR_NONE. + #1 API call: Input Frame1, Output Frame0.5 and Return MFX_ERR_MORE_SURFACE. + #2 API call: Input Frame1, Output Frame1, Return MFX_ERR_NONE. + #3 API call: Input Frame2, Output Frame1.5, Return MFX_ERR_MORE_SURFACE. + #4 API call: Input Frame2, Output Frame2, Return MFX_ERR_NONE. +*/ +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_AI_FRAME_INTERPOLATION.*/ + mfxAIFrameInterpolationMode FIMode; /*!< Indicates frame interpolation mode. The mfxAIFrameInterpolationMode enumerator.*/ + mfxU16 EnableScd; /*!< Indicates if enabling scene change detection(SCD) of the library. Recommend to enable this flag for + better quality. Value 0 means disable SCD, Value 1 means enable SCD.*/ + + mfxU32 reserved1[24]; /*!< Reserved for future use. */ + mfxHDL reserved2[8]; /*!< Reserved for future use. */ +} mfxExtVPPAIFrameInterpolation; +MFX_PACK_END() + +/*! The mfxQualityInfoMode enumerator specifies the mode of Quality information. */ +typedef enum { + MFX_QUALITY_INFO_DISABLE = 0, /*!< Quality reporting disabled. */ + MFX_QUALITY_INFO_LEVEL_FRAME = 0x1, /*!< Frame level quality report. */ +} mfxQualityInfoMode; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to set quality information report mode for the encoded picture. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE. */ + mfxQualityInfoMode QualityInfoMode;/*!< See mfxQualityInfoMode enumeration for supported modes. */ + mfxU32 reserved[5]; /*!< Reserved for future use. */ +} mfxExtQualityInfoMode; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Used by the encoder to report quality information about the encoded picture. The application can attach + this buffer to the mfxBitstream structure before calling MFXVideoENCODE_EncodeFrameAsync function. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_QUALITY_INFO_OUTPUT. */ + mfxU32 FrameOrder; /*!< Frame display order of encoded picture. */ + mfxU32 MSE[3]; /*!< Frame level mean squared errors (MSE) for Y/U/V channel. + @note MSE is stored in U24.8 format. The calculation formula is: PSNR = 10 * log10(256.0 * (2^bitDepth - 1)^2 / (double)MSE)). */ + mfxU32 reserved1[50]; /*!< Reserved for future use. */ + mfxHDL reserved2[4]; /*!< Reserved for future use. */ +} mfxExtQualityInfoOutput; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to set the screen content tools. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_SCREEN_CONTENT_TOOLS. */ + /*! + Set this flag to MFX_CODINGOPTION_ON to enable palette prediction for encoder. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value will be used which can be obtained from the MFXVideoENCODE_GetVideoParam function after encoding initialization. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 Palette; + /*! + Set this flag to MFX_CODINGOPTION_ON to enable intra block copy prediction for encoder. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value will be used which can be obtained from the MFXVideoENCODE_GetVideoParam function after encoding initialization. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 IntraBlockCopy; + mfxU16 reserved[10]; /*!< Reserved for future use. */ +} mfxExtAV1ScreenContentTools; +MFX_PACK_END() + + +/*! The AlphaChannelMode enumerator specifies alpha is straight or pre-multiplied. */ +enum { + /*! + RGB and alpha are independent, then the alpha value specifies how solid it is. + We set it to the default value, i.e., the alpha source data is already pre-multiplied, so that the decoded samples of the associated primary picture + should not be multiplied by the interpretation sample values of the auxiliary coded picture in the display process after output from the decoding process. + */ + MFX_ALPHA_MODE_PREMULTIPLIED = 1, + + /*! + RGB and alpha are linked, then the alpha value specifies how much it obscures whatever is behind it. + Therefore, the decoded samples of the associated primary picture should be multiplied by the interpretation sample values + of the auxiliary coded picture in the display process after output from the decoding process. + */ + MFX_ALPHA_MODE_STRAIGHT = 2 +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Configure the alpha channel encoding. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. BufferId must be equal to MFX_EXTBUFF_ALPHA_CHANNEL_ENC_CTRL. */ + /*! + Set this flag to MFX_CODINGOPTION_ON to enable alpha channel encoding. See the CodingOptionValue enumerator for values of this option. + This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 EnableAlphaChannelEncoding; + /*! + Specifies alpha is straight or pre-multiplied. See the AlphaChannelMode enumerator for details. + Encoder just record this in the SEI for post-decoding rendering. + */ + mfxU16 AlphaChannelMode; + /*! + Indicates the percentage of the auxiliary alpha layer in the total bitrate. Valid range for this parameter is [1, 99]. + We set 25 as the default value, i.e. Alpha(25) : Total(100), then 25% of the bits will be spent on alpha layer encoding whereas the other 75% will be spent on base(YUV) layer. + Affects the following variables: InitialDelayInKB, BufferSizeInKB, TargetKbps, MaxKbps. + */ + mfxU16 AlphaChannelBitrateRatio; + mfxU16 reserved[9]; +} mfxExtAlphaChannelEncCtrl; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Defines the uncompressed frames surface information and data buffers for alpha channel encoding. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. BufferId must be equal to MFX_EXTBUFF_ALPHA_CHANNEL_SURFACE. */ + mfxFrameSurface1* AlphaSurface; /*!< Alpha channel surface. */ + mfxU16 reserved[8]; +} mfxExtAlphaChannelSurface; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to switch to ai assisted encoder solutions. + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AI_ENC_CTRL. */ + /*! + Set this flag to MFX_CODINGOPTION_ON to enable saliency encoder solution. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value OFF will be used. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 SaliencyEncoder; + /*! + Set this flag to MFX_CODINGOPTION_ON to enable ML-based adaptive target usage solution. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value will be used which can be obtained from the MFXVideoENCODE_GetVideoParam function after encoding initialization. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 AdaptiveTargetUsage; + mfxU16 reserved[26]; /*!< Reserved for future use. */ +} mfxExtAIEncCtrl; +MFX_PACK_END() +#endif + +#ifdef __cplusplus +} // extern "C" + +#endif + + +#endif diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxsurfacepool.h b/third-party/IntelVPL/arm64/include/vpl/mfxsurfacepool.h new file mode 100644 index 000000000..48a282d07 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxsurfacepool.h @@ -0,0 +1,184 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFX_SURFACE_POOL_H__ +#define __MFX_SURFACE_POOL_H__ + +#include "mfxstructures.h" + +/*! GUID to obtain mfxSurfacePoolInterface. */ +static const mfxGUID MFX_GUID_SURFACE_POOL = {{0x35, 0x24, 0xf3, 0xda, 0x96, 0x4e, 0x47, 0xf1, 0xaf, 0xb4, 0xec, 0xb1, 0x15, 0x08, 0x06, 0xb1}}; + +/*! Specifies type of pool for VPP component. */ +typedef enum { + MFX_VPP_POOL_IN = 0, /*!< Input pool. */ + MFX_VPP_POOL_OUT = 1 /*!< Output pool. */ +} mfxVPPPoolType; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The extension buffer specifies surface pool management policy. + Absence of the attached buffer means MFX_ALLOCATION_UNLIMITED policy: + each call of GetSurfaceForXXX leads to surface allocation. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ALLOCATION_HINTS. */ + mfxPoolAllocationPolicy AllocationPolicy; /*!< Allocation policy. */ + /*! How many surfaces to allocate during Init. + It's applicable for any polices set by mfxPoolAllocationPolicy::AllocationPolicy + even if the requested number exceeds recommended size of the pool. */ + mfxU32 NumberToPreAllocate; + /*! DeltaToAllocateOnTheFly specifies how many surfaces are allocated + in addition to NumberToPreAllocate in MFX_ALLOCATION_LIMITED mode. + Maximum number of allocated frames will be + NumberToPreAllocate + DeltaToAllocateOnTheFly. + */ + mfxU32 DeltaToAllocateOnTheFly; + union { + mfxVPPPoolType VPPPoolType; /*!< Defines what VPP pool is targeted - input or output. Ignored for other components. */ + mfxU32 reserved; + }; + mfxU32 Wait; /*!< Time in milliseconds for GetSurfaceForXXX() and DecodeFrameAsync functions to wait until surface will be available. */ + mfxU32 reserved1[4]; /*!< Reserved for future use */ +} mfxExtAllocationHints; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Specifies the surface pool interface. */ +typedef struct mfxSurfacePoolInterface +{ + mfxHDL Context; /*!< The context of the surface pool interface. User should not touch (change, set, null) this pointer. */ + + /*! @brief + Increments the internal reference counter of the mfxSurfacePoolInterface. The mfxSurfacePoolInterface is not destroyed until the + mfxSurfacePoolInterface is destroyed with mfxSurfacePoolInterface::Release function. mfxSurfacePoolInterface::AddRef should be used each time a new link to the + mfxSurfacePoolInterface is created for proper management. + + @param[in] pool Valid pool. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxSurfacePoolInterface *pool); + /*! @brief + Decrements the internal reference counter of the mfxSurfacePoolInterface. mfxSurfacePoolInterface::Release + should be called after using the mfxSurfacePoolInterface::AddRef function to add a mfxSurfacePoolInterface or when allocation logic requires it. + For example, call mfxSurfacePoolInterface::Release to release a mfxSurfacePoolInterface obtained with + the mfxFrameSurfaceInterface::QueryInterface function. + + @param[in] pool Valid pool. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of mfxSurfacePoolInterface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxSurfacePoolInterface *pool); + /*! @brief + Returns current reference counter of mfxSurfacePoolInterface structure. + + @param[in] pool Valid pool. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(struct mfxSurfacePoolInterface *pool, mfxU32* counter); + /*! @brief + The function should be called by oneAPI Video Processing Library (oneVPL) components or application to specify how many surfaces + it will use concurrently. + Internally, oneVPL allocates surfaces in the shared pool according to the component's policy set by mfxPoolAllocationPolicy. + The exact moment of surfaces allocation is defined by the component and generally independent from that call. + + @param[in] pool Valid pool. + @param[in] num_surfaces The number of surfaces required by the component. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM If pool has MFX_ALLOCATION_UNLIMITED or MFX_ALLOCATION_LIMITED policy. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *SetNumSurfaces)(struct mfxSurfacePoolInterface *pool, mfxU32 num_surfaces); + + /*! @brief + The function should be called by oneVPL components when component is closed or reset and doesn't need to use pool more. It helps + to manage memory accordingly and release redundant memory. Important to specify the same number of surfaces which is requested + during SetNumSurfaces call, otherwise it may lead to the pipeline stalls. + + @param[in] pool Valid pool. + @param[in] num_surfaces The number of surfaces used by the component. + + @return + MFX_ERR_NONE If no error. \n + + MFX_WRN_OUT_OF_RANGE If num_surfaces doesn't equal to num_surfaces requested during SetNumSurfaces call. \n + + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM If pool has MFX_ALLOCATION_UNLIMITED or MFX_ALLOCATION_LIMITED policy. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *RevokeSurfaces)(struct mfxSurfacePoolInterface *pool, mfxU32 num_surfaces); + /*! @brief + Returns current allocation policy. + + @param[in] pool Valid pool. + @param[out] policy Sets policy to the current allocation policy value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or policy is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetAllocationPolicy)(struct mfxSurfacePoolInterface *pool, mfxPoolAllocationPolicy *policy); + + /*! @brief + Returns maximum pool size. In case of mfxPoolAllocationPolicy::MFX_ALLOCATION_UNLIMITED policy 0xFFFFFFFF will be returned. + + @param[in] pool Valid pool. + @param[out] size Sets size to the maximum pool size value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or size is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetMaximumPoolSize)(struct mfxSurfacePoolInterface *pool, mfxU32 *size); + + /*! @brief + Returns current pool size. + + @param[in] pool Valid pool. + @param[out] size Sets size to the current pool size value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or size is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetCurrentPoolSize)(struct mfxSurfacePoolInterface *pool, mfxU32 *size); + + mfxHDL reserved[4]; /*!< Reserved for future use. */ + +} mfxSurfacePoolInterface; +MFX_PACK_END() + + +#endif /* __MFX_SURFACE_POOL_H__ */ + diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxvideo++.h b/third-party/IntelVPL/arm64/include/vpl/mfxvideo++.h new file mode 100644 index 000000000..5b01821b4 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxvideo++.h @@ -0,0 +1,594 @@ +/*########################################################################### + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ###########################################################################*/ + +#ifndef __MFXVIDEOPLUSPLUS_H +#define __MFXVIDEOPLUSPLUS_H + +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD +#include "vpl/mfx.h" +#define MFX_IMPL_ACCELMODE(x) (0xff00 & (x)) +#else +#include "mfxvideo.h" +#endif + +class MFXVideoSessionBase { +public: + virtual ~MFXVideoSessionBase() {} + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion* ver) = 0; + virtual mfxStatus InitEx(mfxInitParam par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus QueryIMPL(mfxIMPL* impl) = 0; + virtual mfxStatus QueryVersion(mfxVersion* version) = 0; + + virtual mfxStatus JoinSession(mfxSession child_session) = 0; + virtual mfxStatus DisjoinSession() = 0; + virtual mfxStatus CloneSession(mfxSession* clone) = 0; + virtual mfxStatus SetPriority(mfxPriority priority) = 0; + virtual mfxStatus GetPriority(mfxPriority* priority) = 0; + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator* allocator) = 0; + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) = 0; + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL* hdl) = 0; + virtual mfxStatus QueryPlatform(mfxPlatform* platform) = 0; + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) = 0; + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPP(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) = 0; + + virtual operator mfxSession(void) = 0; +}; + +class MFXVideoENCODEBase { +public: + virtual ~MFXVideoENCODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetEncodeStat(mfxEncodeStat* stat) = 0; + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl* ctrl, + mfxFrameSurface1* surface, + mfxBitstream* bs, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoDECODEBase { +public: + virtual ~MFXVideoDECODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus DecodeHeader(mfxBitstream* bs, mfxVideoParam* par) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + + virtual mfxStatus GetDecodeStat(mfxDecodeStat* stat) = 0; + virtual mfxStatus GetPayload(mfxU64* ts, mfxPayload* payload) = 0; + virtual mfxStatus SetSkipMode(mfxSkipMode mode) = 0; + virtual mfxStatus DecodeFrameAsync(mfxBitstream* bs, + mfxFrameSurface1* surface_work, + mfxFrameSurface1** surface_out, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoVPPBase { +public: + virtual ~MFXVideoVPPBase() {} + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest request[2]) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetVPPStat(mfxVPPStat* stat) = 0; + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1* in, + mfxFrameSurface1* out, + mfxExtVppAuxData* aux, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1* in, mfxFrameSurface1** out) = 0; +}; + +class MFXVideoSession : public MFXVideoSessionBase { +public: + MFXVideoSession(void) { + m_session = (mfxSession)0; +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + m_loader = (mfxLoader)0; +#endif + } + virtual ~MFXVideoSession(void) { + Close(); + } + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion *ver) override { +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + mfxInitParam par = {}; + par.Implementation = impl; + par.Version = *ver; + return InitSession(par); +#else + return MFXInit(impl, ver, &m_session); +#endif + } + virtual mfxStatus InitEx(mfxInitParam par) override { +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + return InitSession(par); +#else + return MFXInitEx(par, &m_session); +#endif + } + virtual mfxStatus Close(void) override { +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + if (m_session) { + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + if (m_loader) { + MFXUnload(m_loader); + m_loader = (mfxLoader)0; + } + return mfxRes; + } + else { + return MFX_ERR_NONE; + } +#else + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + return mfxRes; +#endif + } + + virtual mfxStatus QueryIMPL(mfxIMPL *impl) override { + return MFXQueryIMPL(m_session, impl); + } + virtual mfxStatus QueryVersion(mfxVersion *version) override { + return MFXQueryVersion(m_session, version); + } + + virtual mfxStatus JoinSession(mfxSession child_session) override { + return MFXJoinSession(m_session, child_session); + } + virtual mfxStatus DisjoinSession() override { + return MFXDisjoinSession(m_session); + } + virtual mfxStatus CloneSession(mfxSession *clone) override { + return MFXCloneSession(m_session, clone); + } + virtual mfxStatus SetPriority(mfxPriority priority) override { + return MFXSetPriority(m_session, priority); + } + virtual mfxStatus GetPriority(mfxPriority *priority) override { + return MFXGetPriority(m_session, priority); + } + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator *allocator) override { + return MFXVideoCORE_SetFrameAllocator(m_session, allocator); + } + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) override { + return MFXVideoCORE_SetHandle(m_session, type, hdl); + } + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *hdl) override { + return MFXVideoCORE_GetHandle(m_session, type, hdl); + } + virtual mfxStatus QueryPlatform(mfxPlatform *platform) override { + return MFXVideoCORE_QueryPlatform(m_session, platform); + } + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) override { + return MFXVideoCORE_SyncOperation(m_session, syncp, wait); + } + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPP (mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP (m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual operator mfxSession(void) override { + return m_session; + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session + +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + mfxLoader m_loader; + + inline void InitVariant(mfxVariant *var, mfxU32 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U32; + var->Data.U32 = data; + } + + inline void InitVariant(mfxVariant *var, mfxU16 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U16; + var->Data.U16 = data; + } + + inline void InitVariant(mfxVariant *var, mfxHDL data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_PTR; + var->Data.Ptr = data; + } + + template + mfxStatus CreateConfig(varDataType data, const char *propertyName) { + mfxConfig cfg = MFXCreateConfig(m_loader); + if (cfg == nullptr) + return MFX_ERR_NULL_PTR; + + mfxVariant variant; + InitVariant(&variant, data); + + return MFXSetConfigFilterProperty(cfg, (mfxU8 *)propertyName, variant); + } + + mfxStatus InitSession(mfxInitParam par) { + // already initialized + if (m_session) + return MFX_ERR_NONE; + + m_loader = MFXLoad(); + if (!m_loader) + return MFX_ERR_NOT_FOUND; + + mfxStatus mfxRes = MFX_ERR_NONE; + + mfxU32 implBaseType = MFX_IMPL_BASETYPE(par.Implementation); + + // select implementation type + switch (implBaseType) { + case MFX_IMPL_AUTO: + case MFX_IMPL_AUTO_ANY: + break; + + case MFX_IMPL_SOFTWARE: + mfxRes = CreateConfig(MFX_IMPL_TYPE_SOFTWARE, "mfxImplDescription.Impl"); + break; + + case MFX_IMPL_HARDWARE: + case MFX_IMPL_HARDWARE_ANY: + case MFX_IMPL_HARDWARE2: + case MFX_IMPL_HARDWARE3: + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(MFX_IMPL_TYPE_HARDWARE, "mfxImplDescription.Impl"); + break; + + default: + mfxRes = MFX_ERR_UNSUPPORTED; + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // select adapter index (if specified) + // see notes below about how VendorImplID is interpreted for each acceleration mode + switch (implBaseType) { + case MFX_IMPL_HARDWARE: + mfxRes = CreateConfig(0, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE2: + mfxRes = CreateConfig(1, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE3: + mfxRes = CreateConfig(2, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(3, "mfxImplDescription.VendorImplID"); + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + mfxU32 implAccelMode = MFX_IMPL_ACCELMODE(par.Implementation); + if (implAccelMode == MFX_IMPL_VIA_D3D9) { + // D3D9 - because VendorImplID corresponds to DXGI adapter index (DX11 enumeration), + // this may not map directly to D3D9 index in multi-adapter/multi-monitor configurations + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D9, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_D3D11) { + // D3D11 - VendorImplID corresponds to DXGI adapter index + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D11, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_VAAPI) { + // VAAPI - in general MFXInitEx treats any HARDWAREn the same way (relies on application to pass + // correct VADisplay via SetHandle), but 2.x RT only reports actual number of adapters + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_VAAPI, + "mfxImplDescription.AccelerationMode"); + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set required API level + mfxRes = + CreateConfig(par.Version.Version, "mfxImplDescription.ApiVersion.Version"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set GPUCopy parameter + if (par.GPUCopy) { + mfxRes = CreateConfig(par.GPUCopy, "DeviceCopy"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + + // ExternalThreads was deprecated in API 2.x along with MFXDoWork() + if (par.ExternalThreads) { + return MFX_ERR_UNSUPPORTED; + } + + // pass extBufs + if (par.NumExtParam) { + for (mfxU32 idx = 0; idx < par.NumExtParam; idx++) { + mfxRes = CreateConfig(par.ExtParam[idx], "ExtBuffer"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + } + + // create session with highest priority implementation remaining after filters + mfxRes = MFXCreateSession(m_loader, 0, &m_session); + + return mfxRes; + } +#endif + +private: + MFXVideoSession(const MFXVideoSession &); + void operator=(MFXVideoSession &); +}; + +class MFXVideoENCODE : public MFXVideoENCODEBase { +public: + explicit MFXVideoENCODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoENCODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoENCODE_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoENCODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoENCODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoENCODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoENCODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoENCODE_GetVideoParam(m_session, par); + } + virtual mfxStatus GetEncodeStat(mfxEncodeStat *stat) override { + return MFXVideoENCODE_GetEncodeStat(m_session, stat); + } + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl *ctrl, + mfxFrameSurface1 *surface, + mfxBitstream *bs, + mfxSyncPoint *syncp) override { + return MFXVideoENCODE_EncodeFrameAsync(m_session, ctrl, surface, bs, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoENCODE(const MFXVideoENCODE& other); + MFXVideoENCODE& operator=(const MFXVideoENCODE& other); +}; + +class MFXVideoDECODE : public MFXVideoDECODEBase { +public: + explicit MFXVideoDECODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoDECODE_Query(m_session, in, out); + } + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) override { + return MFXVideoDECODE_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoDECODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoDECODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoDECODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoDECODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoDECODE_GetVideoParam(m_session, par); + } + + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) override { + return MFXVideoDECODE_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) override { + return MFXVideoDECODE_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) override { + return MFXVideoDECODE_SetSkipMode(m_session, mode); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, + mfxFrameSurface1 *surface_work, + mfxFrameSurface1 **surface_out, + mfxSyncPoint *syncp) override { + return MFXVideoDECODE_DecodeFrameAsync(m_session, bs, surface_work, surface_out, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoDECODE(const MFXVideoDECODE& other); + MFXVideoDECODE& operator=(const MFXVideoDECODE& other); +}; + +class MFXVideoVPP : public MFXVideoVPPBase { +public: + explicit MFXVideoVPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoVPP(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoVPP_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2]) override { + return MFXVideoVPP_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoVPP_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoVPP_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoVPP_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoVPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetVPPStat(mfxVPPStat *stat) override { + return MFXVideoVPP_GetVPPStat(m_session, stat); + } + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in, + mfxFrameSurface1 *out, + mfxExtVppAuxData *aux, + mfxSyncPoint *syncp) override { + return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp); + } + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP(m_session, output_surf); + } + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1 *in, mfxFrameSurface1 **out) override { + return MFXVideoVPP_ProcessFrameAsync(m_session, in, out); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoVPP(const MFXVideoVPP& other); + MFXVideoVPP& operator=(const MFXVideoVPP& other); +}; + +class MFXVideoDECODE_VPP +{ +public: + explicit MFXVideoDECODE_VPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE_VPP(void) { + Close(); + } + + virtual mfxStatus Init(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Init(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus Reset(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Reset(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus GetChannelParam(mfxVideoChannelParam *par, mfxU32 channel_id) { + return MFXVideoDECODE_VPP_GetChannelParam(m_session, par, channel_id); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, mfxU32* skip_channels, mfxU32 num_skip_channels, mfxSurfaceArray **surf_array_out) { + return MFXVideoDECODE_VPP_DecodeFrameAsync(m_session, bs, skip_channels, num_skip_channels, surf_array_out); + } + + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) { + return MFXVideoDECODE_VPP_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus Close(void) { + return MFXVideoDECODE_VPP_Close(m_session); + } + virtual mfxStatus GetVideoParam(mfxVideoParam *par) { + return MFXVideoDECODE_VPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) { + return MFXVideoDECODE_VPP_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) { + return MFXVideoDECODE_VPP_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) { + return MFXVideoDECODE_VPP_SetSkipMode(m_session, mode); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoDECODE_VPP(const MFXVideoDECODE_VPP& other); + MFXVideoDECODE_VPP& operator=(const MFXVideoDECODE_VPP& other); +}; + +#endif //__MFXVIDEOPLUSPLUS_H diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxvideo.h b/third-party/IntelVPL/arm64/include/vpl/mfxvideo.h new file mode 100644 index 000000000..4aab2d87f --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxvideo.h @@ -0,0 +1,1095 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXVIDEO_H__ +#define __MFXVIDEO_H__ +#include "mfxsession.h" +#include "mfxstructures.h" +#include "mfxmemory.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the API callback functions Alloc, Lock, Unlock, GetHDL, and Free that the + implementation might use for allocating internal frames. Applications that operate on OS-specific video surfaces must + implement these API callback functions. + + Using the default allocator implies that frame data passes in or out of functions through pointers, + as opposed to using memory IDs. + + Behavior is undefined when using an incompletely defined external allocator. + \verbatim embed:rst + See the :ref:`Memory Allocation and External Allocators section ` for additional information. + \endverbatim +*/ +typedef struct { + mfxU32 reserved[4]; + mfxHDL pthis; /*!< Pointer to the allocator object. */ + + /*! + @brief Allocates surface frames. For decoders, MFXVideoDECODE_Init calls Alloc only once. That call + includes all frame allocation requests. For encoders, MFXVideoENCODE_Init calls Alloc twice: once for the + input surfaces and again for the internal reconstructed surfaces. If application also calls this function explicitly, + it should have the logic to avoid duplicated allocation for the same request. + + If two library components must share DirectX* surfaces, this function should pass the pre-allocated surface + chain to the library instead of allocating new DirectX surfaces. + \verbatim embed:rst + See the :ref:`Surface Pool Allocation section ` for additional information. + \endverbatim + + @param[in] pthis Pointer to the allocator object. + @param[in] request Pointer to the mfxFrameAllocRequest structure that specifies the type and number of required frames. + @param[out] response Pointer to the mfxFrameAllocResponse structure that retrieves frames actually allocated. + @return + MFX_ERR_NONE The function successfully allocated the memory block. \n + MFX_ERR_MEMORY_ALLOC The function failed to allocate the video frames. \n + MFX_ERR_UNSUPPORTED The function does not support allocating the specified type of memory. + */ + mfxStatus (MFX_CDECL *Alloc) (mfxHDL pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response); + + /*! + @brief Locks a frame and returns its pointer. + @param[in] pthis Pointer to the allocator object. + @param[in] mid Memory block ID. + @param[out] ptr Pointer to the returned frame structure. + @return + MFX_ERR_NONE The function successfully locked the memory block. \n + MFX_ERR_LOCK_MEMORY This function failed to lock the frame. + */ + mfxStatus (MFX_CDECL *Lock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr); + + /*! + @brief Unlocks a frame and invalidates the specified frame structure. + @param[in] pthis Pointer to the allocator object. + @param[in] mid Memory block ID. + @param[out] ptr Pointer to the frame structure. This pointer can be NULL. + @return + MFX_ERR_NONE The function successfully locked the memory block. + */ + mfxStatus (MFX_CDECL *Unlock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr); + + /*! + @brief Returns the OS-specific handle associated with a video frame. If the handle is a COM interface, + the reference counter must increase. The library will release the interface afterward. + @param[in] pthis Pointer to the allocator object. + @param[in] mid Memory block ID. + @param[out] handle Pointer to the returned OS-specific handle. + @return + MFX_ERR_NONE The function successfully returned the OS-specific handle. \n + MFX_ERR_UNSUPPORTED The function does not support obtaining OS-specific handle.. + @note For D3D11 surfaces, GetHDL should return an mfxHDLPair instead of an mfxHDL. In the mfxHDLPair struct, + mfxHDLPair.first should be is set to the Texture2D address, and mfxHDLPair.second should be set to the array index. + */ + mfxStatus (MFX_CDECL *GetHDL) (mfxHDL pthis, mfxMemId mid, mfxHDL *handle); + + /*! + @brief De-allocates all allocated frames. + MFXClose will call this function. If application also calls this function, it should have logic to avoid double free. + @param[in] pthis Pointer to the allocator object. + @param[in] response Pointer to the mfxFrameAllocResponse structure returned by the Alloc function. + @return + MFX_ERR_NONE The function successfully de-allocated the memory block. + */ + mfxStatus (MFX_CDECL *Free) (mfxHDL pthis, mfxFrameAllocResponse *response); +} mfxFrameAllocator; +MFX_PACK_END() + +/*! + @brief + Sets the external allocator callback structure for frame allocation. + + If the allocator argument is NULL, the library uses the + default allocator, which allocates frames from system memory or hardware devices. The behavior of the API is undefined if it uses this + function while the previous allocator is in use. A general guideline is to set the allocator immediately after initializing the session. + + @param[in] session Session handle. + @param[in] allocator Pointer to the mfxFrameAllocator structure + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_SetFrameAllocator(mfxSession session, mfxFrameAllocator *allocator); + +/*! + @brief + Sets any essential system handle that the library might use. The handle must remain valid until after + the application calls the MFXClose function. + + If the specified system handle is a COM interface, the reference counter of the COM interface will increase. + The counter will decrease when the session closes. + + @param[in] session Session handle. + @param[in] type Handle type + @param[in] hdl Handle to be set + + @returns + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNDEFINED_BEHAVIOR The same handle is redefined. + For example, the function has been called twice with the same handle type or an + internal handle has been created before this function call. + MFX_ERR_DEVICE_FAILED The SDK cannot initialize using the handle. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_SetHandle(mfxSession session, mfxHandleType type, mfxHDL hdl); + +/*! + @brief + Obtains system handles previously set by the MFXVideoCORE_SetHandle function. + + If the handler is a COM interface, the reference counter of the interface increases. + The calling application must release the COM interface. + + @param[in] session Session handle. + @param[in] type Handle type + @param[in] hdl Pointer to the handle to be set + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNDEFINED_BEHAVIOR Specified handle type not found. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_GetHandle(mfxSession session, mfxHandleType type, mfxHDL *hdl); + +/*! + @brief + Returns information about current hardware platform in the Legacy mode. + + @param[in] session Session handle. + @param[out] platform Pointer to the mfxPlatform structure + + @return + MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.19. + + Notes: Deprecated mfxPlatform::CodeName will be filled with MFX_PLATFORM_MAXIMUM for future new platforms. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_QueryPlatform(mfxSession session, mfxPlatform* platform); + +/*! + @brief + Initiates execution of an asynchronous function not already started and returns the status code after the specified asynchronous operation completes. + If wait is zero, the function returns immediately + + @param[in] session Session handle. + @param[in] syncp Sync point + @param[in] wait wait time in milliseconds + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NONE_PARTIAL_OUTPUT The function completed successfully, bitstream contains a portion of the encoded frame according to required granularity. \n + MFX_WRN_IN_EXECUTION The specified asynchronous function is in execution. \n + MFX_ERR_ABORTED The specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, mfxU32 wait); + +/*! Maximum allowed length of parameter key and value strings, in bytes. */ +#define MAX_PARAM_STRING_LENGTH 4096 + +/*! The mfxStructureType enumerator specifies the structure type for configuration with the string interface. */ +typedef enum { + MFX_STRUCTURE_TYPE_UNKNOWN = 0, /*!< Unknown structure type. */ + + MFX_STRUCTURE_TYPE_VIDEO_PARAM = 1, /*!< Structure of type mfxVideoParam. */ +} mfxStructureType; + +#define MFX_CONFIGINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/* Specifies config interface. */ +typedef struct mfxConfigInterface { + mfxHDL Context; /*!< The context of the config interface. User should not touch (change, set, null) this pointer. */ + mfxStructVersion Version; /*!< The version of the structure. */ + + /*! @brief + Sets a parameter to specified value in the current session. If a parameter already has a value, + the new value will overwrite the existing value. + + @param[in] config_interface The valid interface returned by calling MFXQueryInterface(). + @param[in] key Null-terminated string containing parameter to set. The string length must be < MAX_PARAM_STRING_LENGTH bytes. + @param[in] value Null-terminated string containing value to which key should be set. The string length must be < MAX_PARAM_STRING_LENGTH bytes. + value will be converted from a string to the expected data type for the given key, or return an error if conversion fails. + @param[in] struct_type Type of structure pointed to by structure. + @param[out] structure If and only if SetParameter returns MFX_ERR_NONE, the contents of structure (including any attached extension + buffers) will be updated according to the provided key and value. If key modifies a field in an extension buffer + which is not already attached, the function will return MFX_ERR_MORE_EXTBUFFER and fill ext_buffer with the header for + the required mfxExtBuffer type. + @param[out] ext_buffer If and only if SetParameter returns MFX_ERR_MORE_EXTBUFFER, ext_buffer will contain the header for a buffer + of type mfxExtBuffer. The caller should allocate a buffer of the size ext_buffer.BufferSz, copy the header in ext_buffer + to the start of this new buffer, attach this buffer to videoParam, then call SetParameter again. Otherwise, the + contents of ext_buffer will be cleared. + @return + MFX_ERR_NONE The function completed successfully. + MFX_ERR_NULL_PTR If key, value, videoParam, and/or ext_buffer is NULL. + MFX_ERR_NOT_FOUND If key contains an unknown parameter name. + MFX_ERR_UNSUPPORTED If value is of the wrong format for key (for example, a string is provided where an integer is required) + or if value cannot be converted into any valid data type. + MFX_ERR_INVALID_VIDEO_PARAM If length of key or value is >= MAX_PARAM_STRING_LENGTH or is zero (empty string). + MFX_ERR_MORE_EXTBUFFER If key requires modifying a field in an mfxExtBuffer which is not attached. Caller must allocate and attach + the buffer type provided in ext_buffer then call the function again. + + @since This function is available since API version 2.10. + */ + mfxStatus (MFX_CDECL *SetParameter)(struct mfxConfigInterface *config_interface, const mfxU8* key, const mfxU8* value, mfxStructureType struct_type, mfxHDL structure, mfxExtBuffer *ext_buffer); + + mfxHDL reserved[16]; +} mfxConfigInterface; +MFX_PACK_END() + +/*! Alias for returning interface of type mfxConfigInterface. */ +#define MFXGetConfigInterface(session, piface) MFXVideoCORE_GetHandle((session), MFX_HANDLE_CONFIG_INTERFACE, (mfxHDL *)(piface)) + +/* VideoENCODE */ + +/*! + @brief + Works in either of four modes: + + @li If the @p in parameter is zero, the function returns the class configurability in the output structure. The application must set to zero the fields it wants to check for support. If the field is supported, function sets non-zero value to this field, otherwise it would be ignored. It indicates that the SDK implementation can configure the field with Init. + + @li If the @p in parameter is non-zero, the function checks the validity of the fields in the input structure. Then the function returns the corrected values in + the output structure. If there is insufficient information to determine the validity or correction is impossible, the function zeroes the fields. + This feature can verify whether the implementation supports certain profiles, levels or bitrates. + + @li If the @p in parameter is non-zero and mfxExtEncoderResetOption structure is attached to it, the function queries for the outcome of the MFXVideoENCODE_Reset function + and returns it in the mfxExtEncoderResetOption structure attached to out. The query function succeeds if a reset is possible and returns an error otherwise. Unlike other + modes that are independent of the encoder state, this one checks if reset is possible in the present encoder state. + This mode also requires a completely defined mfxVideoParam structure, unlike other modes that support partially defined configurations. + See mfxExtEncoderResetOption description for more details. + + @li If the @p in parameter is non-zero and mfxExtEncoderCapability structure is attached to it, the function returns encoder capability in the mfxExtEncoderCapability structure + attached to out. It is recommended to fill in the mfxVideoParam structure and set the hardware acceleration device handle before calling the function in this mode. + + The application can call this function before or after it initializes the encoder. The ``CodecId`` field of the output structure is a mandated field (to be filled by the + application) to identify the coding standard. + + @param[in] session Session handle. + @param[in] in Pointer to the mfxVideoParam structure as input. + @param[out] out Pointer to the mfxVideoParam structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function failed to identify a specific implementation for the required features. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); + +/*! + @brief + Returns minimum and suggested numbers of the input frame surfaces required for encoding initialization and their type. + + Init will call the external allocator for the required frames with the same set of numbers. + This function does not validate I/O parameters except those used in calculating the number of input surfaces. + + The use of this function is recommended. + \verbatim embed:rst + For more information, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim + + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure as input. + @param[in] request Pointer to the mfxFrameAllocRequest structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); + +/*! + @brief + Allocates memory and prepares tables and necessary structures for encoding. + + This function also does extensive validation to ensure if the + configuration, as specified in the input parameters, is supported. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The function is called twice without a close; + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Init(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Stops the current encoding operation and restores internal structures or parameters for a new encoding operation, possibly with new parameters. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Reset(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Terminates the current encoding operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Close(mfxSession session); + +/*! + @brief + Retrieves current working parameters to the specified output structure. + + If extended buffers are to be returned, the + application must allocate those extended buffers and attach them as part of the output structure. + The application can retrieve a copy of the bitstream header by attaching the mfxExtCodingOptionSPSPPS structure to the mfxVideoParam structure. + + @param[in] session Session handle. + @param[in] par Pointer to the corresponding parameter structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_GetVideoParam(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Obtains statistics collected during encoding. + + @param[in] session Session handle. + @param[in] stat Pointer to the mfxEncodeStat structure. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_GetEncodeStat(mfxSession session, mfxEncodeStat *stat); + +/*! + @brief + Takes a single input frame in either encoded or display order and generates its output bitstream. + + In the case of encoded ordering, the mfxEncodeCtrl + structure must specify the explicit frame type. In the case of display ordering, this function handles frame order shuffling according to the GOP structure + parameters specified during initialization. + + Since encoding may process frames differently from the input order, not every call of the function generates output and the function returns MFX_ERR_MORE_DATA. + If the encoder needs to cache the frame, the function locks the frame. The application should not alter the frame until the encoder unlocks the frame. + If there is output (with return status MFX_ERR_NONE), the return is a frame's worth of bitstream. + + It is the calling application's responsibility to ensure that there is sufficient space in the output buffer. The value ``BufferSizeInKB`` in the + mfxVideoParam structure at encoding initialization specifies the maximum possible size for any compressed frames. This value can also be obtained from the + MFXVideoENCODE_GetVideoParam function after encoding initialization. + + To mark the end of the encoding sequence, call this function with a NULL surface pointer. Repeat the call to drain any remaining internally cached bitstreams + (one frame at a time) until MFX_ERR_MORE_DATA is returned. + + This function is asynchronous. + + @param[in] session Session handle. + @param[in] ctrl Pointer to the mfxEncodeCtrl structure for per-frame encoding control; this parameter is optional (it can be NULL) if the encoder works in the display order mode. + ctrl can be freed right after successful MFXVideoENCODE_EncodeFrameAsync (it is copied inside), but not the ext buffers attached to this ctrl. + If the ext buffers are allocated by the user, do not move, alter or delete unless surface.Data.Locked is zero. + @param[in] surface Pointer to the frame surface structure. + For surfaces allocated by oneAPI Video Processing Library (oneVPL) RT it is safe to call mfxFrameSurface1::FrameInterface->Release after successful MFXVideoENCODE_EncodeFrameAsync. + If it is allocated by user, do not move, alter or delete unless surface.Data.Locked is zero. + @param[out] bs Pointer to the output bitstream. + @param[out] syncp Pointer to the returned sync point associated with this operation. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NOT_ENOUGH_BUFFER The bitstream buffer size is insufficient. \n + MFX_ERR_MORE_DATA The function requires more data to generate any output. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM Inconsistent parameters detected not conforming to Configuration Parameter Constraints. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_EncodeFrameAsync(mfxSession session, mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxSyncPoint *syncp); + +/*! + @brief + Works in one of two modes: + + @li If the @p in parameter is zero, the function returns the class configurability in the output structure. A non-zero value in each field of the output structure + indicates that the field is configurable by the implementation with the MFXVideoDECODE_Init function. + + @li If the @p in parameter is non-zero, the function checks the validity of the fields in the input structure. Then the function returns the corrected values to + the output structure. If there is insufficient information to determine the validity or correction is impossible, the function zeros the fields. This + feature can verify whether the implementation supports certain profiles, levels, or bitrates. + + The application can call this function before or after it initializes the decoder. The ``CodecId`` field of the output structure is a mandated field + (to be filled by the application) to identify the coding standard. + + @param[in] session Session handle. + @param[in] in Pointer to the mfxVideoParam structure as input. + @param[out] out Pointer to the mfxVideoParam structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function failed to identify a specific implementation for the required features. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The decoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ + +mfxStatus MFX_CDECL MFXVideoDECODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); + +/*! + @brief + Parses the input bitstream and fills the mfxVideoParam structure with appropriate values, such as resolution and frame rate, for the Init API function. + + The application can then pass the resulting structure to the MFXVideoDECODE_Init function for decoder initialization. + + An application can call this API function at any time before or after decoder initialization. If the library finds a sequence header in the bitstream, the function + moves the bitstream pointer to the first bit of the sequence header. Otherwise, the function moves the bitstream pointer close to the end of the bitstream buffer but leaves enough data in the buffer to avoid possible loss of start code. + + The ``CodecId`` field of the mfxVideoParam structure is a mandated field (to be filled by the application) to identify the coding standard. + + The application can retrieve a copy of the bitstream header, by attaching the mfxExtCodingOptionSPSPPS structure to the mfxVideoParam structure. + + @param[in] session Session handle. + @param[in] bs Pointer to the bitstream. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + - MFX_ERR_NONE The function successfully filled the structure. It does not mean that the stream can be decoded by the library. + The application should call MFXVideoDECODE_Query function to check if decoding of the stream is supported. \n + - MFX_ERR_MORE_DATA The function requires more bitstream data. \n + - MFX_ERR_UNSUPPORTED ``CodecId`` field of the mfxVideoParam structure indicates some unsupported codec. \n + - MFX_ERR_INVALID_HANDLE Session is not initialized. \n + - MFX_ERR_NULL_PTR @p bs or @p par pointer is NULL. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_DecodeHeader(mfxSession session, mfxBitstream *bs, mfxVideoParam *par); + +/*! + @brief + Returns minimum and suggested numbers of the output frame surfaces required for decoding initialization and their type. + + Init will call the external allocator for the required frames with the same set of numbers. + The use of this function is recommended. + \verbatim embed:rst + For more information, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim + + The ``CodecId`` field of the mfxVideoParam structure is a mandated field (to be filled by the application) to identify the coding standard. + This function does not validate I/O parameters except those used in calculating the number of output surfaces. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure as input. + @param[in] request Pointer to the mfxFrameAllocRequest structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); + +/*! + @brief + Allocates memory and prepares tables and necessary structures for encoding. + + This function also does extensive validation to ensure if the + configuration, as specified in the input parameters, is supported. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The function is called twice without a close. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_Init(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Stops the current decoding operation and restores internal structures or parameters for a new decoding operation. + + Reset serves two purposes: + + @li It recovers the decoder from errors. + @li It restarts decoding from a new position + + The function resets the old sequence header (sequence parameter set in H.264, or sequence header in MPEG-2 and VC-1). The decoder will expect a new sequence header + before it decodes the next frame and will skip any bitstream before encountering the new sequence header. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected that video parameters are wrong or they conflict with initialization parameters. Reset is impossible. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_Reset(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Terminates the current decoding operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_Close(mfxSession session); + +/*! + @brief + Retrieves current working parameters to the specified output structure. + + If extended buffers are to be returned, the + application must allocate those extended buffers and attach them as part of the output structure. + The application can retrieve a copy of the bitstream header, by attaching the mfxExtCodingOptionSPSPPS structure to the mfxVideoParam structure. + + @param[in] session Session handle. + @param[in] par Pointer to the corresponding parameter structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_GetVideoParam(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Obtains statistics collected during decoding. + + @param[in] session Session handle. + @param[in] stat Pointer to the mfxDecodeStat structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_GetDecodeStat(mfxSession session, mfxDecodeStat *stat); + +/*! + @brief + Sets the decoder skip mode. + + The application may use this API function to increase decoding performance by sacrificing output quality. Increasing the skip + level first results in skipping of some decoding operations like deblocking and then leads to frame skipping; first B, then P. Particular details are platform dependent. + + @param[in] session Session handle. + @param[in] mode Decoder skip mode. See the mfxSkipMode enumerator for details. + + @return + MFX_ERR_NONE The function completed successfully and the output surface is ready for decoding \n + MFX_WRN_VALUE_NOT_CHANGED The skip mode is not affected as the maximum or minimum skip range is reached. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_SetSkipMode(mfxSession session, mfxSkipMode mode); + +/*! + @brief + Extracts user data (MPEG-2) or SEI (H.264) messages from the bitstream. + + Internally, the decoder implementation stores encountered user data or + SEI messages. The application may call this API function multiple times to retrieve the user data or SEI messages, one at a time. + + If there is no payload available, the function returns with payload->NumBit=0. + + @param[in] session Session handle. + @param[in] ts Pointer to the user data time stamp in units of 90 KHz; divide ts by 90,000 (90 KHz) to obtain the time in seconds; the time stamp matches the payload + with a specific decoded frame. + @param[in] payload Pointer to the mfxPayload structure; the payload contains user data in MPEG-2 or SEI messages in H.264. + + @return + MFX_ERR_NONE The function completed successfully and the output buffer is ready for decoding. \n + MFX_ERR_NOT_ENOUGH_BUFFER The payload buffer size is insufficient. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_GetPayload(mfxSession session, mfxU64 *ts, mfxPayload *payload); + +/*! + @brief + Decodes the input bitstream to a single output frame. + + The @p surface_work parameter provides a working frame buffer for the decoder. The application should allocate the working frame buffer, which stores decoded frames. + If the function requires caching frames after decoding, it locks the frames and the application must provide a new frame buffer in the next call. + + If, and only if, the function returns MFX_ERR_NONE, the pointer @p surface_out points to the output frame in the display order. If there are no further frames, + the function will reset the pointer to zero and return the appropriate status code. + + Before decoding the first frame, a sequence header (sequence parameter set in H.264 or sequence header in MPEG-2 and VC-1) must be present. The function skips any + bitstreams before it encounters the new sequence header. + + The input bitstream @p bs can be of any size. If there are not enough bits to decode a frame, the function returns MFX_ERR_MORE_DATA, and consumes all input bits except if + a partial start code or sequence header is at the end of the buffer. In this case, the function leaves the last few bytes in the bitstream buffer. + If there is more incoming bitstream, the application should append the incoming bitstream to the bitstream buffer. Otherwise, the application should ignore the + remaining bytes in the bitstream buffer and apply the end of stream procedure described below. + + The application must set @p bs to NULL to signal end of stream. The application may need to call this API function several times to drain any internally cached frames until the + function returns MFX_ERR_MORE_DATA. + + If more than one frame is in the bitstream buffer, the function decodes until the buffer is consumed. The decoding process can be interrupted for events such as if the + decoder needs additional working buffers, is readying a frame for retrieval, or encountering a new header. In these cases, the function returns appropriate status code + and moves the bitstream pointer to the remaining data. + + The decoder may return MFX_ERR_NONE without taking any data from the input bitstream buffer. If the application appends additional data to the bitstream buffer, it + is possible that the bitstream buffer may contain more than one frame. It is recommended that the application invoke the function repeatedly until the function + returns MFX_ERR_MORE_DATA, before appending any more data to the bitstream buffer. + + Starting from API 2.0 it is possible to pass NULL instead of surface_work. In such case runtime will allocate output frames internally. + + This function is asynchronous. + + @param[in] session Session handle. + @param[in] bs Pointer to the input bitstream. + @param[in] surface_work Pointer to the working frame buffer for the decoder. + @param[out] surface_out Pointer to the output frame in the display order. + @param[out] syncp Pointer to the sync point associated with this operation. + + @return + MFX_ERR_NONE The function completed successfully and the output surface is ready for decoding. \n + MFX_ERR_MORE_DATA The function requires more bitstream at input before decoding can proceed. \n + MFX_ERR_MORE_SURFACE The function requires more frame surface at output before decoding can proceed. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_WRN_VIDEO_PARAM_CHANGED The decoder detected a new sequence header in the bitstream. Video parameters may have changed. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The decoder detected incompatible video parameters in the bitstream and failed to follow them. \n + MFX_ERR_REALLOC_SURFACE Bigger surface_work required. May be returned only if mfxInfoMFX::EnableReallocRequest was set to ON during initialization. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED Timeout expired for internal output frame allocation (if set with mfxExtAllocationHints and NULL passed as surface_work). Repeat the call in a few milliseconds or re-initialize decoder with higher surface limit. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp); + +/* VideoVPP */ + +/*! + @brief + Works in one of two modes: + + @li If the @p in pointer is zero, the function returns the class configurability in the output structure. A non-zero value in a field indicates that the + implementation can configure it with Init. + + @li If the @p in parameter is non-zero, the function checks the validity of the fields in the input structure. Then the function returns the corrected values to + the output structure. If there is insufficient information to determine the validity or correction is impossible, the function zeroes the fields. + + The application can call this function before or after it initializes the preprocessor. + + @param[in] session Session handle. + @param[in] in Pointer to the mfxVideoParam structure as input. + @param[out] out Pointer to the mfxVideoParam structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The implementation does not support the specified configuration. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The video processing may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); + +/*! + @brief + Returns minimum and suggested numbers of the input frame surfaces required for video processing initialization and their type. + + The parameter ``request[0]`` refers to the input requirements; ``request[1]`` refers to output requirements. Init will call the external allocator for the + required frames with the same set of numbers. + This function does not validate I/O parameters except those used in calculating the number of input surfaces. + + The use of this function is recommended. + \verbatim embed:rst + For more information, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure as input. + @param[in] request Pointer to the mfxFrameAllocRequest structure; use ``request[0]`` for input requirements and ``request[1]`` for output requirements for video processing. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The video processing may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest request[2]); + +/*! + @brief + Allocates memory and prepares tables and necessary structures for video processing. + + This function also does extensive validation to ensure if the + configuration, as specified in the input parameters, is supported. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The video processing may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The function is called twice without a close. \n + MFX_WRN_FILTER_SKIPPED The VPP skipped one or more filters requested by the application. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Init(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Stops the current video processing operation and restores internal structures or parameters for a new operation + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected that video parameters are wrong or they conflict with initialization parameters. Reset is impossible. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Reset(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Terminates the current video processing operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return MFX_ERR_NONE + The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Close(mfxSession session); + +/*! + @brief + Retrieves current working parameters to the specified output structure. + + If extended buffers are to be returned, the + application must allocate those extended buffers and attach them as part of the output structure. + + @param[in] session Session handle. + @param[in] par Pointer to the corresponding parameter structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_GetVideoParam(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Obtains statistics collected during video processing. + + @param[in] session Session handle. + @param[in] stat Pointer to the mfxVPPStat structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_GetVPPStat(mfxSession session, mfxVPPStat *stat); + +/*! + @brief + Processes a single input frame to a single output frame. + + Retrieval of the auxiliary data is optional; the encoding process may use it. + The video processing process may not generate an instant output given an input. + \verbatim embed:rst + See the :ref:`Video Processing Procedures section` for details on how to + correctly send input and retrieve output. + \endverbatim + + + At the end of the stream, call this function with the input argument ``in=NULL`` to retrieve any remaining frames, until the function returns MFX_ERR_MORE_DATA. + This function is asynchronous. + + @param[in] session Session handle. + @param[in] in Pointer to the input video surface structure. + @param[out] out Pointer to the output video surface structure. + @param[in] aux Optional pointer to the auxiliary data structure. + @param[out] syncp Pointer to the output sync point. + + @return + MFX_ERR_NONE The output frame is ready after synchronization. \n + MFX_ERR_MORE_DATA Need more input frames before VPP can produce an output. \n + MFX_ERR_MORE_SURFACE The output frame is ready after synchronization. Need more surfaces at output for additional output frames available. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_RunFrameVPPAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp); + +/*! + @brief + The function processes a single input frame to a single output frame with internal allocation of output frame. + + At the end of the stream, call this function with the input argument ``in=NULL`` to retrieve any remaining frames, until the function returns MFX_ERR_MORE_DATA. + This function is asynchronous. + + @param[in] session Session handle. + @param[in] in Pointer to the input video surface structure. + @param[out] out Pointer to the output video surface structure which is reference counted object allocated by the library. + + @return + MFX_ERR_NONE The output frame is ready after synchronization. \n + MFX_ERR_MORE_DATA Need more input frames before VPP can produce an output. \n + MFX_ERR_MEMORY_ALLOC The function failed to allocate output video frame. \n + + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED Timeout expired for internal output frame allocation (if set with mfxExtAllocationHints). Repeat the call in a few milliseconds or reinitialize VPP with higher surface limit. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_ProcessFrameAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 **out); + +/*! + @brief + Initialize the SDK in (decode + vpp) mode. The logic of this function is similar to MFXVideoDECODE_Init, + but application has to provide array of pointers to mfxVideoChannelParam and num_channel_param - number of channels. Application is responsible for + memory allocation for mfxVideoChannelParam parameters and for each channel it should specify channel IDs: + mfxVideoChannelParam::mfxFrameInfo::ChannelId. ChannelId should be unique value within one session. ChannelID equals to the 0 + is reserved for the original decoded frame. + The application can attach mfxExtInCrops to mfxVideoChannelParam::ExtParam to annotate input video frame if it wants to enable + letterboxing operation. + @param[in] session SDK session handle. + @param[in] decode_par Pointer to the mfxVideoParam structure which contains initialization parameters for decoder. + @param[in] vpp_par_array Array of pointers to `mfxVideoChannelParam`structures. Each mfxVideoChannelParam contains initialization + parameters for each VPP channel. + @param[in] num_vpp_par Size of array of pointers to mfxVideoChannelParam structures. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or + the combination of them resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility + resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The component is already initialized. \n + MFX_WRN_FILTER_SKIPPED The VPP skipped one or more filters requested by the application. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_Init(mfxSession session, mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_vpp_par); + +/*! + @brief + This function is similar to MFXVideoDECODE_DecodeFrameAsync and inherits all bitstream processing logic. As output, + it allocates and returns @p surf_array_out array of processed surfaces according to the chain of filters specified + by application in MFXVideoDECODE_VPP_Init, including original decoded frames. In the @p surf_array_out, the original + decoded frames are returned through surfaces with mfxFrameInfo::ChannelId == 0, followed by each of the subsequent + frame surfaces for each of the requested mfxVideoChannelParam entries provided to the MFXVideoCECODE_VPP_Init + function. At maximum, the number of frame surfaces return is 1 + the value of @p num_vpp_par to the + MFXVideoDECODE_VPP_Init function, but the application must be prepared to the case when some particular filters + are not ready to output surfaces, so the length of @p surf_array_out will be less. Application should use + mfxFrameInfo::ChannelId parameter to match output surface against configured filter. + + An application must synchronize each output surface from the @p surf_array_out surface array independently. + + @param[in] session SDK session handle. + @param[in] bs Pointer to the input bitstream. + @param[in] skip_channels Pointer to the array of `ChannelId`s which specifies channels with skip output frames. Memory for + the array is allocated by application. + @param[in] num_skip_channels Number of channels addressed by skip_channels. + @param[out] surf_array_out The address of a pointer to the structure with frame surfaces. + + @return + MFX_ERR_NONE The function completed successfully and the output surface is ready for decoding. \n + MFX_ERR_MORE_DATA The function requires more bitstream at input before decoding can proceed. \n + MFX_ERR_MORE_SURFACE The function requires more frame surface at output before decoding can proceed. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_WRN_VIDEO_PARAM_CHANGED The decoder detected a new sequence header in the bitstream. Video parameters may have changed. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The decoder detected incompatible video parameters in the bitstream and failed to follow them. \n + MFX_ERR_NULL_PTR num_skip_channels doesn't equal to 0 when skip_channels is NULL. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxU32* skip_channels, mfxU32 num_skip_channels, mfxSurfaceArray **surf_array_out); + +/*! + @brief + This function is similar to MFXVideoDECODE_Reset and stops the current decoding and vpp operation, and restores internal + structures or parameters for a new decoding plus vpp operation. It resets the state of the decoder and/or all initialized vpp + channels. Applications have to care about draining of buffered frames for decode and all vpp channels before call this function. + The application can attach mfxExtInCrops to mfxVideoChannelParam::ExtParam to annotate input video frame if it wants to enable + letterboxing operation. + + @param[in] session Session handle. + @param[in] decode_par Pointer to the `mfxVideoParam` structure which contains new initialization parameters for decoder. Might + be NULL if application wants to Reset only VPP channels. + @param[in] vpp_par_array Array of pointers to mfxVideoChannelParam structures. Each mfxVideoChannelParam contains new + initialization parameters for each VPP channel. + @param[in] num_vpp_par Size of array of pointers to mfxVideoChannelParam structures. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected that video parameters are wrong or they conflict with initialization parameters. Reset is impossible. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + MFX_ERR_NULL_PTR Both pointers decode_par and vpp_par_array` equal to zero. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_Reset(mfxSession session, mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_vpp_par); + +/*! + @brief + Returns actual VPP parameters for selected channel which should be specified by application through + mfxVideoChannelParam::mfxFrameInfo::ChannelId. + + @param[in] session Session handle. + @param[in] par Pointer to the `mfxVideoChannelParam` structure which allocated by application + @param[in] channel_id specifies the requested channel's info + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR par pointer is NULL. \n + MFX_ERR_NOT_FOUND the library is not able to find VPP channel with such channel_id. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_GetChannelParam(mfxSession session, mfxVideoChannelParam *par, mfxU32 channel_id); + +/*! + @brief + This function is similar to MFXVideoDECODE_Close. It terminates the current decoding and vpp operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 2.1. +*/ + +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_Close(mfxSession session); + +/*! Alias for MFXVideoDECODE_DecodeHeader function. */ +#define MFXVideoDECODE_VPP_DecodeHeader MFXVideoDECODE_DecodeHeader + +/*! Alias for MFXVideoDECODE_GetVideoParam function. */ +#define MFXVideoDECODE_VPP_GetVideoParam MFXVideoDECODE_GetVideoParam + +/*! Alias for MFXVideoDECODE_GetDecodeStat function. */ +#define MFXVideoDECODE_VPP_GetDecodeStat MFXVideoDECODE_GetDecodeStat + +/*! Alias for MFXVideoDECODE_SetSkipMode function. */ +#define MFXVideoDECODE_VPP_SetSkipMode MFXVideoDECODE_SetSkipMode + +/*! Alias for MFXVideoDECODE_GetPayload function. */ +#define MFXVideoDECODE_VPP_GetPayload MFXVideoDECODE_GetPayload + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/third-party/IntelVPL/arm64/include/vpl/mfxvp8.h b/third-party/IntelVPL/arm64/include/vpl/mfxvp8.h new file mode 100644 index 000000000..d2de824fa --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/mfxvp8.h @@ -0,0 +1,65 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXVP8_H__ +#define __MFXVP8_H__ + +#include "mfxdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + MFX_CODEC_VP8 = MFX_MAKEFOURCC('V','P','8',' '), +}; + +/* VP8 CodecProfile*/ +enum { + MFX_PROFILE_VP8_0 = 0+1, + MFX_PROFILE_VP8_1 = 1+1, + MFX_PROFILE_VP8_2 = 2+1, + MFX_PROFILE_VP8_3 = 3+1, +}; + +/* Extended Buffer Ids */ +enum { + /*! + This extended buffer describes VP8 encoder configuration parameters. See the mfxExtVP8CodingOption structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_VP8_CODING_OPTION = MFX_MAKEFOURCC('V','P','8','E'), +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Describes VP8 coding options. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP8_CODING_OPTION. */ + + mfxU16 Version; /*!< Determines the bitstream version. Corresponds to the same VP8 syntax element in frame_tag. */ + mfxU16 EnableMultipleSegments; /*!< Set this option to ON to enable segmentation. This is tri-state option. See the CodingOptionValue + enumerator for values of this option. */ + mfxU16 LoopFilterType; /*!< Select the type of filter (normal or simple). Corresponds to VP8 syntax element filter_type. */ + mfxU16 LoopFilterLevel[4]; /*!< Controls the filter strength. Corresponds to VP8 syntax element loop_filter_level. */ + mfxU16 SharpnessLevel; /*!< Controls the filter sensitivity. Corresponds to VP8 syntax element sharpness_level. */ + mfxU16 NumTokenPartitions; /*!< Specifies number of token partitions in the coded frame. */ + mfxI16 LoopFilterRefTypeDelta[4]; /*!< Loop filter level delta for reference type (intra, last, golden, altref). */ + mfxI16 LoopFilterMbModeDelta[4]; /*!< Loop filter level delta for MB modes. */ + mfxI16 SegmentQPDelta[4]; /*!< QP delta for segment. */ + mfxI16 CoeffTypeQPDelta[5]; /*!< QP delta for coefficient type (YDC, Y2AC, Y2DC, UVAC, UVDC). */ + mfxU16 WriteIVFHeaders; /*!< Set this option to ON to enable insertion of IVF container headers into bitstream. This is tri-state + option. See the CodingOptionValue enumerator for values of this option */ + mfxU32 NumFramesForIVFHeader; /*!< Specifies number of frames for IVF header when WriteIVFHeaders is ON. */ + mfxU16 reserved[223]; +} mfxExtVP8CodingOption; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/third-party/IntelVPL/arm64/include/vpl/preview/README.txt b/third-party/IntelVPL/arm64/include/vpl/preview/README.txt new file mode 100644 index 000000000..14311574c --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/preview/README.txt @@ -0,0 +1,2 @@ +The files in this preview folder are provided as a preview of upcoming features. +The content of this folder may be changed or removed without respect for backward compatibility. \ No newline at end of file diff --git a/third-party/IntelVPL/arm64/include/vpl/preview/legacy/README.txt b/third-party/IntelVPL/arm64/include/vpl/preview/legacy/README.txt new file mode 100644 index 000000000..6944060c7 --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/preview/legacy/README.txt @@ -0,0 +1,25 @@ +The file preview/legacy/mfxvideo++.h is a preview implementation of "class +MFXVideoSession" which takes advantage of API 2.0 functions of the +Intel® Video Processing Library (Intel® VPL) for implementation selection and +session creation. + +Known limitations: + +- The parameter mfxInitParam.ExternalThreads is not supported. + +- The API version returned by MFXVideoSession::QueryVersion() may be different + on platforms for which libmfx-gen is the default runtime implementation. + +- On Windows, accelerators selected using MFX_IMPL_HARDWARE, MFX_IMPL_HARDWARE2, + MFX_IMPL_HARDWARE3, or MFX_IMPL_HARDWARE4 are always enumerated according to + IDXGIFactory::EnumAdapters (i.e. D3D11) indexes, regardless of the + acceleration mode selected. On a multi-monitor or multi-adapter system, D3D9 + and D3D11 adapter indexing may not match. Applications needing to create a + session on a specific D3D9 adapter should instead use the Dispatcher + Configuration Property mfxExtendedDeviceId.DeviceLUID to select the desired + adapter. + +- Identical behavior between the production implementation of mfxvideo++.h and + the preview is not guaranteed. Applications may however define + MFXVIDEO_CPP_USE_DEPRECATED when compiling the preview application to build + with the previous implementation. diff --git a/third-party/IntelVPL/arm64/include/vpl/preview/legacy/mfxvideo++.h b/third-party/IntelVPL/arm64/include/vpl/preview/legacy/mfxvideo++.h new file mode 100644 index 000000000..0c78d785a --- /dev/null +++ b/third-party/IntelVPL/arm64/include/vpl/preview/legacy/mfxvideo++.h @@ -0,0 +1,581 @@ +/*########################################################################### + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ###########################################################################*/ + +#ifndef __MFXVIDEOPLUSPLUS_H +#define __MFXVIDEOPLUSPLUS_H + +#include "vpl/mfx.h" + +#define MFX_IMPL_ACCELMODE(x) (0xff00 & (x)) + +class MFXVideoSessionBase { +public: + virtual ~MFXVideoSessionBase() {} + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion* ver) = 0; + virtual mfxStatus InitEx(mfxInitParam par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus QueryIMPL(mfxIMPL* impl) = 0; + virtual mfxStatus QueryVersion(mfxVersion* version) = 0; + + virtual mfxStatus JoinSession(mfxSession child_session) = 0; + virtual mfxStatus DisjoinSession() = 0; + virtual mfxStatus CloneSession(mfxSession* clone) = 0; + virtual mfxStatus SetPriority(mfxPriority priority) = 0; + virtual mfxStatus GetPriority(mfxPriority* priority) = 0; + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator* allocator) = 0; + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) = 0; + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL* hdl) = 0; + virtual mfxStatus QueryPlatform(mfxPlatform* platform) = 0; + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) = 0; + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPP(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) = 0; + + virtual operator mfxSession(void) = 0; +}; + +class MFXVideoENCODEBase { +public: + virtual ~MFXVideoENCODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetEncodeStat(mfxEncodeStat* stat) = 0; + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl* ctrl, + mfxFrameSurface1* surface, + mfxBitstream* bs, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoDECODEBase { +public: + virtual ~MFXVideoDECODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus DecodeHeader(mfxBitstream* bs, mfxVideoParam* par) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + + virtual mfxStatus GetDecodeStat(mfxDecodeStat* stat) = 0; + virtual mfxStatus GetPayload(mfxU64* ts, mfxPayload* payload) = 0; + virtual mfxStatus SetSkipMode(mfxSkipMode mode) = 0; + virtual mfxStatus DecodeFrameAsync(mfxBitstream* bs, + mfxFrameSurface1* surface_work, + mfxFrameSurface1** surface_out, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoVPPBase { +public: + virtual ~MFXVideoVPPBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest request[2]) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetVPPStat(mfxVPPStat* stat) = 0; + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1* in, + mfxFrameSurface1* out, + mfxExtVppAuxData* aux, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1* in, mfxFrameSurface1** out) = 0; +}; + +class MFXVideoSession : public MFXVideoSessionBase { +public: + MFXVideoSession(void) { + m_session = (mfxSession)0; +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + m_loader = (mfxLoader)0; +#endif + } + virtual ~MFXVideoSession(void) { + Close(); + } + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion *ver) override { +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + mfxInitParam par = {}; + par.Implementation = impl; + par.Version = *ver; + return InitSession(par); +#else + return MFXInit(impl, ver, &m_session); +#endif + } + virtual mfxStatus InitEx(mfxInitParam par) override { +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + return InitSession(par); +#else + return MFXInitEx(par, &m_session); +#endif + } + virtual mfxStatus Close(void) override { +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + if (m_session) { + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + if (m_loader) { + MFXUnload(m_loader); + m_loader = (mfxLoader)0; + } + return mfxRes; + } + else { + return MFX_ERR_NONE; + } +#else + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + return mfxRes; +#endif + } + + virtual mfxStatus QueryIMPL(mfxIMPL *impl) override { + return MFXQueryIMPL(m_session, impl); + } + virtual mfxStatus QueryVersion(mfxVersion *version) override { + return MFXQueryVersion(m_session, version); + } + + virtual mfxStatus JoinSession(mfxSession child_session) override { + return MFXJoinSession(m_session, child_session); + } + virtual mfxStatus DisjoinSession() override { + return MFXDisjoinSession(m_session); + } + virtual mfxStatus CloneSession(mfxSession *clone) override { + return MFXCloneSession(m_session, clone); + } + virtual mfxStatus SetPriority(mfxPriority priority) override { + return MFXSetPriority(m_session, priority); + } + virtual mfxStatus GetPriority(mfxPriority *priority) override { + return MFXGetPriority(m_session, priority); + } + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator *allocator) override { + return MFXVideoCORE_SetFrameAllocator(m_session, allocator); + } + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) override { + return MFXVideoCORE_SetHandle(m_session, type, hdl); + } + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *hdl) override { + return MFXVideoCORE_GetHandle(m_session, type, hdl); + } + virtual mfxStatus QueryPlatform(mfxPlatform *platform) override { + return MFXVideoCORE_QueryPlatform(m_session, platform); + } + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) override { + return MFXVideoCORE_SyncOperation(m_session, syncp, wait); + } + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPP (mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP (m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual operator mfxSession(void) override { + return m_session; + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session + +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + mfxLoader m_loader; + + inline void InitVariant(mfxVariant *var, mfxU32 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U32; + var->Data.U32 = data; + } + + inline void InitVariant(mfxVariant *var, mfxU16 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U16; + var->Data.U16 = data; + } + + inline void InitVariant(mfxVariant *var, mfxHDL data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_PTR; + var->Data.Ptr = data; + } + + template + mfxStatus CreateConfig(varDataType data, const char *propertyName) { + mfxConfig cfg = MFXCreateConfig(m_loader); + if (cfg == nullptr) + return MFX_ERR_NULL_PTR; + + mfxVariant variant; + InitVariant(&variant, data); + + return MFXSetConfigFilterProperty(cfg, (mfxU8 *)propertyName, variant); + } + + mfxStatus InitSession(mfxInitParam par) { + // already initialized + if (m_session) + return MFX_ERR_NONE; + + m_loader = MFXLoad(); + if (!m_loader) + return MFX_ERR_NOT_FOUND; + + mfxStatus mfxRes = MFX_ERR_NONE; + + mfxU32 implBaseType = MFX_IMPL_BASETYPE(par.Implementation); + + // select implementation type + switch (implBaseType) { + case MFX_IMPL_AUTO: + case MFX_IMPL_AUTO_ANY: + break; + + case MFX_IMPL_SOFTWARE: + mfxRes = CreateConfig(MFX_IMPL_TYPE_SOFTWARE, "mfxImplDescription.Impl"); + break; + + case MFX_IMPL_HARDWARE: + case MFX_IMPL_HARDWARE_ANY: + case MFX_IMPL_HARDWARE2: + case MFX_IMPL_HARDWARE3: + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(MFX_IMPL_TYPE_HARDWARE, "mfxImplDescription.Impl"); + break; + + default: + mfxRes = MFX_ERR_UNSUPPORTED; + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // select adapter index (if specified) + // see notes below about how VendorImplID is interpreted for each acceleration mode + switch (implBaseType) { + case MFX_IMPL_HARDWARE: + mfxRes = CreateConfig(0, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE2: + mfxRes = CreateConfig(1, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE3: + mfxRes = CreateConfig(2, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(3, "mfxImplDescription.VendorImplID"); + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + mfxU32 implAccelMode = MFX_IMPL_ACCELMODE(par.Implementation); + if (implAccelMode == MFX_IMPL_VIA_D3D9) { + // D3D9 - because VendorImplID corresponds to DXGI adapter index (DX11 enumeration), + // this may not map directly to D3D9 index in multi-adapter/multi-monitor configurations + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D9, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_D3D11) { + // D3D11 - VendorImplID corresponds to DXGI adapter index + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D11, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_VAAPI) { + // VAAPI - in general MFXInitEx treats any HARDWAREn the same way (relies on application to pass + // correct VADisplay via SetHandle), but 2.x RT only reports actual number of adapters + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_VAAPI, + "mfxImplDescription.AccelerationMode"); + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set required API level + mfxRes = + CreateConfig(par.Version.Version, "mfxImplDescription.ApiVersion.Version"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set GPUCopy parameter + if (par.GPUCopy) { + mfxRes = CreateConfig(par.GPUCopy, "DeviceCopy"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + + // set ExternalThreads parameter + if (par.ExternalThreads) { + // TO DO - need to add this as config filter property and member of mfxInitializationParam + return MFX_ERR_UNSUPPORTED; + } + + // pass extBufs + if (par.NumExtParam) { + for (mfxU32 idx = 0; idx < par.NumExtParam; idx++) { + mfxRes = CreateConfig(par.ExtParam[idx], "ExtBuffer"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + } + + // create session with highest priority implementation remaining after filters + mfxRes = MFXCreateSession(m_loader, 0, &m_session); + + return mfxRes; + } +#endif + +private: + MFXVideoSession(const MFXVideoSession &); + void operator=(MFXVideoSession &); +}; + +class MFXVideoENCODE : public MFXVideoENCODEBase { +public: + explicit MFXVideoENCODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoENCODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoENCODE_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoENCODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoENCODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoENCODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoENCODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoENCODE_GetVideoParam(m_session, par); + } + virtual mfxStatus GetEncodeStat(mfxEncodeStat *stat) override { + return MFXVideoENCODE_GetEncodeStat(m_session, stat); + } + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl *ctrl, + mfxFrameSurface1 *surface, + mfxBitstream *bs, + mfxSyncPoint *syncp) override { + return MFXVideoENCODE_EncodeFrameAsync(m_session, ctrl, surface, bs, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoDECODE : public MFXVideoDECODEBase { +public: + explicit MFXVideoDECODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoDECODE_Query(m_session, in, out); + } + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) override { + return MFXVideoDECODE_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoDECODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoDECODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoDECODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoDECODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoDECODE_GetVideoParam(m_session, par); + } + + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) override { + return MFXVideoDECODE_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) override { + return MFXVideoDECODE_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) override { + return MFXVideoDECODE_SetSkipMode(m_session, mode); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, + mfxFrameSurface1 *surface_work, + mfxFrameSurface1 **surface_out, + mfxSyncPoint *syncp) override { + return MFXVideoDECODE_DecodeFrameAsync(m_session, bs, surface_work, surface_out, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoVPP : public MFXVideoVPPBase { +public: + explicit MFXVideoVPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoVPP(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoVPP_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2]) override { + return MFXVideoVPP_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoVPP_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoVPP_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoVPP_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoVPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetVPPStat(mfxVPPStat *stat) override { + return MFXVideoVPP_GetVPPStat(m_session, stat); + } + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in, + mfxFrameSurface1 *out, + mfxExtVppAuxData *aux, + mfxSyncPoint *syncp) override { + return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp); + } + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP(m_session, output_surf); + } + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1 *in, mfxFrameSurface1 **out) override { + return MFXVideoVPP_ProcessFrameAsync(m_session, in, out); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoDECODE_VPP +{ +public: + explicit MFXVideoDECODE_VPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE_VPP(void) { + Close(); + } + + virtual mfxStatus Init(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Init(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus Reset(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Reset(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus GetChannelParam(mfxVideoChannelParam *par, mfxU32 channel_id) { + return MFXVideoDECODE_VPP_GetChannelParam(m_session, par, channel_id); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, mfxU32* skip_channels, mfxU32 num_skip_channels, mfxSurfaceArray **surf_array_out) { + return MFXVideoDECODE_VPP_DecodeFrameAsync(m_session, bs, skip_channels, num_skip_channels, surf_array_out); + } + + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) { + return MFXVideoDECODE_VPP_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus Close(void) { + return MFXVideoDECODE_VPP_Close(m_session); + } + virtual mfxStatus GetVideoParam(mfxVideoParam *par) { + return MFXVideoDECODE_VPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) { + return MFXVideoDECODE_VPP_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) { + return MFXVideoDECODE_VPP_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) { + return MFXVideoDECODE_VPP_SetSkipMode(m_session, mode); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +#endif //__MFXVIDEOPLUSPLUS_H diff --git a/third-party/IntelVPL/arm64/lib/cmake/vpl/VPLConfig.cmake b/third-party/IntelVPL/arm64/lib/cmake/vpl/VPLConfig.cmake new file mode 100644 index 000000000..e724c5b95 --- /dev/null +++ b/third-party/IntelVPL/arm64/lib/cmake/vpl/VPLConfig.cmake @@ -0,0 +1,146 @@ +# ############################################################################## +# Copyright (C) Intel Corporation +# +# SPDX-License-Identifier: MIT +# ############################################################################## + +# * Config file for the VPL package It defines the following variables +# VPL__FOUND VPL_IMPORTED_TARGETS +# +# VPLConfigVersion.cmake defines VPL_VERSION + +option(VPL_SHARED "Use shared instead of static version of dispatcher." + ON) + +# Initialize to default values +set(VPL_INTERFACE_VERSION 2) +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) + +get_filename_component(VPL_LIB_DIR "${_vpl_config_dir}/../../" + ABSOLUTE) +get_filename_component(VPL_INCLUDE_DIR "${_vpl_config_dir}/../../../include" + ABSOLUTE) +get_filename_component(VPL_BIN_DIR "${_vpl_config_dir}/../../../bin" + ABSOLUTE) + +if(CMAKE_SYSTEM_NAME MATCHES Windows) + set(VPL_SHLIB_DIR ${VPL_BIN_DIR}) +else() + set(VPL_SHLIB_DIR ${VPL_LIB_DIR}) +endif() + +if(NOT VPL_IMPORTED_TARGETS) + set(VPL_IMPORTED_TARGETS "") +endif() + +if(NOT VPL_FIND_COMPONENTS) + set(VPL_FIND_COMPONENTS "dispatcher;api") + foreach(_vpl_component ${VPL_FIND_COMPONENTS}) + set(VPL_FIND_REQUIRED_${_vpl_component} 1) + endforeach() +endif() + +# VPL::dispatcher +set(VPL_dispatcher_FOUND 0) + +get_filename_component(_dispatcher_shlib "${VPL_SHLIB_DIR}/libvpl.dll" + ABSOLUTE) +get_filename_component(_dispatcher_debug_shlib + "${VPL_SHLIB_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) +get_filename_component(_dispatcher_implib "${VPL_LIB_DIR}/vpl.lib" + ABSOLUTE) +get_filename_component(_dispatcher_debug_implib + "${VPL_LIB_DIR}/vpld.lib" ABSOLUTE) + +if(TARGET VPL::dispatcher) + list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) + set(VPL_dispatcher_FOUND 1) +else() + if(VPL_SHARED) + if(EXISTS "${_dispatcher_shlib}" OR EXISTS "${_dispatcher_debug_shlib}") + list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) + set(VPL_dispatcher_FOUND 1) + + add_library(VPL::dispatcher SHARED IMPORTED) + set_target_properties( + VPL::dispatcher + PROPERTIES IMPORTED_LOCATION_RELEASE ${_dispatcher_shlib} + IMPORTED_LOCATION_RELWITHDEBINFO ${_dispatcher_shlib} + IMPORTED_LOCATION_MINSIZEREL ${_dispatcher_shlib} + IMPORTED_LOCATION_DEBUG ${_dispatcher_debug_shlib} + IMPORTED_LOCATION_RELWITHDEBRT ${_dispatcher_debug_shlib}) + if(CMAKE_SYSTEM_NAME MATCHES Windows) + set_target_properties( + VPL::dispatcher + PROPERTIES IMPORTED_IMPLIB_RELEASE ${_dispatcher_implib} + IMPORTED_IMPLIB_RELWITHDEBINFO ${_dispatcher_implib} + IMPORTED_IMPLIB_MINSIZEREL ${_dispatcher_implib} + IMPORTED_IMPLIB_DEBUG ${_dispatcher_debug_implib} + IMPORTED_IMPLIB_RELWITHDEBRT ${_dispatcher_debug_implib}) + endif() + elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher) + message(STATUS "Unable to find required VPL component: dispatcher") + set(VPL_FOUND FALSE) + endif() + else() + if(EXISTS "${_dispatcher_lib}" OR EXISTS "${_dispatcher_debug_lib}") + list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) + set(VPL_dispatcher_FOUND 1) + add_library(VPL::dispatcher STATIC IMPORTED) + set_target_properties( + VPL::dispatcher + PROPERTIES IMPORTED_LOCATION_RELEASE ${_dispatcher_lib} + IMPORTED_LOCATION_RELWITHDEBINFO ${_dispatcher_lib} + IMPORTED_LOCATION_MINSIZEREL ${_dispatcher_lib} + IMPORTED_LOCATION_DEBUG ${_dispatcher_debug_lib} + IMPORTED_LOCATION_RELWITHDEBRT ${_dispatcher_debug_lib}) + if(UNIX) + # require pthreads for loading legacy MSDK runtimes + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads REQUIRED) + target_link_libraries(VPL::dispatcher INTERFACE Threads::Threads) + endif() + target_link_libraries(VPL::dispatcher INTERFACE ${CMAKE_DL_LIBS}) + elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher) + message(STATUS "Unable to find required VPL component: dispatcher") + set(VPL_FOUND FALSE) + endif() + endif() + set_target_properties(VPL::dispatcher PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${VPL_INCLUDE_DIR}") +endif() + +unset(_dispatcher_shlib) + +# VPL::api +set(VPL_api_FOUND 0) +if(EXISTS ${VPL_INCLUDE_DIR}) + if(NOT TARGET VPL::api) + add_library(VPL::api INTERFACE IMPORTED) + set_target_properties(VPL::api PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${VPL_INCLUDE_DIR}") + endif() + 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/third-party/IntelVPL/arm64/lib/cmake/vpl/VPLConfigVersion.cmake b/third-party/IntelVPL/arm64/lib/cmake/vpl/VPLConfigVersion.cmake new file mode 100644 index 000000000..4c86e69ca --- /dev/null +++ b/third-party/IntelVPL/arm64/lib/cmake/vpl/VPLConfigVersion.cmake @@ -0,0 +1,17 @@ +# ############################################################################## +# Copyright (C) Intel Corporation +# +# SPDX-License-Identifier: MIT +# ############################################################################## + +set(PACKAGE_VERSION "2.16") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/third-party/IntelVPL/arm64/lib/pkgconfig/vpl.pc b/third-party/IntelVPL/arm64/lib/pkgconfig/vpl.pc new file mode 100644 index 000000000..c58ed5256 --- /dev/null +++ b/third-party/IntelVPL/arm64/lib/pkgconfig/vpl.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../../ +libdir=${pcfiledir}/../ +includedir=${pcfiledir}/../../include + +Name: Intel(R) Video Processing Library +Description: Accelerated video decode, encode, and frame processing capabilities on Intel(R) GPUs +Version: 2.16 +URL: https://github.com/intel/libvpl + +Libs: -L${libdir} -lvpl +Libs.private: +Cflags: -I${includedir} -I${includedir}/vpl diff --git a/third-party/IntelVPL/arm64/lib/vpl.lib b/third-party/IntelVPL/arm64/lib/vpl.lib new file mode 100644 index 000000000..7a62233ff Binary files /dev/null and b/third-party/IntelVPL/arm64/lib/vpl.lib differ diff --git a/third-party/IntelVPL/x64/bin/libvpl.dll b/third-party/IntelVPL/x64/bin/libvpl.dll new file mode 100644 index 000000000..d4d8760dd Binary files /dev/null and b/third-party/IntelVPL/x64/bin/libvpl.dll differ diff --git a/third-party/IntelVPL/x64/include/vpl/mfx.h b/third-party/IntelVPL/x64/include/vpl/mfx.h new file mode 100644 index 000000000..ce24fcb28 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfx.h @@ -0,0 +1,31 @@ +/*############################################################################ + # 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" + +#include "mfxsurfacepool.h" + +#ifdef ONEVPL_EXPERIMENTAL +#include "mfxencodestats.h" +#endif + +#endif /* __MFXDEFS_H__ */ diff --git a/third-party/IntelVPL/x64/include/vpl/mfxadapter.h b/third-party/IntelVPL/x64/include/vpl/mfxadapter.h new file mode 100644 index 000000000..6820da9de --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxadapter.h @@ -0,0 +1,85 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#include "mfxdefs.h" +#ifndef __MFXADAPTER_H__ +#define __MFXADAPTER_H__ + +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + @brief + Returns a list of adapters that are suitable to handle workload @p input_info. The list is sorted in priority order, with iGPU given the highest precedence. + This rule may change in the future. If the @p input_info pointer is NULL, the list of all available adapters will be returned. + + @param[in] input_info Pointer to workload description. See mfxComponentInfo description for details. + @param[out] adapters Pointer to output description of all suitable adapters for input workload. See mfxAdaptersInfo description for details. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR + @p input_info or adapters pointer is NULL. \n + MFX_ERR_NOT_FOUND No suitable adapters found. \n + MFX_WRN_OUT_OF_RANGE Not enough memory to report back entire list of adapters. In this case as many adapters as possible will be returned. + + @since This function is available since API version 1.31. + + @deprecated Deprecated in API version 2.9. Use MFXEnumImplementations and MFXSetConfigFilterProperty to query adapter capabilities and + to select a suitable adapter for the input workload. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. +*/ +MFX_DEPRECATED mfxStatus MFX_CDECL MFXQueryAdapters(mfxComponentInfo* input_info, mfxAdaptersInfo* adapters); + +/*! + @brief + Returns list of adapters that are suitable to decode the input bitstream. The list is sorted in priority order, with iGPU given the highest precedence. This rule may change in the future. This function is a simplification of MFXQueryAdapters, because bitstream is a description of the workload itself. + + @param[in] bitstream Pointer to bitstream with input data. + @param[in] codec_id Codec ID to determine the type of codec for the input bitstream. + @param[out] adapters Pointer to the output list of adapters. Memory should be allocated by user. See mfxAdaptersInfo description for details. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR bitstream or @p adapters pointer is NULL. \n + MFX_ERR_NOT_FOUND No suitable adapters found. \n + MFX_WRN_OUT_OF_RANGE Not enough memory to report back entire list of adapters. In this case as many adapters as possible will be returned. + + @since This function is available since API version 1.31. + + @deprecated Deprecated in API version 2.9. Use MFXEnumImplementations and MFXSetConfigFilterProperty to query adapter capabilities and + to select a suitable adapter for the input workload. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. +*/ +MFX_DEPRECATED mfxStatus MFX_CDECL MFXQueryAdaptersDecode(mfxBitstream* bitstream, mfxU32 codec_id, mfxAdaptersInfo* adapters); + +/*! + @brief + Returns the number of detected graphics adapters. It can be used before calling MFXQueryAdapters to determine the size of input data that the user will need to allocate. + + @param[out] num_adapters Pointer for the output number of detected graphics adapters. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR num_adapters pointer is NULL. + + @since This function is available since API version 1.31. + + @deprecated Deprecated in API version 2.9. Use MFXEnumImplementations and MFXSetConfigFilterProperty to query adapter capabilities and + to select a suitable adapter for the input workload. + Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. +*/ +MFX_DEPRECATED mfxStatus MFX_CDECL MFXQueryAdaptersNumber(mfxU32* num_adapters); +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MFXADAPTER_H__ + diff --git a/third-party/IntelVPL/x64/include/vpl/mfxbrc.h b/third-party/IntelVPL/x64/include/vpl/mfxbrc.h new file mode 100644 index 000000000..da6f09aa3 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxbrc.h @@ -0,0 +1,175 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXBRC_H__ +#define __MFXBRC_H__ + +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! See the mfxExtBRC structure for details. */ +enum { + MFX_EXTBUFF_BRC = MFX_MAKEFOURCC('E','B','R','C') +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes frame parameters required for external BRC functions. +*/ +typedef struct { + mfxU32 reserved[23]; + mfxU16 SceneChange; /*!< Frame belongs to a new scene if non zero. */ + mfxU16 LongTerm; /*!< Frame is a Long Term Reference frame if non zero. */ + mfxU32 FrameCmplx; /*!< Frame Complexity Frame spatial complexity if non zero. Zero if complexity is not available. */ + mfxU32 EncodedOrder; /*!< The frame number in a sequence of reordered frames starting from encoder Init. */ + mfxU32 DisplayOrder; /*!< The frame number in a sequence of frames in display order starting from last IDR. */ + mfxU32 CodedFrameSize; /*!< Size of the frame in bytes after encoding. */ + mfxU16 FrameType; /*!< Frame type. See FrameType enumerator for possible values. */ + mfxU16 PyramidLayer; /*!< B-pyramid or P-pyramid layer that the frame belongs to. */ + mfxU16 NumRecode; /*!< Number of recodings performed for this frame. */ + mfxU16 NumExtParam; /*!< Reserved for future use. */ + mfxExtBuffer** ExtParam;/*!< Reserved for future use. */ +} mfxBRCFrameParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Specifies controls for next frame encoding provided by external BRC functions. +*/ +typedef struct { + mfxI32 QpY; /*!< Frame-level Luma QP. */ + mfxU32 InitialCpbRemovalDelay; /*!< See initial_cpb_removal_delay in codec standard. Ignored if no HRD control: + mfxExtCodingOption::VuiNalHrdParameters = MFX_CODINGOPTION_OFF. Calculated by encoder if + initial_cpb_removal_delay==0 && initial_cpb_removal_offset == 0 && HRD control is switched on. */ + mfxU32 InitialCpbRemovalOffset; /*!< See initial_cpb_removal_offset in codec standard. Ignored if no HRD control: + mfxExtCodingOption::VuiNalHrdParameters = MFX_CODINGOPTION_OFF. Calculated by encoder if + initial_cpb_removal_delay==0 && initial_cpb_removal_offset == 0 && HRD control is switched on. */ + mfxU32 reserved1[7]; + mfxU32 MaxFrameSize; /*!< Max frame size in bytes. Option for repack feature. Driver calls PAK until current frame size is + less than or equal to MaxFrameSize, or number of repacking for this frame is equal to MaxNumRePak. Repack is available + if there is driver support, MaxFrameSize !=0, and MaxNumRePak != 0. Ignored if MaxNumRePak == 0. */ + mfxU8 DeltaQP[8]; /*!< Option for repack feature. Ignored if MaxNumRePak == 0 or MaxNumRePak==0. If current + frame size > MaxFrameSize and/or number of repacking (nRepack) for this frame <= MaxNumRePak, + PAK is called with QP = mfxBRCFrameCtrl::QpY + Sum(DeltaQP[i]), where i = [0,nRepack]. + Non zero DeltaQP[nRepack] are ignored if nRepack > MaxNumRePak. + If repacking feature is on ( MaxFrameSize & MaxNumRePak are not zero), it is calculated by the encoder. */ + mfxU16 MaxNumRepak; /*!< Number of possible repacks in driver if current frame size > MaxFrameSize. Ignored if MaxFrameSize==0. + See MaxFrameSize description. Possible values are in the range of 0 to 8. */ + mfxU16 NumExtParam; /*!< Reserved for future use. */ + mfxExtBuffer** ExtParam; /*!< Reserved for future use. */ +} mfxBRCFrameCtrl; +MFX_PACK_END() + +/*! The BRCStatus enumerator itemizes instructions to the encoder by mfxExtBrc::Update. */ +enum { + MFX_BRC_OK = 0, /*!< CodedFrameSize is acceptable, no further recoding/padding/skip required, proceed to next frame. */ + MFX_BRC_BIG_FRAME = 1, /*!< Coded frame is too big, recoding required. */ + MFX_BRC_SMALL_FRAME = 2, /*!< Coded frame is too small, recoding required. */ + MFX_BRC_PANIC_BIG_FRAME = 3, /*!< Coded frame is too big, no further recoding possible - skip frame. */ + MFX_BRC_PANIC_SMALL_FRAME = 4 /*!< Coded frame is too small, no further recoding possible - required padding to mfxBRCFrameStatus::MinFrameSize. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Specifies instructions for the encoder provided by external BRC after each frame encoding. See the BRCStatus enumerator for details. +*/ +typedef struct { + mfxU32 MinFrameSize; /*!< Size in bytes, coded frame must be padded to when Status = MFX_BRC_PANIC_SMALL_FRAME. */ + mfxU16 BRCStatus; /*!< BRC status. See the BRCStatus enumerator for possible values. */ + mfxU16 reserved[25]; + mfxHDL reserved1; +} mfxBRCFrameStatus; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains a set of callbacks to perform external bitrate control. Can be attached to the mfxVideoParam structure during + encoder initialization. Set the mfxExtCodingOption2::ExtBRC option to ON to make the encoder use the external BRC instead of the native one. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_BRC. */ + + mfxU32 reserved[14]; + mfxHDL pthis; /*!< Pointer to the BRC object. */ + + /*! + @brief Initializes the BRC session according to parameters from input mfxVideoParam and attached structures. It does not modify the input mfxVideoParam and attached structures. Invoked during MFXVideoENCODE_Init. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function detected unsupported video parameters. + */ + mfxStatus (MFX_CDECL *Init) (mfxHDL pthis, mfxVideoParam* par); + + /*! + @brief Resets BRC session according to new parameters. It does not modify the input mfxVideoParam and attached structures. Invoked during MFXVideoENCODE_Reset. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function detected unsupported video parameters. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that the video parameters provided by the application are incompatible with + initialization parameters. Reset requires additional memory allocation and cannot be executed. + */ + mfxStatus (MFX_CDECL *Reset) (mfxHDL pthis, mfxVideoParam* par); + + /*! + @brief Deallocates any internal resources acquired in Init for this BRC session. Invoked during MFXVideoENCODE_Close. + + @param[in] pthis Pointer to the BRC object. + + @return + MFX_ERR_NONE The function completed successfully. + */ + mfxStatus (MFX_CDECL *Close) (mfxHDL pthis); + + /*! @brief Returns controls (@p ctrl) to encode next frame based on info from input mfxBRCFrameParam structure (@p par) and + internal BRC state. Invoked asynchronously before each frame encoding or recoding. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + @param[out] ctrl Pointer to the output mfxBRCFrameCtrl structure. + + @return + MFX_ERR_NONE The function completed successfully. + */ + mfxStatus (MFX_CDECL* GetFrameCtrl) (mfxHDL pthis, mfxBRCFrameParam* par, mfxBRCFrameCtrl* ctrl); + + /*! + @brief Updates internal BRC state and returns status to instruct encoder whether it should recode the previous frame, + skip the previous frame, do padding, or proceed to next frame based on info from input mfxBRCFrameParam and mfxBRCFrameCtrl structures. + Invoked asynchronously after each frame encoding or recoding. + + @param[in] pthis Pointer to the BRC object. + @param[in] par Pointer to the mfxVideoParam structure that was used for the encoder initialization. + @param[in] ctrl Pointer to the output mfxBRCFrameCtrl structure. + @param[in] status Pointer to the output mfxBRCFrameStatus structure. + + + @return + MFX_ERR_NONE The function completed successfully. + */ + mfxStatus (MFX_CDECL* Update) (mfxHDL pthis, mfxBRCFrameParam* par, mfxBRCFrameCtrl* ctrl, mfxBRCFrameStatus* status); + + mfxHDL reserved1[10]; +} mfxExtBRC; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif + diff --git a/third-party/IntelVPL/x64/include/vpl/mfxcamera.h b/third-party/IntelVPL/x64/include/vpl/mfxcamera.h new file mode 100644 index 000000000..72023a46a --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxcamera.h @@ -0,0 +1,375 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ +#ifndef __MFXCAMERA_H__ +#define __MFXCAMERA_H__ + +#include "mfxcommon.h" + + +#if !defined(__GNUC__) + #pragma warning(disable : 4201) +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*! + The ExtendedBufferID enumerator itemizes and defines identifiers (BufferId) for extended buffers in camera processing. + The application should attach these extended buffers to the mfxVideoParam structure to configure camera processing through VideoVPP functions. + And Implementation capabilities of camera processing features can be delivered by the function MFXQueryImplsDescription via VPP configuration + mfxVPPDescription. + */ +enum { + /*! + This extended buffer is mandatory for camera raw accelerator initialization. See the mfxExtCamPipeControl structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_PIPECONTROL = MFX_MAKEFOURCC('C', 'P', 'P', 'C'), + /*! + This extended buffer defines control parameters for the Camera White Balance filter algorithm. See mfxExtCamWhiteBalance structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_WHITE_BALANCE = MFX_MAKEFOURCC('C', 'W', 'B', 'L'), + /*! + This extended buffer defines control parameters for the Camera Hot Pixel Removal filter algorithm. See mfxExtCamHotPixelRemoval structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_HOT_PIXEL_REMOVAL = MFX_MAKEFOURCC('C', 'H', 'P', 'R'), + /*! + This extended buffer defines control parameters for the Camera Black Level Correction filter algorithm. See mfxExtCamBlackLevelCorrection structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_BLACK_LEVEL_CORRECTION = MFX_MAKEFOURCC('C', 'B', 'L', 'C'), + /*! + This extended buffer defines control parameters for the Camera Vignette Correction filter algorithm. See mfxCamVignetteCorrectionParam structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_VIGNETTE_CORRECTION = MFX_MAKEFOURCC('C', 'V', 'G', 'T'), + /*! + This extended buffer defines control parameters for the Camera Bayer Denoise filter algorithm. See mfxExtCamBayerDenoise structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_BAYER_DENOISE = MFX_MAKEFOURCC('C', 'D', 'N', 'S'), + /*! + This extended buffer defines control parameters for the Camera Color Correction filter algorithm. See mfxExtCamColorCorrection3x3 structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_COLOR_CORRECTION_3X3 = MFX_MAKEFOURCC('C', 'C', '3', '3'), + /*! + This extended buffer defines control parameters for the Camera Padding. See mfxExtCamPadding structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_PADDING = MFX_MAKEFOURCC('C', 'P', 'A', 'D'), + /*! + This extended buffer defines control parameters for the Camera Forward Gamma Correction filter algorithm. See mfxExtCamFwdGamma structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_FORWARD_GAMMA_CORRECTION = + MFX_MAKEFOURCC('C', 'F', 'G', 'C'), + /*! + This extended buffer defines control parameters for the Camera Lens Geometry Distortion and Chroma Aberration Correction filter algorithm. See mfxExtCamLensGeomDistCorrection structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_LENS_GEOM_DIST_CORRECTION = + MFX_MAKEFOURCC('C', 'L', 'G', 'D'), + /*! + This extended buffer defines control parameters for the Camera 3DLUT filter algorithm. See mfxExtCam3DLut structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_3DLUT = MFX_MAKEFOURCC('C', 'L', 'U', 'T'), + /*! + This extended buffer defines control parameters for the Camera Total Color Control algorithm. See mfxExtCamTotalColorControl structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_TOTAL_COLOR_CONTROL = MFX_MAKEFOURCC('C', 'T', 'C', 'C'), + /*! + This extended buffer defines control parameters for the Camera YUV to RGB conversion algorithm. See mfxExtCamCscYuvRgb structure for details. + The application should attach this extended buffer to the mfxVideoParam structure to configure camera processing initialization. + */ + MFX_EXTBUF_CAM_CSC_YUV_RGB = MFX_MAKEFOURCC('C', 'C', 'Y', 'R') +}; + +/*! + A enumeration that defines white balance mode. +*/ +typedef enum { + MFX_CAM_WHITE_BALANCE_MANUAL = 0x0001, /*!< White balance manual mode.*/ + MFX_CAM_WHITE_BALANCE_AUTO = 0x0002 /*!< White balance auto mode.*/ +} mfxCamWhiteBalanceMode; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera White Balance filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_WHITE_BALANCE. */ + mfxU32 Mode; /*!< Specifies one of White Balance operation modes defined in enumeration mfxCamWhiteBalanceMode. */ + mfxF64 R; /*!< White Balance Red correction.*/ + mfxF64 G0; /*!< White Balance Green Top correction.*/ + mfxF64 B; /*!< White Balance Blue correction.*/ + mfxF64 G1; /*!< White Balance Green Bottom correction. */ + mfxU32 reserved[8]; /*!< Reserved for future extension. */ +} mfxExtCamWhiteBalance; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Total Color Control filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_TOTAL_COLOR_CONTROL. */ + mfxU16 R; /*!< Red element.*/ + mfxU16 G; /*!< Green element.*/ + mfxU16 B; /*!< Blue element.*/ + mfxU16 C; /*!< Cyan element.*/ + mfxU16 M; /*!< Magenta element.*/ + mfxU16 Y; /*!< Yellow element.*/ + mfxU16 reserved[6]; /*!< Reserved for future extension.*/ +} mfxExtCamTotalColorControl; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera YUV to RGB format conversion. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_CSC_YUV_RGB. */ + mfxF32 PreOffset[3]; /*!< Specifies offset for conversion from full range RGB input to limited range YUV for input color coordinate.*/ + mfxF32 Matrix[3][3]; /*!< Specifies conversion matrix with CSC coefficients.*/ + mfxF32 PostOffset[3]; /*!< Specifies offset for conversion from full range RGB input to limited range YUV for output color coordinate.*/ + mfxU16 reserved[30]; /*!< Reserved for future extension.*/ +} mfxExtCamCscYuvRgb; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Hot Pixel Removal filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_HOT_PIXEL_REMOVAL. */ + mfxU16 PixelThresholdDifference; /*!< Threshold for Hot Pixel difference. */ + mfxU16 PixelCountThreshold; /*!< Count pixel detection.*/ + mfxU16 reserved[32]; /*!< Reserved for future extension.*/ +} mfxExtCamHotPixelRemoval; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +typedef struct { +/*! + A hint structure that configures Camera black level correction. +*/ + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_BLACK_LEVEL_CORRECTION. */ + mfxU16 R; /*!< Black Level Red correction.*/ + mfxU16 G0; /*!< Black Level Green Top correction.*/ + mfxU16 B; /*!< Black Level Blue correction.*/ + mfxU16 G1; /*!< Black Level Green Bottom correction.*/ + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxExtCamBlackLevelCorrection; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that defines Camera Vignette Correction Element. +*/ +typedef struct { + mfxU8 integer; /*!< Integer part of correction element.*/ + mfxU8 mantissa; /*!< Fractional part of correction element.*/ + mfxU8 reserved[6]; /*!< Reserved for future extension.*/ +} mfxCamVignetteCorrectionElement; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that defines Camera Vignette Correction Parameters. +*/ +typedef struct { + mfxCamVignetteCorrectionElement R; /*!< Red correction element.*/ + mfxCamVignetteCorrectionElement G0; /*!< Green top correction element.*/ + mfxCamVignetteCorrectionElement B; /*!< Blue Correction element.*/ + mfxCamVignetteCorrectionElement G1; /*!< Green bottom correction element.*/ + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxCamVignetteCorrectionParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + A hint structure that configures Camera Vignette Correction filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_VIGNETTE_CORRECTION. */ + mfxU32 Width; /*!< Width of Correction Map 2D buffer in mfxCamVignetteCorrectionParam elements. */ + mfxU32 Height; /*!< Height of Correction Map 2D buffer in mfxCamVignetteCorrectionParam elements. */ + mfxU32 Pitch; /*!< Pitch of Correction Map 2D buffer in mfxCamVignetteCorrectionParam elements. */ + mfxU32 reserved[7]; /*!< Reserved for future extension.*/ + + union { + mfxCamVignetteCorrectionParam* CorrectionMap; /*!< 2D buffer of mfxCamVignetteCorrectionParam elements.*/ + mfxU64 reserved1; /*!< Reserved for alignment on 32bit and 64bit.*/ + }; +} mfxExtCamVignetteCorrection; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Bayer denoise filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_BAYER_DENOISE. */ + mfxU16 Threshold; /*!< Level of denoise, legal values: [0:63].*/ + mfxU16 reserved[27]; /*!< Reserved for future extension.*/ +} mfxExtCamBayerDenoise; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures Camera Color correction filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_COLOR_CORRECTION_3X3. */ + mfxF32 CCM[3][3]; /*!< 3x3 dimension matrix providing RGB Color Correction coefficients.*/ + mfxU32 reserved[32]; /*!< Reserved for future extension.*/ +} mfxExtCamColorCorrection3x3; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Padding. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_PADDING. */ + mfxU16 Top; /*!< Specify number of padded columns respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU16 Bottom; /*!< Specify number of padded columns respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU16 Left; /*!< Specify number of padded rows respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU16 Right; /*!< Specify number of padded rows respectively. Currently only 8 pixels supported for all dimensions. */ + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +} mfxExtCamPadding; +MFX_PACK_END() + +/*! + A enumeration that defines Bayer mode. +*/ +typedef enum { + /*! + Pixel Representation BG + GR. + */ + MFX_CAM_BAYER_BGGR = 0x0000, + /*! + Pixel Representation RG + GB. + */ + MFX_CAM_BAYER_RGGB = 0x0001, + /*! + Pixel Representation GB + RG. + */ + MFX_CAM_BAYER_GBRG = 0x0002, + /*! + Pixel Representation GR + BG. + */ + MFX_CAM_BAYER_GRBG = 0x0003 +} mfxCamBayerFormat; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures camera pipe control. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_PIPECONTROL. */ + mfxU16 RawFormat; /*!< Specifies one of the four Bayer patterns defined in mfxCamBayerFormat enumeration. */ + mfxU16 reserved1; /*!< Reserved for future extension.*/ + mfxU32 reserved[5]; /*!< Reserved for future extension.*/ +} mfxExtCamPipeControl; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that specifies forward gamma segment. +*/ +typedef struct { + mfxU16 Pixel; /*!< Pixel value.*/ + mfxU16 Red; /*!< Corrected Red value.*/ + mfxU16 Green; /*!< Corrected Green value.*/ + mfxU16 Blue; /*!< Corrected Blue value.*/ +} mfxCamFwdGammaSegment; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures Camera Forward Gamma Correction filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_FORWARD_GAMMA_CORRECTION. */ + + mfxU16 reserved[19]; /*!< Reserved for future extension.*/ + mfxU16 NumSegments; /*!< Number of Gamma segments.*/ + union { + mfxCamFwdGammaSegment* Segment; /*!< Pointer to Gamma segments array.*/ + mfxU64 reserved1; /*!< Reserved for future extension.*/ + }; +} mfxExtCamFwdGamma; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures Camera Lens Geometry Distortion and Chroma Aberration Correction filter. +*/ +typedef struct { + mfxExtBuffer + Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_LENS_GEOM_DIST_CORRECTION. */ + + mfxF32 a[3]; /*!< Polynomial coefficients a for R/G/B*/ + mfxF32 b[3]; /*!< Polynomial coefficients b for R/G/B*/ + mfxF32 c[3]; /*!< Polynomial coefficients c for R/G/B*/ + mfxF32 d[3]; /*!< Polynomial coefficients d for R/G/B*/ + mfxU16 reserved[36]; /*!< Reserved for future extension.*/ +} mfxExtCamLensGeomDistCorrection; +MFX_PACK_END() + +/*! + A enumeration that defines 3DLUT size. +*/ +enum { + MFX_CAM_3DLUT17_SIZE = (17 * 17 * 17), /*!< 17^3 LUT size*/ + MFX_CAM_3DLUT33_SIZE = (33 * 33 * 33), /*!< 33^3 LUT size*/ + MFX_CAM_3DLUT65_SIZE = (65 * 65 * 65) /*!< 65^3 LUT size*/ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A structure that defines 3DLUT entry. +*/ +typedef struct { + mfxU16 R; /*!< R channel*/ + mfxU16 G; /*!< G channel*/ + mfxU16 B; /*!< B channel*/ + mfxU16 Reserved; /*!< Reserved for future extension.*/ +} mfxCam3DLutEntry; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures Camera 3DLUT filter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUF_CAM_3DLUT. */ + + mfxU16 reserved[10]; /*!< Reserved for future extension.*/ + mfxU32 Size; /*!< LUT size, defined in MFX_CAM_3DLUT17/33/65_SIZE enumeration.*/ + union { + mfxCam3DLutEntry* Table; /*!< Pointer to mfxCam3DLutEntry, size of each dimension depends on LUT size, e.g. LUT[17][17][17] for 17x17x17 look up table.*/ + mfxU64 reserved1; /*!< Reserved for future extension.*/ + }; +} mfxExtCam3DLut; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MFXCAMERA_H__ \ No newline at end of file diff --git a/third-party/IntelVPL/x64/include/vpl/mfxcommon.h b/third-party/IntelVPL/x64/include/vpl/mfxcommon.h new file mode 100644 index 000000000..1b3737d72 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxcommon.h @@ -0,0 +1,740 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXCOMMON_H__ +#define __MFXCOMMON_H__ +#include "mfxdefs.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +#define MFX_MAKEFOURCC(A,B,C,D) ((((int)A))+(((int)B)<<8)+(((int)C)<<16)+(((int)D)<<24)) + +/* Extended Configuration Header Structure */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The common header definition for external buffers and video + processing hints. */ +typedef struct { + mfxU32 BufferId; /*!< Identifier of the buffer content. See the ExtendedBufferID enumerator for a complete list of extended buffers. */ + mfxU32 BufferSz; /*!< Size of the buffer. */ +} mfxExtBuffer; +MFX_PACK_END() + + +#define MFX_REFINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure represents reference counted interface structure. + The memory is allocated and released by the implementation. +*/ +typedef struct mfxRefInterface { + mfxHDL Context; /*!< The context of the container interface. User should not touch (change, set, null) this pointer. */ + mfxStructVersion Version; /*!< The version of the structure. */ + /*! @brief + Increments the internal reference counter of the container. The container is not destroyed until the container + is released using the mfxRefInterface::Release function. + mfxRefInterface::AddRef should be used each time a new link to the container is created + (for example, copy structure) for proper management. + + @param[in] ref_interface Valid interface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxRefInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxRefInterface* ref_interface); + /*! @brief + Decrements the internal reference counter of the container. mfxRefInterface::Release should be called after using the + mfxRefInterface::AddRef function to add a container or when allocation logic requires it. + + @param[in] ref_interface Valid interface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxRefInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of container is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxRefInterface* ref_interface); + /*! @brief + Returns current reference counter of mfxRefInterface structure. + + @param[in] ref_interface Valid interface. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxRefInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(struct mfxRefInterface* ref_interface, mfxU32* counter); + mfxHDL reserved[4]; + +}mfxRefInterface; +MFX_PACK_END() + +/* Library initialization and deinitialization */ +/*! + This enumerator itemizes implementation types. + The implementation type is a bit OR'ed value of the base type and any decorative flags. + @note This enumerator is for legacy dispatcher compatibility only. The new dispatcher does not use it. + */ +typedef mfxI32 mfxIMPL; +/*! + The application can use the macro MFX_IMPL_BASETYPE(x) to obtain the base implementation type. +*/ +#define MFX_IMPL_BASETYPE(x) (0x00ff & (x)) + +enum { + MFX_IMPL_AUTO = 0x0000, /*!< Auto Selection/In or Not Supported/Out. */ + MFX_IMPL_SOFTWARE = 0x0001, /*!< Pure software implementation. */ + MFX_IMPL_HARDWARE = 0x0002, /*!< Hardware accelerated implementation (default device). */ + MFX_IMPL_AUTO_ANY = 0x0003, /*!< Auto selection of any hardware/software implementation. */ + MFX_IMPL_HARDWARE_ANY = 0x0004, /*!< Auto selection of any hardware implementation. */ + MFX_IMPL_HARDWARE2 = 0x0005, /*!< Hardware accelerated implementation (2nd device). */ + MFX_IMPL_HARDWARE3 = 0x0006, /*!< Hardware accelerated implementation (3rd device). */ + MFX_IMPL_HARDWARE4 = 0x0007, /*!< Hardware accelerated implementation (4th device). */ + MFX_IMPL_RUNTIME = 0x0008, /*!< This value cannot be used for session initialization. It may be returned by the MFXQueryIMPL + function to show that the session has been initialized in run-time mode. */ + MFX_IMPL_VIA_ANY = 0x0100, /*!< Hardware acceleration can go through any supported OS infrastructure. This is the default value. The default value + is used by the legacy Intel(r) Media SDK if none of the MFX_IMPL_VIA_xxx flags are specified by the application. */ + MFX_IMPL_VIA_D3D9 = 0x0200, /*!< Hardware acceleration goes through the Microsoft* Direct3D* 9 infrastructure. */ + MFX_IMPL_VIA_D3D11 = 0x0300, /*!< Hardware acceleration goes through the Microsoft* Direct3D* 11 infrastructure. */ + MFX_IMPL_VIA_VAAPI = 0x0400, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure. */ + MFX_IMPL_VIA_HDDLUNITE = 0x0500, /*!< Hardware acceleration goes through the HDDL* Unite*. */ + + MFX_IMPL_UNSUPPORTED = 0x0000 /*!< One of the MFXQueryIMPL returns. */ +}; + +/* Version Info */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The mfxVersion union describes the version of the implementation.*/ +typedef union { + /*! @brief Structure with Major and Minor fields. */ + /*! @struct Anonymous */ + struct { + /*! @{ + @name Major and Minor fields + Anonymous structure with Major and Minor fields. + */ + mfxU16 Minor; /*!< Minor number of the implementation. */ + mfxU16 Major; /*!< Major number of the implementation. */ + /*! @} */ + }; + mfxU32 Version; /*!< Implementation version number. */ +} mfxVersion; +MFX_PACK_END() + +/*! The mfxPriority enumerator describes the session priority. */ +typedef enum +{ + MFX_PRIORITY_LOW = 0, /*!< Low priority: the session operation halts when high priority tasks are executing and more than 75% of the CPU is being used for normal priority tasks.*/ + MFX_PRIORITY_NORMAL = 1, /*!< Normal priority: the session operation is halted if there are high priority tasks.*/ + MFX_PRIORITY_HIGH = 2 /*!< High priority: the session operation blocks other lower priority session operations.*/ + +} mfxPriority; + +typedef struct _mfxEncryptedData mfxEncryptedData; +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! Defines the buffer that holds compressed video data. */ +typedef struct { + /*! @internal :unnamed(union) @endinternal */ + union { + struct { + mfxEncryptedData* EncryptedData; /*!< Reserved and must be zero. */ + mfxExtBuffer **ExtParam; /*!< Array of extended buffers for additional bitstream configuration. See the ExtendedBufferID enumerator for a complete list of extended buffers. */ + mfxU16 NumExtParam; /*!< The number of extended buffers attached to this structure. */ + mfxU16 reserved1; /*!< Reserved for future use. */ + mfxU32 CodecId; /*!< Specifies the codec format identifier in the FourCC code. See the CodecFormatFourCC enumerator for details. This optional parameter is required for the simplified decode initialization. */ + + }; + mfxU32 reserved[6]; + }; + /*! Decode time stamp of the compressed bitstream in units of 90KHz. A value of MFX_TIMESTAMP_UNKNOWN indicates that there is no time stamp. + + This value is calculated by the encoder from the presentation time stamp provided by the application in the mfxFrameSurface1 structure and + from the frame rate provided by the application during the encoder initialization. */ + mfxI64 DecodeTimeStamp; + mfxU64 TimeStamp; /*!< Time stamp of the compressed bitstream in units of 90KHz. A value of MFX_TIMESTAMP_UNKNOWN indicates that there is no time stamp. */ + mfxU8* Data; /*!< Bitstream buffer pointer, 32-bytes aligned. */ + mfxU32 DataOffset; /*!< Next reading or writing position in the bitstream buffer. */ + mfxU32 DataLength; /*!< Size of the actual bitstream data in bytes. */ + mfxU32 MaxLength; /*!< Allocated bitstream buffer size in bytes. */ + + mfxU16 PicStruct; /*!< Type of the picture in the bitstream. Output parameter. */ + mfxU16 FrameType; /*!< Frame type of the picture in the bitstream. Output parameter. */ + mfxU16 DataFlag; /*!< Indicates additional bitstream properties. See the BitstreamDataFlag enumerator for details. */ + mfxU16 reserved2; /*!< Reserved for future use. */ +} mfxBitstream; +MFX_PACK_END() + +/*! Synchronization point object handle. */ +typedef struct _mfxSyncPoint *mfxSyncPoint; + +/*! The GPUCopy enumerator controls usage of GPU accelerated copying between video and system memory in the legacy Intel(r) Media SDK components. */ +enum { + MFX_GPUCOPY_DEFAULT = 0, /*!< Use default mode for the legacy Intel(r) Media SDK implementation. */ + MFX_GPUCOPY_ON = 1, /*!< The hint to enable GPU accelerated copying when it is supported by the library. + If the library doesn't support GPU accelerated copy the operation will be made by CPU. + Buffer caching usage decision is up to runtime to decide, for explicit hints please use MFX_GPUCOPY_SAFE or MFX_GPUCOPY_FAST */ + MFX_GPUCOPY_OFF = 2, /*!< Disable GPU accelerated copying. */ + MFX_GPUCOPY_SAFE = 3, /*!< The hint to disable buffer caching for GPU accelerated copying. Actual when GPU accelerated copying is supported by the library. */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_GPUCOPY_FAST = 4 /*!< The hint to enable buffer caching for GPU accelerated copying. Actual when GPU accelerated copying is supported by the library. */ +#endif +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Specifies advanced initialization parameters. + A zero value in any of the fields indicates that the corresponding field + is not explicitly specified. +*/ +typedef struct { + mfxIMPL Implementation; /*!< Enumerator that indicates the desired legacy Intel(r) Media SDK implementation. */ + mfxVersion Version; /*!< Structure which specifies minimum library version or zero, if not specified. */ + mfxU16 ExternalThreads; /*!< Desired threading mode. Value 0 means internal threading, 1 - external. */ + /*! @internal :unnamed(union) @endinternal */ + union { + struct { + mfxExtBuffer **ExtParam; /*!< Points to an array of pointers to the extra configuration structures; see the ExtendedBufferID enumerator for a list of extended configurations. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + }; + mfxU16 reserved2[5]; + }; + mfxU16 GPUCopy; /*!< Enables or disables GPU accelerated copying between video and system memory in legacy Intel(r) Media SDK components. See the GPUCopy enumerator for a list of valid values. */ + mfxU16 reserved[21]; +} mfxInitParam; +MFX_PACK_END() + +enum { + MFX_EXTBUFF_THREADS_PARAM = MFX_MAKEFOURCC('T','H','D','P') /*!< mfxExtThreadsParam buffer ID. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies options for threads created by this session. Attached to the + mfxInitParam structure during legacy Intel(r) Media SDK session initialization + or to mfxInitializationParam by the dispatcher in MFXCreateSession function. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_THREADS_PARAM. */ + + mfxU16 NumThread; /*!< The number of threads. */ + mfxI32 SchedulingType; /*!< Scheduling policy for all threads.*/ + mfxI32 Priority; /*!< Priority for all threads. */ + mfxU16 reserved[55]; /*!< Reserved for future use. */ +} mfxExtThreadsParam; +MFX_PACK_END() + +/*! Deprecated. */ +enum { + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_UNKNOWN) = 0, /*!< Unknown platform. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_SANDYBRIDGE) = 1, /*!< Intel(r) microarchitecture code name Sandy Bridge. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_IVYBRIDGE) = 2, /*!< Intel(r) microarchitecture code name Ivy Bridge. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_HASWELL) = 3, /*!< Code name Haswell. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_BAYTRAIL) = 4, /*!< Code name Bay Trail. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_BROADWELL) = 5, /*!< Intel(r) microarchitecture code name Broadwell. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_CHERRYTRAIL) = 6, /*!< Code name Cherry Trail. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_SKYLAKE) = 7, /*!< Intel(r) microarchitecture code name Skylake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_APOLLOLAKE) = 8, /*!< Code name Apollo Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_KABYLAKE) = 9, /*!< Code name Kaby Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_GEMINILAKE) = 10, /*!< Code name Gemini Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_COFFEELAKE) = 11, /*!< Code name Coffee Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_CANNONLAKE) = 20, /*!< Code name Cannon Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ICELAKE) = 30, /*!< Code name Ice Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_JASPERLAKE) = 32, /*!< Code name Jasper Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ELKHARTLAKE) = 33, /*!< Code name Elkhart Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_TIGERLAKE) = 40, /*!< Code name Tiger Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ROCKETLAKE) = 42, /*!< Code name Rocket Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ALDERLAKE_S) = 43, /*!< Code name Alder Lake S. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ALDERLAKE_P) = 44, /*!< Code name Alder Lake P. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ARCTICSOUND_P) = 45, + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_XEHP_SDV) = 45, /*!< Code name XeHP SDV. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_DG2) = 46, /*!< Code name DG2. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ATS_M) = 46, /*!< Code name ATS-M, same media functionality as DG2. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ALDERLAKE_N) = 55, /*!< Code name Alder Lake N. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_KEEMBAY) = 50, /*!< Code name Keem Bay. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_METEORLAKE) = 51, /*!< Code name Meteor Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_BATTLEMAGE) = 52, /*!< Code name Battlemage. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_LUNARLAKE) = 53, /*!< Code name Lunar Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_ARROWLAKE) = 54, /*!< Code name Arrow Lake. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_PLATFORM_MAXIMUM) = 65535, /*!< General code name. */ +}; + +/*! The mfxMediaAdapterType enumerator itemizes types of graphics adapters. */ +typedef enum +{ + MFX_MEDIA_UNKNOWN = 0xffff, /*!< Unknown type. */ + MFX_MEDIA_INTEGRATED = 0, /*!< Integrated graphics adapter. */ + MFX_MEDIA_DISCRETE = 1 /*!< Discrete graphics adapter. */ +} mfxMediaAdapterType; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Contains information about hardware platform for the Legacy mode. */ +typedef struct { + MFX_DEPRECATED mfxU16 CodeName; /*!< Deprecated. */ + mfxU16 DeviceId; /*!< Unique identifier of graphics device. */ + mfxU16 MediaAdapterType; /*!< Description of graphics adapter type. See the mfxMediaAdapterType enumerator for a list of possible values. */ + mfxU16 reserved[13]; /*!< Reserved for future use. */ +} mfxPlatform; +MFX_PACK_END() + + +/*! The mfxResourceType enumerator specifies types of different native data frames and buffers. */ +typedef enum { + MFX_RESOURCE_SYSTEM_SURFACE = 1, /*!< System memory. */ + MFX_RESOURCE_VA_SURFACE_PTR = 2, /*!< Pointer to VA surface index. */ + MFX_RESOURCE_VA_SURFACE = MFX_RESOURCE_VA_SURFACE_PTR, /*!< Pointer to VA surface index. */ + MFX_RESOURCE_VA_BUFFER_PTR = 3, /*!< Pointer to VA buffer index. */ + MFX_RESOURCE_VA_BUFFER = MFX_RESOURCE_VA_BUFFER_PTR, /*!< Pointer to VA buffer index. */ + MFX_RESOURCE_DX9_SURFACE = 4, /*!< Pointer to IDirect3DSurface9. */ + MFX_RESOURCE_DX11_TEXTURE = 5, /*!< Pointer to ID3D11Texture2D. */ + MFX_RESOURCE_DX12_RESOURCE = 6, /*!< Pointer to ID3D12Resource. */ + MFX_RESOURCE_DMA_RESOURCE = 7, /*!< DMA resource. */ + MFX_RESOURCE_HDDLUNITE_REMOTE_MEMORY = 8, /*!< HDDL Unite Remote memory handle. */ +} mfxResourceType; + +/*! Maximum allowed length of the implementation name. */ +#define MFX_IMPL_NAME_LEN 32 +/*! Maximum allowed length of the implementation name. */ +#define MFX_STRFIELD_LEN 128 + +#ifdef ONEVPL_EXPERIMENTAL + +#define MFX_DECEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxDecExtDescription structure represents the extended description of a decoder. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[14]; /*!< Reserved for future use. */ + mfxU16 NumExtBufferIDs; /*!< Number of supported extended buffer IDs. */ + mfxU32* ExtBufferIDs; /*!< Pointer to the array of supported extended buffer IDs. */ +} mfxDecExtDescription; +MFX_PACK_END() + +#define MFX_DECMEMEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxDecMemExtDescription structure represents the extended description for decoder memory. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[13]; /*!< Reserved for future use. */ + mfxU16 MaxBitDepth; /*!< Maximum supported bit depth. */ + mfxU16 NumChromaSubsamplings; /*!< Number of supported output chroma subsamplings. */ + mfxU16* ChromaSubsamplings; /*!< Pointer to the array of supported output chroma subsamplings. */ +} mfxDecMemExtDescription; +MFX_PACK_END() + +#endif + +#ifdef ONEVPL_EXPERIMENTAL +#define MFX_DECODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 1) +#else +#define MFX_DECODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) +#endif + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxDecoderDescription structure represents the description of a decoder. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumCodecs; /*!< Number of supported decoders. */ + /*! This structure represents the decoder description. */ + struct decoder { + mfxU32 CodecID; /*!< Decoder ID in FourCC format. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 reserved[2]; /*!< Reserved for future use. */ + union { + mfxDecExtDescription* DecExtDesc; /*!< Pointer to the extended descriptions of the decoder. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved3[2]; /*!< Reserved for future use. */ +#else + mfxU16 reserved[8]; /*!< Reserved for future use. */ +#endif + mfxU16 MaxcodecLevel; /*!< Maximum supported codec level. See the CodecProfile enumerator for possible values. */ + mfxU16 NumProfiles; /*!< Number of supported profiles. */ + /*! This structure represents the codec profile description. */ + struct decprofile { + mfxU32 Profile; /*!< Profile ID. See the CodecProfile enumerator for possible values.*/ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumMemTypes; /*!< Number of supported memory types. */ + /*! This structure represents the underlying details of the memory type. */ + struct decmemdesc { + mfxResourceType MemHandleType; /*!< Memory handle type. */ + mfxRange32U Width; /*!< Range of supported image widths. */ + mfxRange32U Height; /*!< Range of supported image heights. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 reserved[2]; /*!< Reserved for future use. */ + union { + mfxDecMemExtDescription* MemExtDesc; /*!< Pointer to the extended descriptions for decoder memory. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved3; /*!< Reserved for future use. */ +#else + mfxU16 reserved[7]; /*!< Reserved for future use. */ +#endif + mfxU16 NumColorFormats; /*!< Number of supported output color formats. */ + mfxU32* ColorFormats; /*!< Pointer to the array of supported output color formats (in FOURCC). */ + } * MemDesc; /*!< Pointer to the array of memory types. */ + } * Profiles; /*!< Pointer to the array of profiles supported by the codec. */ + } * Codecs; /*!< Pointer to the array of decoders. */ +} mfxDecoderDescription; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL + +#define MFX_ENCEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxEncExtDescription structure represents the extended description of an encoder. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[10]; /*!< Reserved for future use. */ + mfxU16 NumRateControlMethods; /*!< Number of supported bitrate control methods. */ + mfxU16* RateControlMethods; /*!< Pointer to the array of supported bitrate control methods. */ + mfxU16 reserved2[11]; /*!< Reserved for future use. */ + mfxU16 NumExtBufferIDs; /*!< Number of supported extended buffer IDs. */ + mfxU32* ExtBufferIDs; /*!< Pointer to the array of supported extended buffer IDs. */ +} mfxEncExtDescription; +MFX_PACK_END() + +#define MFX_ENCMEMEXTDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxEncMemExtDescription structure represents the extended description for encoder memory. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[13]; /*!< Reserved for future use. */ + mfxU16 TargetMaxBitDepth; /*!< Maximum supported bit depth. */ + mfxU16 NumTargetChromaSubsamplings; /*!< Number of supported target chroma subsamplings. */ + mfxU16* TargetChromaSubsamplings; /*!< Pointer to the array of supported target chroma subsamplings. */ +} mfxEncMemExtDescription; +MFX_PACK_END() + +#endif + +#ifdef ONEVPL_EXPERIMENTAL +#define MFX_ENCODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 1) +#else +#define MFX_ENCODERDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) +#endif + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents an encoder description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumCodecs; /*!< Number of supported encoders. */ + /*! This structure represents encoder description. */ + struct encoder { + mfxU32 CodecID; /*!< Encoder ID in FourCC format. */ + mfxU16 MaxcodecLevel; /*!< Maximum supported codec level. See the CodecProfile enumerator for possible values. */ + mfxU16 BiDirectionalPrediction; /*!< Indicates B-frames support. */ +#ifdef ONEVPL_EXPERIMENTAL + union { + mfxEncExtDescription* EncExtDesc; /*!< Pointer to the extended descriptions of the encoder. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved[3]; /*!< Reserved for future use. */ +#else + mfxU16 reserved[7]; /*!< Reserved for future use. */ +#endif + mfxU16 NumProfiles; /*!< Number of supported profiles. */ + /*! This structure represents the codec profile description. */ + struct encprofile { + mfxU32 Profile; /*!< Profile ID. See the CodecProfile enumerator for possible values.*/ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumMemTypes; /*!< Number of supported memory types. */ + /*! This structure represents the underlying details of the memory type. */ + struct encmemdesc { + mfxResourceType MemHandleType; /*!< Memory handle type. */ + mfxRange32U Width; /*!< Range of supported image widths. */ + mfxRange32U Height; /*!< Range of supported image heights. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 reserved[2]; /*!< Reserved for future use. */ + union { + mfxEncMemExtDescription* MemExtDesc; /*!< Pointer to the extended descriptions for encoder memory. */ + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + }; + mfxU16 reserved3; /*!< Reserved for future use. */ +#else + mfxU16 reserved[7]; /*!< Reserved for future use. */ +#endif + mfxU16 NumColorFormats; /*!< Number of supported input color formats. */ + mfxU32* ColorFormats; /*!< Pointer to the array of supported input color formats (in FOURCC). */ + } * MemDesc; /*!< Pointer to the array of memory types. */ + } * Profiles; /*!< Pointer to the array of profiles supported by the codec. */ + } * Codecs; /*!< Pointer to the array of encoders. */ +} mfxEncoderDescription; +MFX_PACK_END() + +#define MFX_VPPDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents VPP description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumFilters; /*!< Number of supported VPP filters. */ + /*! This structure represents the VPP filters description. */ + struct filter { + mfxU32 FilterFourCC; /*!< Filter ID in FourCC format. */ + mfxU16 MaxDelayInFrames; /*!< Introduced output delay in frames. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumMemTypes; /*!< Number of supported memory types. */ + /*! This structure represents the underlying details of the memory type. */ + struct memdesc { + mfxResourceType MemHandleType; /*!< Memory handle type. */ + mfxRange32U Width; /*!< Range of supported image widths. */ + mfxRange32U Height; /*!< Range of supported image heights. */ + mfxU16 reserved[7]; /*!< Reserved for future use. */ + mfxU16 NumInFormats; /*!< Number of supported input color formats. */ + /*! This structure represents the input color format description. */ + struct format { + mfxU32 InFormat; /*!< Input color in FourCC format. */ + mfxU16 reserved[5]; /*!< Reserved for future use. */ + mfxU16 NumOutFormat; /*!< Number of supported output color formats. */ + mfxU32* OutFormats; /*!< Pointer to the array of supported output color formats (in FOURCC). */ + } * Formats; /*!< Pointer to the array of supported formats. */ + } * MemDesc; /*!< Pointer to the array of memory types. */ + } * Filters; /*!< Pointer to the array of supported filters. */ +} mfxVPPDescription; +MFX_PACK_END() + +/*! The current version of mfxDeviceDescription structure. */ +#define MFX_DEVICEDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 1) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents device description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[6]; /*!< reserved for future use. */ + mfxU16 MediaAdapterType; /*!< Graphics adapter type. See the mfxMediaAdapterType enumerator for a list of possible values. */ + mfxChar DeviceID[MFX_STRFIELD_LEN]; /*!< Null terminated string with device ID. */ + mfxU16 NumSubDevices; /*!< Number of available uniform sub-devices. Pure software implementation can report 0. */ + /*! This structure represents sub-device description. */ + struct subdevices { + mfxU32 Index; /*!< Index of the sub-device, started from 0 and increased by 1.*/ + mfxChar SubDeviceID[MFX_STRFIELD_LEN]; /*!< Null terminated string with unique sub-device ID, mapped to the system ID. */ + mfxU32 reserved[7]; /*!< reserved for future use. */ + } * SubDevices; /*!< Pointer to the array of available sub-devices. */ +} mfxDeviceDescription; +MFX_PACK_END() + +/*! This enum itemizes implementation type. */ +typedef enum { + MFX_IMPL_TYPE_SOFTWARE = 0x0001, /*!< Pure Software Implementation. */ + MFX_IMPL_TYPE_HARDWARE = 0x0002, /*!< Hardware Accelerated Implementation. */ +} mfxImplType; + +/*! This enum itemizes hardware acceleration stack to use. */ +typedef enum { + MFX_ACCEL_MODE_NA = 0, /*!< Hardware acceleration is not applicable. */ + MFX_ACCEL_MODE_VIA_D3D9 = 0x0200, /*!< Hardware acceleration goes through the Microsoft* Direct3D9* infrastructure. */ + MFX_ACCEL_MODE_VIA_D3D11 = 0x0300, /*!< Hardware acceleration goes through the Microsoft* Direct3D11* infrastructure. */ + MFX_ACCEL_MODE_VIA_VAAPI = 0x0400, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure. */ + MFX_ACCEL_MODE_VIA_VAAPI_DRM_RENDER_NODE + = MFX_ACCEL_MODE_VIA_VAAPI, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with DRM RENDER MODE as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_DRM_MODESET = 0x0401, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with DRM MODESET as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_GLX = 0x0402, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with OpenGL Extension to the X Window System + as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_X11 = 0x0403, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with X11 as default acceleration access point. */ + MFX_ACCEL_MODE_VIA_VAAPI_WAYLAND = 0x0404, /*!< Hardware acceleration goes through the Linux* VA-API infrastructure with Wayland as default acceleration access point. */ + 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() +/*! This structure represents acceleration modes description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[2]; /*!< reserved for future use. */ + mfxU16 NumAccelerationModes; /*!< Number of supported acceleration modes. */ + mfxAccelerationMode* Mode; /*!< Pointer to the array of supported acceleration modes. */ +} mfxAccelerationModeDescription; +MFX_PACK_END() + +/*! Specifies the surface pool allocation policies. */ + typedef enum { + /*! Recommends to limit max pool size by sum of requested surfaces asked by components. */ + MFX_ALLOCATION_OPTIMAL = 0, + + /*! Dynamic allocation with no limit. */ + MFX_ALLOCATION_UNLIMITED = 1, + + /*! Max pool size is limited by NumberToPreAllocate + DeltaToAllocateOnTheFly. */ + MFX_ALLOCATION_LIMITED = 2, + +} mfxPoolAllocationPolicy; + +/*! The current version of mfxPoolPolicyDescription structure. */ +#define MFX_POOLPOLICYDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents pool policy description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 reserved[2]; /*!< reserved for future use. */ + mfxU16 NumPoolPolicies; /*!< Number of supported pool policies. */ + mfxPoolAllocationPolicy* Policy; /*!< Pointer to the array of supported pool policies. */ +} mfxPoolPolicyDescription; +MFX_PACK_END() + +/*! The current version of mfxImplDescription structure. */ +#define MFX_IMPLDESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 2) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents the implementation description. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxImplType Impl; /*!< Impl type: software/hardware. */ + mfxAccelerationMode AccelerationMode; /*!< Default Hardware acceleration stack to use. OS dependent parameter. Use VA for Linux* and DX* for Windows*. */ + mfxVersion ApiVersion; /*!< Supported API version. */ + mfxChar ImplName[MFX_IMPL_NAME_LEN]; /*!< Null-terminated string with implementation name given by vendor. */ + mfxChar License[MFX_STRFIELD_LEN]; /*!< Null-terminated string with comma-separated list of license names of the implementation. */ + mfxChar Keywords[MFX_STRFIELD_LEN]; /*!< Null-terminated string with comma-separated list of keywords specific to this implementation that dispatcher can search for. */ + mfxU32 VendorID; /*!< Standard vendor ID 0x8086 - Intel. */ + mfxU32 VendorImplID; /*!< Vendor specific number with given implementation ID. */ + mfxDeviceDescription Dev; /*!< Supported device. */ + mfxDecoderDescription Dec; /*!< Decoder configuration. */ + mfxEncoderDescription Enc; /*!< Encoder configuration. */ + mfxVPPDescription VPP; /*!< VPP configuration. */ + union + { + mfxAccelerationModeDescription AccelerationModeDescription; /*!< Supported acceleration modes. */ + mfxU32 reserved3[4]; + }; + mfxPoolPolicyDescription PoolPolicies; /*!< Supported surface pool polices. */ + mfxU32 reserved[8]; /*!< Reserved for future use. */ + mfxU32 NumExtParam; /*!< Number of extension buffers. Reserved for future use. Must be 0. */ + union { + mfxExtBuffer **ExtParam; /*!< Array of extension buffers. */ + mfxU64 Reserved2; /*!< Reserved for future use. */ + } ExtParams; /*!< Extension buffers. Reserved for future. */ +} mfxImplDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure represents the list of names of implemented functions. */ +typedef struct { + mfxU16 NumFunctions; /*!< Number of function names in the FunctionsName array. */ + mfxChar** FunctionsName; /*!< Array of the null-terminated strings. Each string contains name of the implemented function. */ +} mfxImplementedFunctions; +MFX_PACK_END() + + +#define MFX_EXTENDEDDEVICEID_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies various physical device properties for device matching and identification outside of oneAPI Video Processing Library (oneVPL). */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxU16 VendorID; /*!< PCI vendor ID. */ + mfxU16 DeviceID; /*!< PCI device ID. */ + mfxU32 PCIDomain; /*!< PCI bus domain. Equals to '0' if OS doesn't support it or + has sequential numbering of buses across domains. */ + mfxU32 PCIBus; /*!< The number of the bus that the physical device is located on. */ + mfxU32 PCIDevice; /*!< The index of the physical device on the bus. */ + mfxU32 PCIFunction; /*!< The function number of the device on the physical device. */ + mfxU8 DeviceLUID[8]; /*!< LUID of DXGI adapter. */ + mfxU32 LUIDDeviceNodeMask; /*!< Bitfield identifying the node within a linked + device adapter corresponding to the device. */ + mfxU32 LUIDValid; /*!< Boolean value that will be 1 if DeviceLUID contains a valid LUID + and LUIDDeviceNodeMask contains a valid node mask, + and 0 if they do not. */ + mfxU32 DRMRenderNodeNum; /*!< Number of the DRM render node from the path /dev/dri/RenderD\. + Value equals to 0 means that this field doesn't contain valid DRM Render + Node number.*/ + mfxU32 DRMPrimaryNodeNum; /*!< Number of the DRM primary node from the path /dev/dri/card\. + Value equals to 0x7FFFFFFF means that this field doesn't contain valid DRM Primary + Node number.*/ + mfxU16 RevisionID; /*!< PCI revision ID. The value contains microarchitecture version. */ + mfxU8 reserved1[18]; /*!< Reserved for future use. */ + mfxChar DeviceName[MFX_STRFIELD_LEN]; /*!< Null-terminated string in utf-8 with the name of the device. */ +} mfxExtendedDeviceId; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Cross domain structure to define device UUID. It is defined here to check backward compatibility.*/ +typedef struct { + mfxU16 vendor_id; /*!< PCI vendor ID. Same as mfxExtendedDeviceId::VendorID. */ + mfxU16 device_id; /*!< PCI device ID. Same as mfxExtendedDeviceId::DeviceID. */ + mfxU16 revision_id; /*!< PCI revision ID. Same as mfxExtendedDeviceId::RevisionID. */ + mfxU16 pci_domain; /*!< PCI bus domain. Same as mfxExtendedDeviceId::PCIDomain. */ + mfxU8 pci_bus; /*!< The number of the bus that the physical device is located on. Same as mfxExtendedDeviceId::PCIBus. */ + mfxU8 pci_dev; /*!< The index of the physical device on the bus. Same as mfxExtendedDeviceId::PCIDevice. */ + mfxU8 pci_func; /*!< The function number of the device on the physical device. Same as mfxExtendedDeviceId::PCIFunction. */ + mfxU8 reserved[4]; /*!< Reserved for future use. */ + mfxU8 sub_device_id; /*!< SubDevice ID.*/ +} extDeviceUUID; +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_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. */ + MFX_IMPLCAPS_DEVICE_ID_EXTENDED = 4, /*!< Deliver extended device ID information as mfxExtendedDeviceId + structure.*/ +#ifdef ONEVPL_EXPERIMENTAL + MFX_IMPLCAPS_SURFACE_TYPES = 5, /*!< Deliver capabilities as mfxSurfaceTypesSupported structure. */ +#endif +} mfxImplCapsDeliveryFormat; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Specifies initialization parameters for API version starting from 2.0. +*/ +typedef struct { + mfxAccelerationMode AccelerationMode; /*!< Hardware acceleration stack to use. OS dependent parameter. Use VA for Linux*, DX* for Windows* or HDDL. */ +#ifdef ONEVPL_EXPERIMENTAL + mfxU16 DeviceCopy; /*!< Enables or disables device's accelerated copying between device and + host. See the GPUCopy enumerator for a list of valid values. + This parameter is the equivalent of mfxInitParam::GPUCopy. */ + mfxU16 reserved[2]; /*!< Reserved for future use. */ +#else + mfxU16 reserved[3]; /*!< Reserved for future use. */ +#endif + 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 field from mfxImplDescription. */ + mfxU32 reserved2[3]; /*!< Reserved for future use. */ +} mfxInitializationParam; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Represents a name/value pair to indicate requested properties. For use with MFXQueryImplsProperties() */ +typedef struct { + mfxU8* PropName; /*!< Property name string to indicate the requested Property. */ + mfxVariant PropVar; /*!< Property value corresponding to the property name. */ +} mfxQueryProperty; +MFX_PACK_END() +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/third-party/IntelVPL/x64/include/vpl/mfxdefs.h b/third-party/IntelVPL/x64/include/vpl/mfxdefs.h new file mode 100644 index 000000000..5b9be9422 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxdefs.h @@ -0,0 +1,349 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXDEFS_H__ +#define __MFXDEFS_H__ + +#define MFX_VERSION_MAJOR 2 +#define MFX_VERSION_MINOR 16 + +// 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 + + +#if !defined(MFX_VERSION) + #define MFX_VERSION (MFX_VERSION_MAJOR * 1000 + MFX_VERSION_MINOR) +#else + #undef MFX_VERSION_MAJOR + #define MFX_VERSION_MAJOR ((MFX_VERSION) / 1000) + + #undef MFX_VERSION_MINOR + #define MFX_VERSION_MINOR ((MFX_VERSION) % 1000) +#endif + +/*! 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 1035 + + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* In preprocessor syntax # symbol has stringize meaning, + so to expand some macro to preprocessor pragma we need to use + special compiler dependent construction */ + +#if defined(_MSC_VER) + #define MFX_PRAGMA_IMPL(x) __pragma(x) +#else + #define MFX_PRAGMA_IMPL(x) _Pragma(#x) +#endif + +#define MFX_PACK_BEGIN_X(x) MFX_PRAGMA_IMPL(pack(push, x)) +#define MFX_PACK_END() MFX_PRAGMA_IMPL(pack(pop)) + +/* The general rule for alignment is following: + - structures with pointers have 4/8 bytes alignment on 32/64 bit systems + - structures with fields of type mfxU64/mfxF64 (unsigned long long / double) + have alignment 8 bytes on 64 bit and 32 bit Windows, on Linux alignment is 4 bytes + - all the rest structures are 4 bytes aligned + - there are several exceptions: some structs which had 4-byte alignment were extended + with pointer / long type fields; such structs have 4-byte alignment to keep binary + compatibility with previously release API */ + +#define MFX_PACK_BEGIN_USUAL_STRUCT() MFX_PACK_BEGIN_X(4) + +/* 64-bit LP64 data model */ +#if defined(_WIN64) || defined(__LP64__) + #define MFX_PACK_BEGIN_STRUCT_W_PTR() MFX_PACK_BEGIN_X(8) + #define MFX_PACK_BEGIN_STRUCT_W_L_TYPE() MFX_PACK_BEGIN_X(8) +/* 32-bit ILP32 data model Windows* (Intel(r) architecture) */ +#elif defined(_WIN32) || defined(_M_IX86) && !defined(__linux__) + #define MFX_PACK_BEGIN_STRUCT_W_PTR() MFX_PACK_BEGIN_X(4) + #define MFX_PACK_BEGIN_STRUCT_W_L_TYPE() MFX_PACK_BEGIN_X(8) +/* 32-bit ILP32 data model Linux* */ +#elif defined(__ILP32__) || defined(__arm__) + #define MFX_PACK_BEGIN_STRUCT_W_PTR() MFX_PACK_BEGIN_X(4) + #define MFX_PACK_BEGIN_STRUCT_W_L_TYPE() MFX_PACK_BEGIN_X(4) +#else + #error Unknown packing +#endif + +#ifdef _WIN32 + #define MFX_CDECL __cdecl + #define MFX_STDCALL __stdcall +#else + #define MFX_CDECL + #define MFX_STDCALL +#endif /* _WIN32 */ + +#define MFX_INFINITE 0xFFFFFFFF + +#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 + +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. */ +typedef unsigned short mfxU16; /*!< Unsigned integer, 16 bit type. */ +typedef unsigned int mfxU32; /*!< Unsigned integer, 32 bit type. */ +typedef int mfxI32; /*!< Signed integer, 32 bit type. */ +#if defined( _WIN32 ) || defined ( _WIN64 ) +typedef unsigned long mfxUL32; /*!< Unsigned integer, 32 bit type. */ +typedef long mfxL32; /*!< Signed integer, 32 bit type. */ +#else +typedef unsigned int mfxUL32; /*!< Unsigned integer, 32 bit type. */ +typedef int mfxL32; /*!< Signed integer, 32 bit type. */ +#endif +typedef float mfxF32; /*!< Single-precision floating point, 32 bit type. */ +typedef double mfxF64; /*!< Double-precision floating point, 64 bit type. */ +typedef unsigned long long mfxU64; /*!< Unsigned integer, 64 bit type. */ +typedef long long mfxI64; /*!< Signed integer, 64 bit type. */ +typedef void* mfxHDL; /*!< Handle type. */ +typedef mfxHDL mfxMemId; /*!< Memory ID type. */ +typedef void* mfxThreadTask; /*!< Thread task type. */ +typedef char mfxChar; /*!< UTF-8 byte. */ +typedef unsigned short mfxFP16; /*!< Half precision floating point, 16 bit type. */ + +/* MFX structures version info */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Introduce the field Version for any structure. +Assumed that any structure changes are backward binary compatible. + mfxStructVersion starts from {1,0} for any new API structures. If mfxStructVersion is + added to the existent legacy structure (replacing reserved fields) it starts from {1, 1}. +*/ +typedef union { + /*! Structure with Major and Minor fields. */ + /*! @struct Anonymous */ + struct { + /*! @{ + @name Major and Minor fields + Anonymous structure with Major and Minor fields. Minor number is incremented when reserved fields are used. Major number is incremented when the size of structure is increased. */ + mfxU8 Minor; /*!< Minor number of the correspondent structure. */ + mfxU8 Major; /*!< Major number of the correspondent structure. */ + /*! @} */ + }; + mfxU16 Version; /*!< Structure version number. */ +} mfxStructVersion; +MFX_PACK_END() + +#define MFX_STRUCT_VERSION(MAJOR, MINOR) (256*(MAJOR) + (MINOR)) + +#define MFX_VARIANT_VERSION MFX_STRUCT_VERSION(1, 1) + +/*! 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. */ + MFX_DATA_TYPE_PTR, /*!< Generic type pointer. */ + MFX_DATA_TYPE_FP16, /*!< 16-bit half precision floating point. */ +}mfxDataType; + +/*! The mfxVariantType enumerator data types for mfxVariantType. */ +typedef enum { + 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 = MFX_DATA_TYPE_PTR, /*!< Generic type pointer. */ + MFX_VARIANT_TYPE_FP16 = MFX_DATA_TYPE_FP16, /*!< 16-bit half precision floating point. */ + +#ifdef ONEVPL_EXPERIMENTAL + MFX_VARIANT_TYPE_QUERY = 0x00000100, /*!< Bitmask to OR with other variant types when using property-based query API */ +#endif +} mfxVariantType; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The mfxVariantType enumerator data types for mfxVariant type. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + mfxVariantType Type; /*!< Value type. */ + /*! Value data holder. */ + union data { + mfxU8 U8; /*!< mfxU8 data. */ + mfxI8 I8; /*!< mfxI8 data. */ + mfxU16 U16; /*!< mfxU16 data. */ + mfxI16 I16; /*!< mfxI16 data. */ + mfxU32 U32; /*!< mfxU32 data. */ + mfxI32 I32; /*!< mfxI32 data. */ + mfxU64 U64; /*!< mfxU64 data. */ + mfxI64 I64; /*!< mfxI64 data. */ + mfxF32 F32; /*!< mfxF32 data. */ + mfxF64 F64; /*!< mfxF64 data. */ + mfxFP16 FP16; /*!< mfxFP16 data. */ + mfxHDL Ptr; /*!< Pointer. When this points to a string the string must be null terminated. */ + } Data; /*!< Value data member. */ +} mfxVariant; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Represents a range of unsigned values. */ +typedef struct { + mfxU32 Min; /*!< Minimal value of the range. */ + mfxU32 Max; /*!< Maximal value of the range. */ + mfxU32 Step; /*!< Value increment. */ +} mfxRange32U; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Represents a pair of numbers of type mfxI16. */ +typedef struct { + mfxI16 x; /*!< First number. */ + mfxI16 y; /*!< Second number. */ +} mfxI16Pair; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Represents pair of handles of type mfxHDL. */ +typedef struct { + mfxHDL first; /*!< First handle. */ + mfxHDL second; /*!< Second handle. */ +} mfxHDLPair; +MFX_PACK_END() + +/*********************************************************************************\ +Error message +\*********************************************************************************/ +/*! @enum mfxStatus Itemizes status codes returned by API functions. */ +typedef enum +{ + /* no error */ + MFX_ERR_NONE = 0, /*!< No error. */ + /* reserved for unexpected errors */ + MFX_ERR_UNKNOWN = -1, /*!< Unknown error. */ + + /* error codes <0 */ + MFX_ERR_NULL_PTR = -2, /*!< Null pointer. */ + MFX_ERR_UNSUPPORTED = -3, /*!< Unsupported feature. */ + MFX_ERR_MEMORY_ALLOC = -4, /*!< Failed to allocate memory. */ + MFX_ERR_NOT_ENOUGH_BUFFER = -5, /*!< Insufficient buffer at input/output. */ + MFX_ERR_INVALID_HANDLE = -6, /*!< Invalid handle. */ + MFX_ERR_LOCK_MEMORY = -7, /*!< Failed to lock the memory block. */ + MFX_ERR_NOT_INITIALIZED = -8, /*!< Member function called before initialization. */ + MFX_ERR_NOT_FOUND = -9, /*!< The specified object is not found. */ + MFX_ERR_MORE_DATA = -10, /*!< Expect more data at input. */ + MFX_ERR_MORE_SURFACE = -11, /*!< Expect more surface at output. */ + MFX_ERR_ABORTED = -12, /*!< Operation aborted. */ + MFX_ERR_DEVICE_LOST = -13, /*!< Lose the hardware acceleration device. */ + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM = -14, /*!< Incompatible video parameters. */ + MFX_ERR_INVALID_VIDEO_PARAM = -15, /*!< Invalid video parameters. */ + MFX_ERR_UNDEFINED_BEHAVIOR = -16, /*!< Undefined behavior. */ + MFX_ERR_DEVICE_FAILED = -17, /*!< Device operation failure. */ + MFX_ERR_MORE_BITSTREAM = -18, /*!< Expect more bitstream buffers at output. */ + MFX_ERR_GPU_HANG = -21, /*!< Device operation failure caused by GPU hang. */ + MFX_ERR_REALLOC_SURFACE = -22, /*!< Bigger output surface required. */ + MFX_ERR_RESOURCE_MAPPED = -23, /*!< Write access is already acquired and user requested + another write access, or read access with MFX_MEMORY_NO_WAIT flag. */ + MFX_ERR_NOT_IMPLEMENTED = -24, /*!< Feature or function not implemented. */ + MFX_ERR_MORE_EXTBUFFER = -25, /*!< Expect additional extended configuration buffer. */ + + /* warnings >0 */ + MFX_WRN_IN_EXECUTION = 1, /*!< The previous asynchronous operation is in execution. */ + MFX_WRN_DEVICE_BUSY = 2, /*!< The hardware acceleration device is busy. */ + MFX_WRN_VIDEO_PARAM_CHANGED = 3, /*!< The video parameters are changed during decoding. */ + MFX_WRN_PARTIAL_ACCELERATION = 4, /*!< Software acceleration is used. */ + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM = 5, /*!< Incompatible video parameters. */ + MFX_WRN_VALUE_NOT_CHANGED = 6, /*!< The value is saturated based on its valid range. */ + MFX_WRN_OUT_OF_RANGE = 7, /*!< The value is out of valid range. */ + MFX_WRN_FILTER_SKIPPED = 10, /*!< One of requested filters has been skipped. */ + /* low-delay partial output */ + MFX_ERR_NONE_PARTIAL_OUTPUT = 12, /*!< Frame is not ready, but bitstream contains partial output. */ + + MFX_WRN_ALLOC_TIMEOUT_EXPIRED = 13, /*!< Timeout expired for internal frame allocation. */ + + /* threading statuses */ + MFX_TASK_DONE = MFX_ERR_NONE, /*!< Task has been completed. */ + MFX_TASK_WORKING = 8, /*!< There is some more work to do. */ + MFX_TASK_BUSY = 9, /*!< Task is waiting for resources. */ + + /* plug-in statuses */ + MFX_ERR_MORE_DATA_SUBMIT_TASK = -10000, /*!< Return MFX_ERR_MORE_DATA but submit internal asynchronous task. */ + +} 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) + +#include "mfxdispatcherprefixedfunctions.h" + +#endif // MFX_DISPATCHER_EXPOSED_PREFIX + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __MFXDEFS_H__ */ diff --git a/third-party/IntelVPL/x64/include/vpl/mfxdispatcher.h b/third-party/IntelVPL/x64/include/vpl/mfxdispatcher.h new file mode 100644 index 000000000..df7d7ae3d --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxdispatcher.h @@ -0,0 +1,271 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXDISPATCHER_H__ +#define __MFXDISPATCHER_H__ + +#include "mfxdefs.h" +#include "mfxcommon.h" +#include "mfxsession.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! Loader handle. */ +typedef struct _mfxLoader *mfxLoader; + +/*! Config handle. */ +typedef struct _mfxConfig *mfxConfig; + +/*! + @brief Creates the loader. + @return Loader Loader handle or NULL if failed. + + @since This function is available since API version 2.0. +*/ +mfxLoader MFX_CDECL MFXLoad(void); + +/*! + @brief Destroys the dispatcher. + @param[in] loader Loader handle. + + @since This function is available since API version 2.0. +*/ +void MFX_CDECL MFXUnload(mfxLoader loader); + +/*! + @brief Creates dispatcher configuration. + @details Creates the dispatcher internal configuration, which is used to filter out available implementations. + This configuration is used to walk through selected implementations to gather more details and select the appropriate + implementation to load. The loader object remembers all created mfxConfig objects and destroys them during the mfxUnload + function call. + + Multiple configurations per single mfxLoader object are possible. + + Usage example: + @code + mfxLoader loader = MFXLoad(); + mfxConfig cfg = MFXCreateConfig(loader); + MFXCreateSession(loader,0,&session); + @endcode + @param[in] loader Loader handle. + @return Config handle or NULL pointer is failed. + + @since This function is available since API version 2.0. +*/ +mfxConfig MFX_CDECL MFXCreateConfig(mfxLoader loader); + +/*! + @brief Adds additional filter properties (any fields of the mfxImplDescription structure) to the configuration of the loader object. + @note Each new call with the same parameter name will overwrite the previously set value. This may invalidate other properties. + + @param[in] config Config handle. + @param[in] name Name of the parameter (see mfxImplDescription structure and example). + @param[in] value Value of the parameter. + @return + MFX_ERR_NONE The function completed successfully. + MFX_ERR_NULL_PTR If config is NULL. \n + MFX_ERR_NULL_PTR If name is NULL. \n + MFX_ERR_NOT_FOUND If name contains unknown parameter name. + MFX_ERR_UNSUPPORTED If value data type does not equal the parameter with provided name. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXSetConfigFilterProperty(mfxConfig config, const mfxU8* name, mfxVariant value); + +/*! + @brief Iterates over filtered out implementations to gather their details. This function allocates memory to store + a structure or string corresponding to the type specified by format. For example, if format is set to + MFX_IMPLCAPS_IMPLDESCSTRUCTURE, then idesc will return a pointer to a structure of type mfxImplDescription. + Use the MFXDispReleaseImplDescription function to free memory allocated to this structure or string. + @param[in] loader Loader handle. + @param[in] i Index of the implementation. + @param[in] format Format in which capabilities need to be delivered. See the mfxImplCapsDeliveryFormat enumerator for more details. + @param[out] idesc Pointer to the structure or string corresponding to the requested format. + @return + MFX_ERR_NONE The function completed successfully. The idesc contains valid information.\n + MFX_ERR_NULL_PTR If loader is NULL. \n + MFX_ERR_NULL_PTR If idesc is NULL. \n + MFX_ERR_NOT_FOUND Provided index is out of possible range. \n + MFX_ERR_UNSUPPORTED If requested format is not supported. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXEnumImplementations(mfxLoader loader, mfxU32 i, mfxImplCapsDeliveryFormat format, mfxHDL* idesc); + + +/*! + @brief Loads and initializes the implementation. + @code + mfxLoader loader = MFXLoad(); + int i=0; + while(1) { + mfxImplDescription *idesc; + MFXEnumImplementations(loader, i, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL*)&idesc); + if(is_good(idesc)) { + MFXCreateSession(loader, i,&session); + // ... + MFXDispReleaseImplDescription(loader, idesc); + } + else + { + MFXDispReleaseImplDescription(loader, idesc); + break; + } + } + @endcode + @param[in] loader Loader handle. + @param[in] i Index of the implementation. + @param[out] session Pointer to the session handle. + @return + MFX_ERR_NONE The function completed successfully. The session contains a pointer to the session handle.\n + MFX_ERR_NULL_PTR If loader is NULL. \n + MFX_ERR_NULL_PTR If session is NULL. \n + MFX_ERR_NOT_FOUND Provided index is out of possible range. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXCreateSession(mfxLoader loader, mfxU32 i, mfxSession* session); + +/*! + @brief + Destroys handle allocated by the MFXEnumImplementations function. + + @param[in] loader Loader handle. + @param[in] hdl Handle to destroy. Can be equal to NULL. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR If loader is NULL. \n + MFX_ERR_INVALID_HANDLE Provided hdl handle is not associated with this loader. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXDispReleaseImplDescription(mfxLoader loader, mfxHDL hdl); + +/*! + @brief + Macro help to return UUID in the common oneAPI format. + + @param[in] devinfo Handle to mfxExtendedDeviceId. + @param[in] sub_dev_num SubDevice number. Can be obtained from mfxDeviceDescription::SubDevices::Index. Set to zero if no SubDevices. + @param[out] uuid Pointer to UUID. + +*/ +#define MFX_UUID_COMPUTE_DEVICE_ID(devinfo, sub_dev_num, uuid) \ +{ \ + extDeviceUUID t_uuid = { 0 }; \ + extDeviceUUID* shared_uuid = (extDeviceUUID*)(uuid); \ + t_uuid.vendor_id = (devinfo)->VendorID; \ + t_uuid.device_id = (devinfo)->DeviceID; \ + t_uuid.revision_id = (devinfo)->RevisionID; \ + t_uuid.pci_domain = (devinfo)->PCIDomain; \ + t_uuid.pci_bus = (mfxU8)(devinfo)->PCIBus; \ + t_uuid.pci_dev = (mfxU8)(devinfo)->PCIDevice; \ + t_uuid.pci_func = (mfxU8)(devinfo)->PCIFunction; \ + t_uuid.sub_device_id = (mfxU8)(sub_dev_num); \ + *shared_uuid = t_uuid; \ +} + +/* Helper macro definitions to add config filter properties. */ + +/*! Adds single property of mfxU32 type. + @param[in] loader Valid mfxLoader object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_ADD_PROPERTY_U32(loader, name, value) \ +{ \ + mfxVariant impl_value; \ + mfxConfig cfg = MFXCreateConfig(loader); \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U32; \ + impl_value.Data.U32 = value; \ + MFXSetConfigFilterProperty(cfg, (mfxU8 *)name, impl_value); \ +} + +/*! Adds single property of mfxU16 type. + @param[in] loader Valid mfxLoader object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_ADD_PROPERTY_U16(loader, name, value) \ +{ \ + mfxVariant impl_value = { 0 }; \ + mfxConfig cfg = MFXCreateConfig(loader); \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U16; \ + impl_value.Data.U16 = value; \ + MFXSetConfigFilterProperty(cfg, (mfxU8 *)name, impl_value); \ +} + +/*! Adds single property of pointer type. + @param[in] loader Valid mfxLoader object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_ADD_PROPERTY_PTR(loader, name, value) \ +{ \ + mfxVariant impl_value = { 0 }; \ + mfxConfig cfg = MFXCreateConfig(loader); \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_PTR; \ + impl_value.Data.Ptr = (mfxHDL)value; \ + MFXSetConfigFilterProperty(cfg, (mfxU8 *)name, impl_value); \ +} + +/*! Update existing property of mfxU32 type. + @param[in] loader Valid mfxLoader object + @param[in] config Valid mfxConfig object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_UPDATE_PROPERTY_U32(loader, config, name, value) \ +{ \ + mfxVariant impl_value; \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U32; \ + impl_value.Data.U32 = value; \ + MFXSetConfigFilterProperty(config, (mfxU8 *)name, impl_value); \ +} + +/*! Update existing property of mfxU16 type. + @param[in] loader Valid mfxLoader object + @param[in] config Valid mfxConfig object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_UPDATE_PROPERTY_U16(loader, config, name, value) \ +{ \ + mfxVariant impl_value; \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_U16; \ + impl_value.Data.U16 = value; \ + MFXSetConfigFilterProperty(config, (mfxU8 *)name, impl_value); \ +} + +/*! Update existing property of pointer type. + @param[in] loader Valid mfxLoader object + @param[in] config Valid mfxConfig object + @param[in] name Property name string + @param[in] value Property value +*/ +#define MFX_UPDATE_PROPERTY_PTR(loader, config, name, value) \ +{ \ + mfxVariant impl_value; \ + impl_value.Version.Version = MFX_VARIANT_VERSION; \ + impl_value.Type = MFX_VARIANT_TYPE_PTR; \ + impl_value.Data.Ptr = (mfxHDL)value; \ + MFXSetConfigFilterProperty(config, (mfxU8 *)name, impl_value); \ +} + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/third-party/IntelVPL/x64/include/vpl/mfxdispatcherprefixedfunctions.h b/third-party/IntelVPL/x64/include/vpl/mfxdispatcherprefixedfunctions.h new file mode 100644 index 000000000..38fe0cca7 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxdispatcherprefixedfunctions.h @@ -0,0 +1,154 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXDISPATCHERPREFIXEDFUNCTIONS_H__ +#define __MFXDISPATCHERPREFIXEDFUNCTIONS_H__ + +// API 1.0 functions +#define MFXInit disp_MFXInit +#define MFXClose disp_MFXClose +#define MFXQueryIMPL disp_MFXQueryIMPL +#define MFXQueryVersion disp_MFXQueryVersion + +#define MFXJoinSession disp_MFXJoinSession +#define MFXDisjoinSession disp_MFXDisjoinSession +#define MFXCloneSession disp_MFXCloneSession +#define MFXSetPriority disp_MFXSetPriority +#define MFXGetPriority disp_MFXGetPriority + +#define MFXVideoCORE_SetFrameAllocator disp_MFXVideoCORE_SetFrameAllocator +#define MFXVideoCORE_SetHandle disp_MFXVideoCORE_SetHandle +#define MFXVideoCORE_GetHandle disp_MFXVideoCORE_GetHandle +#define MFXVideoCORE_SyncOperation disp_MFXVideoCORE_SyncOperation + +#define MFXVideoENCODE_Query disp_MFXVideoENCODE_Query +#define MFXVideoENCODE_QueryIOSurf disp_MFXVideoENCODE_QueryIOSurf +#define MFXVideoENCODE_Init disp_MFXVideoENCODE_Init +#define MFXVideoENCODE_Reset disp_MFXVideoENCODE_Reset +#define MFXVideoENCODE_Close disp_MFXVideoENCODE_Close +#define MFXVideoENCODE_GetVideoParam disp_MFXVideoENCODE_GetVideoParam +#define MFXVideoENCODE_GetEncodeStat disp_MFXVideoENCODE_GetEncodeStat +#define MFXVideoENCODE_EncodeFrameAsync disp_MFXVideoENCODE_EncodeFrameAsync + +#define MFXVideoDECODE_Query disp_MFXVideoDECODE_Query +#define MFXVideoDECODE_DecodeHeader disp_MFXVideoDECODE_DecodeHeader +#define MFXVideoDECODE_QueryIOSurf disp_MFXVideoDECODE_QueryIOSurf +#define MFXVideoDECODE_Init disp_MFXVideoDECODE_Init +#define MFXVideoDECODE_Reset disp_MFXVideoDECODE_Reset +#define MFXVideoDECODE_Close disp_MFXVideoDECODE_Close +#define MFXVideoDECODE_GetVideoParam disp_MFXVideoDECODE_GetVideoParam +#define MFXVideoDECODE_GetDecodeStat disp_MFXVideoDECODE_GetDecodeStat +#define MFXVideoDECODE_SetSkipMode disp_MFXVideoDECODE_SetSkipMode +#define MFXVideoDECODE_GetPayload disp_MFXVideoDECODE_GetPayload +#define MFXVideoDECODE_DecodeFrameAsync disp_MFXVideoDECODE_DecodeFrameAsync + +#define MFXVideoVPP_Query disp_MFXVideoVPP_Query +#define MFXVideoVPP_QueryIOSurf disp_MFXVideoVPP_QueryIOSurf +#define MFXVideoVPP_Init disp_MFXVideoVPP_Init +#define MFXVideoVPP_Reset disp_MFXVideoVPP_Reset +#define MFXVideoVPP_Close disp_MFXVideoVPP_Close + +#define MFXVideoVPP_GetVideoParam disp_MFXVideoVPP_GetVideoParam +#define MFXVideoVPP_GetVPPStat disp_MFXVideoVPP_GetVPPStat +#define MFXVideoVPP_RunFrameVPPAsync disp_MFXVideoVPP_RunFrameVPPAsync + +// API 1.1 functions +#define MFXVideoUSER_Register disp_MFXVideoUSER_Register +#define MFXVideoUSER_Unregister disp_MFXVideoUSER_Unregister +#define MFXVideoUSER_ProcessFrameAsync disp_MFXVideoUSER_ProcessFrameAsync + +// API 1.10 functions + +#define MFXVideoENC_Query disp_MFXVideoENC_Query +#define MFXVideoENC_QueryIOSurf disp_MFXVideoENC_QueryIOSurf +#define MFXVideoENC_Init disp_MFXVideoENC_Init +#define MFXVideoENC_Reset disp_MFXVideoENC_Reset +#define MFXVideoENC_Close disp_MFXVideoENC_Close +#define MFXVideoENC_ProcessFrameAsync disp_MFXVideoENC_ProcessFrameAsync +#define MFXVideoVPP_RunFrameVPPAsyncEx disp_MFXVideoVPP_RunFrameVPPAsyncEx +#define MFXVideoUSER_Load disp_MFXVideoUSER_Load +#define MFXVideoUSER_UnLoad disp_MFXVideoUSER_UnLoad + +// API 1.11 functions + +#define MFXVideoPAK_Query disp_MFXVideoPAK_Query +#define MFXVideoPAK_QueryIOSurf disp_MFXVideoPAK_QueryIOSurf +#define MFXVideoPAK_Init disp_MFXVideoPAK_Init +#define MFXVideoPAK_Reset disp_MFXVideoPAK_Reset +#define MFXVideoPAK_Close disp_MFXVideoPAK_Close +#define MFXVideoPAK_ProcessFrameAsync disp_MFXVideoPAK_ProcessFrameAsync + +// API 1.13 functions + +#define MFXVideoUSER_LoadByPath disp_MFXVideoUSER_LoadByPath + +// API 1.14 functions +#define MFXInitEx disp_MFXInitEx + +// Audio library functions + +// API 1.8 functions + +#define MFXAudioCORE_SyncOperation disp_MFXAudioCORE_SyncOperation +#define MFXAudioENCODE_Query disp_MFXAudioENCODE_Query +#define MFXAudioENCODE_QueryIOSize disp_MFXAudioENCODE_QueryIOSize +#define MFXAudioENCODE_Init disp_MFXAudioENCODE_Init +#define MFXAudioENCODE_Reset disp_MFXAudioENCODE_Reset +#define MFXAudioENCODE_Close disp_MFXAudioENCODE_Close +#define MFXAudioENCODE_GetAudioParam disp_MFXAudioENCODE_GetAudioParam +#define MFXAudioENCODE_EncodeFrameAsync disp_MFXAudioENCODE_EncodeFrameAsync + +#define MFXAudioDECODE_Query disp_MFXAudioDECODE_Query +#define MFXAudioDECODE_DecodeHeader disp_MFXAudioDECODE_DecodeHeader +#define MFXAudioDECODE_Init disp_MFXAudioDECODE_Init +#define MFXAudioDECODE_Reset disp_MFXAudioDECODE_Reset +#define MFXAudioDECODE_Close disp_MFXAudioDECODE_Close +#define MFXAudioDECODE_QueryIOSize disp_MFXAudioDECODE_QueryIOSize +#define MFXAudioDECODE_GetAudioParam disp_MFXAudioDECODE_GetAudioParam +#define MFXAudioDECODE_DecodeFrameAsync disp_MFXAudioDECODE_DecodeFrameAsync + +// API 1.9 functions + +#define MFXAudioUSER_Register disp_MFXAudioUSER_Register +#define MFXAudioUSER_Unregister disp_MFXAudioUSER_Unregister +#define MFXAudioUSER_ProcessFrameAsync disp_MFXAudioUSER_ProcessFrameAsync +#define MFXAudioUSER_Load disp_MFXAudioUSER_Load +#define MFXAudioUSER_UnLoad disp_MFXAudioUSER_UnLoad + +// API 1.19 functions + +#define MFXVideoENC_GetVideoParam disp_MFXVideoENC_GetVideoParam +#define MFXVideoPAK_GetVideoParam disp_MFXVideoPAK_GetVideoParam +#define MFXVideoCORE_QueryPlatform disp_MFXVideoCORE_QueryPlatform +#define MFXVideoUSER_GetPlugin disp_MFXVideoUSER_GetPlugin + +// API 2.0 functions +#define MFXMemory_GetSurfaceForVPP disp_MFXMemory_GetSurfaceForVPP +#define MFXMemory_GetSurfaceForEncode disp_MFXMemory_GetSurfaceForEncode +#define MFXMemory_GetSurfaceForDecode disp_MFXMemory_GetSurfaceForDecode + +#define MFXQueryImplsDescription disp_MFXQueryImplsDescription +#define MFXReleaseImplDescription disp_MFXReleaseImplDescription + +#define MFXInitialize disp_MFXInitialize + +// API 2.1 functions +#define MFXMemory_GetSurfaceForVPPOut disp_MFXMemory_GetSurfaceForVPPOut + +#define MFXVideoDECODE_VPP_Init disp_MFXVideoDECODE_VPP_Init +#define MFXVideoDECODE_VPP_DecodeFrameAsync disp_MFXVideoDECODE_VPP_DecodeFrameAsync +#define MFXVideoDECODE_VPP_Reset disp_MFXVideoDECODE_VPP_Reset +#define MFXVideoDECODE_VPP_GetChannelParam disp_MFXVideoDECODE_VPP_GetChannelParam +#define MFXVideoDECODE_VPP_Close disp_MFXVideoDECODE_VPP_Close + +#define MFXVideoVPP_ProcessFrameAsync disp_MFXVideoVPP_ProcessFrameAsync + +// API 2.15 functions +#ifdef ONEVPL_EXPERIMENTAL +#define MFXQueryImplsProperties disp_MFXQueryImplsProperties +#endif + +#endif diff --git a/third-party/IntelVPL/x64/include/vpl/mfxencodestats.h b/third-party/IntelVPL/x64/include/vpl/mfxencodestats.h new file mode 100644 index 000000000..940e94a8a --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxencodestats.h @@ -0,0 +1,458 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifdef ONEVPL_EXPERIMENTAL + + +#ifndef __MFXENCODESTATS_H__ +#define __MFXENCODESTATS_H__ +#include "mfxcommon.h" +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*!< The enum to specify memory layout for statistics. */ +typedef enum { + MFX_ENCODESTATS_MEMORY_LAYOUT_DEFAULT = 0, /*!< The default memory layout for statistics. */ +} mfxEncodeBlkStatsMemLayout; + +/*!< The enum to specify mode to gather statistics. */ +typedef enum { + MFX_ENCODESTATS_MODE_DEFAULT = 0, /*!< Encode mode is selected by the implementation. */ + MFX_ENCODESTATS_MODE_ENCODE = 1, /*!< Full encode mode. */ +} mfxEncodeStatsMode; + +/*!< Flags to specify what statistics will be reported by the implementation. */ +enum { + MFX_ENCODESTATS_LEVEL_BLK = 0x1, /*!< Block level statistics. */ + MFX_ENCODESTATS_LEVEL_SLICE = 0x2, /*!< Slice level statistics. */ + MFX_ENCODESTATS_LEVEL_TILE = 0x4, /*!< Tile level statistics. */ + MFX_ENCODESTATS_LEVEL_FRAME = 0x8, /*!< Frame level statistics. */ +}; + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*!< Specifies H.265 CTU header. */ +typedef struct { + union { + struct { + mfxU32 CUcountminus1 : 6; /*!< Number of CU per CTU. */ + mfxU32 MaxDepth : 2; /*!< Max quad-tree depth of CU in CTU. */ + mfxU32 reserved : 24; + } bitfields0; + mfxU32 dword0; + }; + mfxU16 CurrXAddr; /*!< Horizontal address of CTU. */ + mfxU16 CurrYAddr; /*!< Vertical address of CTU. */ + mfxU32 reserved1; +} mfxCTUHeader; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*!< Specifies H.265 CU info. */ +typedef struct { + union { + struct { + mfxU32 CU_Size : 2; /*!< indicates the CU size of the current CU. 0: 8x8 1: 16x16 2: 32x32 3: 64x64 */ + mfxU32 CU_pred_mode : 1; /*!< indicates the prediction mode for the current CU. 0: intra 1: inter */ + /*! + indicates the PU partition mode for the current CU. + 0: 2Nx2N + 1: 2NxN (inter) + 2: Nx2N (inter) + 3: NXN (intra only, CU Size=8x8 only. Luma Intra Mode indicates the intra prediction mode for 4x4_0. The additional prediction modes are overloaded on 4x4_1, 4x4_2, 4x4_3 below) + 4: 2NxnT (inter only) + 5: 2NxnB (inter only) + 6: nLx2N (inter only) + 7: nRx2N (inter only). + */ + mfxU32 CU_part_mode : 3; + mfxU32 InterPred_IDC_MV0 : 2; /*!< indicates the prediction direction for PU0 of the current CU. 0: L0 1: L1 2: Bi 3: reserved */ + mfxU32 InterPred_IDC_MV1 : 2; /*!< indicates the prediction direction for PU1 of the current CU. 0: L0 1: L1 2: Bi 3: reserved */ + /*! + Final explicit Luma Intra Mode 4x4_0 for NxN. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode : 6; + /*! + indicates the final explicit Luma Intra Mode for the CU. + 0: DM (use Luma mode, from block 0 if NxN) + 1: reserved + 2: Planar + 3: Vertical + 4: Horizontal + 5: DC */ + mfxU32 ChromaIntraMode : 3; + mfxU32 reserved : 13; + } bitfields0; + mfxU32 dword0; + }; + + union { + struct { + /*! + Final explicit Luma Intra Mode 4x4_1. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode4x4_1 : 6; + /*! + Final explicit Luma Intra Mode 4x4_2. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode4x4_2 : 6; + /*! + Final explicit Luma Intra Mode 4x4_3. + Valid values 0..34 + Note: CU_part_mode==NxN. + */ + mfxU32 LumaIntraMode4x4_3 : 6; + mfxU32 reserved1 : 14; + } bitfields1; + mfxU32 dword1; + }; + + mfxI8 QP; // signed QP value + mfxU8 reserved2[3]; + /*! distortion measure, approximation to SAD. + Will deviate significantly (pre, post reconstruction) and due to variation in algorithm. + */ + mfxU32 SAD; + + /*! + These parameters indicate motion vectors that are associated with the PU0/PU1 winners + range [-2048.00..2047.75]. + L0/PU0 - MV[0][0] + L0/PU1 - MV[0][1] + L1/PU0 - MV[1][0] + L1/PU1 - MV[1][1] + */ + mfxI16Pair MV[2][2]; + + union { + struct { + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L0_MV0.X and L0_MV0.Y fields. */ + mfxU32 L0_MV0_RefID : 4; + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L0_MV1.X and L0_MV1.Y fields. */ + mfxU32 L0_MV1_RefID : 4; + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L1_MV0.X and L1_MV0.Y fields. */ + mfxU32 L1_MV0_RefID : 4; + /*! + This parameter indicates the reference index associated with the MV X/Y + that is populated in the L1_MV1.X and L1_MV1.Y fields. */ + mfxU32 L1_MV1_RefID : 4; + + mfxU32 reserved3 : 16; + } bitfields8; + mfxU32 dword8; + }; + mfxU32 reserved4[10]; +} mfxCUInfo; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*!< Specifies H.265 CTU. */ +typedef struct { + mfxCTUHeader CtuHeader; /*!< H.265 CTU header. */ + mfxCUInfo CuInfo[64]; /*!< Array of CU. */ + mfxU32 reserved; +} mfxCTUInfo; +MFX_PACK_END() + + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + The structure describes H.264 stats per MB. +*/ +typedef struct { + union { + struct { + /*! + Together with @p IntraMbFlag this parameter specifies macroblock type according to the + ISO\*\/IEC\* 14496-10 with the following difference - it stores either intra or inter + values according to @p IntraMbFlag, but not intra after inter. + Values for P-slices are mapped to B-slice values. For example P_16x8 is coded with + B_FWD_16x8 value. + */ + mfxU32 MBType : 5; + /*! + This field specifies inter macroblock mode and is ignored for intra MB. It is derived from @p MbType and has next values: + @li 0 - 16x16 mode + @li 1 - 16x8 mode + @li 2 - 8x16 mode + @li 3 - 8x8 mode + */ + mfxU32 InterMBMode : 2; + /*! + This field specifies intra macroblock mode and is ignored for inter MB. It is derived from @p MbType and has next values: + @li 0 - 16x16 mode + @li 1 - 8x8 mode + @li 2 - 4x4 mode + @li 3 - PCM + */ + mfxU32 IntraMBMode : 2; + /*! + This flag specifies intra/inter MB type and has next values: + 0 - Inter prediction MB type + 1 - Intra prediction MB type + */ + mfxU32 IntraMBFlag : 1; + /*! + This field specifies subblock shapes for the current MB. Each block is described by 2 bits starting from lower bits for block 0. + + @li 0 - 8x8 + @li 1 - 8x4 + @li 2 - 4x8 + @li 3 - 4x4 + */ + mfxU32 SubMBShapes : 8; + /*! + This field specifies prediction modes for the current MB partition blocks. Each block is described by 2 bits starting from lower bits for block 0. + @li 0 - Pred_L0 + @li 1 - Pred_L1 + @li 2 - BiPred + @li 3 - reserved + + Only one prediction value for partition is reported, the rest values are set to zero. For example: + @li 16x16 Pred_L1 - 0x01 (only 2 lower bits are used) + @li 16x8 Pred_L1 / BiPred - 0x09 (1001b) + @li 8x16 BiPred / BiPred - 0x0a (1010b) + + For P MBs this value is always zero. + */ + mfxU32 SubMBShapeMode : 8; + /*! + This value specifies chroma intra prediction mode. + @li 0 - DC + @li 1 - Horizontal + @li 2 - Vertical + @li 3 - Plane + */ + mfxU32 ChromaIntraPredMode : 2; + mfxU32 reserved : 4; + } bitfields0; + mfxU32 dword0; + } ; + /*! + Distortion measure, approximation to SAD. + Deviate significantly (pre, post reconstruction) and due to variation in algorithm. + */ + mfxU32 SAD; + mfxI8 Qp; /*!< MB QP. */ + mfxU8 reserved1[3]; + + /*! + These values specify luma intra prediction modes for current MB. Each element of the array + corresponds to 8x8 block and each holds prediction modes for four 4x4 subblocks. + Four bits per mode, lowest bits for left top subblock. + All 16 prediction modes are always specified. For 8x8 case, block prediction mode is + populated to all subblocks of the 8x8 block. For 16x16 case - to all subblocks of the MB. + + Prediction directions for 4x4 and 8x8 blocks: + @li 0 - Vertical + @li 1 - Horizontal + @li 2 - DC + @li 3 - Diagonal Down Left + @li 4 - Diagonal Down Right + @li 5 - Vertical Right + @li 6 - Horizontal Down + @li 7 - Vertical Left + @li 8 - Horizontal Up + + Prediction directions for 16x16 blocks: + @li 0 - Vertical + @li 1 - Horizontal + @li 2 - DC + @li 3 - Plane + */ + mfxU16 LumaIntraMode[4]; + + mfxU32 reserved2; +} mfxMBInfo; +MFX_PACK_END() + +/*! + The enum specifies block size. +*/ +typedef enum { + MFX_BLOCK_4X4 = 0, /*!< 4x4 block size. */ + MFX_BLOCK_16X16 = 1, /*!< 16x16 block size. */ +} mfxBlockSize; + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + The structure describes H.264 and H.265 stats per MB or CTUs. +*/ +typedef struct { + union { + mfxU32 NumMB; /*!< Number of MBs per frame for H.264. */ + mfxU32 NumCTU; /*!< number of CTUs per frame for H.265. */ + }; + union { + mfxCTUInfo *HEVCCTUArray; /*!< Array of CTU statistics. */ + mfxMBInfo *AVCMBArray; /*!< Array of MB statistics. */ + }; + mfxU32 reserved[8]; + +} mfxEncodeBlkStats; +MFX_PACK_END() + + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + The structure describes H.264/H.265 frame/slice/tile level statistics. +*/ +typedef struct { + mfxF32 PSNRLuma; /*!< PSNR for LUMA samples. */ + mfxF32 PSNRCb; /*!< PSNR for Chroma (Cb) samples. */ + mfxF32 PSNRCr; /*!< PSNR for Chroma (Cr) samples. */ + /*! distortion measure, approximation to SAD. + Will deviate significantly (pre, post reconstruction) and due to variation in algorithm. + */ + mfxU64 SADLuma; + mfxF32 Qp; /*!< average frame QP, may have fractional part in case of MBQP. */ + + union { + mfxU32 NumMB; /*!< Number of MBs per frame for H.264. */ + mfxU32 NumCTU; /*!< number of CTUs per frame for H.265. */ + }; + + mfxBlockSize BlockSize; /*! For H.264 it is always 16x16 corresponding to MB size. + In H.265 it's normalized to 4x4, so for each CU we calculate number of 4x4 which belongs to the block. */ + + mfxU32 NumIntraBlock; /*! Number of intra blocks in the frame. The size of block is defined by BlockSize. + For H.265 it can be more than number of intra CU. */ + mfxU32 NumInterBlock; /*! Number of inter blocks in the frame. The size of block is defined by BlockSize. + For H.265 it can be more than number of inter CU. */ + mfxU32 NumSkippedBlock; /*! Number of skipped blocks in the frame. The size of block is defined by BlockSize. + For H.265 it can be more than number of skipped CU. */ + + mfxU32 reserved[8]; + +} mfxEncodeHighLevelStats; +MFX_PACK_END() + +/*! + Alias for the structure to describe H.264 and H.265 frame level stats. +*/ +typedef mfxEncodeHighLevelStats mfxEncodeFrameStats; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + The structure describes H.264 and H.265 stats per Slice or Tile. +*/ +typedef struct { + mfxU32 NumElements; /*!< Number of Slices or Tiles per frame for H.264/H.265. */ + mfxEncodeHighLevelStats *HighLevelStatsArray; /*!< Array of CTU statistics. */ + mfxU32 reserved[8]; + +} mfxEncodeSliceStats; +MFX_PACK_END() + +/*! + Alias for the structure to describe H.264 and H.265 tile level stats. +*/ +typedef mfxEncodeSliceStats mfxEncodeTileStats; + + +#define MFX_ENCODESTATSCONTAINER_VERSION MFX_STRUCT_VERSION(1, 0) + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure represents reference counted container for output after encoding operation which includes statistics + and synchronization primitive for compressed bitstream. + The memory is allocated and released by the library. +*/ +typedef struct mfxEncodeStatsContainer { + mfxStructVersion Version; /*!< The version of the structure. */ + mfxRefInterface RefInterface; /*! < Reference counting interface. */ + /*! @brief + Guarantees readiness of the statistics after a function completes. + Instead of MFXVideoCORE_SyncOperation which leads to the synchronization of all output objects, + users may directly call the mfxEncodeStatsContainer::SynchronizeStatistics function to get output statistics. + + + @param[in] ref_interface Valid interface. + @param[out] wait Wait time in milliseconds. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of container is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the container is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *SynchronizeStatistics)(mfxRefInterface* ref_interface, mfxU32 wait); + /*! @brief + Guarantees readiness of associated compressed bitstream after a function completes. + Instead of MFXVideoCORE_SyncOperation which leads to the synchronization of all output objects, + users may directly call the mfxEncodeStatsContainer::SynchronizeStatistics function to get output bitstream. + + + @param[in] ref_interface Valid interface. + @param[out] wait Wait time in milliseconds. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If interface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of container is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the container is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *SynchronizeBitstream)(mfxRefInterface* ref_interface, mfxU32 wait); + mfxHDL reserved[4]; + mfxU32 reserved1[2]; + mfxU32 DisplayOrder; /*!< To which frame number statistics belong. */ + mfxEncodeBlkStatsMemLayout MemLayout; /*!< Memory layout for statistics. */ + mfxEncodeBlkStats *EncodeBlkStats; /*!< Block level statistics. */ + mfxEncodeSliceStats *EncodeSliceStats; /*!< Slice level statistics. */ + mfxEncodeTileStats *EncodeTileStats; /*!< Tile level statistics. */ + mfxEncodeFrameStats *EncodeFrameStats; /*!< Frame level statistics. */ + mfxU32 reserved2[8]; +}mfxEncodeStatsContainer; +MFX_PACK_END() + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The extension buffer which should be attached by application for mfxBitstream buffer before + encode operation. As result the encoder will allocate memory for statistics and fill appropriate structures. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODESTATS_BLK. */ + mfxU16 EncodeStatsFlags; /*!< What statistics is required: block/slice/tile/frame level or any combinations. + In case of slice or tile output statistics for one slice or tile will be available only.*/ + mfxEncodeStatsMode Mode; /*!< What encoding mode should be used to gather statistics. */ + mfxEncodeStatsContainer *EncodeStatsContainer; /*!< encode output, filled by the implementation. */ + mfxU32 reserved[8]; +} mfxExtEncodeStatsOutput; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + +#endif \ No newline at end of file diff --git a/third-party/IntelVPL/x64/include/vpl/mfximplcaps.h b/third-party/IntelVPL/x64/include/vpl/mfximplcaps.h new file mode 100644 index 000000000..b78b0be69 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfximplcaps.h @@ -0,0 +1,78 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#include "mfxdefs.h" + +#ifndef __MFXIMPLCAPS_H__ +#define __MFXIMPLCAPS_H__ + +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + @brief + Delivers implementation capabilities in the requested format according to the format value. Calling this + function directly is not recommended. Instead, applications must call the MFXEnumImplementations function. + + @param[in] format Format in which capabilities must be delivered. See mfxImplCapsDeliveryFormat for more details. + @param[out] num_impls Number of the implementations. + + @return + Array of handles to the capability report or NULL in case of unsupported format or NULL num_impls pointer. + Length of array is equal to num_impls. + + @since This function is available since API version 2.0. +*/ +mfxHDL* MFX_CDECL MFXQueryImplsDescription(mfxImplCapsDeliveryFormat format, mfxU32* num_impls); + +/*! + @brief + Destroys the handle allocated by the MFXQueryImplsDescription function or the MFXQueryImplsProperties 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. Calling this function directly is not recommended. Instead, applications must call + the MFXDispReleaseImplDescription function. + + @param[in] hdl Handle to destroy. Can be equal to NULL. + + @return + MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXReleaseImplDescription(mfxHDL hdl); + +#ifdef ONEVPL_EXPERIMENTAL +/*! + @brief + Delivers implementation capabilities for configured properties. + The returned capability report will be sparsely filled out, with only properties available which + were set via MFXSetConfigFilterProperty(). Calling this function directly is not recommended. + Instead, applications must call the MFXEnumImplementations function. + + + @param[in] properties Array of property name/value pairs indicating which properties to populate in the capability report. + @param[in] num_properties Number of property name/value pairs. + @param[out] num_impls Number of the implementations. + + @return + Array of handles to the capability report or NULL in case of NULL properties pointer or zero num_properties or NULL num_impls pointer. + Length of array is equal to num_impls. + + @since This function is available since API version 2.15. +*/ +mfxHDL* MFX_CDECL MFXQueryImplsProperties(mfxQueryProperty** properties, mfxU32 num_properties, mfxU32* num_impls); +#endif + + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // __MFXIMPLCAPS_H__ diff --git a/third-party/IntelVPL/x64/include/vpl/mfxjpeg.h b/third-party/IntelVPL/x64/include/vpl/mfxjpeg.h new file mode 100644 index 000000000..fe9d5421a --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxjpeg.h @@ -0,0 +1,136 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFX_JPEG_H__ +#define __MFX_JPEG_H__ + +#include "mfxdefs.h" +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* CodecId */ +enum { + MFX_CODEC_JPEG = MFX_MAKEFOURCC('J','P','E','G') /*!< JPEG codec */ +}; + +/* CodecProfile, CodecLevel */ +enum +{ + MFX_PROFILE_JPEG_BASELINE = 1 /*!< Baseline JPEG profile. */ +}; + +/*! The Rotation enumerator itemizes the JPEG rotation options. */ +enum +{ + MFX_ROTATION_0 = 0, /*!< No rotation. */ + MFX_ROTATION_90 = 1, /*!< 90 degree rotation. */ + MFX_ROTATION_180 = 2, /*!< 180 degree rotation. */ + MFX_ROTATION_270 = 3 /*!< 270 degree rotation. */ +}; + +enum { + MFX_EXTBUFF_JPEG_QT = MFX_MAKEFOURCC('J','P','G','Q'), /*!< This extended buffer defines quantization tables for JPEG encoder. */ + MFX_EXTBUFF_JPEG_HUFFMAN = MFX_MAKEFOURCC('J','P','G','H') /*!< This extended buffer defines Huffman tables for JPEG encoder. */ +}; + +/*! The JPEGColorFormat enumerator itemizes the JPEG color format options. */ +enum { + MFX_JPEG_COLORFORMAT_UNKNOWN = 0, /*! Unknown color format. The decoder tries to determine color format from available in bitstream information. + If such information is not present, then MFX_JPEG_COLORFORMAT_YCbCr color format is assumed. */ + MFX_JPEG_COLORFORMAT_YCbCr = 1, /*! Bitstream contains Y, Cb and Cr components. */ + MFX_JPEG_COLORFORMAT_RGB = 2 /*! Bitstream contains R, G and B components. */ +}; + +/*! The JPEGScanType enumerator itemizes the JPEG scan types. */ +enum { + MFX_SCANTYPE_UNKNOWN = 0, /*!< Unknown scan type. */ + MFX_SCANTYPE_INTERLEAVED = 1, /*!< Interleaved scan. */ + MFX_SCANTYPE_NONINTERLEAVED = 2 /*!< Non-interleaved scan. */ +}; + +enum { + MFX_CHROMAFORMAT_JPEG_SAMPLING = 6 /*!< Color sampling specified via mfxInfoMFX::SamplingFactorH and SamplingFactorV. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies quantization tables. The application may specify up to 4 quantization tables. The encoder assigns an ID to each table. + That ID is equal to the table index in the Qm array. Table "0" is used for encoding of the Y component, table "1" for the U component, and table "2" + for the V component. The application may specify fewer tables than the number of components in the image. If two tables are specified, + then table "1" is used for both U and V components. If only one table is specified then it is used for all components in the image. + The following table illustrates this behavior. + + @internal + +------------------+---------+------+---+ + | Table ID | 0 | 1 | 2 | + +------------------+---------+------+---+ + | Number of tables | | | | + +==================+=========+======+===+ + | 0 | Y, U, V | | | + +------------------+---------+------+---+ + | 1 | Y | U, V | | + +------------------+---------+------+---+ + | 2 | Y | U | V | + +------------------+---------+------+---+ + @endinternal +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_JPEG_QT. */ + + mfxU16 reserved[7]; + mfxU16 NumTable; /*!< Number of quantization tables defined in Qm array. */ + + mfxU16 Qm[4][64]; /*!< Quantization table values. */ +} mfxExtJPEGQuantTables; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies Huffman tables. The application may specify up to 2 quantization table pairs for baseline process. The encoder + assigns an ID to each table. That ID is equal to the table index in the DCTables and ACTables arrays. Table "0" is used for encoding of the Y component and + table "1" is used for encoding of the U and V component. The application may specify only one table, in which case the table will be used for all components in the image. + The following table illustrates this behavior. + + @internal + +------------------+---------+------+ + | Table ID | 0 | 1 | + +------------------+---------+------+ + | Number of tables | | | + +==================+=========+======+ + | 0 | Y, U, V | | + +------------------+---------+------+ + | 1 | Y | U, V | + +------------------+---------+------+ + @endinternal +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_JPEG_HUFFMAN. */ + + mfxU16 reserved[2]; + mfxU16 NumDCTable; /*!< Number of DC quantization table in DCTables array. */ + mfxU16 NumACTable; /*!< Number of AC quantization table in ACTables array. */ + + struct { + mfxU8 Bits[16]; /*!< Number of codes for each code length. */ + mfxU8 Values[12]; /*!< List of the 8-bit symbol values. */ + } DCTables[4]; /*!< Array of DC tables. */ + + struct { + mfxU8 Bits[16]; /*!< Number of codes for each code length. */ + mfxU8 Values[162]; /*!< Array of AC tables. */ + } ACTables[4]; /*!< List of the 8-bit symbol values. */ +} mfxExtJPEGHuffmanTables; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif // __MFX_JPEG_H__ diff --git a/third-party/IntelVPL/x64/include/vpl/mfxmemory.h b/third-party/IntelVPL/x64/include/vpl/mfxmemory.h new file mode 100644 index 000000000..5a7ceeb12 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxmemory.h @@ -0,0 +1,322 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXMEMORY_H__ +#define __MFXMEMORY_H__ +#include "mfxsession.h" +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + @brief + Returns surface which can be used as input for VPP. + + VPP should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0. + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR If double-pointer to the @p surface is NULL. \n + MFX_ERR_INVALID_HANDLE If @p session was not initialized. \n + MFX_ERR_NOT_INITIALIZED If VPP was not initialized (allocator needs to know surface size from somewhere). \n + MFX_ERR_MEMORY_ALLOC In case of any other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.0. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForVPP(mfxSession session, mfxFrameSurface1** surface); + +/*! + @brief + Returns surface which can be used as output of VPP. + + VPP should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0. + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR If double-pointer to the @p surface is NULL. \n + MFX_ERR_INVALID_HANDLE If @p session was not initialized. \n + MFX_ERR_NOT_INITIALIZED If VPP was not initialized (allocator needs to know surface size from somewhere). \n + MFX_ERR_MEMORY_ALLOC In case of any other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.1. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForVPPOut(mfxSession session, mfxFrameSurface1** surface); + +/*! Alias for MFXMemory_GetSurfaceForVPP function. */ +#define MFXMemory_GetSurfaceForVPPIn MFXMemory_GetSurfaceForVPP + +/*! + @brief + Returns a surface which can be used as input for the encoder. + + Encoder should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0. + + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully.\n + MFX_ERR_NULL_PTR If surface is NULL.\n + MFX_ERR_INVALID_HANDLE If session was not initialized.\n + MFX_ERR_NOT_INITIALIZED If the encoder was not initialized (allocator needs to know surface size from somewhere).\n + MFX_ERR_MEMORY_ALLOC In case of any other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.0. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForEncode(mfxSession session, mfxFrameSurface1** surface); + +/*! + @brief + Returns a surface which can be used as output of the decoder. + + Decoder should be initialized before this call. + Surface should be released with mfxFrameSurface1::FrameInterface.Release(...) after usage. The value of mfxFrameSurface1::Data.Locked for the returned surface is 0.' + + @note This function was added to simplify transition from legacy surface management to the proposed internal allocation approach. + Previously, the user allocated surfaces for the working pool and fed them to the decoder using DecodeFrameAsync calls. With MFXMemory_GetSurfaceForDecode + it is possible to change the existing pipeline by just changing the source of work surfaces. + Newly developed applications should prefer direct usage of DecodeFrameAsync with internal allocation. + + + @param[in] session Session handle. + @param[out] surface Pointer is set to valid mfxFrameSurface1 object. + + @return + MFX_ERR_NONE The function completed successfully.\n + MFX_ERR_NULL_PTR If surface is NULL.\n + MFX_ERR_INVALID_HANDLE If session was not initialized.\n + MFX_ERR_NOT_INITIALIZED If the decoder was not initialized (allocator needs to know surface size from somewhere).\n + MFX_ERR_MEMORY_ALLOC Other internal allocation error. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED In case of waiting timeout expired (if set with mfxExtAllocationHints). + + @since This function is available since API version 2.0. + +*/ +mfxStatus MFX_CDECL MFXMemory_GetSurfaceForDecode(mfxSession session, mfxFrameSurface1** surface); + +#ifdef ONEVPL_EXPERIMENTAL + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL texture2D; /*!< Pointer to texture, type ID3D11Texture2D* */ + mfxHDL reserved[7]; +} mfxSurfaceD3D11Tex2D; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL vaDisplay; /*!< Object of type VADisplay. */ + mfxU32 vaSurfaceID; /*!< Object of type VASurfaceID. */ + mfxU32 reserved1; + + mfxHDL reserved[6]; +} mfxSurfaceVAAPI; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Optional extension buffer, which can be attached to mfxSurfaceHeader::ExtParam + (second parameter of mfxFrameSurfaceInterface::Export) in order to pass OCL parameters + during mfxFrameSurface1 exporting to OCL surface. + If buffer is not provided all resources will be created by oneAPI Video Processing Library (oneVPL) RT internally. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_EXPORT_SHARING_DESC_OCL. */ + + mfxHDL ocl_context; /*!< Object of type cl_context (OpenCL context). */ + mfxHDL ocl_command_queue; /*!< Object of type cl_command_queue (OpenCL command queue). */ + + mfxHDL reserved[8]; +} mfxExtSurfaceOpenCLImg2DExportDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL ocl_context; /*!< Object of type cl_context (OpenCL context). */ + mfxHDL ocl_command_queue; /*!< Object of type cl_command_queue (OpenCL command queue). */ + + mfxHDL ocl_image[4]; /*!< Object of type cl_mem[4] (array of 4 OpenCL 2D images). */ + mfxU32 ocl_image_num; /*!< Number of valid images (planes), depends on color format. */ + + mfxHDL reserved[8]; +} mfxSurfaceOpenCLImg2D; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Optional extension buffer, which can be attached to mfxSurfaceHeader::ExtParam + (second parameter of mfxFrameSurfaceInterface::Export) in order to pass D3D12 parameters + during mfxFrameSurface1 exporting to D3D12 resource. + If buffer is not provided all resources will be created by oneAPI Video Processing Library (oneVPL) RT internally. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_EXPORT_SHARING_DESC_D3D12. */ + + mfxHDL d3d12Device; /*!< Pointer to D3D12 Device, type ID3D12Device*. */ + + mfxHDL reserved[9]; +} mfxExtSurfaceD3D12Tex2DExportDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL texture2D; /*!< Pointer to D3D12 resource, type ID3D12Resource*. */ + + mfxHDL reserved[7]; +} mfxSurfaceD3D12Tex2D; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Optional extension buffer, which can be attached to mfxSurfaceHeader::ExtParam + (second parameter of mfxFrameSurfaceInterface::Export) in order to pass Vulkan parameters + during mfxFrameSurface1 exporting to Vulkan surface. + If buffer is not provided all resources will be created by oneAPI Video Processing Library (oneVPL) RT internally. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_EXPORT_SHARING_DESC_VULKAN. */ + + mfxHDL instance; /*!< Object of type VkInstance (Vulkan instance). */ + mfxHDL physicalDevice; /*!< Object of type VkPhysicalDevice (Vulkan physical device). */ + mfxHDL device; /*!< Object of type VkDevice (Vulkan device). */ + + mfxHDL reserved[7]; +} mfxExtSurfaceVulkanImg2DExportDescription; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceInterface SurfaceInterface; + + mfxHDL instance; /*!< Object of type VkInstance (Vulkan instance). */ + mfxHDL physicalDevice; /*!< Object of type VkPhysicalDevice (Vulkan physical device). */ + mfxHDL device; /*!< Object of type VkDevice (Vulkan device). */ + + mfxHDL image2D; /*!< Object of type VkImage (Vulkan 2D images). */ + mfxHDL image2DMemory; /*!< Object of type VkDeviceMemory (Vulkan device memory). */ + + mfxHDL reserved[10]; +} mfxSurfaceVulkanImg2D; +MFX_PACK_END() + +/*! The mfxSurfaceComponent enumerator specifies the internal surface pool to use when importing surfaces. */ +typedef enum { + MFX_SURFACE_COMPONENT_UNKNOWN = 0, /*!< Unknown surface component. */ + + MFX_SURFACE_COMPONENT_ENCODE = 1, /*!< Shared surface for encoding. */ + MFX_SURFACE_COMPONENT_DECODE = 2, /*!< Shared surface for decoding. */ + MFX_SURFACE_COMPONENT_VPP_INPUT = 3, /*!< Shared surface for VPP input. */ + MFX_SURFACE_COMPONENT_VPP_OUTPUT = 4, /*!< Shared surface for VPP output. */ +} mfxSurfaceComponent; + +/*! The current version of mfxSurfaceTypesSupported structure. */ +#define MFX_SURFACETYPESSUPPORTED_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! This structure describes the supported surface types and modes. */ +typedef struct { + mfxStructVersion Version; /*!< Version of the structure. */ + + mfxU16 NumSurfaceTypes; /*!< Number of supported surface types. */ + struct surftype { + mfxSurfaceType SurfaceType; /*!< Supported surface type. */ + mfxU32 reserved[6]; /*!< Reserved for future use. */ + mfxU16 NumSurfaceComponents; /*!< Number of supported surface components. */ + struct surfcomp { + mfxSurfaceComponent SurfaceComponent; /*!< Supported surface component. */ + mfxU32 SurfaceFlags; /*!< Supported surface flags for this component (may be OR'd). */ + mfxU32 reserved[7]; /*!< Reserved for future use. */ + } *SurfaceComponents; + } *SurfaceTypes; + + mfxU32 reserved[4]; /*!< Reserved for future use. */ +} mfxSurfaceTypesSupported; +MFX_PACK_END() + +#define MFX_MEMORYINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/* Specifies memory interface. */ +typedef struct mfxMemoryInterface { + mfxHDL Context; /*!< The context of the memory interface. User should not touch (change, set, null) this pointer. */ + mfxStructVersion Version; /*!< The version of the structure. */ + + /*! + @brief + Imports an application-provided surface into mfxFrameSurface1 which may be used as input for encoding or video processing. + + @param[in] memory_interface Valid memory interface. + @param[in] surf_component Surface component type. Required for allocating new surfaces from the appropriate pool. + @param[in,out] external_surface Pointer to the mfxSurfaceXXX object describing the surface to be imported. All fields in + mfxSurfaceHeader must be set by the application. mfxSurfaceHeader::SurfaceType is + read by oneVPL runtime to determine which particular mfxSurfaceXXX structure is supplied. + For example, if mfxSurfaceXXX::SurfaceType == MFX_SURFACE_TYPE_D3D11_TEX2D, then the handle + will be interpreted as an object of type mfxSurfaceD3D11Tex2D. The application should + set or clear other fields as specified in the corresponding structure description. + After successful import, the value of mfxSurfaceHeader::SurfaceFlags will be replaced with the actual + import type. It can be used to determine which import type (with or without copy) took place in the case + of initial default setting, or if multiple import flags were OR'ed. + All external sync operations on the ext_surface must be completed before calling this function. + @param[out] imported_surface Pointer to a valid mfxFrameSurface1 object containing the imported frame. + imported_surface may be passed as an input to Encode or VPP processing operations. + + @return + MFX_ERR_NONE The function completed successfully.\n + MFX_ERR_NULL_PTR If ext_surface or imported_surface are NULL.\n + MFX_ERR_INVALID_HANDLE If the corresponding session was not initialized.\n + MFX_ERR_UNSUPPORTED If surf_component is not one of [MFX_SURFACE_COMPONENT_ENCODE, MFX_SURFACE_COMPONENT_VPP_INPUT], or if + mfxSurfaceHeader::SurfaceType is not supported by oneVPL runtime for this operation.\n + + @since This function is available since API version 2.10. + */ + + /* For reference with Export flow please search for mfxFrameSurfaceInterface::Export. */ + mfxStatus (MFX_CDECL *ImportFrameSurface)(struct mfxMemoryInterface* memory_interface, mfxSurfaceComponent surf_component, mfxSurfaceHeader* external_surface, mfxFrameSurface1** imported_surface); + + mfxHDL reserved[16]; +} mfxMemoryInterface; +MFX_PACK_END() + +/*! Alias for returning interface of type mfxMemoryInterface. */ +#define MFXGetMemoryInterface(session, piface) MFXVideoCORE_GetHandle((session), MFX_HANDLE_MEMORY_INTERFACE, (mfxHDL *)(piface)) + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/third-party/IntelVPL/x64/include/vpl/mfxmvc.h b/third-party/IntelVPL/x64/include/vpl/mfxmvc.h new file mode 100644 index 000000000..5e5a3413e --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxmvc.h @@ -0,0 +1,105 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXMVC_H__ +#define __MFXMVC_H__ + +#include "mfxdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* CodecProfile, CodecLevel */ +enum { + /* MVC profiles */ + MFX_PROFILE_AVC_MULTIVIEW_HIGH = 118, /*!< Multi-view high profile. The encoding of VDEnc or LowPower ON is not supported. */ + MFX_PROFILE_AVC_STEREO_HIGH = 128 /*!< Stereo high profile. The encoding of VDEnc or LowPower ON is not supported. */ +}; + +/* Extended Buffer Ids */ +enum { + MFX_EXTBUFF_MVC_SEQ_DESC = MFX_MAKEFOURCC('M','V','C','D'), /*!< This extended buffer describes the MVC stream information of view dependencies, view identifiers, and operation points. See the ITU*-T H.264 specification chapter H.7.3.2.1.4 for details. */ + MFX_EXTBUFF_MVC_TARGET_VIEWS = MFX_MAKEFOURCC('M','V','C','T') /*!< This extended buffer defines target views at the decoder output.*/ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Describes MVC view dependencies. +*/ +typedef struct { + mfxU16 ViewId; /*!< View identifier of this dependency structure. */ + + mfxU16 NumAnchorRefsL0; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList0 for anchor view components. */ + mfxU16 NumAnchorRefsL1; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList1 for anchor view components. */ + mfxU16 AnchorRefL0[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList0 for anchor view components. */ + mfxU16 AnchorRefL1[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList1 for anchor view components. */ + + mfxU16 NumNonAnchorRefsL0; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList0 for non-anchor view components. */ + mfxU16 NumNonAnchorRefsL1; /*!< Number of view components for inter-view prediction in the initial reference picture list RefPicList1 for non-anchor view components. */ + mfxU16 NonAnchorRefL0[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList0 for non-anchor view components. */ + mfxU16 NonAnchorRefL1[16]; /*!< View identifiers of the view components for inter-view prediction in the initial reference picture list RefPicList0 for non-anchor view components. */ +} mfxMVCViewDependency; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the MVC operation point. +*/ +typedef struct { + mfxU16 TemporalId; /*!< Temporal identifier of the operation point. */ + mfxU16 LevelIdc; /*!< Level value signaled for the operation point. */ + + mfxU16 NumViews; /*!< Number of views required for decoding the target output views that correspond to the operation point. */ + mfxU16 NumTargetViews; /*!< Number of target output views for the operation point. */ + mfxU16 *TargetViewId; /*!< Target output view identifiers for operation point. */ +} mfxMVCOperationPoint; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the MVC stream information of view dependencies, view identifiers, and operation points. See the ITU*-T H.264 specification chapter H.7.3.2.1.4 for details. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MVC_SEQUENCE_DESCRIPTION. */ + + mfxU32 NumView; /*!< Number of views. */ + mfxU32 NumViewAlloc; /*!< The allocated view dependency array size. */ + mfxMVCViewDependency *View; /*!< Pointer to a list of the mfxMVCViewDependency. */ + + mfxU32 NumViewId; /*!< Number of view identifiers. */ + mfxU32 NumViewIdAlloc; /*!< The allocated view identifier array size. */ + mfxU16 *ViewId; /*!< Pointer to the list of view identifier. */ + + mfxU32 NumOP; /*!< Number of operation points. */ + mfxU32 NumOPAlloc; /*!< The allocated operation point array size. */ + mfxMVCOperationPoint *OP; /*!< Pointer to a list of the mfxMVCOperationPoint structure. */ + + mfxU16 NumRefsTotal; /*!< Total number of reference frames in all views required to decode the stream. This value is returned from the MFXVideoDECODE_Decodeheader function. Do not modify this value. */ + mfxU32 Reserved[16]; + +} mfxExtMVCSeqDesc; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures views for the decoding output. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MVC_TARGET_VIEWS. */ + + mfxU16 TemporalId; /*!< The temporal identifier to be decoded. */ + mfxU32 NumView; /*!< The number of views to be decoded. */ + mfxU16 ViewId[1024]; /*!< List of view identifiers to be decoded. */ +} mfxExtMVCTargetViews ; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/third-party/IntelVPL/x64/include/vpl/mfxpcp.h b/third-party/IntelVPL/x64/include/vpl/mfxpcp.h new file mode 100644 index 000000000..a55c0e404 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxpcp.h @@ -0,0 +1,45 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXPCP_H__ +#define __MFXPCP_H__ +#include "mfxstructures.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! The Protected enumerator describes the protection schemes. */ +enum { + MFX_PROTECTION_CENC_WV_CLASSIC = 0x0004, /*!< The protection scheme is based on the Widevine* DRM from Google*. */ + MFX_PROTECTION_CENC_WV_GOOGLE_DASH = 0x0005, /*!< The protection scheme is based on the Widevine* Modular DRM* from Google*. */ +}; + +/* Extended Buffer Ids */ +enum { + MFX_EXTBUFF_CENC_PARAM = MFX_MAKEFOURCC('C','E','N','P') /*!< This structure is used to pass decryption status report index for Common + Encryption usage model. See the mfxExtCencParam structure for more details. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to pass the decryption status report index for the Common Encryption usage model. The application can + attach this extended buffer to the mfxBitstream structure at runtime. +*/ +typedef struct _mfxExtCencParam{ + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CENC_PARAM. */ + + mfxU32 StatusReportIndex; /*!< Decryption status report index. */ + mfxU32 reserved[15]; +} mfxExtCencParam; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif /* __cplusplus */ + +#endif diff --git a/third-party/IntelVPL/x64/include/vpl/mfxsession.h b/third-party/IntelVPL/x64/include/vpl/mfxsession.h new file mode 100644 index 000000000..d68ff1a72 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxsession.h @@ -0,0 +1,234 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXSESSION_H__ +#define __MFXSESSION_H__ +#include "mfxcommon.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* Global Functions */ + +/*! Session handle. */ +typedef struct _mfxSession *mfxSession; + +/*! + @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. + + Call this function before calling + any other API function. If the desired implementation specified by ``impl`` is MFX_IMPL_AUTO, + the function will search for the platform-specific implementation. + If the function cannot find the platform-specific implementation, it will use the software implementation instead. + + The ``ver`` argument indicates the desired version of the library implementation. + The loaded implementation will have an API version compatible to the specified version (equal in + the major version number, and no less in the minor version number.) If the desired version + is not specified, the default is to use the API version from the library release with + which an application is built. + + Production applications should always specify the minimum API version that meets the + functional requirements. 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. + + @param[in] impl mfxIMPL enumerator that indicates the desired legacy Intel(r) Media SDK implementation. + @param[in] ver Pointer to the minimum library version or zero, if not specified. + @param[out] session Pointer to the legacy Intel(r) Media SDK session handle. + + @return + MFX_ERR_NONE The function completed successfully. The output parameter contains the handle of the session.\n + 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); + +/*! + @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. + + 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 + the platform-specific implementation. If the function cannot find the platform-specific implementation, it will use the software implementation instead. + + The argument ``par.Version`` indicates the desired version of the implementation. The loaded implementation will have an API + version compatible to the specified version (equal in the major version number, and no less in the minor version number.) + If the desired version is not specified, the default is to use the API version from the library release with + which an application is built. + + Production applications should always specify the minimum API version that meets the functional requirements. + 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). + + @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. + + @return + MFX_ERR_NONE The function completed successfully. The output parameter contains the handle of the session.\n + 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); + +/*! + @brief + Creates and initializes a session starting from API version 2.0. This function is used by the dispatcher. + The dispatcher creates and fills the mfxInitializationParam structure according to mfxConfig values set by an application. + Calling this function directly is not recommended. Instead, applications must call the MFXCreateSession function. + + + @param[in] par mfxInitializationParam structure that indicates the minimum library version and acceleration type. + @param[out] session Pointer to the session handle. + + @return + MFX_ERR_NONE The function completed successfully. The output parameter contains the handle of the session.\n + MFX_ERR_UNSUPPORTED The function cannot find the desired implementation or version. + + @since This function is available since API version 2.0. +*/ +mfxStatus MFX_CDECL MFXInitialize(mfxInitializationParam par, mfxSession *session); + +/*! + @brief Completes and deinitializes a session. Any active tasks in execution or + in queue are aborted. The application cannot call any API function after calling this function. + + All child sessions must be disjoined before closing a parent session. + @param[in] session session handle. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXClose(mfxSession session); + +/*! + @brief Returns the implementation type of a given session. + + @param[in] session Session handle. + @param[out] impl Pointer to the implementation type + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXQueryIMPL(mfxSession session, mfxIMPL *impl); + +/*! + @brief Returns the implementation version. + + @param[in] session Session handle. + @param[out] version Pointer to the returned implementation version. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXQueryVersion(mfxSession session, mfxVersion *version); + +/*! + @brief Joins the child session to the current session. + + After joining, the two sessions share thread and resource scheduling for asynchronous + operations. However, each session still maintains its own device manager and buffer/frame + allocator. Therefore, the application must use a compatible device manager and buffer/frame + allocator to share data between two joined sessions. + + The application can join multiple sessions by calling this function multiple times. When joining + the first two sessions, the current session becomes the parent responsible for thread and + resource scheduling of any later joined sessions. + + Joining of two parent sessions is not supported. + + @param[in,out] session The current session handle. + @param[in] child The child session handle to be joined + + @return MFX_ERR_NONE The function completed successfully. \n + MFX_WRN_IN_EXECUTION Active tasks are executing or in queue in one of the + sessions. Call this function again after all tasks are completed. \n + MFX_ERR_UNSUPPORTED The child session cannot be joined with the current session. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXJoinSession(mfxSession session, mfxSession child); + +/*! + @brief Removes the joined state of the current session. + + After disjoining, the current session becomes independent. The application must ensure there is no active task running in the session before calling this API function. + + @param[in,out] session The current session handle. + + @return MFX_ERR_NONE The function completed successfully. \n + MFX_WRN_IN_EXECUTION Active tasks are executing or in queue in one of the + sessions. Call this function again after all tasks are completed. \n + MFX_ERR_UNDEFINED_BEHAVIOR The session is independent, or this session is the parent of all joined sessions. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXDisjoinSession(mfxSession session); + +/*! + @brief Creates a clean copy of the current session. + + The cloned session is an independent session and does not inherit any user-defined buffer, frame allocator, or device manager handles from the current session. + This function is a light-weight equivalent of MFXJoinSession after MFXInit. + + @param[in] session The current session handle. + @param[out] clone Pointer to the cloned session handle. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXCloneSession(mfxSession session, mfxSession *clone); + +/*! + @brief Sets the current session priority. + + @param[in] session The current session handle. + @param[in] priority Priority value. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXSetPriority(mfxSession session, mfxPriority priority); + +/*! + @brief Returns the current session priority. + + @param[in] session The current session handle. + @param[out] priority Pointer to the priority value. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.1. +*/ +mfxStatus MFX_CDECL MFXGetPriority(mfxSession session, mfxPriority *priority); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif + diff --git a/third-party/IntelVPL/x64/include/vpl/mfxstructures.h b/third-party/IntelVPL/x64/include/vpl/mfxstructures.h new file mode 100644 index 000000000..3ee64fe12 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxstructures.h @@ -0,0 +1,5399 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXSTRUCTURES_H__ +#define __MFXSTRUCTURES_H__ +#include "mfxcommon.h" + +#if !defined (__GNUC__) +#pragma warning(disable: 4201) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Frame ID for MVC */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Describes the view and layer of a frame picture. */ +typedef struct { + mfxU16 TemporalId; /*!< The temporal identifier as defined in the annex H of the ITU*-T H.264 specification. */ + mfxU16 PriorityId; /*!< Reserved and must be zero. */ + union { + struct { + mfxU16 DependencyId; /*!< Reserved for future use. */ + mfxU16 QualityId; /*!< Reserved for future use. */ + }; + struct { + mfxU16 ViewId; /*!< The view identifier as defined in the annex H of the ITU-T H.264 specification. */ + }; + }; +} mfxFrameId; +MFX_PACK_END() + +/* This struct has 4-byte alignment for binary compatibility with previously released versions of API. */ +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 + zero. It's allowed to skip setting of decoder's parameters for simplified decoding procedure */ + 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; + /*! Number of bits used to represent chroma samples. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU16 BitDepthChroma; + /*! The Shift flag indicates whether the values of luma and chroma samples are shifted. For the decoding process, the recommended value + is specified by the DecodeHeader or GetVideoParam API. A value of one indicates that the luma and chroma sample values are shifted, + while a value of zero indicates that there is no shift. Please refer to the example data alignment provided below. + + @note Not all codecs and implementations support this flag. Use the Query API function to check if this feature is supported. + AVC and HEVC allow users to set the Shift flag to either 0 or 1. However, setting the Shift flag to a value different from the + recommended one may lead to increased CPU utilization. For other codecs, attempting to set the Shift flag to a value other than + the recommended one will result in an error status. + */ + mfxU16 Shift; + mfxFrameId FrameId; /*!< Describes the view and layer of a frame picture. */ + mfxU32 FourCC; /*!< FourCC code of the color format. See the ColorFourCC enumerator for details. */ + union { + struct { /* Frame parameters */ + /*! Width of the video frame in pixels. Must be a multiple of 16. + In case of fused operation of decode plus VPP it can be set to zero to signalize that scaling operation is not requested. */ + mfxU16 Width; + /*! Height of the video frame in pixels. Must be a multiple of 16 for progressive frame sequence and a multiple of 32 otherwise. + In case of fused operation of decode plus VPP it can be set to zero to signalize that scaling operation is not requested. */ + mfxU16 Height; + + /*! @{ + @name ROI + The region of interest of the frame. Specify the display width and height in mfxVideoParam. */ + /*! X coordinate. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropX; + /*! Y coordinate. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropY; + /*! Width in pixels. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropW; + /*! Height in pixels. + In case of fused operation of decode plus VPP it can be set to zero to signalize that cropping operation is not requested. */ + mfxU16 CropH; + /*! @} */ + }; + struct { /* Buffer parameters (for plain formats like P8) */ + mfxU64 BufferSize; /*!< Size of frame buffer in bytes. Valid only for plain formats (when FourCC is P8). In this case, Width, Height, and crop values are invalid. */ + mfxU32 reserved5; + }; + }; + + /*! @{ + @name FrameRate + Specify the frame rate with the following formula: FrameRateExtN / FrameRateExtD. + + For encoding, frame rate must be specified. For decoding, frame rate may be unspecified (FrameRateExtN and FrameRateExtD + are all zeros.) In this case, the frame rate is defaulted to 0 frames per second, and timestamp will be calculated by 30fps in SDK. + + In decoding process: + + If there is frame rate information in bitstream, MFXVideoDECODE_DecodeHeader will carry actual frame rate in FrameRateExtN and FrameRateExtD parameters. + MFXVideoDECODE_Init, MFXVideoDECODE_Query, MFXVideoDECODE_DecodeFrameAsync and MFXVideoDECODE_GetVideoParam will also carry these values for frame rate. + Timestamp will be calculated by the actual frame rate. + + If there is no frame rate information in bitstream, MFXVideoDECODE_DecodeHeader will assign 0 for frame rate in FrameRateExtN and FrameRateExtD parameters. + MFXVideoDECODE_Init, MFXVideoDECODE_Query, MFXVideoDECODE_DecodeFrameAsync and MFXVideoDECODE_GetVideoParam will also assign 0 for frame rate. Timestamp will be calculated by 30fps. + + If these two parameters are modified through MFXVideoDECODE_Init, then the modified values for frame rate will be used in + MFXVideoDECODE_Query, MFXVideoDECODE_DecodeFrameAsync and MFXVideoDECODE_GetVideoParam. Timestamps will be calculated using the modified values. + */ + mfxU32 FrameRateExtN; /*!< Frame rate numerator. */ + mfxU32 FrameRateExtD; /*!< Frame rate denominator. */ + /*! @} */ + mfxU16 reserved3; + + /*! @{ + @name AspectRatio + AspectRatioW and AspectRatioH are used to specify the sample aspect ratio. If sample aspect ratio is explicitly defined by the standards (see + Table 6-3 in the MPEG-2 specification or Table E-1 in the H.264 specification), AspectRatioW and AspectRatioH should be the defined values. + Otherwise, the sample aspect ratio can be derived as follows: + + @li @c AspectRatioW=display_aspect_ratio_width*display_height + + @li @c AspectRatioH=display_aspect_ratio_height*display_width + + For MPEG-2, the above display aspect ratio must be one of the defined values in Table 6-3 in the MPEG-2 specification. For H.264, there is no restriction + on display aspect ratio values. + + If both parameters are zero, the encoder uses the default value of sample aspect ratio. + */ + mfxU16 AspectRatioW; /*!< Aspect Ratio for width. */ + mfxU16 AspectRatioH; /*!< Aspect Ratio for height. */ + /*! @} */ + + mfxU16 PicStruct; /*!< Picture type as specified in the PicStruct enumerator. */ + mfxU16 ChromaFormat; /*!< Color sampling method. Value is the same as that of ChromaFormatIdc. + ChromaFormat is not defined if FourCC is zero.*/ + mfxU16 reserved2; +} mfxFrameInfo; +MFX_PACK_END() + +/*! The ColorFourCC enumerator itemizes color formats. */ +enum { + MFX_FOURCC_NV12 = MFX_MAKEFOURCC('N','V','1','2'), /*!< NV12 color planes. Native format for 4:2:0/8b Gen hardware implementation. */ + MFX_FOURCC_YV12 = MFX_MAKEFOURCC('Y','V','1','2'), /*!< YV12 color planes. */ + MFX_FOURCC_NV16 = MFX_MAKEFOURCC('N','V','1','6'), /*!< 4:2:2 color format with similar to NV12 layout. */ + MFX_FOURCC_YUY2 = MFX_MAKEFOURCC('Y','U','Y','2'), /*!< YUY2 color planes. */ + MFX_FOURCC_RGB565 = MFX_MAKEFOURCC('R','G','B','2'), /*!< 2 bytes per pixel, uint16 in little-endian format, where 0-4 bits are blue, bits 5-10 are green and bits 11-15 are red. */ + /*! RGB 24 bit planar layout (3 separate channels, 8-bits per sample each). This format should be mapped to D3DFMT_R8G8B8 or VA_FOURCC_RGBP. */ + MFX_FOURCC_RGBP = MFX_MAKEFOURCC('R','G','B','P'), + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_FOURCC_RGB3) = MFX_MAKEFOURCC('R','G','B','3'), /* Deprecated. */ + MFX_FOURCC_RGB4 = MFX_MAKEFOURCC('R','G','B','4'), /*!< RGB4 (RGB32) color planes. BGRA is the order, 'B' is 8 LSBs in 32-bit unit, then 8 bits for 'G' channel, then 'R' and 'A' channels. */ + /*! + Internal color format. The application should use the following functions to create a surface that corresponds to the Direct3D* version in use. + + For Direct3D* 9: IDirectXVideoDecoderService::CreateSurface() + + For Direct3D* 11: ID3D11Device::CreateBuffer() + */ + MFX_FOURCC_P8 = 41, + /*! + Internal color format. The application should use the following functions to create a surface that corresponds to the Direct3D* version in use. + + For Direct3D 9: IDirectXVideoDecoderService::CreateSurface() + + For Direct3D 11: ID3D11Device::CreateTexture2D() + */ + MFX_FOURCC_P8_TEXTURE = MFX_MAKEFOURCC('P','8','M','B'), + MFX_FOURCC_P010 = MFX_MAKEFOURCC('P','0','1','0'), /*!< P010 color format. This is 10 bit per sample format with similar to NV12 layout. This format should be mapped to DXGI_FORMAT_P010. */ + MFX_FOURCC_P016 = MFX_MAKEFOURCC('P','0','1','6'), /*!< P016 color format. This is 16 bit per sample format with similar to NV12 layout. This format should be mapped to DXGI_FORMAT_P016. */ + MFX_FOURCC_P210 = MFX_MAKEFOURCC('P','2','1','0'), /*!< 10 bit per sample 4:2:2 color format with similar to NV12 layout. */ + MFX_FOURCC_BGR4 = MFX_MAKEFOURCC('B','G','R','4'), /*!< RGBA color format. It is similar to MFX_FOURCC_RGB4 but with different order of channels. 'R' is 8 LSBs in 32-bit unit, then 8 bits for 'G' channel, then 'B' and 'A' channels. */ + MFX_FOURCC_A2RGB10 = MFX_MAKEFOURCC('R','G','1','0'), /*!< 10 bits ARGB color format packed in 32 bits. 'A' channel is two MSBs, then 'R', then 'G' and then 'B' channels. This format should be mapped to DXGI_FORMAT_R10G10B10A2_UNORM or D3DFMT_A2R10G10B10. */ + MFX_FOURCC_ARGB16 = MFX_MAKEFOURCC('R','G','1','6'), /*!< 16 bits ARGB color format packed in 64 bits. 'A' channel is 16 MSBs, then 'R', then 'G' and then 'B' channels. This format should be mapped to DXGI_FORMAT_R16G16B16A16_UNORM or D3DFMT_A16B16G16R16 formats. */ + MFX_FOURCC_ABGR16 = MFX_MAKEFOURCC('B','G','1','6'), /*!< 16 bits ABGR color format packed in 64 bits. 'A' channel is 16 MSBs, then 'B', then 'G' and then 'R' channels. This format should be mapped to DXGI_FORMAT_R16G16B16A16_UNORM or D3DFMT_A16B16G16R16 formats. */ + MFX_FOURCC_R16 = MFX_MAKEFOURCC('R','1','6','U'), /*!< 16 bits single channel color format. This format should be mapped to DXGI_FORMAT_R16_TYPELESS or D3DFMT_R16F. */ + MFX_FOURCC_AYUV = MFX_MAKEFOURCC('A','Y','U','V'), /*!< YUV 4:4:4, AYUV color format. This format should be mapped to DXGI_FORMAT_AYUV. */ + MFX_FOURCC_AYUV_RGB4 = MFX_MAKEFOURCC('A','V','U','Y'), /*!< RGB4 stored in AYUV surface. This format should be mapped to DXGI_FORMAT_AYUV. */ + MFX_FOURCC_UYVY = MFX_MAKEFOURCC('U','Y','V','Y'), /*!< UYVY color planes. Same as YUY2 except the byte order is reversed. */ + MFX_FOURCC_Y210 = MFX_MAKEFOURCC('Y','2','1','0'), /*!< 10 bit per sample 4:2:2 packed color format with similar to YUY2 layout. This format should be mapped to DXGI_FORMAT_Y210. */ + MFX_FOURCC_Y410 = MFX_MAKEFOURCC('Y','4','1','0'), /*!< 10 bit per sample 4:4:4 packed color format. This format should be mapped to DXGI_FORMAT_Y410. */ + MFX_FOURCC_Y216 = MFX_MAKEFOURCC('Y','2','1','6'), /*!< 16 bit per sample 4:2:2 packed color format with similar to YUY2 layout. This format should be mapped to DXGI_FORMAT_Y216. */ + MFX_FOURCC_Y416 = MFX_MAKEFOURCC('Y','4','1','6'), /*!< 16 bit per sample 4:4:4 packed color format. This format should be mapped to DXGI_FORMAT_Y416. */ + MFX_FOURCC_NV21 = MFX_MAKEFOURCC('N', 'V', '2', '1'), /*!< Same as NV12 but with weaved V and U values. */ + MFX_FOURCC_IYUV = MFX_MAKEFOURCC('I', 'Y', 'U', 'V'), /*!< Same as YV12 except that the U and V plane order is reversed. */ + MFX_FOURCC_I010 = MFX_MAKEFOURCC('I', '0', '1', '0'), /*!< 10-bit YUV 4:2:0, each component has its own plane. */ + MFX_FOURCC_I210 = MFX_MAKEFOURCC('I', '2', '1', '0'), /*!< 10-bit YUV 4:2:2, each component has its own plane. */ + MFX_FOURCC_I420 = MFX_FOURCC_IYUV, /*!< Alias for the IYUV color format. */ + MFX_FOURCC_I422 = MFX_MAKEFOURCC('I', '4', '2', '2'), /*!< Same as YV16 except that the U and V plane order is reversed */ + 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'), + /*! 8bit per sample 4:4:4 format packed in 32 bits, X=unused/undefined, 'X' channel is 8 MSBs, then 'Y', then 'U', and then 'V' channels. This format should be mapped to VA_FOURCC_XYUV. */ + MFX_FOURCC_XYUV = MFX_MAKEFOURCC('X','Y','U','V'), + MFX_FOURCC_ABGR16F = MFX_MAKEFOURCC('B', 'G', 'R', 'F'), /*!< 16 bits float point ABGR color format packed in 64 bits. 'A' channel is 16 MSBs, then 'B', then 'G' and then 'R' channels. This format should be mapped to DXGI_FORMAT_R16G16B16A16_FLOAT or D3DFMT_A16B16G16R16F formats.. */ +}; + +/* PicStruct */ +enum { + MFX_PICSTRUCT_UNKNOWN =0x00, /*!< Unspecified or mixed progressive/interlaced/field pictures. */ + MFX_PICSTRUCT_PROGRESSIVE =0x01, /*!< Progressive picture. */ + MFX_PICSTRUCT_FIELD_TFF =0x02, /*!< Top field in first interlaced picture. */ + MFX_PICSTRUCT_FIELD_BFF =0x04, /*!< Bottom field in first interlaced picture. */ + + MFX_PICSTRUCT_FIELD_REPEATED=0x10, /*!< First field repeated: pic_struct=5 or 6 in H.264. */ + MFX_PICSTRUCT_FRAME_DOUBLING=0x20, /*!< Double the frame for display: pic_struct=7 in H.264. */ + MFX_PICSTRUCT_FRAME_TRIPLING=0x40, /*!< Triple the frame for display: pic_struct=8 in H.264. */ + + MFX_PICSTRUCT_FIELD_SINGLE =0x100, /*!< Single field in a picture. */ + MFX_PICSTRUCT_FIELD_TOP =MFX_PICSTRUCT_FIELD_SINGLE | MFX_PICSTRUCT_FIELD_TFF, /*!< Top field in a picture: pic_struct = 1 in H.265. */ + MFX_PICSTRUCT_FIELD_BOTTOM =MFX_PICSTRUCT_FIELD_SINGLE | MFX_PICSTRUCT_FIELD_BFF, /*!< Bottom field in a picture: pic_struct = 2 in H.265. */ + MFX_PICSTRUCT_FIELD_PAIRED_PREV =0x200, /*!< Paired with previous field: pic_struct = 9 or 10 in H.265. */ + MFX_PICSTRUCT_FIELD_PAIRED_NEXT =0x400, /*!< Paired with next field: pic_struct = 11 or 12 in H.265 */ +}; + +/*! The ChromaFormatIdc enumerator itemizes color-sampling formats. */ +enum { + MFX_CHROMAFORMAT_MONOCHROME =0, /*!< Monochrome. */ + MFX_CHROMAFORMAT_YUV420 =1, /*!< 4:2:0 color. */ + MFX_CHROMAFORMAT_YUV422 =2, /*!< 4:2:2 color. */ + MFX_CHROMAFORMAT_YUV444 =3, /*!< 4:4:4 color. */ + MFX_CHROMAFORMAT_YUV400 = MFX_CHROMAFORMAT_MONOCHROME, /*!< Equal to monochrome. */ + MFX_CHROMAFORMAT_YUV411 = 4, /*!< 4:1:1 color. */ + MFX_CHROMAFORMAT_YUV422H = MFX_CHROMAFORMAT_YUV422, /*!< 4:2:2 color, horizontal sub-sampling. It is equal to 4:2:2 color. */ + MFX_CHROMAFORMAT_YUV422V = 5, /*!< 4:2:2 color, vertical sub-sampling. */ + MFX_CHROMAFORMAT_RESERVED1 = 6 /*!< Reserved. */ +}; + +enum { + MFX_TIMESTAMP_UNKNOWN = -1 /*!< Indicates that time stamp is unknown for this frame/bitstream portion. */ +}; + +enum { + MFX_FRAMEORDER_UNKNOWN = -1 /*!< Unused entry or API functions that generate the frame output do not use this frame. */ +}; + +/*! The FrameDataFlag enumerator itemizes DataFlag value in mfxFrameData. */ +enum { + MFX_FRAMEDATA_TIMESTAMP_UNKNOWN = 0x0000,/*!< Indicates the time stamp of this frame is unknown and will be calculated by SDK. */ + MFX_FRAMEDATA_ORIGINAL_TIMESTAMP = 0x0001 /*!< Indicates the time stamp of this frame is not calculated and is a pass-through of the original time stamp. */ +}; + +/*! Corrupted in mfxFrameData */ +enum { + MFX_CORRUPTION_NO = 0x0000, /*!< No corruption. */ + MFX_CORRUPTION_MINOR = 0x0001, /*!< Minor corruption in decoding certain macro-blocks. */ + MFX_CORRUPTION_MAJOR = 0x0002, /*!< Major corruption in decoding the frame - incomplete data, for example. */ + MFX_CORRUPTION_ABSENT_TOP_FIELD = 0x0004, /*!< Top field of frame is absent in bitstream. Only bottom field has been decoded. */ + MFX_CORRUPTION_ABSENT_BOTTOM_FIELD = 0x0008, /*!< Bottom field of frame is absent in bitstream. Only top filed has been decoded. */ + MFX_CORRUPTION_REFERENCE_FRAME = 0x0010, /*!< Decoding used a corrupted reference frame. A corrupted reference frame was used for decoding this + frame. For example, if the frame uses a reference frame that was decoded with minor/major corruption flag, then this + frame is also marked with a reference corruption flag. */ + MFX_CORRUPTION_REFERENCE_LIST = 0x0020, /*!< The reference list information of this frame does not match what is specified in the Reference Picture Marking + Repetition SEI message. (ITU-T H.264 D.1.8 dec_ref_pic_marking_repetition) */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_CORRUPTION_HW_RESET = 0x0040 /*!< The hardware reset is reported from media driver. */ +#endif +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in Y410 color format. */ +typedef struct +{ + mfxU32 U : 10; /*!< U component. */ + mfxU32 Y : 10; /*!< Y component. */ + mfxU32 V : 10; /*!< V component. */ + mfxU32 A : 2; /*!< A component. */ +} mfxY410; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in Y416 color format. */ +typedef struct +{ + mfxU32 U : 16; /*!< U component. */ + mfxU32 Y : 16; /*!< Y component. */ + mfxU32 V : 16; /*!< V component. */ + mfxU32 A : 16; /*!< A component. */ +} mfxY416; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in A2RGB10 color format */ +typedef struct +{ + mfxU32 B : 10; /*!< B component. */ + mfxU32 G : 10; /*!< G component. */ + mfxU32 R : 10; /*!< R component. */ + mfxU32 A : 2; /*!< A component. */ +} mfxA2RGB10; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies "pixel" in ABGR 16 bit half float point color format */ +typedef struct +{ + mfxFP16 R; /*!< R component. */ + mfxFP16 G; /*!< G component. */ + mfxFP16 B; /*!< B component. */ + mfxFP16 A; /*!< A component. */ +} mfxABGR16FP; +MFX_PACK_END() + +/*! Describes frame buffer pointers. */ +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +typedef struct { + /*! @name Extension Buffers */ + /*! @{ */ + union { + mfxExtBuffer **ExtParam; /*!< Points to an array of pointers to the extra configuration structures. See the ExtendedBufferID + enumerator for a list of extended configurations. */ + mfxU64 reserved2; + }; + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + /*! @} */ + + /*! @name General members */ + /*! @{ */ + mfxU16 reserved[9]; /*!< Reserved for future use. */ + mfxU16 MemType; /*!< Allocated memory type. See the ExtMemFrameType enumerator for details. Used for better integration of + 3rd party plugins into the pipeline. */ + mfxU16 PitchHigh; /*!< Distance in bytes between the start of two consecutive rows in a frame. */ + + mfxU64 TimeStamp; /*!< Time stamp of the video frame in units of 90KHz. Divide TimeStamp by 90,000 (90 KHz) to obtain the time in seconds. + A value of MFX_TIMESTAMP_UNKNOWN indicates that there is no time stamp. */ + mfxU32 FrameOrder; /*!< Current frame counter for the top field of the current frame. An invalid value of MFX_FRAMEORDER_UNKNOWN indicates that + API functions that generate the frame output do not use this frame. */ + mfxU16 Locked; /*!< Counter flag for the application. If Locked is greater than zero then the application locks the frame or field pair. + Do not move, alter or delete the frame. */ + union{ + mfxU16 Pitch; + mfxU16 PitchLow; /*!< Distance in bytes between the start of two consecutive rows in a frame. */ + }; + /*! @} */ + + /*! + @name Color Planes + Data pointers to corresponding color channels (planes). The frame buffer pointers must be 16-byte aligned. The application has to specify pointers to + all color channels even for packed formats. For example, for YUY2 format the application must specify Y, U, and V pointers. + For RGB32 format, the application must specify R, G, B, and A pointers. + */ + /*! @{ */ + union { + mfxU8 *Y; /*!< Y channel. */ + mfxU16 *Y16; /*!< Y16 channel. */ + mfxU8 *R; /*!< R channel. */ + }; + union { + mfxU8 *UV; /*!< UV channel for UV merged formats. */ + mfxU8 *VU; /*!< YU channel for VU merged formats. */ + mfxU8 *CbCr; /*!< CbCr channel for CbCr merged formats. */ + mfxU8 *CrCb; /*!< CrCb channel for CrCb merged formats. */ + mfxU8 *Cb; /*!< Cb channel. */ + mfxU8 *U; /*!< U channel. */ + mfxU16 *U16; /*!< U16 channel. */ + mfxU8 *G; /*!< G channel. */ + mfxY410 *Y410; /*!< T410 channel for Y410 format (merged AVYU). */ + mfxY416 *Y416; /*!< This format is a packed 16-bit representation that includes 16 bits of alpha. */ + }; + union { + mfxU8 *Cr; /*!< Cr channel. */ + mfxU8 *V; /*!< V channel. */ + mfxU16 *V16; /*!< V16 channel. */ + mfxU8 *B; /*!< B channel. */ + mfxA2RGB10 *A2RGB10; /*!< A2RGB10 channel for A2RGB10 format (merged ARGB). */ + mfxABGR16FP* ABGRFP16; /*!< ABGRFP16 channel for half float ARGB format (use this merged one due to no separate FP16 Alpha Channel). */ + }; + mfxU8 *A; /*!< A channel. */ + mfxMemId MemId; /*!< Memory ID of the data buffers. Ignored if any of the preceding data pointers is non-zero. */ + /*! @} */ + + /*! + @name Additional Flags + */ + /*! @{ */ + mfxU16 Corrupted; /*!< Some part of the frame or field pair is corrupted. See the Corruption enumerator for details. */ + mfxU16 DataFlag; /*!< Additional flags to indicate frame data properties. See the FrameDataFlag enumerator for details. */ + /*! @} */ +} mfxFrameData; +MFX_PACK_END() + +/*! The mfxHandleType enumerator itemizes system handle types that implementations might use. */ +typedef enum { + MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9 = 1, /*!< Pointer to the IDirect3DDeviceManager9 interface. See Working with Microsoft* DirectX* Applications for more details on how to use this handle. */ + MFX_HANDLE_D3D9_DEVICE_MANAGER = MFX_HANDLE_DIRECT3D_DEVICE_MANAGER9, /*!< Pointer to the IDirect3DDeviceManager9 interface. See Working with Microsoft* DirectX* Applications for more details on how to use this handle. */ + MFX_HANDLE_RESERVED1 = 2, /* Reserved. */ + MFX_HANDLE_D3D11_DEVICE = 3, /*!< Pointer to the ID3D11Device interface. See Working with Microsoft* DirectX* Applications for more details on how to use this handle. */ + MFX_HANDLE_VA_DISPLAY = 4, /*!< VADisplay interface. See Working with VA-API Applications for more details on how to use this handle. */ + MFX_HANDLE_RESERVED3 = 5, /* Reserved. */ + MFX_HANDLE_VA_CONFIG_ID = 6, /*!< Pointer to VAConfigID interface. It represents external VA config for Common Encryption usage model. */ + MFX_HANDLE_VA_CONTEXT_ID = 7, /*!< Pointer to VAContextID interface. It represents external VA context for Common Encryption usage model. */ + MFX_HANDLE_CM_DEVICE = 8, /*!< Pointer to CmDevice interface ( Intel(r) C for Metal Runtime ). */ + MFX_HANDLE_HDDLUNITE_WORKLOADCONTEXT = 9, /*!< Pointer to HddlUnite::WorkloadContext interface. */ + MFX_HANDLE_PXP_CONTEXT = 10, /*!< Pointer to PXP context for protected content support. */ + + MFX_HANDLE_CONFIG_INTERFACE = 1000, /*!< Pointer to interface of type mfxConfigInterface. */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_HANDLE_MEMORY_INTERFACE = 1001, /*!< Pointer to interface of type mfxMemoryInterface. */ +#endif +} mfxHandleType; + +/*! The mfxMemoryFlags enumerator specifies memory access mode. */ +typedef enum +{ + MFX_MAP_READ = 0x1, /*!< The surface is mapped for reading. */ + MFX_MAP_WRITE = 0x2, /*!< The surface is mapped for writing. */ + MFX_MAP_READ_WRITE = MFX_MAP_READ|MFX_MAP_WRITE, /*!< The surface is mapped for reading and writing. */ + /*! + * The mapping would be done immediately without any implicit synchronizations. + * \attention This flag is optional. + */ + MFX_MAP_NOWAIT = 0x10 +} mfxMemoryFlags; + +#define MFX_FRAMESURFACE1_VERSION MFX_STRUCT_VERSION(1, 1) + +/* Frame Surface */ +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! Defines the uncompressed frames surface information and data buffers. + The frame surface is in the frame or complementary field pairs of pixels up to four color-channels, in two parts: + mfxFrameInfo and mfxFrameData. +*/ +typedef struct { + union + { + struct mfxFrameSurfaceInterface* FrameInterface; /*!< Specifies interface to work with surface. */ + mfxU32 reserved[2]; + }; + mfxStructVersion Version; /*!< Specifies version of mfxFrameSurface1 structure. */ + mfxU16 reserved1[3]; + mfxFrameInfo Info; /*!< Specifies surface properties. */ + mfxFrameData Data; /*!< Describes the actual frame buffer. */ +} mfxFrameSurface1; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL + +/*! The mfxSurfaceType enumerator specifies the surface type described by mfxSurfaceHeader. */ +typedef enum { + MFX_SURFACE_TYPE_UNKNOWN = 0, /*!< Unknown surface type. */ + + MFX_SURFACE_TYPE_D3D11_TEX2D = 2, /*!< D3D11 surface of type ID3D11Texture2D. */ + MFX_SURFACE_TYPE_VAAPI = 3, /*!< VA-API surface. */ + MFX_SURFACE_TYPE_OPENCL_IMG2D = 4, /*!< OpenCL 2D image (cl_mem). */ + MFX_SURFACE_TYPE_D3D12_TEX2D = 5, /*!< D3D12 surface of type ID3D12Resource with 2D texture type. */ + MFX_SURFACE_TYPE_VULKAN_IMG2D = 6, /*!< Vulkan 2D image (VkImage). */ +} mfxSurfaceType; + +/*! This enumerator specifies the sharing modes which are allowed for importing or exporting shared surfaces. */ +enum { + MFX_SURFACE_FLAG_DEFAULT = 0x0000, /*!< Default is SHARED import or export. */ + + MFX_SURFACE_FLAG_IMPORT_SHARED = 0x0010, /*!< Import frames directly by mapping a shared native handle from an application-provided surface to an internally-allocated surface. */ + MFX_SURFACE_FLAG_IMPORT_COPY = 0x0020, /*!< Import frames by copying data from an application-provided surface to an internally-allocated surface. */ + + MFX_SURFACE_FLAG_EXPORT_SHARED = 0x0100, /*!< Export frames directly by mapping a shared native handle from an internally-allocated surface to an application-provided surface. */ + MFX_SURFACE_FLAG_EXPORT_COPY = 0x0200, /*!< Export frames by copying data from an internally-allocated surface to an application-provided surface. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxSurfaceType SurfaceType; /*!< Set to the MFX_SURFACE_TYPE enum corresponding to the specific structure. */ + mfxU32 SurfaceFlags; /*!< Set to the MFX_SURFACE_FLAG enum (or combination) corresponding to the allowed import / export mode(s). Multiple flags may be combined with OR. + Upon a successful Import or Export operation, this field will indicate the actual mode used.*/ + + mfxU32 StructSize; /*!< Size in bytes of the complete mfxSurfaceXXX structure. */ + + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to the 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 reserved[6]; +} mfxSurfaceHeader; +MFX_PACK_END() + + +#define MFX_SURFACEINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +/*! + Contains mfxSurfaceHeader and the callback functions AddRef, Release and GetRefCounter + that the application may use to manage access to exported surfaces. + These interfaces are only valid for surfaces obtained by mfxFrameSurfaceInterface::Export. + They are not used for surface descriptions passed to function mfxMemoryInterface::ImportFrameSurface. +*/ +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct mfxSurfaceInterface { + mfxSurfaceHeader Header; /*!< Exported surface header. Contains description of current surface. */ + + mfxStructVersion Version; /*!< The version of the structure. */ + + mfxHDL Context; /*!< The context of the exported surface interface. User should not touch (change, set, null) this pointer. */ + + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the mfxSurfaceInterface::Release function. + mfxSurfaceInterface::AddRef should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxSurfaceInterface* surface); + + /*! @brief + Decrements the internal reference counter of the surface. mfxSurfaceInterface::Release should be called after using the + mfxSurfaceInterface::AddRef function to add a surface or when allocation logic requires it. For example, call + mfxSurfaceInterface::Release to release a surface obtained with the mfxFrameSurfaceInterface::Export function. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxSurfaceInterface* surface); + + /*! @brief + Returns current reference counter of exported surface. + + @param[in] surface Valid surface. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(struct mfxSurfaceInterface* surface, mfxU32* counter); + + /*! @brief + This function is only valuable for surfaces which were exported in sharing mode (without a copy). + Guarantees readiness of both the data (pixels) and any original mfxFrameSurface1 frame's meta information (for example corruption flags) after a function completes. + + Instead of MFXVideoCORE_SyncOperation, users may directly call the mfxSurfaceInterface::Synchronize function after the corresponding + Decode or VPP function calls (MFXVideoDECODE_DecodeFrameAsync or MFXVideoVPP_RunFrameVPPAsync). + The prerequisites to call the functions are: + + @li The main processing functions return MFX_ERR_NONE. + @li A valid surface object. + + @param[in] surface Valid surface. + @param[out] wait Wait time in milliseconds. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the surface is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Synchronize)(struct mfxSurfaceInterface* surface, mfxU32 wait); + + mfxHDL reserved[11]; +} mfxSurfaceInterface; +MFX_PACK_END() + +#endif + +#ifdef ONEVPL_EXPERIMENTAL +#define MFX_FRAMESURFACEINTERFACE_VERSION MFX_STRUCT_VERSION(1, 1) +#else +#define MFX_FRAMESURFACEINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) +#endif + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! Specifies frame surface interface. */ +typedef struct mfxFrameSurfaceInterface { + 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 reserved1[3]; + + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the mfxFrameSurfaceInterface::Release function. + mfxFrameSurfaceInterface::AddRef should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(mfxFrameSurface1* surface); + + /*! @brief + Decrements the internal reference counter of the surface. mfxFrameSurfaceInterface::Release should be called after using the + mfxFrameSurfaceInterface::AddRef function to add a surface or when allocation logic requires it. For example, call + mfxFrameSurfaceInterface::Release to release a surface obtained with the GetSurfaceForXXX function. + + @param[in] surface Valid surface. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(mfxFrameSurface1* surface); + + /*! @brief + Returns current reference counter of mfxFrameSurface1 structure. + + @param[in] surface Valid surface. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(mfxFrameSurface1* surface, mfxU32* counter); + + /*! @brief + Sets pointers of surface->Info.Data to actual pixel data, providing read-write access. + + In case of video memory, the surface with data in video memory becomes mapped to system memory. + An application can map a surface for read access with any value of mfxFrameSurface1::Data::Locked, but can map a surface for write access only when mfxFrameSurface1::Data::Locked equals to 0. + + Note: A surface allows shared read access, but exclusive write access. Consider the following cases: + @li Map with Write or Read|Write flags. A request during active another read or write access returns MFX_ERR_LOCK_MEMORY error immediately, without waiting. + MFX_MAP_NOWAIT does not impact behavior. This type of request does not lead to any implicit synchronizations. + @li Map with Read flag. A request during active write access will wait for resource to become free, + or exits immediately with error if MFX_MAP_NOWAIT flag was set. This request may lead to the implicit synchronization (with same logic as Synchronize call) + waiting for surface to become ready to use (all dependencies should be resolved and upstream components finished writing to this surface). + + It is guaranteed that read access will be acquired right after synchronization without allowing another thread to acquire this surface for writing. + + If MFX_MAP_NOWAIT was set and the surface is not ready yet (for example the surface has unresolved data dependencies or active processing), the read access request exits immediately with error. + + Read-write access with MFX_MAP_READ_WRITE provides exclusive simultaneous reading and writing access. + + @note Bitwise copying of mfxFrameSurface1 object between map / unmap calls may result in having dangling data pointers in copies. + + @param[in] surface Valid surface. + @param[out] flags Specify mapping mode. + @param[out] surface->Info.Data Pointers set to actual pixel data. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNSUPPORTED If flags are invalid. \n + MFX_ERR_LOCK_MEMORY If user wants to map the surface for write and surface->Data.Locked does not equal to 0. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Map)(mfxFrameSurface1* surface, mfxU32 flags); + + /*! @brief + Invalidates pointers of surface->Info.Data and sets them to NULL. + In case of video memory, the underlying texture becomes unmapped after last reader or writer unmap. + + + @param[in] surface Valid surface. + @param[out] surface->Info.Data Pointers set to NULL. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxFrameSurfaceInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNSUPPORTED If surface is already unmapped. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Unmap)(mfxFrameSurface1* surface); + + /*! @brief + Returns a native resource's handle and type. The handle is returned *as-is*, meaning that the reference counter of base resources is not incremented. + The native resource is not detached from surface and the library still owns the resource. User must not destroy + the native resource or assume that the resource will be alive after mfxFrameSurfaceInterface::Release. + + + + @param[in] surface Valid surface. + @param[out] resource Pointer is set to the native handle of the resource. + @param[out] resource_type Type of native resource. See mfxResourceType enumeration). + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If any of surface, resource or resource_type is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface, resource or resource_type is not valid object (no native resource was allocated). \n + MFX_ERR_UNSUPPORTED If surface is in system memory. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetNativeHandle)(mfxFrameSurface1* surface, mfxHDL* resource, mfxResourceType* resource_type); + + /*! @brief + Returns a device abstraction that was used to create that resource. + The handle is returned *as-is*, meaning that the reference counter for the device abstraction is not incremented. + The native resource is not detached from the surface and the library still has a reference to the resource. + User must not destroy the device or assume that the device will be alive after mfxFrameSurfaceInterface::Release. + + + @param[in] surface Valid surface. + @param[out] device_handle Pointer is set to the device which created the resource + @param[out] device_type Type of device (see mfxHandleType enumeration). + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If any of surface, device_handle or device_type is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface, resource or resource_type is not valid object (no native resource was allocated). \n + MFX_ERR_UNSUPPORTED If surface is in system memory. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetDeviceHandle)(mfxFrameSurface1* surface, mfxHDL* device_handle, mfxHandleType* device_type); + + /*! @brief + Guarantees readiness of both the data (pixels) and any frame's meta information (for example corruption flags) after a function completes. + + Instead of MFXVideoCORE_SyncOperation, users may directly call the mfxFrameSurfaceInterface::Synchronize function after the corresponding + Decode or VPP function calls (MFXVideoDECODE_DecodeFrameAsync or MFXVideoVPP_RunFrameVPPAsync). + The prerequisites to call the functions are: + + @li The main processing functions return MFX_ERR_NONE. + @li A valid mfxFrameSurface1 object. + + + + @param[in] surface Valid surface. + @param[out] wait Wait time in milliseconds. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If any of surface is not valid object . \n + MFX_WRN_IN_EXECUTION If the given timeout is expired and the surface is not ready. \n + MFX_ERR_ABORTED If the specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. \n + 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. + + @note The library calls this callback only when this surface is used as the output surface. + + 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); + + /*! @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); + +#ifdef ONEVPL_EXPERIMENTAL + /*! @brief + If successful returns an exported surface, which is a refcounted object allocated by runtime. It could be exported with or without copy, depending + on export flags and the possibility of such export. Exported surface is valid throughout the session, as long as the original mfxFrameSurface1 + object is not closed and the refcount of exported surface is not zero. + + @param[in] surface Valid surface. + @param[in] export_header Description of export: caller should fill in SurfaceType (type to export to) and SurfaceFlags (allowed export modes). + @param[out] exported_surface Exported surface, allocated by runtime, user needs to decrement refcount after usage for object release. + After successful export, the value of mfxSurfaceHeader::SurfaceFlags will contain the actual export mode. + + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If export surface or surface is NULL. \n + MFX_ERR_UNSUPPORTED If requested export is not supported. \n + MFX_ERR_NOT_IMPLEMENTED If requested export is not implemented. \n + MFX_ERR_UNKNOWN Any internal error. + */ + + /* For reference with Import flow please search for mfxMemoryInterface::ImportFrameSurface. */ + mfxStatus (MFX_CDECL *Export)(mfxFrameSurface1* surface, mfxSurfaceHeader export_header, mfxSurfaceHeader** exported_surface); + + mfxHDL reserved2[1]; +#else + mfxHDL reserved2[2]; +#endif +} mfxFrameSurfaceInterface; +MFX_PACK_END() + +/*! The TimeStampCalc enumerator itemizes time-stamp calculation methods. */ +enum { + /*! The time stamp calculation is based on the input frame rate if time stamp is not explicitly specified. */ + MFX_TIMESTAMPCALC_UNKNOWN = 0, + /*! Adjust time stamp to 29.97fps on 24fps progressively encoded sequences if telecine attributes are available in the bitstream and + time stamp is not explicitly specified. The input frame rate must be specified. */ + MFX_TIMESTAMPCALC_TELECINE = 1, +}; + +/* Transcoding Info */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies configurations for decoding, encoding, and transcoding processes. + A zero value in any of these fields indicates that the field is not explicitly specified. */ +typedef struct { + mfxU32 reserved[7]; /*!< Reserved for future use. */ + + /*! Hint to enable low power consumption mode for encoders. See the CodingOptionValue enumerator for values + of this option. Use the Query API function to check if this feature is supported. */ + mfxU16 LowPower; + /*! Specifies a multiplier for bitrate control parameters. Affects the following variables: InitialDelayInKB, BufferSizeInKB, + TargetKbps, MaxKbps, WinBRCMaxAvgKbps. If this value is not equal to zero, the encoder calculates BRC parameters as ``value * BRCParamMultiplier``. */ + mfxU16 BRCParamMultiplier; + + mfxFrameInfo FrameInfo; /*!< mfxFrameInfo structure that specifies frame parameters. */ + mfxU32 CodecId; /*!< Specifies the codec format identifier in the FourCC code; see the CodecFormatFourCC enumerator for details. + This is a mandated input parameter for the QueryIOSurf and Init API functions. */ + mfxU16 CodecProfile; /*!< Specifies the codec profile; see the CodecProfile enumerator for details. Specify the codec profile explicitly or the API functions will determine + the correct profile from other sources, such as resolution and bitrate. */ + mfxU16 CodecLevel; /*!< Codec level; see the CodecLevel enumerator for details. Specify the codec level explicitly or the functions will determine the correct level from other sources, + such as resolution and bitrate. */ + mfxU16 NumThread; + + union { + struct { /* Encoding Options */ + mfxU16 TargetUsage; /*!< Target usage model that guides the encoding process; see the TargetUsage enumerator for details. */ + + /*! Number of pictures within the current GOP (Group of Pictures); if GopPicSize = 0, then the GOP size is unspecified. If GopPicSize = 1, only I-frames are used. + The following pseudo-code that shows how the library uses this parameter: + @code + mfxU16 get_gop_sequence (...) { + pos=display_frame_order; + if (pos == 0) + return MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF; + + If (GopPicSize == 1) // Only I-frames + return MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; + + if (GopPicSize == 0) + frameInGOP = pos; //Unlimited GOP + else + frameInGOP = pos%GopPicSize; + + if (frameInGOP == 0) + return MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; + + if (GopRefDist == 1 || GopRefDist == 0) // Only I,P frames + return MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF; + + frameInPattern = (frameInGOP-1)%GopRefDist; + if (frameInPattern == GopRefDist - 1) + return MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF; + + return MFX_FRAMETYPE_B; + } + @endcode */ + mfxU16 GopPicSize; + /*! Distance between I- or P (or GPB) - key frames; if it is zero, the GOP structure is unspecified. Note: If GopRefDist = 1, + there are no regular B-frames used (only P or GPB); if mfxExtCodingOption3::GPB is ON, GPB frames (B without backward + references) are used instead of P. */ + mfxU16 GopRefDist; + /*! ORs of the GopOptFlag enumerator indicate the additional flags for the GOP specification. */ + mfxU16 GopOptFlag; + /*! For H.264, specifies IDR-frame interval in terms of I-frames. + For example: + @li If IdrInterval = 0, then every I-frame is an IDR-frame. + @li If IdrInterval = 1, then every other I-frame is an IDR-frame. + + For HEVC, if IdrInterval = 0, then only first I-frame is an IDR-frame. For example: + @li If IdrInterval = 1, then every I-frame is an IDR-frame. + @li If IdrInterval = 2, then every other I-frame is an IDR-frame. + + For MPEG2, IdrInterval defines sequence header interval in terms of I-frames. For example: + @li If IdrInterval = 0 (default), then the sequence header is inserted once at the beginning of the stream. + @li If IdrInterval = N, then the sequence header is inserted before every Nth I-frame. + + + If GopPicSize or GopRefDist is zero, IdrInterval is undefined. */ + mfxU16 IdrInterval; + + mfxU16 RateControlMethod; /*! Rate control method; see the RateControlMethod enumerator for details. */ + union { + /*! Initial size of the Video Buffering Verifier (VBV) buffer. + @note In this context, KB is 1000 bytes and Kbps is 1000 bps. */ + mfxU16 InitialDelayInKB; + /*! Quantization Parameter (QP) for I-frames for constant QP mode (CQP). Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPI range. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted QPI value = QPI - (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we minus (6*(10-8)=12) on our side and continue. + @note In av1 design, valid range is 0 to 255 inclusive, and if QPI=QPP=QPB=0, the encoder is in lossless mode. + @note In vp9 design, valid range is 1 to 255 inclusive, and zero QP that the default value is assigned by the library. + @note Default QPI value is implementation dependent and subject to change without additional notice in this document. */ + mfxU16 QPI; + mfxU16 Accuracy; /*!< Specifies accuracy range in the unit of tenth of percent. */ + }; + mfxU16 BufferSizeInKB; /*!< Represents the maximum possible size of any compressed frames. */ + union { + /*! Constant bitrate TargetKbps. Used to estimate the targeted frame size by dividing the frame rate by the bitrate. */ + mfxU16 TargetKbps; + /*! Quantization Parameter (QP) for P-frames for constant QP mode (CQP). Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPP might be clipped to supported QPI range. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted QPP value = QPP - (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we minus (6*(10-8)=12) on our side and continue. + @note In av1 design, valid range is 0 to 255 inclusive, and if QPI=QPP=QPB=0, the encoder is in lossless mode. + @note In vp9 design, valid range is 1 to 255 inclusive, and zero QP that the default value is assigned by the library. + @note Default QPP value is implementation dependent and subject to change without additional notice in this document. */ + mfxU16 QPP; + mfxU16 ICQQuality; /*!< Used by the Intelligent Constant Quality (ICQ) bitrate control algorithm. Values are in the 1 to 51 range, where 1 corresponds the best quality. */ + }; + union { + /*! The maximum bitrate at which the encoded data enters the Video Buffering Verifier (VBV) buffer. */ + mfxU16 MaxKbps; + /*! Quantization Parameter (QP) for B-frames for constant QP mode (CQP). Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPB range. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted QPB value = QPB - (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we minus (6*(10-8)=12) on our side and continue. + @note In av1 design, valid range is 0 to 255 inclusive, and if QPI=QPP=QPB=0, the encoder is in lossless mode. + @note Default QPB value is implementation dependent and subject to change without additional notice in this document. */ + mfxU16 QPB; + mfxU16 Convergence; /*!< Convergence period in the unit of 100 frames. */ + }; + + /*! Number of slices in each video frame. Each slice contains one or more macro-block rows. If NumSlice equals zero, the encoder may choose any slice partitioning + allowed by the codec standard. See also mfxExtCodingOption2::NumMbPerSlice. */ + mfxU16 NumSlice; + /*! Max number of all available reference frames (for AVC/HEVC, NumRefFrame defines DPB size). If NumRefFrame = 0, this parameter is not specified. + See also NumRefActiveP, NumRefActiveBL0, and NumRefActiveBL1 in the mfxExtCodingOption3 structure, which set a number of active references. */ + mfxU16 NumRefFrame; + /*! If not zero, specifies that ENCODE takes the input surfaces in the encoded order and uses explicit frame type control. + The application must still provide GopRefDist and mfxExtCodingOption2::BRefType so the library can pack headers and build reference + lists correctly. */ + mfxU16 EncodedOrder; + }; + struct { /* Decoding Options */ + /*! For AVC and HEVC, used to instruct the decoder to return output frames in the decoded order. Must be zero for all other decoders. + When enabled, correctness of mfxFrameData::TimeStamp and FrameOrder for output surface is not guaranteed, the application should ignore them. */ + mfxU16 DecodedOrder; + /*! Instructs DECODE to output extended picture structure values for additional display attributes. See the PicStruct description for details. */ + mfxU16 ExtendedPicStruct; + /*! Time stamp calculation method. See the TimeStampCalc description for details. */ + mfxU16 TimeStampCalc; + /*! Nonzero value indicates that slice groups are present in the bitstream. Used only by AVC decoder. */ + mfxU16 SliceGroupsPresent; + /*! Nonzero value specifies the maximum required size of the decoded picture buffer in frames for AVC and HEVC decoders. */ + mfxU16 MaxDecFrameBuffering; + /*! For decoders supporting dynamic resolution change (VP9), set this option to ON to allow MFXVideoDECODE_DecodeFrameAsync + 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 + 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). + 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 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 reserved2[4]; + }; + struct { /* JPEG Decoding Options */ + /*! Specify the chroma sampling format that has been used to encode a JPEG picture. See the ChromaFormat enumerator for details. */ + mfxU16 JPEGChromaFormat; + /*! Rotation option of the output JPEG picture. See the Rotation enumerator for details. */ + mfxU16 Rotation; + /*! Specify the color format that has been used to encode a JPEG picture. See the JPEGColorFormat enumerator for details. */ + mfxU16 JPEGColorFormat; + /*! Specify JPEG scan type for decoder. See the JPEGScanType enumerator for details. */ + mfxU16 InterleavedDec; + mfxU8 SamplingFactorH[4]; /*!< Horizontal sampling factor. */ + mfxU8 SamplingFactorV[4]; /*!< Vertical sampling factor. */ + mfxU16 reserved3[5]; + }; + struct { /* JPEG Encoding Options */ + /*! Specify interleaved or non-interleaved scans. If it is equal to MFX_SCANTYPE_INTERLEAVED then the image is encoded as interleaved, + all components are encoded in one scan. See the JPEG Scan Type enumerator for details. */ + mfxU16 Interleaved; + /*! Specifies the image quality if the application does not specified quantization table. + The value is from 1 to 100 inclusive. "100" is the best quality. */ + mfxU16 Quality; + /*! Specifies the number of MCU in the restart interval. "0" means no restart interval. */ + mfxU16 RestartInterval; + mfxU16 reserved5[10]; + }; + }; +} mfxInfoMFX; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Specifies configurations for video processing. A zero value in any of the fields indicates + that the corresponding field is not explicitly specified. */ +typedef struct { + mfxU32 reserved[8]; + mfxFrameInfo In; /*!< Input format for video processing. */ + mfxFrameInfo Out; /*!< Output format for video processing. */ +} mfxInfoVPP; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Configuration parameters for encoding, decoding, transcoding, and video processing. */ +typedef struct { + /*! Unique component ID that will be passed by the library to mfxFrameAllocRequest. Useful in pipelines where several + components of the same type share the same allocator. */ + mfxU32 AllocId; + mfxU32 reserved[2]; + mfxU16 reserved3; + /*! Specifies how many asynchronous operations an application performs before the application explicitly synchronizes the result. + If zero, the value is not specified. */ + mfxU16 AsyncDepth; + + union { + mfxInfoMFX mfx; /*!< Configurations related to encoding, decoding, and transcoding. See the definition of the mfxInfoMFX structure for details. */ + mfxInfoVPP vpp; /*!< Configurations related to video processing. See the definition of the mfxInfoVPP structure for details. */ + }; + /*! Specifies the content protection mechanism. See the Protected enumerator for a list of supported protection schemes. */ + mfxU16 Protected; + /*! Input and output memory access types for functions. See the enumerator IOPattern for details. + The Query API functions return the natively supported IOPattern if the Query input argument is NULL. + This parameter is a mandated input for QueryIOSurf and Init API functions. The output pattern must be specified for DECODE. + The input pattern must be specified for ENCODE. Both input and output pattern must be specified for VPP. */ + mfxU16 IOPattern; + mfxExtBuffer** ExtParam; /*!< Points to an array of pointers to the extra configuration structures. See the ExtendedBufferID enumerator + for a list of extended configurations. + The list of extended buffers should not contain duplicated entries, such as entries of the same type. + If the mfxVideoParam structure is used to query library capability, then the list of extended buffers attached to the input + and output mfxVideoParam structure should be equal, that is, it should contain the same number of extended + buffers of the same type. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + mfxU16 reserved2; +} mfxVideoParam; +MFX_PACK_END() + +/*! The IOPattern enumerator itemizes memory access patterns for API functions. Use bit-ORed values to specify an input access + pattern and an output access pattern. */ +enum { + MFX_IOPATTERN_IN_VIDEO_MEMORY = 0x01, /*!< Input to functions is a video memory surface. */ + MFX_IOPATTERN_IN_SYSTEM_MEMORY = 0x02, /*!< Input to functions is a linear buffer directly in system memory or in system memory through an external allocator. */ + MFX_IOPATTERN_OUT_VIDEO_MEMORY = 0x10, /*!< Output to functions is a video memory surface. */ + MFX_IOPATTERN_OUT_SYSTEM_MEMORY = 0x20 /*!< Output to functions is a linear buffer directly in system memory or in system memory through an external allocator. */ +}; + +/*! The CodecFormatFourCC enumerator itemizes codecs in the FourCC format. */ +enum { + MFX_CODEC_AVC =MFX_MAKEFOURCC('A','V','C',' '), /*!< AVC, H.264, or MPEG-4, part 10 codec. */ + MFX_CODEC_HEVC =MFX_MAKEFOURCC('H','E','V','C'), /*!< HEVC codec. */ + MFX_CODEC_MPEG2 =MFX_MAKEFOURCC('M','P','G','2'), /*!< MPEG-2 codec. */ + MFX_CODEC_VC1 =MFX_MAKEFOURCC('V','C','1',' '), /*!< VC-1 codec. */ + MFX_CODEC_CAPTURE =MFX_MAKEFOURCC('C','A','P','T'), /*!< */ + MFX_CODEC_VP9 =MFX_MAKEFOURCC('V','P','9',' '), /*!< VP9 codec. */ + MFX_CODEC_AV1 =MFX_MAKEFOURCC('A','V','1',' '), /*!< AV1 codec. */ + MFX_CODEC_VVC =MFX_MAKEFOURCC('V','V','C',' ') /*!< VVC codec. */ +}; + +/*! +The CodecProfile enumerator itemizes codec profiles for all codecs. +CodecLevel +*/ +enum { + MFX_PROFILE_UNKNOWN =0, /*!< Unspecified profile. */ + MFX_LEVEL_UNKNOWN =0, /*!< Unspecified level. */ + + /*! @{ */ + /* Combined with H.264 profile these flags impose additional constrains. See H.264 specification for the list of constrains. */ + MFX_PROFILE_AVC_CONSTRAINT_SET0 = (0x100 << 0), + MFX_PROFILE_AVC_CONSTRAINT_SET1 = (0x100 << 1), + MFX_PROFILE_AVC_CONSTRAINT_SET2 = (0x100 << 2), + MFX_PROFILE_AVC_CONSTRAINT_SET3 = (0x100 << 3), + MFX_PROFILE_AVC_CONSTRAINT_SET4 = (0x100 << 4), + MFX_PROFILE_AVC_CONSTRAINT_SET5 = (0x100 << 5), + /*! @} */ + + /*! @{ */ + /* H.264 Profiles. */ + MFX_PROFILE_AVC_BASELINE =66, + MFX_PROFILE_AVC_MAIN =77, + MFX_PROFILE_AVC_EXTENDED =88, + MFX_PROFILE_AVC_HIGH =100, + MFX_PROFILE_AVC_HIGH10 =110, + MFX_PROFILE_AVC_HIGH_422 =122, + MFX_PROFILE_AVC_CONSTRAINED_BASELINE =MFX_PROFILE_AVC_BASELINE + MFX_PROFILE_AVC_CONSTRAINT_SET1, + MFX_PROFILE_AVC_CONSTRAINED_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4 + + MFX_PROFILE_AVC_CONSTRAINT_SET5, + MFX_PROFILE_AVC_PROGRESSIVE_HIGH =MFX_PROFILE_AVC_HIGH + MFX_PROFILE_AVC_CONSTRAINT_SET4, + /*! @} */ + + /*! @{ */ + /* H.264 level 1-1.3 */ + MFX_LEVEL_AVC_1 =10, + MFX_LEVEL_AVC_1b =9, + MFX_LEVEL_AVC_11 =11, + MFX_LEVEL_AVC_12 =12, + MFX_LEVEL_AVC_13 =13, + /*! @} */ + /*! @{ */ + /* H.264 level 2-2.2 */ + MFX_LEVEL_AVC_2 =20, + MFX_LEVEL_AVC_21 =21, + MFX_LEVEL_AVC_22 =22, + /*! @} */ + /*! @{ */ + /* H.264 level 3-3.2 */ + MFX_LEVEL_AVC_3 =30, + MFX_LEVEL_AVC_31 =31, + MFX_LEVEL_AVC_32 =32, + /*! @} */ + /*! @{ */ + /* H.264 level 4-4.2 */ + MFX_LEVEL_AVC_4 =40, + MFX_LEVEL_AVC_41 =41, + MFX_LEVEL_AVC_42 =42, + /*! @} */ + /*! @{ */ + /* H.264 level 5-5.2 */ + MFX_LEVEL_AVC_5 =50, + MFX_LEVEL_AVC_51 =51, + MFX_LEVEL_AVC_52 =52, + /*! @} */ + /*! @{ */ + /* H.264 level 6-6.2 */ + MFX_LEVEL_AVC_6 =60, + MFX_LEVEL_AVC_61 =61, + MFX_LEVEL_AVC_62 =62, + /*! @} */ + + /*! @{ */ + /* MPEG2 Profiles. */ + MFX_PROFILE_MPEG2_SIMPLE =0x50, + MFX_PROFILE_MPEG2_MAIN =0x40, + MFX_PROFILE_MPEG2_HIGH =0x10, + /*! @} */ + + /*! @{ */ + /* MPEG2 Levels. */ + MFX_LEVEL_MPEG2_LOW =0xA, + MFX_LEVEL_MPEG2_MAIN =0x8, + MFX_LEVEL_MPEG2_HIGH =0x4, + MFX_LEVEL_MPEG2_HIGH1440 =0x6, + /*! @} */ + + /*! @{ */ + /* VC-1 Profiles. */ + MFX_PROFILE_VC1_SIMPLE =(0+1), + MFX_PROFILE_VC1_MAIN =(4+1), + MFX_PROFILE_VC1_ADVANCED =(12+1), + /*! @} */ + + /*! @{ */ + /* VC-1 Level Low (simple & main profiles) */ + MFX_LEVEL_VC1_LOW =(0+1), + MFX_LEVEL_VC1_MEDIAN =(2+1), + MFX_LEVEL_VC1_HIGH =(4+1), + /*! @} */ + + /*! @{ */ + /* VC-1 advanced profile levels */ + MFX_LEVEL_VC1_0 =(0x00+1), + MFX_LEVEL_VC1_1 =(0x01+1), + MFX_LEVEL_VC1_2 =(0x02+1), + MFX_LEVEL_VC1_3 =(0x03+1), + MFX_LEVEL_VC1_4 =(0x04+1), + /*! @} */ + + /*! @{ */ + /* HEVC profiles */ + MFX_PROFILE_HEVC_MAIN =1, + MFX_PROFILE_HEVC_MAIN10 =2, + MFX_PROFILE_HEVC_MAINSP =3, + MFX_PROFILE_HEVC_REXT =4, + MFX_PROFILE_HEVC_SCC =9, + /*! @} */ + + /*! @{ */ + /* HEVC levels */ + MFX_LEVEL_HEVC_1 = 10, + MFX_LEVEL_HEVC_2 = 20, + MFX_LEVEL_HEVC_21 = 21, + MFX_LEVEL_HEVC_3 = 30, + MFX_LEVEL_HEVC_31 = 31, + MFX_LEVEL_HEVC_4 = 40, + MFX_LEVEL_HEVC_41 = 41, + MFX_LEVEL_HEVC_5 = 50, + MFX_LEVEL_HEVC_51 = 51, + MFX_LEVEL_HEVC_52 = 52, + MFX_LEVEL_HEVC_6 = 60, + MFX_LEVEL_HEVC_61 = 61, + MFX_LEVEL_HEVC_62 = 62, + MFX_LEVEL_HEVC_85 = 85, + /*! @} */ + + /*! @{ */ + /* HEVC tiers */ + MFX_TIER_HEVC_MAIN = 0, + MFX_TIER_HEVC_HIGH = 0x100, + /*! @} */ + + /*! @{ */ + /* VP9 Profiles */ + MFX_PROFILE_VP9_0 = 1, + MFX_PROFILE_VP9_1 = 2, + MFX_PROFILE_VP9_2 = 3, + MFX_PROFILE_VP9_3 = 4, + /*! @} */ + + /*! @{ */ + /* AV1 Profiles */ + MFX_PROFILE_AV1_MAIN = 1, + MFX_PROFILE_AV1_HIGH = 2, + MFX_PROFILE_AV1_PRO = 3, + /*! @} */ + + /*! @{ */ + /* AV1 Levels */ + MFX_LEVEL_AV1_2 = 20, + MFX_LEVEL_AV1_21 = 21, + MFX_LEVEL_AV1_22 = 22, + MFX_LEVEL_AV1_23 = 23, + MFX_LEVEL_AV1_3 = 30, + MFX_LEVEL_AV1_31 = 31, + MFX_LEVEL_AV1_32 = 32, + MFX_LEVEL_AV1_33 = 33, + MFX_LEVEL_AV1_4 = 40, + MFX_LEVEL_AV1_41 = 41, + MFX_LEVEL_AV1_42 = 42, + MFX_LEVEL_AV1_43 = 43, + MFX_LEVEL_AV1_5 = 50, + MFX_LEVEL_AV1_51 = 51, + MFX_LEVEL_AV1_52 = 52, + MFX_LEVEL_AV1_53 = 53, + MFX_LEVEL_AV1_6 = 60, + MFX_LEVEL_AV1_61 = 61, + MFX_LEVEL_AV1_62 = 62, + MFX_LEVEL_AV1_63 = 63, + MFX_LEVEL_AV1_7 = 70, + MFX_LEVEL_AV1_71 = 71, + MFX_LEVEL_AV1_72 = 72, + MFX_LEVEL_AV1_73 = 73, + /*! @} */ + + /*! @{ */ + /* VVC Profiles */ + MFX_PROFILE_VVC_MAIN10 = 1, + MFX_PROFILE_VVC_MAIN10_STILL_PICTURE = 65, + /*! @} */ + + /*! @{ */ + /* VVC Levels */ + MFX_LEVEL_VVC_1 = 16, + MFX_LEVEL_VVC_2 = 32, + MFX_LEVEL_VVC_21 = 35, + MFX_LEVEL_VVC_3 = 48, + MFX_LEVEL_VVC_31 = 51, + MFX_LEVEL_VVC_4 = 64, + MFX_LEVEL_VVC_41 = 67, + MFX_LEVEL_VVC_5 = 80, + MFX_LEVEL_VVC_51 = 83, + MFX_LEVEL_VVC_52 = 86, + MFX_LEVEL_VVC_6 = 96, + MFX_LEVEL_VVC_61 = 99, + MFX_LEVEL_VVC_62 = 102, + MFX_LEVEL_VVC_63 = 105, + MFX_LEVEL_VVC_155 = 255, + /*! @} */ + + /*! @{ */ + /* VVC tiers */ + MFX_TIER_VVC_MAIN = 0, + MFX_TIER_VVC_HIGH = 0x100, + /*! @} */ +}; + +/*! The GopOptFlag enumerator itemizes special properties in the GOP (Group of Pictures) sequence. */ +enum { + /*! + The encoder generates closed GOP if this flag is set. Frames in this GOP do not use frames in previous GOP as reference. + + The encoder generates open GOP if this flag is not set. In this GOP frames prior to the first frame of GOP in display order may use + frames from previous GOP as reference. Frames subsequent to the first frame of GOP in display order do not use frames from previous + GOP as reference. + + The AVC encoder ignores this flag if IdrInterval in mfxInfoMFX structure is set to 0, i.e. if every GOP starts from IDR frame. + In this case, GOP is encoded as closed. + + This flag does not affect long-term reference frames. + */ + MFX_GOP_CLOSED =1, + /*! + The encoder must strictly follow the given GOP structure as defined by parameter GopPicSize, GopRefDist etc in the mfxVideoParam structure. + Otherwise, the encoder can adapt the GOP structure for better efficiency, whose range is constrained by parameter GopPicSize and + GopRefDist etc. See also description of AdaptiveI and AdaptiveB fields in the mfxExtCodingOption2 structure. + */ + MFX_GOP_STRICT =2 +}; + +/*! The TargetUsage enumerator itemizes a range of numbers from MFX_TARGETUSAGE_1, best quality, to MFX_TARGETUSAGE_7, best speed. + It indicates trade-offs between quality and speed. The application can use any number in the range. The actual number of supported + target usages depends on implementation. If specified target usage is not supported, the encoder will use the closest supported value. */ +enum { + MFX_TARGETUSAGE_1 =1, /*!< Best quality */ + MFX_TARGETUSAGE_2 =2, + MFX_TARGETUSAGE_3 =3, + MFX_TARGETUSAGE_4 =4, /*!< Balanced quality and speed. */ + MFX_TARGETUSAGE_5 =5, + MFX_TARGETUSAGE_6 =6, + MFX_TARGETUSAGE_7 =7, /*!< Best speed */ + + MFX_TARGETUSAGE_UNKNOWN =0, /*!< Unspecified target usage. */ + MFX_TARGETUSAGE_BEST_QUALITY =MFX_TARGETUSAGE_1, /*!< Best quality. */ + MFX_TARGETUSAGE_BALANCED =MFX_TARGETUSAGE_4, /*!< Balanced quality and speed. */ + MFX_TARGETUSAGE_BEST_SPEED =MFX_TARGETUSAGE_7 /*!< Best speed. */ +}; + +/*! The RateControlMethod enumerator itemizes bitrate control methods. */ +enum { + MFX_RATECONTROL_CBR =1, /*!< Use the constant bitrate control algorithm. */ + MFX_RATECONTROL_VBR =2, /*!< Use the variable bitrate control algorithm. */ + MFX_RATECONTROL_CQP =3, /*!< Use the constant quantization parameter algorithm. */ + MFX_RATECONTROL_AVBR =4, /*!< Use the average variable bitrate control algorithm. */ + MFX_RATECONTROL_RESERVED1 =5, + MFX_RATECONTROL_RESERVED2 =6, + MFX_RATECONTROL_RESERVED3 =100, + MFX_RATECONTROL_RESERVED4 =7, + /*! + Use the VBR algorithm with look ahead. It is a special bitrate control mode in the AVC encoder that has been designed + to improve encoding quality. It works by performing extensive analysis of several dozen frames before the actual encoding and as a side + effect significantly increases encoding delay and memory consumption. + + The only available rate control parameter in this mode is mfxInfoMFX::TargetKbps. Two other parameters, MaxKbps and InitialDelayInKB, + are ignored. To control LA depth the application can use mfxExtCodingOption2::LookAheadDepth parameter. + + This method is not HRD compliant. + */ + MFX_RATECONTROL_LA =8, + /*! + Use the Intelligent Constant Quality algorithm. This algorithm improves subjective video quality of encoded stream. Depending on content, + it may or may not decrease objective video quality. Only one control parameter is used - quality factor, specified by mfxInfoMFX::ICQQuality. + */ + MFX_RATECONTROL_ICQ =9, + /*! + Use the Video Conferencing Mode algorithm. This algorithm is similar to the VBR and uses the same set of parameters mfxInfoMFX::InitialDelayInKB, + TargetKbpsandMaxKbps. It is tuned for IPPP GOP pattern and streams with strong temporal correlation between frames. + It produces better objective and subjective video quality in these conditions than other bitrate control algorithms. + It does not support interlaced content, B-frames and produced stream is not HRD compliant. + */ + MFX_RATECONTROL_VCM =10, + /*! + Use Intelligent Constant Quality algorithm with look ahead. Quality factor is specified by mfxInfoMFX::ICQQuality. + To control LA depth the application can use mfxExtCodingOption2::LookAheadDepth parameter. + + This method is not HRD compliant. + */ + MFX_RATECONTROL_LA_ICQ =11, + /*! + MFX_RATECONTROL_LA_EXT has been removed + */ + + /*! Use HRD compliant look ahead rate control algorithm. */ + MFX_RATECONTROL_LA_HRD =13, + /*! + Use the variable bitrate control algorithm with constant quality. This algorithm trying to achieve the target subjective quality with + the minimum number of bits, while the bitrate constraint and HRD compliance are satisfied. It uses the same set of parameters + as VBR and quality factor specified by mfxExtCodingOption3::QVBRQuality. + */ + MFX_RATECONTROL_QVBR =14, +}; + +/*! + The TrellisControl enumerator is used to control trellis quantization in AVC encoder. The application can turn it on + or off for any combination of I-, P- and B-frames by combining different enumerator values. For example, MFX_TRELLIS_I | MFX_TRELLIS_B + turns it on for I- and B-frames. + + @note Due to performance reason on some target usages trellis quantization is always turned off and this control is ignored by the encoder. +*/ +enum { + MFX_TRELLIS_UNKNOWN =0, /*!< Default value, it is up to the encoder to turn trellis quantization on or off. */ + MFX_TRELLIS_OFF =0x01, /*!< Turn trellis quantization off for all frame types. */ + MFX_TRELLIS_I =0x02, /*!< Turn trellis quantization on for I-frames. */ + MFX_TRELLIS_P =0x04, /*!< Turn trellis quantization on for P-frames. */ + MFX_TRELLIS_B =0x08 /*!< Turn trellis quantization on for B-frames. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies additional options for encoding. + + The application can attach this extended buffer to the mfxVideoParam structure to configure initialization. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION. */ + + mfxU16 reserved1; + mfxU16 RateDistortionOpt; /*!< Set this flag if rate distortion optimization is needed. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 MECostType; /*!< Motion estimation cost type. This value is reserved and must be zero. */ + mfxU16 MESearchType; /*!< Motion estimation search algorithm. This value is reserved and must be zero. */ + mfxI16Pair MVSearchWindow; /*!< Rectangular size of the search window for motion estimation. This parameter is reserved and must be (0, 0). */ + MFX_DEPRECATED mfxU16 EndOfSequence; /* Deprecated */ + mfxU16 FramePicture; /*!< Set this flag to encode interlaced fields as interlaced frames. This flag does not affect progressive input frames. See the CodingOptionValue enumerator for values of this option. */ + + mfxU16 CAVLC; /*!< If set, CAVLC is used; if unset, CABAC is used for encoding. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 reserved2[2]; + /*! + Set this flag to insert the recovery point SEI message at the beginning of every intra refresh cycle. See the description of + IntRefType in mfxExtCodingOption2 structure for details on how to enable and configure intra refresh. + + If intra refresh is not enabled then this flag is ignored. + + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 RecoveryPointSEI; + /*! + Set this flag to instruct the MVC encoder to output each view in separate bitstream buffer. See the CodingOptionValue enumerator + for values of this option and the Multi-View Video Coding section for more details about usage of this flag. + */ + mfxU16 ViewOutput; + /*! + If this option is turned ON, then AVC encoder produces an HRD conformant bitstream. If it is turned OFF, then the AVC encoder may (but not necessarily) violate HRD conformance. That is, this option can force the encoder to produce an HRD conformant stream, but + cannot force it to produce a non-conformant stream. + + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 NalHrdConformance; + /*! + If set, encoder puts all SEI messages in the singe NAL unit. It includes messages provided by application and created + by encoder. It is a three-states option. See CodingOptionValue enumerator for values of this option. The three states are: + + @li UNKNOWN Put each SEI in its own NAL unit. + + @li ON Put all SEI messages in the same NAL unit. + + @li OFF The same as unknown. + */ + mfxU16 SingleSeiNalUnit; + /*! + If set and VBR rate control method is used, then VCL HRD parameters are written in bitstream with values identical to the values of the NAL HRD parameters. + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 VuiVclHrdParameters; + + mfxU16 RefPicListReordering; /*!< Set this flag to activate reference picture list reordering. This value is reserved and must be zero. */ + mfxU16 ResetRefList; /*!< Set this flag to reset the reference list to non-IDR I-frames of a GOP sequence. See the CodingOptionValue enumerator for values of this option. */ + /*! + Set this flag to write the reference picture marking repetition SEI message into the output bitstream. + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 RefPicMarkRep; + /*! + Set this flag to instruct the AVC encoder to output bitstreams immediately after the encoder encodes a field, + in the field-encoding mode. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 FieldOutput; + + mfxU16 IntraPredBlockSize; /*!< Minimum block size of intra-prediction. This value is reserved and must be zero. */ + mfxU16 InterPredBlockSize; /*!< Minimum block size of inter-prediction. This value is reserved and must be zero. */ + mfxU16 MVPrecision; /*!< Specify the motion estimation precision. This parameter is reserved and must be zero. */ + mfxU16 MaxDecFrameBuffering; /*!< Specifies the maximum number of frames buffered in a DPB. A value of zero means unspecified. */ + + mfxU16 AUDelimiter; /*!< Set this flag to insert the Access Unit Delimiter NAL. See the CodingOptionValue enumerator for values of this option. */ + MFX_DEPRECATED mfxU16 EndOfStream; /* Deprecated */ + /*! + Set this flag to insert the picture timing SEI with pic_struct syntax element. See sub-clauses D.1.2 and D.2.2 of the ISO/IEC 14496-10 + specification for the definition of this syntax element. See the CodingOptionValue enumerator for values of this option. + The default value is ON. + */ + mfxU16 PicTimingSEI; + mfxU16 VuiNalHrdParameters; /*!< Set this flag to insert NAL HRD parameters in the VUI header. See the CodingOptionValue enumerator for values of this option. */ +} mfxExtCodingOption; +MFX_PACK_END() + +/*! The BRefControl enumerator is used to control usage of B-frames as reference in AVC encoder. */ +enum { + MFX_B_REF_UNKNOWN = 0, /*!< Default value, it is up to the encoder to use B-frames as reference. */ + MFX_B_REF_OFF = 1, /*!< Do not use B-frames as reference. */ + MFX_B_REF_PYRAMID = 2 /*!< Arrange B-frames in so-called "B pyramid" reference structure. */ +}; + +/*! The LookAheadDownSampling enumerator is used to control down sampling in look ahead bitrate control mode in AVC encoder. */ +enum { + MFX_LOOKAHEAD_DS_UNKNOWN = 0, /*!< Default value, it is up to the encoder what down sampling value to use. */ + MFX_LOOKAHEAD_DS_OFF = 1, /*!< Do not use down sampling, perform estimation on original size frames. This is the slowest setting that produces the best quality. */ + MFX_LOOKAHEAD_DS_2x = 2, /*!< Down sample frames two times before estimation. */ + MFX_LOOKAHEAD_DS_4x = 3 /*!< Down sample frames four times before estimation. This option may significantly degrade quality. */ +}; + +/*! The BPSEIControl enumerator is used to control insertion of buffering period SEI in the encoded bitstream. */ +enum { + MFX_BPSEI_DEFAULT = 0x00, /*!< encoder decides when to insert BP SEI. */ + MFX_BPSEI_IFRAME = 0x01 /*!< BP SEI should be inserted with every I-frame */ +}; + +/*! The SkipFrame enumerator is used to define usage of mfxEncodeCtrl::SkipFrame parameter. */ +enum { + MFX_SKIPFRAME_NO_SKIP = 0, /*!< Frame skipping is disabled, mfxEncodeCtrl::SkipFrame is ignored. */ + MFX_SKIPFRAME_INSERT_DUMMY = 1, /*!< Skipping is allowed, when mfxEncodeCtrl::SkipFrame is set encoder inserts into bitstream frame + where all macroblocks are encoded as skipped. Only non-reference P- and B-frames can be skipped. + If GopRefDist = 1 and mfxEncodeCtrl::SkipFrame is set for reference P-frame, it will be encoded + as non-reference. */ + MFX_SKIPFRAME_INSERT_NOTHING = 2, /*!< Similar to MFX_SKIPFRAME_INSERT_DUMMY, but when mfxEncodeCtrl::SkipFrame is set encoder inserts nothing into bitstream. */ + MFX_SKIPFRAME_BRC_ONLY = 3, /*!< mfxEncodeCtrl::SkipFrame indicates number of missed frames before the current frame. Affects only BRC, current frame will be encoded as usual. */ +}; + +/*! The IntraRefreshTypes enumerator itemizes types of intra refresh. */ +enum { + MFX_REFRESH_NO = 0, /*!< Encode without refresh. */ + MFX_REFRESH_VERTICAL = 1, /*!< Vertical refresh, by column of MBs. */ + MFX_REFRESH_HORIZONTAL = 2, /*!< Horizontal refresh, by rows of MBs. */ + MFX_REFRESH_SLICE = 3 /*!< Horizontal refresh by slices without overlapping. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used with the mfxExtCodingOption structure to specify additional options for encoding. + + The application can attach this extended buffer to the mfxVideoParam structure to configure initialization and to the mfxEncodeCtrl during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION2. */ + + /*! + Specifies intra refresh type. See the IntraRefreshTypes. The major goal of intra refresh is improvement of error resilience without + significant impact on encoded bitstream size caused by I-frames. The encoder achieves this by encoding part of each frame in the refresh + cycle using intra MBs. + + This parameter is valid during initialization and + runtime. When used with temporal scalability, intra refresh applied only to base layer. + + MFX_REFRESH_NO No refresh. + + MFX_REFRESH_VERTICAL Vertical refresh, by column of MBs. + + MFX_REFRESH_HORIZONTAL Horizontal refresh, by rows of MBs. + + MFX_REFRESH_SLICE Horizontal refresh by slices without overlapping. + + MFX_REFRESH_SLICE Library ignores IntRefCycleSize (size of refresh cycle equals number slices). + */ + mfxU16 IntRefType; + /*! + Specifies number of pictures within refresh cycle starting from 2. 0 and 1 are invalid values. This parameter is valid only during initialization. + */ + mfxU16 IntRefCycleSize; + /*! + Specifies QP difference for inserted intra MBs. Signed values are in the -51 to 51 range. This parameter is valid during initialization and runtime. + */ + mfxI16 IntRefQPDelta; + + /*! + Specify maximum encoded frame size in byte. This parameter is used in VBR based bitrate control modes and ignored in others. + The encoder tries to keep frame size below specified limit but minor overshoots are possible to preserve visual quality. + This parameter is valid during initialization and runtime. It is recommended to set MaxFrameSize to 5x-10x target frame size + ((TargetKbps*1000)/(8* FrameRateExtN/FrameRateExtD)) for I-frames and 2x-4x target frame size for P- and B-frames. + */ + mfxU32 MaxFrameSize; + /*! + Specify maximum slice size in bytes. If this parameter is specified other controls over number of slices are ignored. + + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU32 MaxSliceSize; + + /*! + Modifies bitrate to be in the range imposed by the encoder. The default value is ON, that is, bitrate is limited. Setting this flag to OFF may lead to violation of HRD conformance.Specifying bitrate below the encoder range might significantly affect quality. + + If set to ON, this option takes effect in non CQP modes: + if TargetKbps is not in the range imposed by the encoder, it will be changed to be in the range. + + This parameter is valid only during initialization. Flag works with MFX_CODEC_AVC only, it is ignored with other codecs. + See the CodingOptionValue + enumerator for values of this option. + + @deprecated Deprecated in API version 2.9 + */ + MFX_DEPRECATED mfxU16 BitrateLimit; /* Deprecated */ + /*! + Setting this flag enables macroblock level bitrate control that generally improves subjective visual quality. Enabling this flag may + have negative impact on performance and objective visual quality metric. See the CodingOptionValue enumerator for values of this option. + The default value depends on target usage settings. + */ + mfxU16 MBBRC; + /*! + Set this option to ON to enable external BRC. See the CodingOptionValue enumerator for values of this option. + Use the Query API function to check if this feature is supported. + */ + mfxU16 ExtBRC; + /*! + Specifies the depth of the look ahead rate control algorithm. The depth value is the number of frames that the encoder analyzes before encoding. Values are in the 10 to 100 range, inclusive. + To instruct the encoder to use the default value the application should zero this field. + */ + mfxU16 LookAheadDepth; + /*! + Used to control trellis quantization in AVC encoder. See TrellisControl enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 Trellis; + /*! + Controls picture parameter set repetition in AVC encoder. Set this flag to ON to repeat PPS with each frame. + See the CodingOptionValue enumerator for values of this option. The default value is ON. This parameter is valid only during initialization. + */ + mfxU16 RepeatPPS; + /*! + Controls usage of B-frames as reference. See BRefControl enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 BRefType; + /*! + Controls insertion of I-frames by the encoder. Set this flag to ON to allow changing of frame type from P and B to I. + This option is ignored if GopOptFlag in mfxInfoMFX structure is equal to MFX_GOP_STRICT. See the CodingOptionValue enumerator + for values of this option. This parameter is valid only during initialization. + */ + mfxU16 AdaptiveI; + /*! + Controls changing of frame type from B to P. Set this flag to ON enable changing of frame type from B to P. This option is ignored if + GopOptFlag in mfxInfoMFX structure is equal to MFX_GOP_STRICT. See the CodingOptionValue enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 AdaptiveB; + /*! + Controls down sampling in look ahead bitrate control mode. See LookAheadDownSampling enumerator for values + of this option. This parameter is valid only during initialization. + */ + mfxU16 LookAheadDS; + /*! + Specifies suggested slice size in number of macroblocks. The library can adjust this number based on platform capability. + If this option is specified, that is, if it is not equal to zero, the library ignores mfxInfoMFX::NumSlice parameter. + */ + mfxU16 NumMbPerSlice; + /*! + Enables usage of mfxEncodeCtrl::SkipFrame parameter. See the SkipFrame enumerator for values of this option. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 SkipFrame; + mfxU8 MinQPI; /*!< Minimum allowed QP value for I-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MaxQPI; /*!< Maximum allowed QP value for I-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted MaxQPI value = 51 + (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we add (6*(10-8)=12) on our side for MaxQPI will reach 63. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MinQPP; /*!< Minimum allowed QP value for P-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MaxQPP; /*!< Maximum allowed QP value for P-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted MaxQPP value = 51 + (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we add (6*(10-8)=12) on our side for MaxQPP will reach 63. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MinQPB; /*!< Minimum allowed QP value for B-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU8 MaxQPB; /*!< Maximum allowed QP value for B-frame types. Valid range varies with the codec. Zero means default value, that is, no limitations on QP. + @note In the HEVC design, a further adjustment to QPs can occur based on bit depth. + Adjusted MaxQPB value = 51 + (6 * (BitDepthLuma - 8)) for BitDepthLuma in the range [8,14]. + For HEVC_MAIN10, we add (6*(10-8)=12) on our side for MaxQPB will reach 63. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + /*! + Sets fixed_frame_rate_flag in VUI. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 FixedFrameRate; + /*! Disables deblocking. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 DisableDeblockingIdc; + /*! + Completely disables VUI in the output bitstream. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 DisableVUI; + /*! + Controls insertion of buffering period SEI in the encoded bitstream. It should be one of the following values: + + MFX_BPSEI_DEFAULT Encoder decides when to insert BP SEI, + + MFX_BPSEI_IFRAME BP SEI should be inserted with every I-frame. + */ + mfxU16 BufferingPeriodSEI; + /*! + Set this flag to ON to enable per-frame reporting of Mean Absolute Difference. This parameter is valid only during initialization. + */ + mfxU16 EnableMAD; + /*! + Set this flag to ON to use raw frames for reference instead of reconstructed frames. This parameter is valid during + initialization and runtime (only if was turned ON during initialization). + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 UseRawRef; +} mfxExtCodingOption2; +MFX_PACK_END() + +/*! The WeightedPred enumerator itemizes weighted prediction modes. */ +enum { + MFX_WEIGHTED_PRED_UNKNOWN = 0, /*!< Allow encoder to decide. */ + MFX_WEIGHTED_PRED_DEFAULT = 1, /*!< Use default weighted prediction. */ + MFX_WEIGHTED_PRED_EXPLICIT = 2, /*!< Use explicit weighted prediction. */ + MFX_WEIGHTED_PRED_IMPLICIT = 3 /*!< Use implicit weighted prediction (for B-frames only). */ +}; + +/*! The ScenarioInfo enumerator itemizes scenarios for the encoding session. */ +enum { + MFX_SCENARIO_UNKNOWN = 0, + MFX_SCENARIO_DISPLAY_REMOTING = 1, + MFX_SCENARIO_VIDEO_CONFERENCE = 2, + MFX_SCENARIO_ARCHIVE = 3, + MFX_SCENARIO_LIVE_STREAMING = 4, + MFX_SCENARIO_CAMERA_CAPTURE = 5, + MFX_SCENARIO_VIDEO_SURVEILLANCE = 6, + MFX_SCENARIO_GAME_STREAMING = 7, + MFX_SCENARIO_REMOTE_GAMING = 8 +}; + +/*! The ContentInfo enumerator itemizes content types for the encoding session. */ +enum { + MFX_CONTENT_UNKNOWN = 0, + MFX_CONTENT_FULL_SCREEN_VIDEO = 1, + MFX_CONTENT_NON_VIDEO_SCREEN = 2, + MFX_CONTENT_NOISY_VIDEO = 3 +}; + +/*! The PRefType enumerator itemizes models of reference list construction and DPB management when GopRefDist=1. */ +enum { + MFX_P_REF_DEFAULT = 0, /*!< Allow encoder to decide. */ + MFX_P_REF_SIMPLE = 1, /*!< Regular sliding window used for DPB removal process. */ + MFX_P_REF_PYRAMID = 2 /*!< Let N be the max reference list's size. Encoder treats each N's frame as a 'strong' + reference and the others as 'weak' references. The encoder uses a 'weak' reference only for + prediction of the next frame and removes it from DPB immediately after use. 'Strong' references are removed from + DPB by a sliding window. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used with mfxExtCodingOption and mfxExtCodingOption2 structures to specify additional options for encoding. + The application can attach this extended buffer to the mfxVideoParam structure to configure initialization and to the mfxEncodeCtrl during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION3. */ + + mfxU16 NumSliceI; /*!< The number of slices for I-frames. + @note Not all codecs and implementations support these values. Use the Query API function to check if this feature is supported */ + mfxU16 NumSliceP; /*!< The number of slices for P-frames. + @note Not all codecs and implementations support these values. Use the Query API function to check if this feature is supported */ + mfxU16 NumSliceB; /*!< The number of slices for B-frames. + @note Not all codecs and implementations support these values. Use the Query API function to check if this feature is supported */ + + /*! + When rate control method is MFX_RATECONTROL_CBR, MFX_RATECONTROL_VBR, MFX_RATECONTROL_LA, MFX_RATECONTROL_LA_HRD, or MFX_RATECONTROL_QVBR + this parameter specifies the maximum bitrate averaged over a sliding window specified by WinBRCSize. + */ + mfxU16 WinBRCMaxAvgKbps; + /*! + When rate control method is MFX_RATECONTROL_CBR, MFX_RATECONTROL_VBR, MFX_RATECONTROL_LA, MFX_RATECONTROL_LA_HRD, or MFX_RATECONTROL_QVBR + this parameter specifies sliding window size in frames. Set WinBRCMaxAvgKbps and WinBRCSize to zero to disable sliding window. + */ + 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. + */ + mfxU16 QVBRQuality; + /*! + Set this flag to ON to enable per-macroblock QP control. Rate control method must be MFX_RATECONTROL_CQP. See the CodingOptionValue + enumerator for values of this option. This parameter is valid only during initialization. + */ + mfxU16 EnableMBQP; + /*! + Distance between the beginnings of the intra-refresh cycles in frames. Zero means no distance between cycles. + */ + mfxU16 IntRefCycleDist; + /*! + Set this flag to ON to enable the ENC mode decision algorithm to bias to fewer B Direct/Skip types. Applies only to B-frames, + all other frames will ignore this setting. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 DirectBiasAdjustment; + /*! + Enables global motion bias. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 GlobalMotionBiasAdjustment; + /*! + Values are: + + @li 0: Set MV cost to be 0. + + @li 1: Scale MV cost to be 1/2 of the default value. + + @li 2: Scale MV cost to be 1/4 of the default value. + + @li 3: Scale MV cost to be 1/8 of the default value. + */ + mfxU16 MVCostScalingFactor; + /*! + Set this flag to ON to enable usage of mfxExtMBDisableSkipMap. See the CodingOptionValue enumerator for values of this option. + This parameter is valid only during initialization. + */ + mfxU16 MBDisableSkipMap; + + mfxU16 WeightedPred; /*!< Weighted prediction mode. See the WeightedPred enumerator for values of these options. */ + mfxU16 WeightedBiPred; /*!< Weighted prediction mode. See the WeightedPred enumerator for values of these options. */ + + /*! + Instructs encoder whether aspect ratio info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 AspectRatioInfoPresent; + /*! + Instructs encoder whether overscan info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 OverscanInfoPresent; + /*! + ON indicates that the cropped decoded pictures output are suitable for display using overscan. OFF indicates that the cropped decoded + pictures output contain visually important information in the entire region out to the edges of the cropping rectangle of the picture. + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 OverscanAppropriate; + /*! + Instructs encoder whether frame rate info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 TimingInfoPresent; + /*! + Instructs encoder whether bitstream restriction info should present in VUI parameters. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 BitstreamRestriction; + /*! + Corresponds to AVC syntax element low_delay_hrd_flag (VUI). See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 LowDelayHrd; + /*! + When set to OFF, no sample outside the picture boundaries and no sample at a fractional sample position for which the sample value + is derived using one or more samples outside the picture boundaries is used for inter prediction of any sample. + + When set to ON, one or more samples outside picture boundaries may be used in inter prediction. + + See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 MotionVectorsOverPicBoundaries; + mfxU16 reserved1[2]; + + mfxU16 ScenarioInfo; /*!< Provides a hint to encoder about the scenario for the encoding session. See the ScenarioInfo enumerator for values of this option. */ + mfxU16 ContentInfo; /*!< Provides a hint to encoder about the content for the encoding session. See the ContentInfo enumerator for values of this option. */ + + mfxU16 PRefType; /*!< When GopRefDist=1, specifies the model of reference list construction and DPB management. See the PRefType enumerator for values of this option. */ + /*! + Instructs encoder whether internal fade detection algorithm should be used for calculation of weigh/offset values for pred_weight_table + unless application provided mfxExtPredWeightTable for this frame. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 FadeDetection; + mfxU16 reserved2[2]; + /*! + Set this flag to OFF to make HEVC encoder use regular P-frames instead of GPB. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 GPB; + + /*! + Same as mfxExtCodingOption2::MaxFrameSize but affects only I-frames. MaxFrameSizeI must be set if MaxFrameSizeP is set. + If MaxFrameSizeI is not specified or greater than spec limitation, spec limitation will be applied to the sizes of I-frames. + */ + mfxU32 MaxFrameSizeI; + /*! + Same as mfxExtCodingOption2::MaxFrameSize but affects only P/B-frames. If MaxFrameSizeP equals 0, the library sets MaxFrameSizeP + equal to MaxFrameSizeI. If MaxFrameSizeP is not specified or greater than spec limitation, spec limitation will be applied to the + sizes of P/B-frames. + */ + mfxU32 MaxFrameSizeP; + mfxU32 reserved3[3]; + + /*! + Enables QPOffset control. See the CodingOptionValue enumerator for values of this option. + */ + mfxU16 EnableQPOffset; + /*! + Specifies QP offset per pyramid layer when EnableQPOffset is set to ON and RateControlMethod is CQP. + + For B-pyramid, B-frame QP = QPB + QPOffset[layer]. + + For P-pyramid, P-frame QP = QPP + QPOffset[layer]. + */ + mfxI16 QPOffset[8]; /* FrameQP = QPX + QPOffset[pyramid_layer]; QPX = QPB for B-pyramid, QPP for P-pyramid */ + + + mfxU16 NumRefActiveP[8]; /*!< Max number of active references for P-frames. Array index is pyramid layer. */ + mfxU16 NumRefActiveBL0[8]; /*!< Max number of active references for B-frames in reference picture list 0. Array index is pyramid layer. */ + mfxU16 NumRefActiveBL1[8]; /*!< Max number of active references for B-frames in reference picture list 1. Array index is pyramid layer. */ + + mfxU16 reserved6; + /*! + For HEVC if this option is turned ON, the transform_skip_enabled_flag will be set to 1 in PPS. OFF specifies that transform_skip_enabled_flag will be set to 0. + */ + mfxU16 TransformSkip; + /*! + Minus 1 specifies target encoding chroma format (see ChromaFormatIdc enumerator). May differ from the source format. + TargetChromaFormatPlus1 = 0 specifies the default target chroma format which is equal to source (mfxVideoParam::mfx::FrameInfo::ChromaFormat + 1), + except RGB4 source format. In case of RGB4 source format default target , chroma format is 4:2:0 (instead of 4:4:4) + for the purpose of backward compatibility. + */ + mfxU16 TargetChromaFormatPlus1; + /*! + Target encoding bit-depth for luma samples. May differ from source bit-depth. 0 specifies a default target bit-depth that is equal to + source (mfxVideoParam::mfx::FrameInfo::BitDepthLuma). + */ + mfxU16 TargetBitDepthLuma; + /*! + Target encoding bit-depth for chroma samples. May differ from source bit-depth. 0 specifies a default target bit-depth that is equal to + source (mfxVideoParam::mfx::FrameInfo::BitDepthChroma). + */ + mfxU16 TargetBitDepthChroma; + mfxU16 BRCPanicMode; /*!< Controls panic mode in AVC and MPEG2 encoders. */ + + /*! + When rate control method is MFX_RATECONTROL_VBR, MFX_RATECONTROL_QVBR or MFX_RATECONTROL_VCM this parameter specifies frame size + tolerance. Set this parameter to MFX_CODINGOPTION_ON to allow strictly obey average frame size set by MaxKbps, for example cases when + MaxFrameSize == (MaxKbps*1000)/(8* FrameRateExtN/FrameRateExtD). Also MaxFrameSizeI and MaxFrameSizeP can be set separately. + */ + mfxU16 LowDelayBRC; + /*! + Set this flag to ON to enable usage of mfxExtMBForceIntra for AVC encoder. See the CodingOptionValue enumerator + for values of this option. This parameter is valid only during initialization. + */ + mfxU16 EnableMBForceIntra; + /*! + If this flag is set to ON, BRC may decide a larger P- or B-frame size than what MaxFrameSizeP dictates when the scene change is detected. + It may benefit the video quality. AdaptiveMaxFrameSize feature is not supported with LowPower ON or if the value of MaxFrameSizeP = 0. + */ + mfxU16 AdaptiveMaxFrameSize; + + /*! + Controls AVC encoder attempts to predict from small partitions. Default value allows encoder to choose preferred mode. + MFX_CODINGOPTION_ON forces encoder to favor quality and MFX_CODINGOPTION_OFF forces encoder to favor performance. + */ + mfxU16 RepartitionCheckEnable; + mfxU16 reserved5[3]; + mfxU16 EncodedUnitsInfo; /*!< Set this flag to ON to make encoded units info available in mfxExtEncodedUnitsInfo. */ + /*! + If this flag is set to ON, the HEVC encoder uses the NAL unit type provided by the application in the mfxEncodeCtrl::MfxNalUnitType field. + This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 EnableNalUnitType; + + union { + MFX_DEPRECATED 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. + Their number and definitions are API implementation specific. + If this flag is set to OFF, default quantization matrix is used for all frames. + This parameter is valid only during initialization. + */ + mfxU16 AdaptiveCQM; + /*! + If this flag is set to ON, encoder adaptively selects list of reference frames to improve 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() + +/*! IntraPredBlockSize/InterPredBlockSize specifies the minimum block size of inter-prediction. */ +enum { + MFX_BLOCKSIZE_UNKNOWN = 0, /*!< Unspecified. */ + MFX_BLOCKSIZE_MIN_16X16 = 1, /*!< 16x16 minimum block size. */ + MFX_BLOCKSIZE_MIN_8X8 = 2, /*!< 8x8 minimum block size. May be 16x16 or 8x8. */ + MFX_BLOCKSIZE_MIN_4X4 = 3 /*!< 4x4 minimum block size. May be 16x16, 8x8, or 4x4. */ +}; + +/*! The MVPrecision enumerator specifies the motion estimation precision. */ +enum { + MFX_MVPRECISION_UNKNOWN = 0, + MFX_MVPRECISION_INTEGER = (1 << 0), + MFX_MVPRECISION_HALFPEL = (1 << 1), + MFX_MVPRECISION_QUARTERPEL = (1 << 2) +}; + +/*! The CodingOptionValue enumerator defines a three-state coding option setting. */ +enum { + MFX_CODINGOPTION_UNKNOWN =0, /*!< Unspecified. */ + MFX_CODINGOPTION_ON =0x10, /*!< Coding option set. */ + MFX_CODINGOPTION_OFF =0x20, /*!< Coding option not set. */ + MFX_CODINGOPTION_ADAPTIVE =0x30 /*!< Reserved. */ +}; + +/*! The BitstreamDataFlag enumerator uses bit-ORed values to itemize additional information about the bitstream buffer. */ +enum { + MFX_BITSTREAM_NO_FLAG = 0x0000, /*!< The bitstream doesn't contain any flags. */ + /*! + The bitstream buffer contains a complete frame or complementary field pair of data for the bitstream. For decoding, this means + that the decoder can proceed with this buffer without waiting for the start of the next frame, which effectively reduces decoding latency. + If this flag is set, but the bitstream buffer contains incomplete frame or pair of field, then decoder will produce corrupted output. + */ + MFX_BITSTREAM_COMPLETE_FRAME = 0x0001, + /*! + The bitstream buffer contains the end of the stream. For decoding, + this means that the application does not have any additional bitstream data to send to decoder. + */ + MFX_BITSTREAM_EOS = 0x0002 +}; +/*! The ExtendedBufferID enumerator itemizes and defines identifiers (BufferId) for extended buffers or video processing algorithm identifiers. */ +enum { + /*! + This extended buffer defines additional encoding controls. See the mfxExtCodingOption structure for details. + The application can attach this buffer to the structure for encoding initialization. + */ + MFX_EXTBUFF_CODING_OPTION = MFX_MAKEFOURCC('C','D','O','P'), + /*! + This extended buffer defines sequence header and picture header for encoders and decoders. See the mfxExtCodingOptionSPSPPS + structure for details. The application can attach this buffer to the mfxVideoParam structure for encoding initialization, + and for obtaining raw headers from the decoders and encoders. + */ + MFX_EXTBUFF_CODING_OPTION_SPSPPS = MFX_MAKEFOURCC('C','O','S','P'), + /*! + This extended buffer defines a list of VPP algorithms that applications should not use. See the mfxExtVPPDoNotUse structure + for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DONOTUSE = MFX_MAKEFOURCC('N','U','S','E'), + /*! + This extended buffer defines auxiliary information at the VPP output. See the mfxExtVppAuxData structure for details. The application + can attach this buffer to the mfxEncodeCtrl structure for per-frame encoding control. + */ + MFX_EXTBUFF_VPP_AUXDATA = MFX_MAKEFOURCC('A','U','X','D'), + /*! + The extended buffer defines control parameters for the VPP denoise filter algorithm. See the mfxExtVPPDenoise2 structure for details. + The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DENOISE2 = MFX_MAKEFOURCC('D','N','I','2'), + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_EXTBUFF_VPP_DENOISE) = MFX_MAKEFOURCC('D','N','I','S'), /*!< Deprecated in 2.2 API version.*/ + MFX_EXTBUFF_VPP_SCENE_ANALYSIS = MFX_MAKEFOURCC('S','C','L','Y'), /*!< Reserved for future use. */ + MFX_DEPRECATED_ENUM_FIELD_INSIDE(MFX_EXTBUFF_VPP_SCENE_CHANGE) = MFX_EXTBUFF_VPP_SCENE_ANALYSIS, /* Deprecated. */ + /*! + The extended buffer defines control parameters for the VPP ProcAmp filter algorithm. See the mfxExtVPPProcAmp structure for details. + The application can attach this buffer to the mfxVideoParam structure for video processing initialization or to the mfxFrameData + structure in the mfxFrameSurface1 structure of output surface for per-frame processing configuration. + */ + MFX_EXTBUFF_VPP_PROCAMP = MFX_MAKEFOURCC('P','A','M','P'), + /*! + The extended buffer defines control parameters for the VPP detail filter algorithm. See the mfxExtVPPDetail structure for details. + The application can attach this buffer to the structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DETAIL = MFX_MAKEFOURCC('D','E','T',' '), + /*! + This extended buffer defines video signal type. See the mfxExtVideoSignalInfo structure for details. The application can attach this + buffer to the mfxVideoParam structure for encoding initialization, and for retrieving such information from the decoders. If video + signal info changes per frame, the application can attach this buffer to the mfxFrameData structure for video processing. + */ + MFX_EXTBUFF_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','S','I','N'), + /*! + This extended buffer defines video signal type. See the mfxExtVideoSignalInfo structure for details. The application can attach this + buffer to the mfxVideoParam structure for the input of video processing if the input video signal information changes in sequence + base. + */ + MFX_EXTBUFF_VIDEO_SIGNAL_INFO_IN = MFX_MAKEFOURCC('V','S','I','I'), + /*! + This extended buffer defines video signal type. See the mfxExtVideoSignalInfo structure for details. The application can attach this + buffer to the mfxVideoParam structure for the output of video processing if the output video signal information changes in sequence + base. + */ + MFX_EXTBUFF_VIDEO_SIGNAL_INFO_OUT = MFX_MAKEFOURCC('V','S','I','O'), + /*! + This extended buffer defines a list of VPP algorithms that applications should use. See the mfxExtVPPDoUse structure for details. + The application can attach this buffer to the structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_DOUSE = MFX_MAKEFOURCC('D','U','S','E'), + /*! + This extended buffer defines additional encoding controls for reference list. See the mfxExtAVCRefListCtrl structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding & decoding initialization, or the mfxEncodeCtrl + structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_AVC_REFLIST_CTRL = MFX_MAKEFOURCC('R','L','S','T'), + /*! + This extended buffer defines control parameters for the VPP frame rate conversion algorithm. See the mfxExtVPPFrameRateConversion structure + for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION = MFX_MAKEFOURCC('F','R','C',' '), + /*! + This extended buffer configures the H.264 picture timing SEI message. See the mfxExtPictureTimingSEI structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization, or the mfxEncodeCtrl structure + for per-frame encoding configuration. + */ + MFX_EXTBUFF_PICTURE_TIMING_SEI = MFX_MAKEFOURCC('P','T','S','E'), + /*! + This extended buffer configures the structure of temporal layers inside the encoded H.264 bitstream. See the mfxExtAvcTemporalLayers + structure for details. The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_AVC_TEMPORAL_LAYERS = MFX_MAKEFOURCC('A','T','M','L'), + /*! + This extended buffer defines additional encoding controls. See the mfxExtCodingOption2 structure for details. + The application can attach this buffer to the structure for encoding initialization. + */ + MFX_EXTBUFF_CODING_OPTION2 = MFX_MAKEFOURCC('C','D','O','2'), + /*! + This extended buffer defines control parameters for the VPP image stabilization filter algorithm. See the mfxExtVPPImageStab structure + for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization. + */ + MFX_EXTBUFF_VPP_IMAGE_STABILIZATION = MFX_MAKEFOURCC('I','S','T','B'), + /*! + This extended buffer is used to retrieve encoder capability. See the mfxExtEncoderCapability structure for details. + The application can attach this buffer to the mfxVideoParam structure before calling MFXVideoENCODE_Query function. + */ + MFX_EXTBUFF_ENCODER_CAPABILITY = MFX_MAKEFOURCC('E','N','C','P'), + /*! + This extended buffer is used to control encoder reset behavior and also to query possible encoder reset outcome. + See the mfxExtEncoderResetOption structure for details. The application can attach this buffer to the mfxVideoParam structure + before calling MFXVideoENCODE_Query or MFXVideoENCODE_Reset functions. + */ + MFX_EXTBUFF_ENCODER_RESET_OPTION = MFX_MAKEFOURCC('E','N','R','O'), + /*! + This extended buffer is used by the encoder to report additional information about encoded picture. + See the mfxExtAVCEncodedFrameInfo structure for details. The application can attach this buffer to the mfxBitstream structure + before calling MFXVideoENCODE_EncodeFrameAsync function. + */ + MFX_EXTBUFF_ENCODED_FRAME_INFO = MFX_MAKEFOURCC('E','N','F','I'), + /*! + This extended buffer is used to control composition of several input surfaces in the one output. In this mode, + the VPP skips any other filters. The VPP returns error if any mandatory filter is specified and filter skipped warning + for optional filter. The only supported filters are deinterlacing and interlaced scaling. + */ + MFX_EXTBUFF_VPP_COMPOSITE = MFX_MAKEFOURCC('V','C','M','P'), + /*! + This extended buffer is used to control transfer matrix and nominal range of YUV frames. + The application should provide it during initialization. + */ + MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO = MFX_MAKEFOURCC('V','V','S','I'), + /*! + This extended buffer is used by the application to specify different Region Of Interests during encoding. + The application should provide it at initialization or at runtime. + */ + MFX_EXTBUFF_ENCODER_ROI = MFX_MAKEFOURCC('E','R','O','I'), + /*! + This extended buffer is used by the application to specify different deinterlacing algorithms. + */ + MFX_EXTBUFF_VPP_DEINTERLACING = MFX_MAKEFOURCC('V','P','D','I'), + /*! + This extended buffer specifies reference lists for the encoder. + */ + MFX_EXTBUFF_AVC_REFLISTS = MFX_MAKEFOURCC('R','L','T','S'), + /*! + See the mfxExtDecVideoProcessing structure for details. + */ + MFX_EXTBUFF_DEC_VIDEO_PROCESSING = MFX_MAKEFOURCC('D','E','C','V'), + /*! + The extended buffer defines control parameters for the VPP field-processing algorithm. See the mfxExtVPPFieldProcessing + structure for details. The application can attach this buffer to the mfxVideoParam structure for video processing initialization + or to the mfxFrameData structure during runtime. + */ + MFX_EXTBUFF_VPP_FIELD_PROCESSING = MFX_MAKEFOURCC('F','P','R','O'), + /*! + This extended buffer defines additional encoding controls. See the mfxExtCodingOption3 structure for details. + The application can attach this buffer to the structure for encoding initialization. + */ + MFX_EXTBUFF_CODING_OPTION3 = MFX_MAKEFOURCC('C','D','O','3'), + /*! + This extended buffer defines chroma samples location information. See the mfxExtChromaLocInfo structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_CHROMA_LOC_INFO = MFX_MAKEFOURCC('C','L','I','N'), + /*! + This extended buffer defines per-macroblock QP. See the mfxExtMBQP structure for details. + The application can attach this buffer to the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_MBQP = MFX_MAKEFOURCC('M','B','Q','P'), + /*! + This extended buffer defines per-macroblock force intra flag. See the mfxExtMBForceIntra structure for details. + The application can attach this buffer to the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_MB_FORCE_INTRA = MFX_MAKEFOURCC('M','B','F','I'), + /*! + This extended buffer defines additional encoding controls for HEVC tiles. See the mfxExtHEVCTiles structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_HEVC_TILES = MFX_MAKEFOURCC('2','6','5','T'), + /*! + This extended buffer defines macroblock map for current frame which forces specified macroblocks to be non skip. See the + mfxExtMBDisableSkipMap structure for details. The application can attach this buffer to the mfxEncodeCtrl structure for + per-frame encoding configuration. + */ + MFX_EXTBUFF_MB_DISABLE_SKIP_MAP = MFX_MAKEFOURCC('M','D','S','M'), + /*! + See the mfxExtHEVCParam structure for details. + */ + MFX_EXTBUFF_HEVC_PARAM = MFX_MAKEFOURCC('2','6','5','P'), + /*! + This extended buffer is used by decoders to report additional information about decoded frame. See the + mfxExtDecodedFrameInfo structure for more details. + */ + MFX_EXTBUFF_DECODED_FRAME_INFO = MFX_MAKEFOURCC('D','E','F','I'), + /*! + See the mfxExtTimeCode structure for more details. + */ + MFX_EXTBUFF_TIME_CODE = MFX_MAKEFOURCC('T','M','C','D'), + /*! + This extended buffer specifies the region to encode. The application can attach this buffer to the + mfxVideoParam structure during HEVC encoder initialization. + */ + MFX_EXTBUFF_HEVC_REGION = MFX_MAKEFOURCC('2','6','5','R'), + /*! + See the mfxExtPredWeightTable structure for details. + */ + MFX_EXTBUFF_PRED_WEIGHT_TABLE = MFX_MAKEFOURCC('E','P','W','T'), + /*! + See the mfxExtDirtyRect structure for details. + */ + MFX_EXTBUFF_DIRTY_RECTANGLES = MFX_MAKEFOURCC('D','R','O','I'), + /*! + See the mfxExtMoveRect structure for details. + */ + MFX_EXTBUFF_MOVING_RECTANGLES = MFX_MAKEFOURCC('M','R','O','I'), + /*! + See the mfxExtCodingOptionVPS structure for details. + */ + MFX_EXTBUFF_CODING_OPTION_VPS = MFX_MAKEFOURCC('C','O','V','P'), + /*! + See the mfxExtVPPRotation structure for details. + */ + MFX_EXTBUFF_VPP_ROTATION = MFX_MAKEFOURCC('R','O','T',' '), + /*! + See the mfxExtEncodedSlicesInfo structure for details. + */ + MFX_EXTBUFF_ENCODED_SLICES_INFO = MFX_MAKEFOURCC('E','N','S','I'), + /*! + See the mfxExtVPPScaling structure for details. + */ + MFX_EXTBUFF_VPP_SCALING = MFX_MAKEFOURCC('V','S','C','L'), + /*! + This extended buffer defines additional encoding controls for reference list. See the mfxExtAVCRefListCtrl structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding & decoding initialization, or + the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_HEVC_REFLIST_CTRL = MFX_EXTBUFF_AVC_REFLIST_CTRL, + /*! + This extended buffer specifies reference lists for the encoder. + */ + MFX_EXTBUFF_HEVC_REFLISTS = MFX_EXTBUFF_AVC_REFLISTS, + /*! + This extended buffer configures the structure of temporal layers inside the encoded H.265 bitstream. See the mfxExtHEVCTemporalLayers + structure for details. The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_HEVC_TEMPORAL_LAYERS = MFX_EXTBUFF_AVC_TEMPORAL_LAYERS, + /*! + See the mfxExtVPPMirroring structure for details. + */ + MFX_EXTBUFF_VPP_MIRRORING = MFX_MAKEFOURCC('M','I','R','R'), + /*! + See the mfxExtMVOverPicBoundaries structure for details. + */ + MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES = MFX_MAKEFOURCC('M','V','P','B'), + /*! + See the mfxExtVPPColorFill structure for details. + */ + MFX_EXTBUFF_VPP_COLORFILL = MFX_MAKEFOURCC('V','C','L','F'), + /*! + This extended buffer is used by decoders to report error information before frames get decoded. + See the mfxExtDecodeErrorReport structure for more details. + */ + MFX_EXTBUFF_DECODE_ERROR_REPORT = MFX_MAKEFOURCC('D', 'E', 'R', 'R'), + /*! + See the mfxExtColorConversion structure for details. + */ + MFX_EXTBUFF_VPP_COLOR_CONVERSION = MFX_MAKEFOURCC('V', 'C', 'S', 'C'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtContentLightLevelInfo structure for details. + */ + MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO = MFX_MAKEFOURCC('L', 'L', 'I', 'S'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtMasteringDisplayColourVolume structure for details. If color volume changes + per frame, the application can attach this buffer to the mfxFrameData structure for video processing. + */ + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME = MFX_MAKEFOURCC('D', 'C', 'V', 'S'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtMasteringDisplayColourVolume structure for details. The application can + attach this buffer to the mfxVideoParam structure for the input of video processing if the mastering display color volume changes per + sequence. In this case, this buffer should be together with MFX_EXTBUFF_CONTENT_LIGHT_LEVEL_INFO to indicate the light level and mastering + color volume of the input of video processing. If color Volume changes per frame instead of per sequence, the application can attach + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME to mfxFrameData for frame based processing. + */ + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME_IN = MFX_MAKEFOURCC('D', 'C', 'V', 'I'), + /*! + This extended buffer configures HDR SEI message. See the mfxExtMasteringDisplayColourVolume structure for details. The application can + attach this buffer to the mfxVideoParam structure for the output of video processing if the mastering display color volume changes per + sequence. If color volume changes per frame instead of per sequence, the application can attach the buffer with MFX_EXTBUFF_MASTERING_ + DISPLAY_COLOUR_VOLUME to mfxFrameData for frame based processing. + */ + MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME_OUT = MFX_MAKEFOURCC('D', 'C', 'V', 'O'), + /*! + See the mfxExtEncodedUnitsInfo structure for details. + */ + MFX_EXTBUFF_ENCODED_UNITS_INFO = MFX_MAKEFOURCC('E', 'N', 'U', 'I'), + /*! + This video processing algorithm identifier is used to enable MCTF via mfxExtVPPDoUse and together with mfxExtVppMctf + */ + MFX_EXTBUFF_VPP_MCTF = MFX_MAKEFOURCC('M', 'C', 'T', 'F'), + /*! + Extends mfxVideoParam structure with VP9 segmentation parameters. See the mfxExtVP9Segmentation structure for details. + */ + MFX_EXTBUFF_VP9_SEGMENTATION = MFX_MAKEFOURCC('9', 'S', 'E', 'G'), + /*! + Extends mfxVideoParam structure with parameters for VP9 temporal scalability. See the mfxExtVP9TemporalLayers structure for details. + */ + MFX_EXTBUFF_VP9_TEMPORAL_LAYERS = MFX_MAKEFOURCC('9', 'T', 'M', 'L'), + /*! + Extends mfxVideoParam structure with VP9-specific parameters. See the mfxExtVP9Param structure for details. + */ + MFX_EXTBUFF_VP9_PARAM = MFX_MAKEFOURCC('9', 'P', 'A', 'R'), + /*! + See the mfxExtAVCRoundingOffset structure for details. + */ + MFX_EXTBUFF_AVC_ROUNDING_OFFSET = MFX_MAKEFOURCC('R','N','D','O'), + /*! + See the mfxExtPartialBitstreamParam structure for details. + */ + MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM = MFX_MAKEFOURCC('P','B','O','P'), + + /*! + See the mfxExtEncoderIPCMArea structure for details. + */ + MFX_EXTBUFF_ENCODER_IPCM_AREA = MFX_MAKEFOURCC('P', 'C', 'M', 'R'), + /*! + See the mfxExtInsertHeaders structure for details. + */ + MFX_EXTBUFF_INSERT_HEADERS = MFX_MAKEFOURCC('S', 'P', 'R', 'E'), + + /*! + See the mfxExtDeviceAffinityMask structure for details. + */ + MFX_EXTBUFF_DEVICE_AFFINITY_MASK = MFX_MAKEFOURCC('D', 'A', 'F', 'M'), + + /*! + See the mfxExtInCrops structure for details. + */ + MFX_EXTBUFF_CROPS = MFX_MAKEFOURCC('C', 'R', 'O', 'P'), + + /*! + See the mfxExtAV1BitstreamParam structure for more details. + */ + MFX_EXTBUFF_AV1_BITSTREAM_PARAM = MFX_MAKEFOURCC('A', '1', 'B', 'S'), + + /*! + See the mfxExtAV1ResolutionParam structure for more details. + */ + MFX_EXTBUFF_AV1_RESOLUTION_PARAM = MFX_MAKEFOURCC('A', '1', 'R', 'S'), + + /*! + See the mfxExtAV1TileParam structure for more details. + */ + MFX_EXTBUFF_AV1_TILE_PARAM = MFX_MAKEFOURCC('A', '1', 'T', 'L'), + + /*! + See the mfxExtAV1Segmentation structure for more details. + */ + MFX_EXTBUFF_AV1_SEGMENTATION = MFX_MAKEFOURCC('1', 'S', 'E', 'G'), + + /*! + See the mfxExtAV1FilmGrainParam structure for more details. + */ + 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 mfxExtTemporalLayers structure for more details. + */ + MFX_EXTBUFF_UNIVERSAL_TEMPORAL_LAYERS = MFX_MAKEFOURCC('U', 'T', 'M', 'P'), + /*! + This extended buffer defines additional encoding controls for reference list. See the mfxExtRefListCtrl structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding & decoding initialization, or + the mfxEncodeCtrl structure for per-frame encoding configuration. + */ + MFX_EXTBUFF_UNIVERSAL_REFLIST_CTRL = MFX_EXTBUFF_AVC_REFLIST_CTRL, +#ifdef ONEVPL_EXPERIMENTAL + /*! + See the mfxExtEncodeStats structure for details. + */ + MFX_EXTBUFF_ENCODESTATS = MFX_MAKEFOURCC('E','N','S','B'), +#endif + /*! + See the mfxExtVPP3DLut structure for more details. + */ + MFX_EXTBUFF_VPP_3DLUT = MFX_MAKEFOURCC('T','D','L','T'), + + /*! + See the mfxExtAllocationHints structure for more details. + */ + MFX_EXTBUFF_ALLOCATION_HINTS = MFX_MAKEFOURCC('A','L','C','H'), + +#ifdef ONEVPL_EXPERIMENTAL + /*! + See the mfxExtVPPPercEncPrefilter structure for details. + */ + MFX_EXTBUFF_VPP_PERC_ENC_PREFILTER = MFX_MAKEFOURCC('V','P','E','F'), + /*! + See the mfxExtTuneEncodeQuality structure for details. + */ + MFX_EXTBUFF_TUNE_ENCODE_QUALITY = MFX_MAKEFOURCC('T','U','N','E'), + /*! + See the mfxExtSurfaceOpenCLImg2DExportDescription structure for more details. + */ + MFX_EXTBUFF_EXPORT_SHARING_DESC_OCL = MFX_MAKEFOURCC('E', 'O', 'C', 'L'), + /*! + See the mfxExtSurfaceD3D12Tex2DExportDescription structure for more details. + */ + MFX_EXTBUFF_EXPORT_SHARING_DESC_D3D12 = MFX_MAKEFOURCC('E', 'D', '1', '2'), + /*! + See the mfxExtSurfaceVulkanImg2DExportDescription structure for more details. + */ + MFX_EXTBUFF_EXPORT_SHARING_DESC_VULKAN = MFX_MAKEFOURCC('E', 'V', 'U', 'L'), +#endif + /*! + See the mfxExtVPPAISuperResolution structure for details. + */ + MFX_EXTBUFF_VPP_AI_SUPER_RESOLUTION = MFX_MAKEFOURCC('V','A','S','R'), + /*! + See the mfxExtVPPAIFrameInterpolation structure for details. + */ + MFX_EXTBUFF_VPP_AI_FRAME_INTERPOLATION = MFX_MAKEFOURCC('V', 'A', 'F', 'I'), + /*! + See the mfxExtQualityInfoMode structure for details. + */ + MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE = MFX_MAKEFOURCC('E', 'N', 'Q', 'M'), + /*! + See the mfxExtQualityInfoOutput structure for details. + */ + MFX_EXTBUFF_ENCODED_QUALITY_INFO_OUTPUT = MFX_MAKEFOURCC('E', 'N', 'Q', 'O'), + /*! + See the mfxExtAV1ScreenContentTools structure for details. + */ + MFX_EXTBUFF_AV1_SCREEN_CONTENT_TOOLS = MFX_MAKEFOURCC('1', 'S', 'C', 'C'), + /*! + See the mfxExtAlphaChannelEncCtrl structure for more details. + */ + MFX_EXTBUFF_ALPHA_CHANNEL_ENC_CTRL = MFX_MAKEFOURCC('A', 'C', 'E', 'C'), + /*! + See the mfxExtAlphaChannelSurface structure for more details. + */ + MFX_EXTBUFF_ALPHA_CHANNEL_SURFACE = MFX_MAKEFOURCC('A', 'C', 'S', 'F'), +#ifdef ONEVPL_EXPERIMENTAL + /*! + See the mfxExtAIEncCtrl structure for more details. + */ + MFX_EXTBUFF_AI_ENC_CTRL = MFX_MAKEFOURCC('A', 'I', 'E', 'C'), +#endif +}; + +/* VPP Conf: Do not use certain algorithms */ +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Tells the VPP not to use certain filters in pipeline. See "Configurable VPP filters" table for complete + list of configurable filters. The user can attach this structure to the mfxVideoParam structure when initializing video processing. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DONOTUSE. */ + mfxU32 NumAlg; /*!< Number of filters (algorithms) not to use */ + mfxU32* AlgList; /*!< Pointer to a list of filters (algorithms) not to use */ +} mfxExtVPPDoNotUse; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP denoise filter algorithm. + @deprecated Deprecated in API version 2.5. Use mfxExtVPPDenoise2 instead. +*/ +MFX_DEPRECATED typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DENOISE. */ + mfxU16 DenoiseFactor; /*!< Indicates the level of noise to remove. Value range of 0 to 100 (inclusive). */ +} mfxExtVPPDenoise; +MFX_PACK_END() + +/*! The mfxDenoiseMode enumerator specifies the mode of denoise. */ +typedef enum { + MFX_DENOISE_MODE_DEFAULT = 0, /*!< Default denoise mode. The library selects the most appropriate denoise mode. */ + MFX_DENOISE_MODE_VENDOR = 1000, /*!< The enumeration to separate common denoise mode above and vendor specific. */ + + MFX_DENOISE_MODE_INTEL_HVS_AUTO_BDRATE = MFX_DENOISE_MODE_VENDOR + 1, /*!< Indicates auto BD rate improvement in pre-processing before video encoding, + ignore Strength.*/ + MFX_DENOISE_MODE_INTEL_HVS_AUTO_SUBJECTIVE = MFX_DENOISE_MODE_VENDOR + 2, /*!< Indicates auto subjective quality improvement in pre-processing before video encoding, + ignore Strength.*/ + MFX_DENOISE_MODE_INTEL_HVS_AUTO_ADJUST = MFX_DENOISE_MODE_VENDOR + 3, /*!< Indicates auto adjust subjective quality in post-processing (after decoding) for video playback, + ignore Strength.*/ + MFX_DENOISE_MODE_INTEL_HVS_PRE_MANUAL = MFX_DENOISE_MODE_VENDOR + 4, /*!< Indicates manual mode for pre-processing before video encoding, + allow to adjust the denoise strength manually.*/ + MFX_DENOISE_MODE_INTEL_HVS_POST_MANUAL = MFX_DENOISE_MODE_VENDOR + 5, /*!< Indicates manual mode for post-processing for video playback, + allow to adjust the denoise strength manually.*/ +} mfxDenoiseMode; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP denoise filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DENOISE2. */ + mfxDenoiseMode Mode; /*!< Indicates the mode of denoise. mfxDenoiseMode enumerator. */ + mfxU16 Strength; /*!< Denoise strength in manual mode. Value of 0-100 (inclusive) indicates the strength of denoise. + The strength of denoise controls degree of possible changes of pixel values; the bigger the strength + the larger the change is. */ + mfxU16 reserved[15]; +} 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() + +#ifdef ONEVPL_EXPERIMENTAL +/*! The mfx3DLutInterpolationMethod enumerator specifies the 3DLUT interpolation method. */ +typedef enum { + MFX_3DLUT_INTERPOLATION_DEFAULT = 0, /*!< Default 3DLUT interpolation Method. The library selects the most appropriate 3DLUT interpolation method. */ + MFX_3DLUT_INTERPOLATION_TRILINEAR = 1, /*!< 3DLUT Trilinear interpolation method. */ + MFX_3DLUT_INTERPOLATION_TETRAHEDRAL = 2, /*!< 3DLUT Tetrahedral interpolation method. */ +} mfx3DLutInterpolationMethod; +#endif + +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.*/ + }; +#ifdef ONEVPL_EXPERIMENTAL + mfx3DLutInterpolationMethod InterpolationMethod; /*!< Indicates 3DLUT Interpolation Method. mfx3DLutInterpolationMethod enumerator.*/ + mfxU32 reserved[3]; /*!< Reserved for future extension.*/ +#else + mfxU32 reserved[4]; /*!< Reserved for future extension.*/ +#endif +} mfxExtVPP3DLut; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP detail/edge enhancement filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DETAIL. */ + mfxU16 DetailFactor; /*!< Indicates the level of details to be enhanced. Value range of 0 to 100 (inclusive). */ +} mfxExtVPPDetail; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + A hint structure that configures the VPP ProcAmp filter algorithm. + The structure parameters will be clipped to their corresponding range and rounded by their corresponding increment. + @note There are no default values for fields in this structure, all settings must be explicitly specified every time this + buffer is submitted for processing. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_PROCAMP. */ + mfxF64 Brightness; /*!< The brightness parameter is in the range of -100.0F to 100.0F, in increments of 0.1F. + Setting this field to 0.0F will disable brightness adjustment. */ + mfxF64 Contrast; /*!< The contrast parameter in the range of 0.0F to 10.0F, in increments of 0.01F, is used for manual + contrast adjustment. Setting this field to 1.0F will disable contrast adjustment. If the parameter + is negative, contrast will be adjusted automatically. */ + mfxF64 Hue; /*!< The hue parameter is in the range of -180F to 180F, in increments of 0.1F. Setting this field to 0.0F + will disable hue adjustment. */ + mfxF64 Saturation; /*!< The saturation parameter is in the range of 0.0F to 10.0F, in increments of 0.01F. + Setting this field to 1.0F will disable saturation adjustment. */ +} mfxExtVPPProcAmp; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Returns statistics collected during encoding. +*/ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; /*!< Number of encoded frames. */ + mfxU64 NumBit; /*!< Number of bits for all encoded frames. */ + mfxU32 NumCachedFrame; /*!< Number of internally cached frames. */ +} mfxEncodeStat; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Returns statistics collected during decoding. +*/ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; /*!< Number of total decoded frames. */ + mfxU32 NumSkippedFrame; /*!< Number of skipped frames. */ + mfxU32 NumError; /*!< Number of errors recovered. */ + mfxU32 NumCachedFrame; /*!< Number of internally cached frames. */ +} mfxDecodeStat; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Returns statistics collected during video processing. +*/ +typedef struct { + mfxU32 reserved[16]; + mfxU32 NumFrame; /*!< Total number of frames processed. */ + mfxU32 NumCachedFrame; /*!< Number of internally cached frames. */ +} mfxVPPStat; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Returns auxiliary data generated by the video processing pipeline. + The encoding process may use the auxiliary data by attaching this structure to the mfxEncodeCtrl structure. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_AUXDATA. */ + + union{ + struct{ + MFX_DEPRECATED mfxU32 SpatialComplexity; /* Deprecated */ + MFX_DEPRECATED mfxU32 TemporalComplexity; /* Deprecated */ + }; + struct{ + /*! + Detected picture structure - top field first, bottom field first, progressive or unknown if video processor cannot + detect picture structure. See the PicStruct enumerator for definition of these values. + + */ + mfxU16 PicStruct; + mfxU16 reserved[3]; + }; + }; + MFX_DEPRECATED mfxU16 SceneChangeRate; /* Deprecated */ + mfxU16 RepeatedFrame; /*!< The flag signalizes that the frame is identical to the previous one. */ +} mfxExtVppAuxData; +MFX_PACK_END() + +/*! The PayloadCtrlFlags enumerator itemizes additional payload properties. */ +enum { + MFX_PAYLOAD_CTRL_SUFFIX = 0x00000001 /*!< Insert this payload into HEVC Suffix SEI NAL-unit. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes user data payload in MPEG-2 or SEI message payload in H.264. + + For encoding, these payloads can be + inserted into the bitstream. The payload buffer must contain a valid formatted payload. + + For H.264, this is the sei_message() as + specified in the section 7.3.2.3.1 'Supplemental enhancement information message syntax' of the ISO/IEC 14496-10 specification. + + For MPEG-2, + this is the section 6.2.2.2.2 'User data' of the ISO/IEC 13818-2 specification, excluding the user data start_code. + + For decoding, + these payloads can be retrieved as the decoder parses the bitstream and caches them in an internal buffer. + + @internal + +-----------+-------------------------------------------+ + | **Codec** | **Supported Types** | + +===========+===========================================+ + | MPEG2 | 0x01B2 //User Data | + +-----------+-------------------------------------------+ + | AVC | 02 //pan_scan_rect | + | | 03 //filler_payload | + | | 04 //user_data_registered_itu_t_t35 | + | | 05 //user_data_unregistered | + | | 06 //recovery_point | + | | 09 //scene_info | + | | 13 //full_frame_freeze | + | | 14 //full_frame_freeze_release | + | | 15 //full_frame_snapshot | + | | 16 //progressive_refinement_segment_start | + | | 17 //progressive_refinement_segment_end | + | | 19 //film_grain_characteristics | + | | 20 //deblocking_filter_display_preference | + | | 21 //stereo_video_info | + | | 45 //frame_packing_arrangement | + +-----------+-------------------------------------------+ + | HEVC | All | + +-----------+-------------------------------------------+ + @endinternal + +*/ +typedef struct { + mfxU32 CtrlFlags; /*!< Additional payload properties. See the PayloadCtrlFlags enumerator for details. */ + mfxU32 reserved[3]; + mfxU8 *Data; /*!< Pointer to the actual payload data buffer. */ + mfxU32 NumBit; /*!< Number of bits in the payload data */ + mfxU16 Type; /*!< MPEG-2 user data start code or H.264 SEI message type. */ + mfxU16 BufSize; /*!< Payload buffer size in bytes. */ +} mfxPayload; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains parameters for per-frame based encoding control. +*/ +typedef struct { + mfxExtBuffer Header; /*!< This extension buffer doesn't have assigned buffer ID. Ignored. */ + mfxU32 reserved[4]; + mfxU16 reserved1; + /*! + Type of NAL unit that contains encoding frame. All supported values are defined by MfxNalUnitType enumerator. Other values + defined in ITU-T H.265 specification are not supported. + + The encoder uses this field only if application sets mfxExtCodingOption3::EnableNalUnitType option to ON during encoder initialization. + + @note Only encoded order is supported. If application specifies this value in display order or uses value inappropriate for current frame or + invalid value, then the encoder silently ignores it. + */ + mfxU16 MfxNalUnitType; + mfxU16 SkipFrame; /*!< Indicates that current frame should be skipped or the number of missed frames before the current frame. See mfxExtCodingOption2::SkipFrame for details. */ + + mfxU16 QP; /*!< If nonzero, this value overwrites the global QP value for the current frame in the constant QP mode. */ + + /*! + Encoding frame type. See the FrameType enumerator for details. If the encoder works in the encoded order, the application must + specify the frame type. If the encoder works in the display order, only key frames are enforceable. + */ + mfxU16 FrameType; + mfxU16 NumExtParam; /*!< Number of extra control buffers. */ + mfxU16 NumPayload; /*!< Number of payload records to insert into the bitstream. */ + mfxU16 reserved2; + + /*! + Pointer to an array of pointers to external buffers that provide additional information or control to the encoder for this + frame or field pair. A typical use is to pass the VPP auxiliary data generated by the video processing pipeline to the encoder. + See the ExtendedBufferID for the list of extended buffers. + */ + mfxExtBuffer **ExtParam; + /*! + Pointer to an array of pointers to user data (MPEG-2) or SEI messages (H.264) for insertion into the bitstream. For field pictures, + odd payloads are associated with the first field and even payloads are associated with the second field. See the mfxPayload structure + for payload definitions. + */ + mfxPayload **Payload; +} mfxEncodeCtrl; +MFX_PACK_END() + +/*! The ExtMemBufferType enumerator specifies the buffer type. It is a bit-ORed value of the following. */ +enum { + MFX_MEMTYPE_PERSISTENT_MEMORY =0x0002 /*!< Memory page for persistent use. */ +}; + +/* Frame Memory Types */ +#define MFX_MEMTYPE_BASE(x) (0x90ff & (x)) + +/*! + The ExtMemFrameType enumerator specifies the memory type of frame. It is a bit-ORed value of the following. + \verbatim embed:rst + For information on working with video memory surfaces, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim +*/ +enum { + MFX_MEMTYPE_DXVA2_DECODER_TARGET =0x0010, /*!< Frames are in video memory and belong to video decoder render targets. */ + MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET =0x0020, /*!< Frames are in video memory and belong to video processor render targets. */ + MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET = MFX_MEMTYPE_DXVA2_DECODER_TARGET, /*!< Frames are in video memory and belong to video decoder render targets. */ + MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET = MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET,/*!< Frames are in video memory and belong to video processor render targets. */ + MFX_MEMTYPE_SYSTEM_MEMORY =0x0040, /*!< The frames are in system memory. */ + MFX_MEMTYPE_RESERVED1 =0x0080, /*!< */ + + MFX_MEMTYPE_FROM_ENCODE = 0x0100, /*!< Allocation request comes from an ENCODE function */ + MFX_MEMTYPE_FROM_DECODE = 0x0200, /*!< Allocation request comes from a DECODE function */ + MFX_MEMTYPE_FROM_VPPIN = 0x0400, /*!< Allocation request comes from a VPP function for input frame allocation */ + MFX_MEMTYPE_FROM_VPPOUT = 0x0800, /*!< Allocation request comes from a VPP function for output frame allocation */ + MFX_MEMTYPE_FROM_ENC = 0x2000, /*!< Allocation request comes from an ENC function */ + MFX_MEMTYPE_FROM_PAK = 0x4000, /* Reserved */ + + MFX_MEMTYPE_INTERNAL_FRAME = 0x0001, /*!< Allocation request for internal frames */ + MFX_MEMTYPE_EXTERNAL_FRAME = 0x0002, /*!< Allocation request for I/O frames */ + MFX_MEMTYPE_EXPORT_FRAME = 0x0008, /*!< Application requests frame handle export to some associated object. For Linux frame handle can be + considered to be exported to DRM Prime FD, DRM FLink or DRM FrameBuffer Handle. Specifics of export + types and export procedure depends on external frame allocator implementation */ + MFX_MEMTYPE_SHARED_RESOURCE = MFX_MEMTYPE_EXPORT_FRAME, /*!< For DX11 allocation use shared resource bind flag. */ + MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET = 0x1000, /*!< Frames are in video memory and belong to video encoder render targets. */ + + MFX_MEMTYPE_VIDEO_MEMORY_UNORDERED_ACCESS = 0x8000 /*!< Frames are in video memory and used as an unordered access resource. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Describes multiple frame allocations when initializing encoders, decoders, and video preprocessors. + A range specifies the number of video frames. Applications are free to allocate additional frames. In all cases, the minimum number of + frames must be at least NumFrameMin or the called API function will return an error. +*/ +typedef struct { + union { + mfxU32 AllocId; /*!< Unique (within the session) ID of component requested the allocation. */ + mfxU32 reserved[1]; + }; + mfxU32 reserved3[3]; + mfxFrameInfo Info; /*!< Describes the properties of allocated frames. */ + mfxU16 Type; /*!< Allocated memory type. See the ExtMemFrameType enumerator for details. */ + mfxU16 NumFrameMin; /*!< Minimum number of allocated frames. */ + mfxU16 NumFrameSuggested; /*!< Suggested number of allocated frames. */ + mfxU16 reserved2; +} mfxFrameAllocRequest; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the response to multiple frame allocations. The calling API function returns the number of + video frames actually allocated and pointers to their memory IDs. +*/ +typedef struct { + mfxU32 AllocId; /*!< Unique (within the session) ID of component requested the allocation. */ + mfxU32 reserved[3]; + mfxMemId *mids; /*!< Pointer to the array of the returned memory IDs. The application allocates or frees this array. */ + mfxU16 NumFrameActual; /*!< Number of frames actually allocated. */ + mfxU16 reserved2; +} mfxFrameAllocResponse; +MFX_PACK_END() + +/*! The FrameType enumerator itemizes frame types. Use bit-ORed values to specify all that apply. */ +enum { + MFX_FRAMETYPE_UNKNOWN =0x0000, /*!< Frame type is unspecified. */ + + MFX_FRAMETYPE_I =0x0001, /*!< This frame or the first field is encoded as an I-frame/field. */ + MFX_FRAMETYPE_P =0x0002, /*!< This frame or the first field is encoded as an P-frame/field. */ + MFX_FRAMETYPE_B =0x0004, /*!< This frame or the first field is encoded as an B-frame/field. */ + MFX_FRAMETYPE_S =0x0008, /*!< This frame or the first field is either an SI- or SP-frame/field. */ + + MFX_FRAMETYPE_REF =0x0040, /*!< This frame or the first field is encoded as a reference. */ + MFX_FRAMETYPE_IDR =0x0080, /*!< This frame or the first field is encoded as an IDR. */ + + MFX_FRAMETYPE_xI =0x0100, /*!< The second field is encoded as an I-field. */ + MFX_FRAMETYPE_xP =0x0200, /*!< The second field is encoded as an P-field. */ + MFX_FRAMETYPE_xB =0x0400, /*!< The second field is encoded as an S-field. */ + MFX_FRAMETYPE_xS =0x0800, /*!< The second field is an SI- or SP-field. */ + + MFX_FRAMETYPE_xREF =0x4000, /*!< The second field is encoded as a reference. */ + MFX_FRAMETYPE_xIDR =0x8000 /*!< The second field is encoded as an IDR. */ +}; + +/*! + The MfxNalUnitType enumerator specifies NAL unit types supported by the HEVC encoder. +*/ +enum { + MFX_HEVC_NALU_TYPE_UNKNOWN = 0, /*!< The encoder will decide what NAL unit type to use. */ + MFX_HEVC_NALU_TYPE_TRAIL_N = ( 0+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_TRAIL_R = ( 1+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RADL_N = ( 6+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RADL_R = ( 7+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RASL_N = ( 8+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_RASL_R = ( 9+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_IDR_W_RADL = (19+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_IDR_N_LP = (20+1), /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ + MFX_HEVC_NALU_TYPE_CRA_NUT = (21+1) /*!< See Table 7-1 of the ITU-T H.265 specification for the definition of these type. */ +}; + +/*! The mfxSkipMode enumerator describes the decoder skip-mode options. */ +typedef enum { + MFX_SKIPMODE_NOSKIP=0, /*! Do not skip any frames. */ + MFX_SKIPMODE_MORE=1, /*! Skip more frames. */ + MFX_SKIPMODE_LESS=2 /*! Skip less frames. */ +} mfxSkipMode; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Attach this structure as part of the extended buffers to configure the encoder during MFXVideoENCODE_Init. The sequence or picture + parameters specified by this structure overwrite any parameters specified by the structure or any other attached extended buffers attached. + + For H.264, SPSBuffer and PPSBuffer must point to valid bitstreams that contain the sequence parameter set and picture parameter set, + respectively. + + For MPEG-2, SPSBuffer must point to valid bitstreams that contain the sequence header followed by any sequence header extension. The PPSBuffer pointer is ignored. + + The encoder imports parameters from these buffers. If the encoder does not support the specified parameters, + the encoder does not initialize and returns the status code MFX_ERR_INCOMPATIBLE_VIDEO_PARAM. + + Check with the MFXVideoENCODE_Query function for the support of this multiple segment encoding feature. If this feature is not supported, + the query returns MFX_ERR_UNSUPPORTED. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION_SPSPPS. */ + mfxU8 *SPSBuffer; /*!< Pointer to a valid bitstream that contains the SPS (sequence parameter set for H.264 or sequence header + followed by any sequence header extension for MPEG-2) buffer. Can be NULL to skip specifying the SPS. */ + mfxU8 *PPSBuffer; /*!< Pointer to a valid bitstream that contains the PPS (picture parameter set for H.264 or picture header + followed by any picture header extension for MPEG-2) buffer. Can be NULL to skip specifying the PPS. */ + mfxU16 SPSBufSize; /*!< Size of the SPS in bytes. */ + mfxU16 PPSBufSize; /*!< Size of the PPS in bytes. */ + mfxU16 SPSId; /*!< SPS identifier. The value is reserved and must be zero. */ + mfxU16 PPSId; /*!< PPS identifier. The value is reserved and must be zero. */ +} mfxExtCodingOptionSPSPPS; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Attach this structure as part of the extended buffers to configure the encoder during MFXVideoENCODE_Init. The sequence or picture + parameters specified by this structure overwrite any parameters specified by the structure or any other attached extended buffers attached. + + If the encoder does not support the specified parameters, the encoder does not initialize and returns the status code + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM. + + Check with the MFXVideoENCODE_Query function for the support of this multiple segment encoding feature. If this feature is not supported, + the query returns MFX_ERR_UNSUPPORTED. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CODING_OPTION_VPS. */ + + union { + mfxU8 *VPSBuffer; /*!< Pointer to a valid bitstream that contains the VPS (video parameter set for HEVC) buffer. */ + mfxU64 reserved1; + }; + mfxU16 VPSBufSize; /*!< Size of the VPS in bytes. */ + mfxU16 VPSId; /*!< VPS identifier; the value is reserved and must be zero. */ + + mfxU16 reserved[6]; +} mfxExtCodingOptionVPS; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Defines the video signal information. + + For H.264, see Annex E of the ISO/IEC 14496-10 specification for the definition of these parameters. + + For MPEG-2, see section 6.3.6 of the ITU* H.262 specification for the definition of these parameters. The field VideoFullRange is ignored. + + For VC-1, see section 6.1.14.5 of the SMPTE* 421M specification. The fields VideoFormat and VideoFullRange are ignored. + + @note If ColourDescriptionPresent is zero, the color description information (including ColourPrimaries, TransferCharacteristics, + and MatrixCoefficients) does not present in the bitstream. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VIDEO_SIGNAL_INFO. */ + mfxU16 VideoFormat; + mfxU16 VideoFullRange; + mfxU16 ColourDescriptionPresent; + mfxU16 ColourPrimaries; + mfxU16 TransferCharacteristics; + mfxU16 MatrixCoefficients; +} mfxExtVideoSignalInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Tells the VPP to include certain filters in the pipeline. + + 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. + + @li Attaching a filter configuration structure directly to the mfxVideoParam structure. + 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. + + The user can attach this structure to the mfxVideoParam structure when initializing video processing. + + @note MFX_EXTBUFF_VPP_COMPOSITE cannot be enabled using mfxExtVPPDoUse because default parameters are undefined for this filter. + The application must attach the appropriate filter configuration structure directly to the mfxVideoParam structure to enable it. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DOUSE. */ + mfxU32 NumAlg; /*!< Number of filters (algorithms) to use */ + mfxU32 *AlgList; /*!< Pointer to a list of filters (algorithms) to use */ +} mfxExtVPPDoUse; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures reference frame options for the H.264 encoder. + \verbatim embed:rst + See the :ref:`Reference List Selection ` and :ref:`Long Term Reference Frame ` sections for more details. + \endverbatim + + + @note Not all implementations of the encoder support LongTermIdx and ApplyLongTermIdx fields in this structure. The application must use + query mode 1 to determine if such functionality is supported. To do this, the application must attach this extended buffer to the + mfxVideoParam structure and call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE and these fields were set to non-zero value, + then the functionality is supported. If the function fails or sets fields to zero, then the functionality is not supported. + +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_REFLIST_CTRL. */ + mfxU16 NumRefIdxL0Active; /*!< Specify the number of reference frames in the active reference list L0. This number should be less or equal to the NumRefFrame parameter from encoding initialization. */ + mfxU16 NumRefIdxL1Active; /*!< Specify the number of reference frames in the active reference list L1. This number should be less or equal to the NumRefFrame parameter from encoding initialization. */ + + struct { + /*! @{ + @name Reference Lists + The following structure members are used by the reference lists contained in the parent structure. */ + mfxU32 FrameOrder; /*!< Together FrameOrder and PicStruct fields are used to identify reference picture. Use FrameOrder = MFX_FRAMEORDER_UNKNOWN to mark unused entry. */ + mfxU16 PicStruct; /*!< Together FrameOrder and PicStruct fields are used to identify reference picture. Use FrameOrder = MFX_FRAMEORDER_UNKNOWN to mark unused entry. */ + mfxU16 ViewId; /*!< Reserved and must be zero. */ + mfxU16 LongTermIdx; /*!< Index that should be used by the encoder to mark long-term reference frame. */ + mfxU16 reserved[3]; /*!< Reserved */ + /*! @} */ + } PreferredRefList[32], /*!< Reference list that specifies the list of frames that should be used to predict the current frame. */ + RejectedRefList[16], /*!< Reference list that specifies the list of frames that should not be used for prediction. */ + LongTermRefList[16]; /*!< Reference list that specifies the list of frames that should be marked as long-term reference frame. */ + + mfxU16 ApplyLongTermIdx;/*!< If it is equal to zero, the encoder assigns long-term index according to internal algorithm. + If it is equal to one, the encoder uses LongTermIdx value as long-term index. */ + mfxU16 reserved[15]; +} mfxExtAVCRefListCtrl; +MFX_PACK_END() + +/*! The FrcAlgm enumerator itemizes frame rate conversion algorithms. See description of mfxExtVPPFrameRateConversion structure for more details. */ +enum { + MFX_FRCALGM_PRESERVE_TIMESTAMP = 0x0001, /*!< Frame dropping/repetition based frame rate conversion algorithm with preserved original + time stamps. Any inserted frames will carry MFX_TIMESTAMP_UNKNOWN. */ + MFX_FRCALGM_DISTRIBUTED_TIMESTAMP = 0x0002, /*!< Frame dropping/repetition based frame rate conversion algorithm with distributed time stamps. + The algorithm distributes output time stamps evenly according to the output frame rate. */ + MFX_FRCALGM_FRAME_INTERPOLATION = 0x0004, /*!< Frame rate conversion algorithm based on frame interpolation. This flag may be combined with + MFX_FRCALGM_PRESERVE_TIMESTAMP or MFX_FRCALGM_DISTRIBUTED_TIMESTAMP flags. */ +#ifdef ONEVPL_EXPERIMENTAL + MFX_FRCALGM_AI_FRAME_INTERPOLATION = 0x0008 /*!< Frame rate conversion algorithm based on AI powered frame interpolation. This flag may be combined with + MFX_FRCALGM_PRESERVE_TIMESTAMP or MFX_FRCALGM_DISTRIBUTED_TIMESTAMP flags. This flag can not be combined + with MFX_FRCALGM_FRAME_INTERPOLATION. If application sets this flag, the application needs to attach + MFX_EXTBUFF_VPP_AI_FRAME_INTERPOLATION for the details of frame interpolation to mfxVideoParam. Refer to + mfxExtVPPAIFrameInterpolation for more details.*/ +#endif +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP frame rate conversion filter. The user can attach this structure to the + mfxVideoParam structure when initializing, resetting, or querying capability of video processing. + + On some platforms the advanced frame rate conversion algorithm (the algorithm based on frame interpolation) is not supported. To query its support, + the application should add the MFX_FRCALGM_FRAME_INTERPOLATION flag to the Algorithm value in the mfxExtVPPFrameRateConversion structure, attach it to the + structure, and call the MFXVideoVPP_Query function. If the filter is supported, the function returns a MFX_ERR_NONE status and copies the content of the + input structure to the output structure. If an advanced filter is not supported, then a simple filter will be used and the function returns + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM, copies content of the input structure to the output structure, and corrects the Algorithm value. + + If advanced FRC algorithm is not supported, both MFXVideoVPP_Init and MFXVideoVPP_Reset functions return the MFX_WRN_INCOMPATIBLE_VIDEO_PARAM status. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION. */ + mfxU16 Algorithm; /*!< See the FrcAlgm enumerator for a list of frame rate conversion algorithms. */ + mfxU16 reserved; + mfxU32 reserved2[15]; +} mfxExtVPPFrameRateConversion; +MFX_PACK_END() + +/*! The ImageStabMode enumerator itemizes image stabilization modes. See description of mfxExtVPPImageStab structure for more details. */ +enum { + MFX_IMAGESTAB_MODE_UPSCALE = 0x0001, /*!< Upscale mode. */ + MFX_IMAGESTAB_MODE_BOXING = 0x0002 /*!< Boxing mode. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that configures the VPP image stabilization filter. + + 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. + + 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 + filter from the mfxExtVPPDoUse structure, and zeroes the mfxExtVPPImageStab structure. + + If the image stabilization filter is not supported, both MFXVideoVPP_Init and MFXVideoVPP_Reset functions return a MFX_WRN_FILTER_SKIPPED status. + + The application can retrieve the list of active filters by attaching the mfxExtVPPDoUse structure to the mfxVideoParam structure and calling the + MFXVideoVPP_GetVideoParam function. The application must allocate enough memory for the filter list. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_IMAGE_STABILIZATION. */ + mfxU16 Mode; /*!< Image stabilization mode. See ImageStabMode enumerator for values. */ + mfxU16 reserved[11]; +} mfxExtVPPImageStab; +MFX_PACK_END() + + +/*! + The InsertHDRPayload enumerator itemizes HDR payloads insertion rules in the encoder, + and indicates if there is valid HDR information in the clip in the decoder. +*/ +enum { + MFX_PAYLOAD_OFF = 0, /*!< Do not insert payload when encoding; + Clip does not have valid HDR information when decoding. */ + MFX_PAYLOAD_IDR = 1 /*!< Insert payload on IDR frames when encoding; + Clip has valid HDR information when decoding. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Handle the HDR information. + + During encoding: If the application attaches this structure to the mfxEncodeCtrl structure at runtime, + the encoder inserts the HDR information 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 information based on InsertPayloadToggle. + + During video processing: If the application attaches this structure for video processing, InsertPayloadToggle will be ignored. + And DisplayPrimariesX[3], DisplayPrimariesY[3] specify the color primaries where 0,1,2 specifies Red, Green, Blue respectively. + + During decoding: If the application attaches this structure to the mfxFrameSurface1 structure at runtime + which will seed to the MFXVideoDECODE_DecodeFrameAsync() as surface_work parameter, + the decoder will parse the HDR information if the bitstream include HDR information per frame. + The parsed HDR information will be attached to the ExtendBuffer of surface_out parameter of MFXVideoDECODE_DecodeFrameAsync() + with flag `InsertPayloadToggle` to indicate if there is valid HDR information in the clip. + `InsertPayloadToggle` will be set to `MFX_PAYLOAD_IDR` if oneAPI Video Processing Library (oneVPL) gets valid HDR information, otherwise it will be set + to `MFX_PAYLOAD_OFF`. + This function is support for HEVC and AV1 only now. + + Encoding or Decoding, Field semantics are defined in ITU-T* H.265 Annex D, AV1 6.7.4 Metadata OBU semantics. + + Video processing, `DisplayPrimariesX[3]` and `WhitePointX` are in increments of 0.00002, in the range of [5, 37000]. `DisplayPrimariesY[3]` + and `WhitePointY` are in increments of 0.00002, in the range of [5, 42000]. `MaxDisplayMasteringLuminance` is in units of 1 candela per square meter. + `MinDisplayMasteringLuminance` is in units of 0.0001 candela per square meter. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MASTERING_DISPLAY_COLOUR_VOLUME. */ + mfxU16 reserved[15]; + + mfxU16 InsertPayloadToggle; /*!< InsertHDRPayload enumerator value. */ + mfxU16 DisplayPrimariesX[3]; /*!< Color primaries for a video source. Consist of RGB x coordinates and + define how to convert colors from RGB color space to CIE XYZ color space. */ + mfxU16 DisplayPrimariesY[3]; /*!< Color primaries for a video source. Consists of RGB y coordinates and + defines how to convert colors from RGB color space to CIE XYZ color space.*/ + mfxU16 WhitePointX; /*!< White point X coordinate. */ + mfxU16 WhitePointY; /*!< White point Y coordinate. */ + mfxU32 MaxDisplayMasteringLuminance; /*!< Specify maximum luminance of the display on which the content was authored.*/ + mfxU32 MinDisplayMasteringLuminance; /*!< Specify minimum luminance of the display on which the content was authored. */ +} mfxExtMasteringDisplayColourVolume; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Handle the HDR information. + + During encoding: If the application attaches this structure to the mfxEncodeCtrl structure at runtime, + the encoder inserts the HDR information 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 information based on InsertPayloadToggle. + + During video processing: If the application attaches this structure for video processing, InsertPayloadToggle will be ignored. + + During decoding: If the application attaches this structure to the mfxFrameSurface1 structure at runtime + which will seed to the MFXVideoDECODE_DecodeFrameAsync() as surface_work parameter, + the decoder will parse the HDR information if the bitstream include HDR information per frame. + The parsed HDR information will be attached to the ExtendBuffer of surface_out parameter of MFXVideoDECODE_DecodeFrameAsync() + with flag `InsertPayloadToggle` to indicate if there is valid HDR information in the clip. + `InsertPayloadToggle` will be set to `MFX_PAYLOAD_IDR` if oneVPL gets valid HDR information, otherwise it will be set to `MFX_PAYLOAD_OFF`. + This function is support for HEVC and AV1 only now. + + Field semantics are defined in ITU-T* H.265 Annex D, AV1 6.7.3 Metadata high dynamic range content light level semantics. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to EXTBUFF_CONTENT_LIGHT_LEVEL_INFO. */ + mfxU16 reserved[9]; + + mfxU16 InsertPayloadToggle; /*!< InsertHDRPayload enumerator value. */ + mfxU16 MaxContentLightLevel; /*!< Maximum luminance level of the content. Field range is 1 to 65535. */ + mfxU16 MaxPicAverageLightLevel; /*!< Maximum average per-frame luminance level of the content. Field range is 1 to 65535. */ +} mfxExtContentLightLevelInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the H.264 picture timing SEI message. The encoder ignores it if HRD information in + the stream is absent and the PicTimingSEI option in the mfxExtCodingOption structure is turned off. See mfxExtCodingOption for details. + + If the application attaches this structure to the mfxVideoParam structure during initialization, the encoder inserts the picture timing + SEI message based on provided template in every access unit of coded bitstream. + + If application attaches this structure to the mfxEncodeCtrl structure at runtime, the encoder inserts the picture timing SEI message + based on provided template in access unit that represents current frame. + + These parameters define the picture timing information. An invalid value of 0xFFFF indicates that application does not set the value and + encoder must calculate it. + + See Annex D of the ISO*\/IEC* 14496-10 specification for the definition of these parameters. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_PICTURE_TIMING_SEI. */ + mfxU32 reserved[14]; + + struct { + mfxU16 ClockTimestampFlag; + mfxU16 CtType; + mfxU16 NuitFieldBasedFlag; + mfxU16 CountingType; + mfxU16 FullTimestampFlag; + mfxU16 DiscontinuityFlag; + mfxU16 CntDroppedFlag; + mfxU16 NFrames; + mfxU16 SecondsFlag; + mfxU16 MinutesFlag; + mfxU16 HoursFlag; + mfxU16 SecondsValue; + mfxU16 MinutesValue; + mfxU16 HoursValue; + mfxU32 TimeOffset; + } TimeStamp[3]; +} mfxExtPictureTimingSEI; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the H.264 temporal layers hierarchy. + + If the application attaches it to the mfxVideoParam + structure during initialization, the encoder generates the temporal layers and inserts the prefix NAL unit before each slice to + indicate the temporal and priority IDs of the layer. + + This structure can be used with the display-order encoding mode only. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_TEMPORAL_LAYERS. */ + mfxU32 reserved1[4]; + mfxU16 reserved2; + mfxU16 BaseLayerPID; /*!< The priority ID of the base layer. The encoder increases the ID for each temporal layer and writes to the prefix NAL unit. */ + + struct { + mfxU16 Scale; /*!< The ratio between the frame rates of the current temporal layer and the base layer. */ + mfxU16 reserved[3]; + }Layer[8]; +} mfxExtAvcTemporalLayers; /*!< The array of temporal layers; Use Scale=0 to specify absent layers. */ +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to retrieve encoder capability. See the description of mode 4 of the MFXVideoENCODE_Query function + for details on how to use this structure. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine + if the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_CAPABILITY. */ + + mfxU32 MBPerSec; /*!< Specify the maximum processing rate in macro blocks per second. */ + mfxU16 reserved[58]; +} mfxExtEncoderCapability; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to control the encoder behavior during reset. By using this structure, the application + instructs the encoder to start a new coded sequence after reset or to continue encoding of the current sequence. + + This structure is also used in mode 3 of the MFXVideoENCODE_Query function to check for reset outcome before actual reset. The application + should set StartNewSequence to the required behavior and call the query function. If the query fails (see status codes below), then reset is not + possible in current encoder state. If the application sets StartNewSequence to MFX_CODINGOPTION_UNKNOWN, then the query function replaces the coding option with the + actual reset type: MFX_CODINGOPTION_ON if the encoder will begin a new sequence after reset or MFX_CODINGOPTION_OFF if the encoder will continue the current sequence. + + Using this structure may cause one of the following status codes from the MFXVideoENCODE_Reset and MFXVideoENCODE_Queryfunctions: + + @li MFX_ERR_INVALID_VIDEO_PARAM If a reset is not possible. For example, the application sets StartNewSequence to off and requests resolution change. + + @li MFX_ERR_INCOMPATIBLE_VIDEO_PARAM If the application requests change that leads to memory allocation. For example, the application sets StartNewSequence to on and + requests resolution change to greater than the initialization value. + + @li MFX_ERR_NONE If reset is possible. + + The following limited list of parameters can be changed without starting a new coded sequence: + + @li The bitrate parameters, TargetKbps and MaxKbps, in the mfxInfoMFX structure. + + @li The number of slices, NumSlice, in the mfxInfoMFX structure. Number of slices should be equal to or less than the number of slices during initialization. + + @li The number of temporal layers in the mfxExtAvcTemporalLayers structure. Reset should be called immediately before encoding of frame from base layer and + number of reference frames should be large enough for the new temporal layers structure. + + @li The quantization parameters, QPI, QPP and QPB, in the mfxInfoMFX structure. + + The application should retrieve all cached frames before calling reset. When the Query API function + checks for reset outcome, it expects that this requirement be satisfied. If it is not true and there are some cached frames inside the + encoder, then the query result may differ from the reset result, because the encoder may insert an IDR frame to produce valid coded sequence. + \verbatim embed:rst + See the :ref:`Configuration Change ` section for more information. + \endverbatim + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if the + functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and call the + MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE, then the functionality is supported. + + \verbatim embed:rst + See the :ref:`Streaming and Video Conferencing Features ` section for more information. + \endverbatim + +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_RESET_OPTION. */ + + /*! + Instructs encoder to start new sequence after reset. Use one of the CodingOptionValue options: + + @li MFX_CODINGOPTION_ON The encoder completely reset internal state and begins new coded sequence after reset, including + insertion of IDR frame, sequence, and picture headers. + + @li MFX_CODINGOPTION_OFF The encoder continues encoding of current coded sequence after reset, without insertion of IDR frame. + + @li MFX_CODINGOPTION_UNKNOWN Depending on the current encoder state and changes in configuration parameters, the encoder may or may not + start new coded sequence. This value is also used to query reset outcome. + */ + mfxU16 StartNewSequence; + mfxU16 reserved[11]; +} mfxExtEncoderResetOption; +MFX_PACK_END() + +/*! The LongTermIdx specifies long term index of picture control. */ +enum { + MFX_LONGTERM_IDX_NO_IDX = 0xFFFF /*!< Long term index of picture is undefined. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to report additional information about the encoded picture. The application can attach + this buffer to the mfxBitstream structure before calling MFXVideoENCODE_EncodeFrameAsync function. For interlaced content the encoder + requires two such structures. They correspond to fields in encoded order. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_FRAME_INFO. */ + + mfxU32 FrameOrder; /*!< Frame order of encoded picture. */ + mfxU16 PicStruct; /*!< Picture structure of encoded picture. */ + mfxU16 LongTermIdx; /*!< Long term index of encoded picture if applicable. */ + mfxU32 MAD; /*!< Mean Absolute Difference between original pixels of the frame and motion compensated (for inter macroblocks) or + spatially predicted (for intra macroblocks) pixels. Only luma component, Y plane, is used in calculation. */ + mfxU16 BRCPanicMode; /*!< Bitrate control was not able to allocate enough bits for this frame. Frame quality may be unacceptably low. */ + mfxU16 QP; /*!< Luma QP. */ + mfxU32 SecondFieldOffset; /*!< Offset to second field. Second field starts at mfxBitstream::Data + mfxBitstream::DataOffset + mfxExtAVCEncodedFrameInfo::SecondFieldOffset. */ + mfxU16 reserved[2]; + + struct { + /*! @{ + @name Reference Lists + The following structure members are used by the reference lists contained in the parent structure. */ + mfxU32 FrameOrder; /*!< Frame order of reference picture. */ + mfxU16 PicStruct; /*!< Picture structure of reference picture. */ + mfxU16 LongTermIdx; /*!< Long term index of reference picture if applicable. */ + mfxU16 reserved[4]; + /*! @} */ + } UsedRefListL0[32], /*!< Reference list that has been used to encode picture. */ + UsedRefListL1[32]; /*!< Reference list that has been used to encode picture. */ +} mfxExtAVCEncodedFrameInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to specify input stream details for composition of several input surfaces in the one output. +*/ +typedef struct mfxVPPCompInputStream { + mfxU32 DstX; /*!< X coordinate of location of input stream in output surface. */ + mfxU32 DstY; /*!< Y coordinate of location of input stream in output surface. */ + mfxU32 DstW; /*!< Width of of location of input stream in output surface.*/ + mfxU32 DstH; /*!< Height of of location of input stream in output surface.*/ + + mfxU16 LumaKeyEnable; /*!< Non-zero value enables luma keying for the input stream. Luma keying is used to mark some of the areas + of the frame with specified luma values as transparent. It may, for example, be used for closed captioning. */ + mfxU16 LumaKeyMin; /*!< Minimum value of luma key, inclusive. Pixels whose luma values fit in this range are rendered transparent. */ + mfxU16 LumaKeyMax; /*!< Maximum value of luma key, inclusive. Pixels whose luma values fit in this range are rendered transparent. */ + + mfxU16 GlobalAlphaEnable; /*!< Non-zero value enables global alpha blending for this input stream. */ + mfxU16 GlobalAlpha; /*!< Alpha value for this stream. Should be in the range of 0 to 255, where 0 is transparent and 255 is opaque. */ + mfxU16 PixelAlphaEnable; /*!< Non-zero value enables per pixel alpha blending for this input stream. The stream should have RGB color format. */ + + mfxU16 TileId; /*!< Specify the tile this video stream is assigned to. Should be in the range of 0 to NumTiles. Valid only if NumTiles > 0. */ + + mfxU16 reserved2[17]; +} mfxVPPCompInputStream; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Used to control composition of several input surfaces in one output. In this mode, the VPP skips + any other filters. The VPP returns an error if any mandatory filter is specified and returns the filter skipped warning if an optional filter is specified. The only + supported filters are deinterlacing and interlaced scaling. The only supported combinations of input and output color formats are: + + - RGB to RGB, + + - NV12 to NV12, + + - RGB and NV12 to NV12, for per the pixel alpha blending use case. + + The VPP returns MFX_ERR_MORE_DATA for additional input until an output is ready. When the output is ready, the VPP returns MFX_ERR_NONE. + The application must process the output frame after synchronization. + + The composition process is controlled by: + + - mfxFrameInfo::CropXYWH in the input surface defines the location of the picture in the input frame. + + - InputStream[i].DstXYWH defines the location of the cropped input picture in the output frame. + + - mfxFrameInfo::CropXYWH in the output surface defines the actual part of the output frame. All pixels in the output frame outside this region will be filled by the specified color. + + If the application uses the composition process on video streams with different frame sizes, the application should provide maximum frame size in the + mfxVideoParam structure during the initialization, reset, or query operations. + + If the application uses the composition process, the MFXVideoVPP_QueryIOSurf function returns the cumulative number of input surfaces, that is, the number + required to process all input video streams. The function sets the frame size in the mfxFrameAllocRequest equal to the size provided by the + application in the mfxVideoParam structure. + + The composition process supports all types of surfaces. + + All input surfaces should have the same type and color format, except for the per pixel alpha blending case, where it is allowable to mix NV12 and RGB + surfaces. + + There are three different blending use cases: + + - Luma keying. All input surfaces should have the NV12 color format specified during VPP initialization. Part of each surface, including the + first one, may be rendered transparent by using LumaKeyEnable, LumaKeyMin, and LumaKeyMax values. + + - Global alpha blending. All input surfaces should have the same color format, NV12 or RGB, specified during VPP initialization. Each input surface, including the first one, can be blended with underlying surfaces by using GlobalAlphaEnable and + GlobalAlpha values. + + - Per-pixel alpha blending. It is allowed to mix NV12 and RGB input surfaces. Each RGB input surface, including the first one, + can be blended with underlying surfaces by using PixelAlphaEnable value. + + It is not allowed to mix different blending use cases in the same function call. + + In the special case where the destination region of the output surface defined by output crops is fully covered with destination sub-regions of the + surfaces, the fast compositing mode can be enabled. The main use case for this mode is a video-wall scenario with a fixed destination surface + partition into sub-regions of potentially different size. + + In order to trigger this mode, the application must cluster input surfaces into tiles, defining at least one tile by setting the NumTiles + field to be greater than 0, and assigning surfaces to the corresponding tiles by setting the TileId field to the value within the 0 to NumTiles range per + input surface. Tiles should also satisfy the following additional constraints: + + - Each tile should not have more than 8 surfaces assigned to it. + + - Tile bounding boxes, as defined by the enclosing rectangles of a union of a surfaces assigned to this tile, should not intersect. + + Background color may be changed dynamically through Reset. There is no default value. YUV black is (0;128;128) or (16;128;128) depending + on the sample range. The library uses a YUV or RGB triple depending on output color format. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_COMPOSITE. */ + + /* background color*/ + union { + mfxU16 Y; /*!< Y value of the background color. */ + mfxU16 R; /*!< R value of the background color. */ + }; + union { + mfxU16 U; /*!< U value of the background color. */ + mfxU16 G; /*!< G value of the background color. */ + }; + union { + mfxU16 V; /*!< V value of the background color. */ + mfxU16 B; /*!< B value of the background color. */ + }; + mfxU16 NumTiles; /*!< Number of input surface clusters grouped together to enable fast compositing. May be changed dynamically + at runtime through Reset. */ + mfxU16 reserved1[23]; + + mfxU16 NumInputStream; /*!< Number of input surfaces to compose one output. May be changed dynamically at runtime through Reset. Number of surfaces + can be decreased or increased, but should not exceed the number specified during initialization. Query mode 2 should be used + to find the maximum supported number. */ + mfxVPPCompInputStream *InputStream; /*!< An array of mfxVPPCompInputStream structures that describe composition of input video streams. It should consist of exactly NumInputStream elements. */ +} mfxExtVPPComposite; +MFX_PACK_END() + +/*! The TransferMatrix enumerator itemizes color transfer matrices. */ +enum { + MFX_TRANSFERMATRIX_UNKNOWN = 0, /*!< Transfer matrix is not specified */ + MFX_TRANSFERMATRIX_BT709 = 1, /*!< Transfer matrix from ITU-R BT.709 standard. */ + MFX_TRANSFERMATRIX_BT601 = 2 /*!< Transfer matrix from ITU-R BT.601 standard. */ +}; + +/*! The NominalRange enumerator itemizes pixel's value nominal range. */ +enum { + MFX_NOMINALRANGE_UNKNOWN = 0, /*!< Range is not defined. */ + MFX_NOMINALRANGE_0_255 = 1, /*!< Range is from 0 to 255. */ + MFX_NOMINALRANGE_16_235 = 2 /*!< Range is from 16 to 235. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to control transfer matrix and nominal range of YUV frames. The application + should provide this during initialization. Supported for multiple conversions, for example YUV to YUV, YUV to RGB, and RGB to YUV. + + @note This structure is used by VPP only and is not compatible with mfxExtVideoSignalInfo. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO. */ + mfxU16 reserved1[4]; + + union { + struct { // Init + struct { + mfxU16 TransferMatrix; /*!< Transfer matrix. */ + mfxU16 NominalRange; /*!< Nominal range. */ + mfxU16 reserved2[6]; + } In, Out; + }; + struct { // Runtime< + mfxU16 TransferMatrix; /*!< Transfer matrix. */ + mfxU16 NominalRange; /*!< Nominal range. */ + mfxU16 reserved3[14]; + }; + }; +} mfxExtVPPVideoSignalInfo; +MFX_PACK_END() + +/*! The ROImode enumerator itemizes QP adjustment mode for ROIs. */ +enum { + MFX_ROI_MODE_PRIORITY = 0, /*!< Priority mode. */ + MFX_ROI_MODE_QP_DELTA = 1, /*!< QP mode */ + MFX_ROI_MODE_QP_VALUE = 2 /*!< Absolute QP */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify different Region Of Interests during encoding. It may be used at + initialization or at runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_ROI. */ + + mfxU16 NumROI; /*!< Number of ROI descriptions in array. The Query API function mode 2 returns maximum supported value (set it to 256 and + query will update it to maximum supported value). */ + mfxU16 ROIMode; /*!< QP adjustment mode for ROIs. Defines if Priority or DeltaQP is used during encoding. */ + mfxU16 reserved1[10]; + + struct { + /*! @{ + @name ROI location rectangle + The ROI rectangle definition uses end-point exclusive notation. In other words, the pixel with (Right, Bottom) + coordinates lies immediately outside of the ROI. Left, Top, Right, Bottom should be aligned by codec-specific block boundaries + (should be dividable by 16 for AVC, or by 32 for HEVC). Every ROI with unaligned coordinates will be expanded by the library to minimal-area + block-aligned ROI, enclosing the original one. For example (5, 5, 15, 31) ROI will be expanded to (0, 0, 16, 32) for AVC encoder, + or to (0, 0, 32, 32) for HEVC. + */ + mfxU32 Left; /*!< Left ROI's coordinate. */ + mfxU32 Top; /*!< Top ROI's coordinate. */ + mfxU32 Right; /*!< Right ROI's coordinate. */ + mfxU32 Bottom; /*!< Bottom ROI's coordinate. */ + union { + /*! Priority of ROI. Used if ROIMode = MFX_ROI_MODE_PRIORITY.This is an absolute value in the range of -3 to 3, + which will be added to the MB QP. Priority is deprecated mode and is used only for backward compatibility. + Bigger value produces better quality. */ + mfxI16 Priority; + /*! Delta QP of ROI. Used if ROIMode = MFX_ROI_MODE_QP_DELTA. This is an absolute value in the range of -51 to 51, + which will be added to the MB QP. Lesser value produces better quality. */ + mfxI16 DeltaQP; + }; + mfxU16 reserved2[7]; + /*! @} */ + } ROI[256]; /*!< Array of ROIs. Different ROI may overlap each other. If macroblock belongs to several ROI, + Priority from ROI with lowest index is used. */ +} mfxExtEncoderROI; +MFX_PACK_END() + +/*! The DeinterlacingMode enumerator itemizes VPP deinterlacing modes. */ +enum { + MFX_DEINTERLACING_BOB = 1, /*!< BOB deinterlacing mode. */ + MFX_DEINTERLACING_ADVANCED = 2, /*!< Advanced deinterlacing mode. */ + MFX_DEINTERLACING_AUTO_DOUBLE = 3, /*!< Auto mode with deinterlacing double frame rate output. */ + MFX_DEINTERLACING_AUTO_SINGLE = 4, /*!< Auto mode with deinterlacing single frame rate output. */ + MFX_DEINTERLACING_FULL_FR_OUT = 5, /*!< Deinterlace only mode with full frame rate output. */ + MFX_DEINTERLACING_HALF_FR_OUT = 6, /*!< Deinterlace only Mode with half frame rate output. */ + MFX_DEINTERLACING_24FPS_OUT = 7, /*!< 24 fps fixed output mode. */ + MFX_DEINTERLACING_FIXED_TELECINE_PATTERN = 8, /*!< Fixed telecine pattern removal mode. */ + MFX_DEINTERLACING_30FPS_OUT = 9, /*!< 30 fps fixed output mode. */ + MFX_DEINTERLACING_DETECT_INTERLACE = 10, /*!< Only interlace detection. */ + MFX_DEINTERLACING_ADVANCED_NOREF = 11, /*!< Advanced deinterlacing mode without using of reference frames. */ + MFX_DEINTERLACING_ADVANCED_SCD = 12, /*!< Advanced deinterlacing mode with scene change detection. */ + MFX_DEINTERLACING_FIELD_WEAVING = 13 /*!< Field weaving. */ +}; + +/*! The TelecinePattern enumerator itemizes telecine patterns. */ +enum { + MFX_TELECINE_PATTERN_32 = 0, /*!< 3:2 telecine. */ + MFX_TELECINE_PATTERN_2332 = 1, /*!< 2:3:3:2 telecine. */ + MFX_TELECINE_PATTERN_FRAME_REPEAT = 2, /*!< One frame repeat telecine. */ + MFX_TELECINE_PATTERN_41 = 3, /*!< 4:1 telecine. */ + MFX_TELECINE_POSITION_PROVIDED = 4 /*!< User must provide position inside a sequence of 5 frames where the artifacts start. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify different deinterlacing algorithms. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_DEINTERLACING. */ + mfxU16 Mode; /*!< Deinterlacing algorithm. See the DeinterlacingMode enumerator for details. */ + mfxU16 TelecinePattern; /*!< Specifies telecine pattern when Mode = MFX_DEINTERLACING_FIXED_TELECINE_PATTERN. See the TelecinePattern enumerator for details.*/ + mfxU16 TelecineLocation; /*!< Specifies position inside a sequence of 5 frames where the artifacts start when TelecinePattern = MFX_TELECINE_POSITION_PROVIDED*/ + mfxU16 reserved[9]; /*!< Reserved for future use. */ +} mfxExtVPPDeinterlacing; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies reference lists for the encoder. It may be used together with the mfxExtAVCRefListCtrl + structure to create customized reference lists. If both structures are used together, then the encoder takes reference lists from the + mfxExtAVCRefLists structure and modifies them according to the mfxExtAVCRefListCtrl instructions. In case of interlaced coding, + the first mfxExtAVCRefLists structure affects TOP field and the second - BOTTOM field. + + @note Not all implementations of the encoder support this structure. The application must use the Query API function to determine if it is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_REFLISTS. */ + mfxU16 NumRefIdxL0Active; /*!< Specify the number of reference frames in the active reference list L0. This number should be less than or + equal to the NumRefFrame parameter from encoding initialization. */ + mfxU16 NumRefIdxL1Active; /*!< Specify the number of reference frames in the active reference list L1. This number should be less than or + equal to the NumRefFrame parameter from encoding initialization. */ + mfxU16 reserved[2]; + + /*! Used by the reference lists contained in the parent structure. Together these fields are used to identify reference picture. */ + struct mfxRefPic{ + mfxU32 FrameOrder; /*!< Use FrameOrder = MFX_FRAMEORDER_UNKNOWN to mark + unused entry. */ + mfxU16 PicStruct; /*!< Use PicStruct = MFX_PICSTRUCT_FIELD_TFF for TOP field, PicStruct = MFX_PICSTRUCT_FIELD_BFF for + BOTTOM field. */ + mfxU16 reserved[5]; + } RefPicList0[32], /*!< Specify L0 reference list. */ + RefPicList1[32]; /*!< Specify L1 reference list. */ + +}mfxExtAVCRefLists; +MFX_PACK_END() + +/*! The VPPFieldProcessingMode enumerator is used to control VPP field processing algorithm. */ +enum { + MFX_VPP_COPY_FRAME =0x01, /*!< Copy the whole frame. */ + MFX_VPP_COPY_FIELD =0x02, /*!< Copy only one field. */ + MFX_VPP_SWAP_FIELDS =0x03 /*!< Swap top and bottom fields. */ +}; + +/*! The PicType enumerator itemizes picture type. */ +enum { + MFX_PICTYPE_UNKNOWN =0x00, /*!< Picture type is unknown. */ + MFX_PICTYPE_FRAME =0x01, /*!< Picture is a frame. */ + MFX_PICTYPE_TOPFIELD =0x02, /*!< Picture is a top field. */ + MFX_PICTYPE_BOTTOMFIELD =0x04 /*!< Picture is a bottom field. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP field processing algorithm. The application can attach this extended buffer to + the mfxVideoParam structure to configure initialization and/or to the mfxFrameData during runtime. Runtime configuration has priority + over initialization configuration. If the field processing algorithm was activated via the mfxExtVPPDoUse structure and the mfxExtVPPFieldProcessing + extended buffer was not provided during initialization, this buffer must be attached to the mfxFrameData structure of each input surface. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_FIELD_PROCESSING. */ + + mfxU16 Mode; /*!< Specifies the mode of the field processing algorithm. See the VPPFieldProcessingMode enumerator for values of this option. */ + mfxU16 InField; /*!< When Mode is MFX_VPP_COPY_FIELD, specifies input field. See the PicType enumerator for values of this parameter. */ + mfxU16 OutField; /*!< When Mode is MFX_VPP_COPY_FIELD, specifies output field. See the PicType enumerator for values of this parameter. */ + mfxU16 reserved[25]; +} mfxExtVPPFieldProcessing; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + If attached to the mfxVideoParam structure during the Init stage, this buffer will instruct the decoder to resize output frames via the + fixed function resize engine (if supported by hardware), utilizing direct pipe connection and bypassing intermediate memory operations. + The main benefits of this mode of pipeline operation are offloading resize operation to a dedicated engine, thus reducing power + consumption and memory traffic. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DEC_VIDEO_PROCESSING. */ + + /*! Input surface description. */ + struct mfxIn{ + mfxU16 CropX; /*!< X coordinate of region of interest of the input surface. */ + mfxU16 CropY; /*!< Y coordinate of region of interest of the input surface. */ + mfxU16 CropW; /*!< Width coordinate of region of interest of the input surface. */ + mfxU16 CropH; /*!< Height coordinate of region of interest of the input surface. */ + mfxU16 reserved[12]; + }In; /*!< Input surface description. */ + + /*! Output surface description. */ + struct mfxOut{ + mfxU32 FourCC; /*!< FourCC of output surface Note: Should be MFX_FOURCC_NV12. */ + mfxU16 ChromaFormat; /*!< Chroma Format of output surface. + @note Should be MFX_CHROMAFORMAT_YUV420 */ + mfxU16 reserved1; + + mfxU16 Width; /*!< Width of output surface. */ + mfxU16 Height; /*!< Height of output surface. */ + + mfxU16 CropX; /*!< X coordinate of region of interest of the output surface. */ + mfxU16 CropY; /*!< Y coordinate of region of interest of the output surface. */ + mfxU16 CropW; /*!< Width coordinate of region of interest of the output surface. */ + mfxU16 CropH; /*!< Height coordinate of region of interest of the output surface. */ + mfxU16 reserved[22]; + }Out; /*!< Output surface description. */ + + mfxU16 reserved[13]; +} mfxExtDecVideoProcessing; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Members of this structure define the location of chroma samples information. + + See Annex E of the ISO*\/IEC* 14496-10 specification for the definition of these parameters. + + @note Not all implementations of the encoder support this structure. The application must use the Query API function to determine if it is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_CHROMA_LOC_INFO. */ + + mfxU16 ChromaLocInfoPresentFlag; + mfxU16 ChromaSampleLocTypeTopField; + mfxU16 ChromaSampleLocTypeBottomField; + mfxU16 reserved[9]; +} mfxExtChromaLocInfo; +MFX_PACK_END() + +/*! The MBQPMode enumerator itemizes QP update modes. */ +enum { + MFX_MBQP_MODE_QP_VALUE = 0, /*!< QP array contains QP values. */ + MFX_MBQP_MODE_QP_DELTA = 1, /*!< QP array contains deltas for QP. */ + MFX_MBQP_MODE_QP_ADAPTIVE = 2 /*!< QP array contains deltas for QP or absolute QP values. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies per-MB or per-CU mode and QP or DeltaQP value depending on the mode type. + */ +typedef struct{ + union { + /*! + QP for MB or CU. Valid when Mode = MFX_MBQP_MODE_QP_VALUE. + + For AVC, the valid range is 1 to 51. + + For HEVC, the valid range is 1 to 51. The application's provided QP values should be valid, otherwise invalid QP values may cause undefined behavior. + + MBQP map should be aligned for 16x16 block size. The align rule is: (width +15 /16) && (height +15 /16). + + For MPEG2, the valid range is 1 to 112. QP corresponds to quantizer_scale of the ISO*\/IEC* 13818-2 specification. + */ + mfxU8 QP; + /*! + Per-macroblock QP delta. Valid when Mode = MFX_MBQP_MODE_QP_DELTA. + */ + mfxI8 DeltaQP; + }; + mfxU16 Mode; /*!< Defines QP update mode. Can be equal to MFX_MBQP_MODE_QP_VALUE or MFX_MBQP_MODE_QP_DELTA. */ +} mfxQPandMode; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Specifies per-macroblock QP for current frame if mfxExtCodingOption3::EnableMBQP was turned ON during + encoder initialization. The application can attach this extended buffer to the mfxEncodeCtrl structure during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MBQP. */ + + mfxU32 reserved[9]; + mfxU32 Pitch; /*!< Distance in bytes between the start of two consecutive rows in the QP array. */ + mfxU16 Mode; /*!< Defines QP update mode. See MBQPMode enumerator for more details. */ + mfxU16 BlockSize; /*!< QP block size, valid for HEVC only during Init and Runtime. */ + mfxU32 NumQPAlloc; /*!< Size of allocated by application QP or DeltaQP array. */ + union { + /*! + Pointer to a list of per-macroblock QP in raster scan order. In case of interlaced encoding the first half of QP array affects the top + field and the second half of QP array affects the bottom field. Valid when Mode = MFX_MBQP_MODE_QP_VALUE. + + For AVC, the valid range is 1 to 51. + + For HEVC, the valid range is 1 to 51. Application's provided QP values should be valid. Otherwise invalid QP values may cause undefined behavior. + MBQP map should be aligned for 16x16 block size. The alignment rule is (width +15 /16) && (height +15 /16). + + For MPEG2, QP corresponds to quantizer_scale of the ISO*\/IEC* 13818-2 specification and has a valid range of 1 to 112. + */ + mfxU8 *QP; + mfxI8 *DeltaQP; /*!< Pointer to a list of per-macroblock QP deltas in raster scan order. + For block i: QP[i] = BrcQP[i] + DeltaQP[i]. Valid when Mode = MFX_MBQP_MODE_QP_DELTA. */ + mfxQPandMode *QPmode; /*!< Block-granularity modes when MFX_MBQP_MODE_QP_ADAPTIVE is set. */ + + mfxU64 reserved2; + }; +} mfxExtMBQP; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Runtime ctrl buffer for SPS/PPS insertion with current encoding frame. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_INSERT_HEADERS. */ + mfxU16 SPS; /*!< Tri-state option to insert SPS. */ + mfxU16 PPS; /*!< Tri-state option to insert PPS. */ + mfxU16 reserved[8]; +} mfxExtInsertHeaders; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Specifies rectangle areas for IPCM coding mode. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODER_IPCM_AREA. */ + mfxU16 reserve1[10]; + + mfxU16 NumArea; /*! Number of areas */ + struct area { + + mfxU32 Left; /*!< Left area coordinate. */ + mfxU32 Top; /*!< Top area coordinate. */ + mfxU32 Right; /*!< Right area coordinate. */ + mfxU32 Bottom; /*!< Bottom area coordinate. */ + + mfxU16 reserved2[8]; + + } * Areas; /*!< Array of areas. */ +} mfxExtEncoderIPCMArea; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Specifies macroblock map for current frame which forces specified macroblocks to be encoded as intra + if mfxExtCodingOption3::EnableMBForceIntra was turned ON during encoder initialization. The application can attach this extended + buffer to the mfxEncodeCtrl structure during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MB_FORCE_INTRA. */ + + mfxU32 reserved[11]; + mfxU32 MapSize; /*!< Macroblock map size. */ + union { + mfxU8 *Map; /*!< Pointer to a list of force intra macroblock flags in raster scan order. Each flag is one byte in map. Set flag to 1 + to force corresponding macroblock to be encoded as intra. In case of interlaced encoding, the first half of map + affects top field and the second half of map affects the bottom field. */ + mfxU64 reserved2; + }; +} mfxExtMBForceIntra; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures tiles options for the HEVC encoder. The application can attach this extended buffer to the + mfxVideoParam structure to configure initialization. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_HEVC_TILES. */ + + mfxU16 NumTileRows; /*!< Number of tile rows. */ + mfxU16 NumTileColumns; /*!< Number of tile columns. */ + mfxU16 reserved[74]; +}mfxExtHEVCTiles; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Specifies macroblock map for current frame which forces specified macroblocks to be non-skip if + mfxExtCodingOption3::MBDisableSkipMap was turned ON during encoder initialization. The application can attach this + extended buffer to the mfxEncodeCtrl structure during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MB_DISABLE_SKIP_MAP. */ + + mfxU32 reserved[11]; + mfxU32 MapSize; /*!< Macroblock map size. */ + union { + mfxU8 *Map; /*!< Pointer to a list of non-skip macroblock flags in raster scan order. Each flag is one byte in map. Set flag to 1 to force + corresponding macroblock to be non-skip. In case of interlaced encoding, the first half of map affects + the top field and the second half of map affects the bottom field. */ + mfxU64 reserved2; + }; +} mfxExtMBDisableSkipMap; +MFX_PACK_END() + +/*! The GeneralConstraintFlags enumerator uses bit-ORed values to itemize HEVC bitstream indications for specific profiles. Each value + indicates for format range extensions profiles. + To specify HEVC Main 10 Still Picture profile applications have to set mfxInfoMFX::CodecProfile == MFX_PROFILE_HEVC_MAIN10 and + mfxExtHEVCParam::GeneralConstraintFlags == MFX_HEVC_CONSTR_REXT_ONE_PICTURE_ONLY. */ +enum { + /* REXT Profile constraint flags*/ + MFX_HEVC_CONSTR_REXT_MAX_12BIT = (1 << 0), + MFX_HEVC_CONSTR_REXT_MAX_10BIT = (1 << 1), + MFX_HEVC_CONSTR_REXT_MAX_8BIT = (1 << 2), + MFX_HEVC_CONSTR_REXT_MAX_422CHROMA = (1 << 3), + MFX_HEVC_CONSTR_REXT_MAX_420CHROMA = (1 << 4), + MFX_HEVC_CONSTR_REXT_MAX_MONOCHROME = (1 << 5), + MFX_HEVC_CONSTR_REXT_INTRA = (1 << 6), + MFX_HEVC_CONSTR_REXT_ONE_PICTURE_ONLY = (1 << 7), + MFX_HEVC_CONSTR_REXT_LOWER_BIT_RATE = (1 << 8) +}; + + +/*! The SampleAdaptiveOffset enumerator uses bit-ORed values to itemize corresponding HEVC encoding feature. */ +enum { + MFX_SAO_UNKNOWN = 0x00, /*!< Use default value for platform/TargetUsage. */ + MFX_SAO_DISABLE = 0x01, /*!< Disable SAO. If set during Init leads to SPS sample_adaptive_offset_enabled_flag = 0. + If set during Runtime, leads to to slice_sao_luma_flag = 0 and slice_sao_chroma_flag = 0 + for current frame. */ + MFX_SAO_ENABLE_LUMA = 0x02, /*!< Enable SAO for luma (slice_sao_luma_flag = 1). */ + MFX_SAO_ENABLE_CHROMA = 0x04 /*!< Enable SAO for chroma (slice_sao_chroma_flag = 1). */ +}; + + +/* This struct has 4-byte alignment for binary compatibility with previously released versions of API */ +MFX_PACK_BEGIN_USUAL_STRUCT() +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_HEVC_PARAM. */ + + mfxU16 PicWidthInLumaSamples; /*!< Specifies the width of each coded picture in units of luma samples. */ + mfxU16 PicHeightInLumaSamples; /*!< Specifies the height of each coded picture in units of luma samples. */ + mfxU64 GeneralConstraintFlags; /*!< Additional flags to specify exact profile and constraints. See the GeneralConstraintFlags enumerator for values of this field. */ + mfxU16 SampleAdaptiveOffset; /*!< Controls SampleAdaptiveOffset encoding feature. See the SampleAdaptiveOffset enumerator for supported values + (bit-ORed). Valid during encoder Init and Runtime. */ + mfxU16 LCUSize; /*!< Specifies largest coding unit size (max luma coding block). Valid during encoder Init. */ + mfxU16 reserved[116]; +} mfxExtHEVCParam; +MFX_PACK_END() + +/*! The ErrorTypes enumerator uses bit-ORed values to itemize bitstream error types. */ +enum { + MFX_ERROR_NO = 0, /*!< No error in bitstream. */ + MFX_ERROR_PPS = (1 << 0), /*!< Invalid/corrupted PPS. */ + MFX_ERROR_SPS = (1 << 1), /*!< Invalid/corrupted SPS. */ + MFX_ERROR_SLICEHEADER = (1 << 2), /*!< Invalid/corrupted slice header. */ + MFX_ERROR_SLICEDATA = (1 << 3), /*!< Invalid/corrupted slice data. */ + MFX_ERROR_FRAME_GAP = (1 << 4), /*!< Missed frames. */ + MFX_ERROR_JPEG_APP0_MARKER = (1 << 5), /*!< Invalid/corrupted APP0 marker. */ + MFX_ERROR_JPEG_APP1_MARKER = (1 << 6), /*!< Invalid/corrupted APP1 marker. */ + MFX_ERROR_JPEG_APP2_MARKER = (1 << 7), /*!< Invalid/corrupted APP2 marker. */ + MFX_ERROR_JPEG_APP3_MARKER = (1 << 8), /*!< Invalid/corrupted APP3 marker. */ + MFX_ERROR_JPEG_APP4_MARKER = (1 << 9), /*!< Invalid/corrupted APP4 marker. */ + MFX_ERROR_JPEG_APP5_MARKER = (1 << 10), /*!< Invalid/corrupted APP5 marker. */ + MFX_ERROR_JPEG_APP6_MARKER = (1 << 11), /*!< Invalid/corrupted APP6 marker. */ + MFX_ERROR_JPEG_APP7_MARKER = (1 << 12), /*!< Invalid/corrupted APP7 marker. */ + MFX_ERROR_JPEG_APP8_MARKER = (1 << 13), /*!< Invalid/corrupted APP8 marker. */ + MFX_ERROR_JPEG_APP9_MARKER = (1 << 14), /*!< Invalid/corrupted APP9 marker. */ + MFX_ERROR_JPEG_APP10_MARKER = (1 << 15), /*!< Invalid/corrupted APP10 marker. */ + MFX_ERROR_JPEG_APP11_MARKER = (1 << 16), /*!< Invalid/corrupted APP11 marker. */ + MFX_ERROR_JPEG_APP12_MARKER = (1 << 17), /*!< Invalid/corrupted APP12 marker. */ + MFX_ERROR_JPEG_APP13_MARKER = (1 << 18), /*!< Invalid/corrupted APP13 marker. */ + MFX_ERROR_JPEG_APP14_MARKER = (1 << 19), /*!< Invalid/corrupted APP14 marker. */ + MFX_ERROR_JPEG_DQT_MARKER = (1 << 20), /*!< Invalid/corrupted DQT marker. */ + MFX_ERROR_JPEG_SOF0_MARKER = (1 << 21), /*!< Invalid/corrupted SOF0 marker. */ + MFX_ERROR_JPEG_DHT_MARKER = (1 << 22), /*!< Invalid/corrupted DHT marker. */ + MFX_ERROR_JPEG_DRI_MARKER = (1 << 23), /*!< Invalid/corrupted DRI marker. */ + MFX_ERROR_JPEG_SOS_MARKER = (1 << 24), /*!< Invalid/corrupted SOS marker. */ + MFX_ERROR_JPEG_UNKNOWN_MARKER = (1 << 25), /*!< Unknown Marker. */ +}; + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the decoders to report bitstream error information right after DecodeHeader or DecodeFrameAsync. + The application can attach this extended buffer to the mfxBitstream structure at runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DECODE_ERROR_REPORT. */ + + mfxU32 ErrorTypes; /*!< Bitstream error types (bit-ORed values). See ErrorTypes enumerator for the list of types. */ + mfxU16 reserved[10]; +} mfxExtDecodeErrorReport; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the decoders to report additional information about a decoded frame. The application can attach this + extended buffer to the mfxFrameSurface1::mfxFrameData structure at runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DECODED_FRAME_INFO. */ + + mfxU16 FrameType; /*!< Frame type. See FrameType enumerator for the list of types. */ + mfxU16 reserved[59]; +} mfxExtDecodedFrameInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the library to pass MPEG 2 specific timing information. + + See ISO/IEC 13818-2 and ITU-T H.262, MPEG-2 Part 2 for the definition of these parameters. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_TIME_CODE. */ + + mfxU16 DropFrameFlag; /*!< Indicated dropped frame. */ + mfxU16 TimeCodeHours; /*!< Hours. */ + mfxU16 TimeCodeMinutes; /*!< Minutes. */ + mfxU16 TimeCodeSeconds; /*!< Seconds. */ + mfxU16 TimeCodePictures; /*!< Pictures. */ + mfxU16 reserved[7]; +} mfxExtTimeCode; +MFX_PACK_END() + +/*! The HEVCRegionType enumerator itemizes type of HEVC region. */ +enum { + MFX_HEVC_REGION_SLICE = 0 /*!< Slice type. */ +}; + +/*! The HEVCRegionEncoding enumerator itemizes HEVC region's encoding. */ +enum { + MFX_HEVC_REGION_ENCODING_ON = 0, + MFX_HEVC_REGION_ENCODING_OFF = 1 +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Attached to the mfxVideoParam structure during HEVC encoder initialization. Specifies the region to encode. + + @note Not all implementations of the encoder support this structure. The application must use the Query API function to determine if it is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_HEVC_REGION. */ + + mfxU32 RegionId; /*!< ID of region. */ + mfxU16 RegionType; /*!< Type of region. See HEVCRegionType enumerator for the list of types. */ + mfxU16 RegionEncoding; /*!< Set to MFX_HEVC_REGION_ENCODING_ON to encode only specified region. */ + mfxU16 reserved[24]; +} mfxExtHEVCRegion; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies weighted prediction table for current frame when all of the following conditions are met: + + @li mfxExtCodingOption3::WeightedPred was set to explicit during encoder Init or Reset . + + @li The current frame is P-frame or mfxExtCodingOption3::WeightedBiPred was set to explicit during encoder Init or Reset. + + @li The current frame is B-frame and is attached to the mfxEncodeCtrl structure. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_PRED_WEIGHT_TABLE. */ + + mfxU16 LumaLog2WeightDenom; /*!< Base 2 logarithm of the denominator for all luma weighting factors. Value must be in the range of 0 to 7, inclusive. */ + mfxU16 ChromaLog2WeightDenom; /*!< Base 2 logarithm of the denominator for all chroma weighting factors. Value must be in the range of 0 to 7, inclusive. */ + mfxU16 LumaWeightFlag[2][32]; /*!< LumaWeightFlag[L][R] equal to 1 specifies that the weighting factors for the luma component are specified for R's entry of RefPicList L. */ + mfxU16 ChromaWeightFlag[2][32]; /*!< ChromaWeightFlag[L][R] equal to 1 specifies that the weighting factors for the chroma component are specified for R's entry of RefPicList L. */ + mfxI16 Weights[2][32][3][2]; /*!< The values of the weights and offsets used in the encoding processing. The value of Weights[i][j][k][m] is + interpreted as: i refers to reference picture list 0 or 1; j refers to reference list entry 0-31; + k refers to data for the luma component when it is 0, the Cb chroma component when it is 1 and + the Cr chroma component when it is 2; m refers to weight when it is 0 and offset when it is 1 */ + mfxU16 reserved[58]; +} mfxExtPredWeightTable; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by encoders to set rounding offset parameters for quantization. It is per-frame based encoding control, + and can be attached to some frames and skipped for others. When the extension buffer is set the application can attach it to the mfxEncodeCtrl + during runtime. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AVC_ROUNDING_OFFSET. */ + + mfxU16 EnableRoundingIntra; /*!< Enable rounding offset for intra blocks. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 RoundingOffsetIntra; /*!< Intra rounding offset. Value must be in the range of 0 to 7, inclusive. */ + mfxU16 EnableRoundingInter; /*!< Enable rounding offset for inter blocks. See the CodingOptionValue enumerator for values of this option. */ + mfxU16 RoundingOffsetInter; /*!< Inter rounding offset. Value must be in the range of 0 to 7, inclusive. */ + + mfxU16 reserved[24]; +} mfxExtAVCRoundingOffset; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify dirty regions within a frame during encoding. It may be used at initialization or at runtime. + + Dirty rectangle definition is using end-point exclusive notation. In other words, the pixel with (Right, Bottom) coordinates lies + immediately outside of the dirty rectangle. Left, Top, Right, Bottom should be aligned by codec-specific block boundaries (should be + dividable by 16 for AVC, or by block size (8, 16, 32 or 64, depends on platform) for HEVC). + + Every dirty rectangle with unaligned + coordinates will be expanded to a minimal-area block-aligned dirty rectangle, enclosing the original one. + For example, a (5, 5, 15, 31) dirty rectangle will be expanded to (0, 0, 16, 32) for AVC encoder, or to (0, 0, 32, 32) for HEVC, + if block size is 32. + + Dirty rectangle (0, 0, 0, 0) is a valid dirty rectangle and means that the frame is not changed. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_DIRTY_RECTANGLES. */ + + mfxU16 NumRect; /*!< Number of dirty rectangles. */ + mfxU16 reserved1[11]; + + struct { + /*! @{ + @name Dirty rectangle coordinates + The following structure members are used by the Rect array contained in the parent structure. + + */ + mfxU32 Left; /*!< Dirty region left coordinate. */ + mfxU32 Top; /*!< Dirty region top coordinate. */ + mfxU32 Right; /*!< Dirty region right coordinate. */ + mfxU32 Bottom; /*!< Dirty region bottom coordinate. */ + + mfxU16 reserved2[8]; + /*! @} */ + } Rect[256]; /*!< Array of dirty rectangles. */ +} mfxExtDirtyRect; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the application to specify moving regions within a frame during encoding. + + Destination rectangle location should be aligned to MB boundaries (should be dividable by 16). If not, the encoder + truncates it to MB boundaries, for example, both 17 and 31 will be truncated to 16. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MOVING_RECTANGLE. */ + + mfxU16 NumRect; /*!< Number of moving rectangles. */ + mfxU16 reserved1[11]; + + struct { + /*! @{ + @name Destination and source rectangle location + The following structure members are used by the Rect array contained in the parent structure. + */ + mfxU32 DestLeft; /*!< Destination rectangle location. */ + mfxU32 DestTop; /*!< Destination rectangle location. */ + mfxU32 DestRight; /*!< Destination rectangle location. */ + mfxU32 DestBottom; /*!< Destination rectangle location. */ + + mfxU32 SourceLeft; /*!< Source rectangle location. */ + mfxU32 SourceTop; /*!< Source rectangle location. */ + mfxU16 reserved2[4]; + /*! @} */ + } Rect[256]; /*!< Array of moving rectangles. */ +} mfxExtMoveRect; +MFX_PACK_END() + +/*! The Angle enumerator itemizes valid rotation angles. */ +enum { + MFX_ANGLE_0 = 0, /*!< 0 degrees. */ + MFX_ANGLE_90 = 90, /*!< 90 degrees. */ + MFX_ANGLE_180 = 180, /*!< 180 degrees. */ + MFX_ANGLE_270 = 270 /*!< 270 degrees. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP Rotation filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_ROTATION. */ + + mfxU16 Angle; /*!< Rotation angle. See Angle enumerator for supported values. */ + mfxU16 reserved[11]; +} mfxExtVPPRotation; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + Used by the encoder to report additional information about encoded slices. The application can attach this + buffer to the mfxBitstream structure before calling the MFXVideoENCODE_EncodeFrameAsync function. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if the + functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and call the + MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE, then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_SLICES_INFO. */ + + mfxU16 SliceSizeOverflow; /*!< When mfxExtCodingOption2::MaxSliceSize is used, indicates the requested slice size was not met for one or more generated slices. */ + mfxU16 NumSliceNonCopliant; /*!< When mfxExtCodingOption2::MaxSliceSize is used, indicates the number of generated slices exceeds specification limits. */ + mfxU16 NumEncodedSlice; /*!< Number of encoded slices. */ + mfxU16 NumSliceSizeAlloc; /*!< SliceSize array allocation size. Must be specified by application. */ + union { + mfxU16 *SliceSize; /*!< Slice size in bytes. Array must be allocated by application. */ + mfxU64 reserved1; + }; + + mfxU16 reserved[20]; +} mfxExtEncodedSlicesInfo; +MFX_PACK_END() + +/*! The ScalingMode enumerator itemizes variants of scaling filter implementation. */ +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_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 Engines). 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). */ +}; + +/*! The InterpolationMode enumerator specifies type of interpolation method used by VPP scaling filter. */ +enum { + MFX_INTERPOLATION_DEFAULT = 0, /*!< Default interpolation mode for scaling. Library selects the most appropriate + scaling method. */ + MFX_INTERPOLATION_NEAREST_NEIGHBOR = 1, /*!< Nearest neighbor interpolation method. */ + MFX_INTERPOLATION_BILINEAR = 2, /*!< Bilinear interpolation method. */ + MFX_INTERPOLATION_ADVANCED = 3 /*!< Advanced interpolation method is defined by each implementation and usually gives best quality. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP Scaling filter algorithm. + Not all combinations of ScalingMode and InterpolationMethod are supported in the library. The application must use the Query API function to determine if a combination is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_SCALING. */ + + mfxU16 ScalingMode; /*!< Scaling mode. See ScalingMode for values. */ + mfxU16 InterpolationMethod; /*!< Interpolation mode for scaling algorithm. See InterpolationMode for values. */ + mfxU16 reserved[10]; +} mfxExtVPPScaling; +MFX_PACK_END() + +typedef mfxExtAVCRefListCtrl mfxExtHEVCRefListCtrl; +typedef mfxExtAVCRefLists mfxExtHEVCRefLists; +typedef mfxExtAvcTemporalLayers mfxExtHEVCTemporalLayers; + +typedef mfxExtAVCRefListCtrl mfxExtRefListCtrl; +typedef mfxExtAVCEncodedFrameInfo mfxExtEncodedFrameInfo; + +/* The MirroringType enumerator itemizes mirroring types. */ +enum +{ + MFX_MIRRORING_DISABLED = 0, + MFX_MIRRORING_HORIZONTAL = 1, + MFX_MIRRORING_VERTICAL = 2 +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP Mirroring filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_MIRRORING. */ + + mfxU16 Type; /*!< Mirroring type. See MirroringType for values. */ + mfxU16 reserved[11]; +} mfxExtVPPMirroring; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Instructs encoder to use or not use samples over specified picture border for inter prediction. Attached to the mfxVideoParam structure. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_MV_OVER_PIC_BOUNDARIES. */ + + mfxU16 StickTop; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 StickBottom; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 StickLeft; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 StickRight; /*!< When set to OFF, one or more samples outside corresponding picture boundary may be used in inter prediction. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 reserved[8]; +} mfxExtMVOverPicBoundaries; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Configures the VPP ColorFill filter algorithm. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_COLORFILL. */ + + mfxU16 Enable; /*!< Set to ON makes VPP fill the area between Width/Height and Crop borders. + See the CodingOptionValue enumerator for values of this option. */ + mfxU16 reserved[11]; +} mfxExtVPPColorFill; +MFX_PACK_END() + + +/*! The ChromaSiting enumerator defines chroma location. Use bit-OR'ed values to specify the desired location. */ +enum { + MFX_CHROMA_SITING_UNKNOWN = 0x0000, /*!< Unspecified. */ + MFX_CHROMA_SITING_VERTICAL_TOP = 0x0001, /*!< Chroma samples are co-sited vertically on the top with the luma samples. */ + MFX_CHROMA_SITING_VERTICAL_CENTER = 0x0002, /*!< Chroma samples are not co-sited vertically with the luma samples. */ + MFX_CHROMA_SITING_VERTICAL_BOTTOM = 0x0004, /*!< Chroma samples are co-sited vertically on the bottom with the luma samples. */ + MFX_CHROMA_SITING_HORIZONTAL_LEFT = 0x0010, /*!< Chroma samples are co-sited horizontally on the left with the luma samples. */ + MFX_CHROMA_SITING_HORIZONTAL_CENTER = 0x0020 /*!< Chroma samples are not co-sited horizontally with the luma samples. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + A hint structure that tunes the VPP Color Conversion algorithm when + attached to the mfxVideoParam structure during VPP Init. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_COLOR_CONVERSION. */ + + mfxU16 ChromaSiting; /*!< See ChromaSiting enumerator for details. */ + mfxU16 reserved[27]; +} mfxExtColorConversion; +MFX_PACK_END() + + +/*! The VP9ReferenceFrame enumerator itemizes reference frame type by mfxVP9SegmentParam::ReferenceFrame parameter. */ +enum { + MFX_VP9_REF_INTRA = 0, /*!< Intra. */ + MFX_VP9_REF_LAST = 1, /*!< Last. */ + MFX_VP9_REF_GOLDEN = 2, /*!< Golden. */ + MFX_VP9_REF_ALTREF = 3 /*!< Alternative reference. */ +}; + +/*! + The SegmentIdBlockSize enumerator indicates the block size represented by each segment_id in segmentation map. + These values are used with the mfxExtVP9Segmentation::SegmentIdBlockSize parameter. +*/ +enum { + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_UNKNOWN = 0, /*!< Unspecified block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_8x8 = 8, /*!< 8x8 block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_16x16 = 16, /*!< 16x16 block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_32x32 = 32, /*!< 32x32 block size. */ + MFX_VP9_SEGMENT_ID_BLOCK_SIZE_64x64 = 64, /*!< 64x64 block size. */ +}; + +/*! + The SegmentFeature enumerator indicates features enabled for the segment. + These values are used with the mfxVP9SegmentParam::FeatureEnabled parameter. +*/ +enum { + MFX_VP9_SEGMENT_FEATURE_QINDEX = 0x0001, /*!< Quantization index delta. */ + MFX_VP9_SEGMENT_FEATURE_LOOP_FILTER = 0x0002, /*!< Loop filter level delta. */ + MFX_VP9_SEGMENT_FEATURE_REFERENCE = 0x0004, /*!< Reference frame. */ + MFX_VP9_SEGMENT_FEATURE_SKIP = 0x0008 /*!< Skip. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Contains features and parameters for the segment. +*/ +typedef struct { + mfxU16 FeatureEnabled; /*!< Indicates which features are enabled for the segment. See the SegmentFeature enumerator for values for this + option. Values from the enumerator can be bit-OR'ed. Support of a particular feature depends on underlying + hardware platform. Application can check which features are supported by calling Query. */ + mfxI16 QIndexDelta; /*!< Quantization index delta for the segment. Ignored if MFX_VP9_SEGMENT_FEATURE_QINDEX isn't set in FeatureEnabled. + Valid range for this parameter is [-255, 255]. If QIndexDelta is out of this range, it will be ignored. + If QIndexDelta is within valid range, but sum of base quantization index and QIndexDelta is out of [0, 255], + QIndexDelta will be clamped. */ + mfxI16 LoopFilterLevelDelta; /*!< Loop filter level delta for the segment. Ignored if MFX_VP9_SEGMENT_FEATURE_LOOP_FILTER is not set in + FeatureEnabled. Valid range for this parameter is [-63, 63]. If LoopFilterLevelDelta is out of this range, + it will be ignored. If LoopFilterLevelDelta is within valid range, but sum of base loop filter level and + LoopFilterLevelDelta is out of [0, 63], LoopFilterLevelDelta will be clamped. */ + mfxU16 ReferenceFrame; /*!< Reference frame for the segment. See VP9ReferenceFrame enumerator for values for this option. Ignored + if MFX_VP9_SEGMENT_FEATURE_REFERENCE isn't set in FeatureEnabled. */ + mfxU16 reserved[12]; +} mfxVP9SegmentParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + In the VP9 encoder it is possible to divide a frame into up to 8 segments and apply particular features (like delta for quantization index or for + loop filter level) on a per-segment basis. "Uncompressed header" of every frame indicates if segmentation is enabled for the current frame, + and (if segmentation enabled) contains full information about features applied to every segment. Every "Mode info block" of a coded + frame has segment_id in the range of 0 to 7. + + To enable Segmentation, the mfxExtVP9Segmentation structure with correct settings should be passed to the encoder. It can be attached to the + mfxVideoParam structure during initialization or the MFXVideoENCODE_Reset call (static configuration). If the mfxExtVP9Segmentation buffer isn't + attached during initialization, segmentation is disabled for static configuration. If the buffer isn't attached for the Reset call, the encoder + continues to use static configuration for segmentation which was the default before this Reset call. If the mfxExtVP9Segmentation buffer with + NumSegments=0 is provided during initialization or Reset call, segmentation becomes disabled for static configuration. + + The buffer can be attached to the mfxEncodeCtrl structure during runtime (dynamic configuration). Dynamic configuration is applied to the + current frame only. After encoding of the current frame, the encoder will switch to the next dynamic configuration or to static configuration if dynamic configuration + is not provided for next frame). + + The SegmentIdBlockSize, NumSegmentIdAlloc, and SegmentId parameters represent a segmentation map. Here, the segmentation map is an array of segment_ids (one + byte per segment_id) for blocks of size NxN in raster scan order. The size NxN is specified by the application and is constant for the whole frame. + If mfxExtVP9Segmentation is attached during initialization and/or during runtime, all three parameters should be set to proper values that do not + conflict with each other and with NumSegments. If any of the parameters are not set or any conflict or error in these parameters is detected by the library, the segmentation + map will be discarded. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP9_SEGMENTATION. */ + mfxU16 NumSegments; /*!< Number of segments for frame. Value 0 means that segmentation is disabled. Sending 0 for a + particular frame will disable segmentation for this frame only. Sending 0 to the Reset API function will + disable segmentation permanently. Segmentation can be enabled again by a subsequent Reset call. */ + mfxVP9SegmentParam Segment[8]; /*!< Array of mfxVP9SegmentParam structures containing features and parameters for every segment. + Entries with indexes bigger than NumSegments-1 are ignored. See the mfxVP9SegmentParam structure for + definitions of segment features and their parameters. */ + mfxU16 SegmentIdBlockSize; /*!< Size of block (NxN) for segmentation map. See SegmentIdBlockSize enumerator for values for this + option. An encoded block that is bigger than SegmentIdBlockSize uses segment_id taken from it's + top-left sub-block from the segmentation map. The application can check if a particular block size is + supported by calling Query. */ + mfxU32 NumSegmentIdAlloc; /*!< Size of buffer allocated for segmentation map (in bytes). Application must assure that + NumSegmentIdAlloc is large enough to cover frame resolution with blocks of size SegmentIdBlockSize. + Otherwise the segmentation map will be discarded. */ + union { + mfxU8 *SegmentId; /*!< Pointer to the segmentation map buffer which holds the array of segment_ids in raster scan order. The application + is responsible for allocation and release of this memory. The buffer pointed to by SegmentId, provided during + initialization or Reset call should be considered in use until another SegmentId is provided via Reset + call (if any), or until MFXVideoENCODE_Close is called. The buffer pointed to by SegmentId provided with + mfxEncodeCtrl should be considered in use while the input surface is locked by the library. Every segment_id in the + map should be in the range of 0 to NumSegments-1. If some segment_id is out of valid range, the + segmentation map cannot be applied. If the mfxExtVP9Segmentation buffer is attached to the mfxEncodeCtrl structure in + runtime, SegmentId can be zero. In this case, the segmentation map from static configuration will be used. */ + mfxU64 reserved1; + }; + mfxU16 reserved[52]; +} mfxExtVP9Segmentation; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Specifies temporal layer. +*/ +typedef struct { + mfxU16 FrameRateScale; /*!< The ratio between the frame rates of the current temporal layer and the base layer. The library treats a particular + temporal layer as "defined" if it has FrameRateScale > 0. If the base layer is defined, it must have FrameRateScale = 1. FrameRateScale of each subsequent layer (if defined) must be a multiple of and greater than the + FrameRateScale value of previous layer. */ + mfxU16 TargetKbps; /*!< Target bitrate for the current temporal layer. Ignored if RateControlMethod is CQP. If RateControlMethod is not CQP, the + application must provide TargetKbps for every defined temporal layer. TargetKbps of each subsequent layer (if defined) + must be greater than the TargetKbps value of the previous layer. */ + mfxU16 reserved[14]; +} mfxVP9TemporalLayer; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + API allows the encoding of VP9 bitstreams that contain several subset bitstreams that differ in frame rates, also called "temporal layers". + + When decoding, each temporal layer can be extracted from the coded stream and decoded separately. The mfxExtVP9TemporalLayers structure + configures the temporal layers for the VP9 encoder. It can be attached to the mfxVideoParam structure during initialization or the + MFXVideoENCODE_Reset call. If the mfxExtVP9TemporalLayers buffer isn't attached during initialization, temporal scalability is disabled. If the buffer isn't attached for the Reset call, the encoder continues to use the temporal scalability configuration that was defined before the Reset call. + + In the API, temporal layers are ordered by their frame rates in ascending order. Temporal layer 0 (having the lowest frame rate) is called the base layer. + Each subsequent temporal layer includes all previous layers. + + The temporal scalability feature requires a minimum number of allocated reference + frames (controlled by the NumRefFrame parameter). If the NumRefFrame value set by the application isn't enough to build the reference structure for the requested + number of temporal layers, the library corrects the NumRefFrame value. The temporal layer structure is reset (re-started) after key-frames. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP9_TEMPORAL_LAYERS. */ + /*! + The array of temporal layers. Layer[0] specifies the base layer. + + The library reads layers from the array when they are defined (FrameRateScale > 0). + All layers starting from first layer with FrameRateScale = 0 are ignored. The last layer that is not ignored is considered the "highest layer". + + The frame rate of the highest layer is specified in the mfxVideoParam structure. Frame rates of lower layers are calculated using their FrameRateScale. + + TargetKbps of the highest layer should be equal to the TargetKbps value specified in the mfxVideoParam structure. If it is not true, TargetKbps of highest temporal layers has priority. + + If there are no defined layers in the Layer array, the temporal scalability feature is disabled. For example, to disable temporal scalability in runtime, the application should + pass mfxExtVP9TemporalLayers buffer to Reset with all FrameRateScales set to 0. + */ + mfxVP9TemporalLayer Layer[8]; + mfxU16 reserved[60]; +} mfxExtVP9TemporalLayers; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Structure attached to the mfxVideoParam structure. Extends the mfxVideoParam structure with VP9-specific parameters. Used by both decoder and encoder. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP9_PARAM. */ + + mfxU16 FrameWidth; /*!< Width of the coded frame in pixels. */ + mfxU16 FrameHeight; /*!< Height of the coded frame in pixels. */ + + mfxU16 WriteIVFHeaders; /*!< Set this option to ON to make the encoder insert IVF container headers to the output stream. The NumFrame field of the IVF + sequence header will be zero. It is the responsibility of the application to update the NumFrame field with the correct value. See the + CodingOptionValue enumerator for values of this option. */ + + mfxI16 reserved1[6]; + mfxI16 QIndexDeltaLumaDC; /*!< Specifies an offset for a particular quantization parameter. */ + mfxI16 QIndexDeltaChromaAC; /*!< Specifies an offset for a particular quantization parameter. */ + mfxI16 QIndexDeltaChromaDC; /*!< Specifies an offset for a particular quantization parameter. */ + /*! + Number of tile rows. Should be power of two. The maximum number of tile rows is 4, per the VP9 specification. In addition, the maximum supported number + of tile rows may depend on the underlying library implementation. + + Use the Query API function to check if a particular pair of values (NumTileRows, NumTileColumns) + is supported. In VP9, tile rows have dependencies and cannot be encoded or decoded in parallel. Therefore, tile rows are always encoded by the library in + serial mode (one-by-one). + */ + mfxU16 NumTileRows; + /*! + Number of tile columns. Should be power of two. Restricted with maximum and minimum tile width in luma pixels, as defined in the VP9 + specification (4096 and 256 respectively). In addition, the maximum supported number of tile columns may depend on the underlying library + implementation. + + Use the Query API function to check if a particular pair of values (NumTileRows, NumTileColumns) is supported. In VP9, tile columns do not have + dependencies and can be encoded/decoded in parallel. Therefore, tile columns can be encoded by the library in both parallel and serial modes. + + Parallel mode is automatically utilized by the library when NumTileColumns exceeds 1 and does not exceed the number of tile coding engines on the + platform. In other cases, serial mode is used. Parallel mode is capable of encoding more than 1 tile row (within limitations provided by VP9 + specification and particular platform). Serial mode supports only tile grids 1xN and Nx1. + */ + mfxU16 NumTileColumns; + mfxU16 reserved[110]; +} mfxExtVP9Param; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used to report encoded unit information. +*/ +typedef struct { + mfxU16 Type; /*!< Codec-dependent coding unit type (NALU type for AVC/HEVC, start_code for MPEG2 etc). */ + mfxU16 reserved1; + mfxU32 Offset; /*!< Offset relative to the associated mfxBitstream::DataOffset. */ + mfxU32 Size; /*!< Unit size, including delimiter. */ + mfxU32 reserved[5]; +} mfxEncodedUnitInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_L_TYPE() +/*! + If mfxExtCodingOption3::EncodedUnitsInfo was set to MFX_CODINGOPTION_ON during encoder initialization, the mfxExtEncodedUnitsInfo structure is + attached to the mfxBitstream structure during encoding. It is used to report information about coding units in the resulting bitstream. + + The number of filled items in UnitInfo is min(NumUnitsEncoded, NumUnitsAlloc). + + For counting a minimal amount of encoded units you can use the following algorithm: + @code + nSEI = amountOfApplicationDefinedSEI; + if (CodingOption3.NumSlice[IPB] != 0 || mfxVideoParam.mfx.NumSlice != 0) + ExpectedAmount = 10 + nSEI + Max(CodingOption3.NumSlice[IPB], mfxVideoParam.mfx.NumSlice); + else if (CodingOption2.NumMBPerSlice != 0) + ExpectedAmount = 10 + nSEI + (FrameWidth * FrameHeight) / (256 * CodingOption2.NumMBPerSlice); + else if (CodingOption2.MaxSliceSize != 0) + ExpectedAmount = 10 + nSEI + Round(MaxBitrate / (FrameRate*CodingOption2.MaxSliceSize)); + else + ExpectedAmount = 10 + nSEI; + + if (mfxFrameInfo.PictStruct != MFX_PICSTRUCT_PROGRESSIVE) + ExpectedAmount = ExpectedAmount * 2; + + if (temporalScaleabilityEnabled) + ExpectedAmount = ExpectedAmount * 2; + @endcode + @note Only supported by the AVC encoder. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_UNITS_INFO. */ + + union { + mfxEncodedUnitInfo *UnitInfo; /*!< Pointer to an array of mfxEncodedUnitsInfo structures whose size is equal to or greater than NumUnitsAlloc. */ + mfxU64 reserved1; + }; + mfxU16 NumUnitsAlloc; /*!< UnitInfo array size. */ + mfxU16 NumUnitsEncoded; /*!< Output field. Number of coding units to report. If NumUnitsEncoded is greater than NumUnitsAlloc, the UnitInfo + array will contain information only for the first NumUnitsAlloc units. User may consider reallocating the + UnitInfo array to avoid this for subsequent frames. */ + + mfxU16 reserved[22]; +} mfxExtEncodedUnitsInfo; +MFX_PACK_END() + + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Provides setup for the Motion-Compensated Temporal Filter (MCTF) during the VPP initialization and for control + parameters at runtime. By default, MCTF is off. An application may enable it by adding MFX_EXTBUFF_VPP_MCTF to the mfxExtVPPDoUse buffer or by + attaching mfxExtVppMctf to the mfxVideoParam structure during initialization or reset. +*/ +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. + + 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; +MFX_PACK_END() + +/*! Describes type of workload passed to MFXQueryAdapters. */ +typedef enum +{ + MFX_COMPONENT_ENCODE = 1, /*!< Encode workload. */ + MFX_COMPONENT_DECODE = 2, /*!< Decode workload. */ + MFX_COMPONENT_VPP = 3 /*!< VPP workload. */ +} mfxComponentType; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains workload description, which is accepted by MFXQueryAdapters function. +*/ +typedef struct +{ + mfxComponentType Type; /*!< Type of workload: Encode, Decode, VPP. See mfxComponentType enumerator for values. */ + mfxVideoParam Requirements; /*!< Detailed description of workload. See mfxVideoParam for details. */ + + mfxU16 reserved[4]; +} mfxComponentInfo; +MFX_PACK_END() + +/* Adapter description */ +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Contains a description of the graphics adapter for the Legacy mode. +*/ +typedef struct +{ + mfxPlatform Platform; /*!< Platform type description. See mfxPlatform for details. */ + mfxU32 Number; /*!< Value which uniquely characterizes media adapter. On Windows* this number can be used for initialization through + DXVA interface (see example). */ + + mfxU16 reserved[14]; +} mfxAdapterInfo; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Contains description of all graphics adapters available on the current system. +*/ +typedef struct +{ + mfxAdapterInfo * Adapters; /*!< Pointer to array of mfxAdapterInfo structs allocated by user. */ + mfxU32 NumAlloc; /*!< Length of Adapters array. */ + mfxU32 NumActual; /*!< Number of Adapters entries filled by MFXQueryAdapters. */ + + mfxU16 reserved[4]; +} mfxAdaptersInfo; +MFX_PACK_END() + + +/*! The PartialBitstreamOutput enumerator indicates flags of partial bitstream output type. */ +enum { + MFX_PARTIAL_BITSTREAM_NONE = 0, /*!< Do not use partial output */ + MFX_PARTIAL_BITSTREAM_SLICE = 1, /*!< Partial bitstream output will be aligned to slice granularity */ + MFX_PARTIAL_BITSTREAM_BLOCK = 2, /*!< Partial bitstream output will be aligned to user-defined block size granularity */ + MFX_PARTIAL_BITSTREAM_ANY = 3 /*!< Partial bitstream output will be return any coded data available at the end of SyncOperation timeout */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by an encoder to output parts of the bitstream as soon as they are ready. The application can attach this extended buffer to the + mfxVideoParam structure at initialization. If this option is turned ON (Granularity != MFX_PARTIAL_BITSTREAM_NONE), then the encoder can output + bitstream by part based on the required granularity. + + This parameter is valid only during initialization and reset. Absence of this buffer means default or previously configured bitstream output + behavior. + + @note Not all codecs and implementations support this feature. Use the Query API function to check if this feature is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_PARTIAL_BITSTREAM_PARAM. */ + mfxU32 BlockSize; /*!< Output block granularity for PartialBitstreamGranularity. Valid only for MFX_PARTIAL_BITSTREAM_BLOCK. */ + mfxU16 Granularity; /*!< Granularity of the partial bitstream: slice/block/any, all types of granularity state in PartialBitstreamOutput enum. */ + mfxU16 reserved[8]; +} mfxExtPartialBitstreamParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + The mfxExtDeviceAffinityMask structure is used by the application to specify + affinity mask for the device with given device ID. See mfxDeviceDescription + for the device ID definition and sub device indexes. If the implementation + manages CPU threads for some purpose, the user can set the CPU thread affinity + mask by using this structure with DeviceID set to "CPU". +*/ +typedef struct { + /*! Extension buffer header. Header.BufferId must be equal to + MFX_EXTBUFF_DEVICE_AFFINITY_MASK. */ + mfxExtBuffer Header; + /*! Null terminated string with device ID. In case of CPU affinity mask + it must be equal to "CPU". */ + mfxChar DeviceID[MFX_STRFIELD_LEN]; + /*! Number of sub devices or threads in case of CPU in the mask. */ + mfxU32 NumSubDevices; + /*! Mask array. Every bit represents sub-device (or thread for CPU). + "1" means execution is allowed. "0" means that execution is prohibited on + this sub-device (or thread). Length of the array is equal to the: + "NumSubDevices / 8" and rounded to the closest (from the right) integer. + Bits order within each entry of the mask array is LSB: bit 0 holds data + for sub device with index 0 and bit 8 for sub device with index 8. + Index of sub device is defined by the mfxDeviceDescription structure. */ + mfxU8 *Mask; + mfxU32 reserved[4]; /*! Reserved for future use. */ +} mfxExtDeviceAffinityMask; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used by AV1 encoder with more parameter control to encode frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_BITSTREAM_PARAM. */ + + mfxU16 WriteIVFHeaders; /*!< Tri-state option to control IVF headers insertion, default is ON. + Writing IVF headers is enabled in the encoder when mfxExtAV1BitstreamParam is attached and its value is ON or zero. + Writing IVF headers is disabled by default in the encoder when mfxExtAV1BitstreamParam is not attached. */ + + mfxU16 reserved[31]; +} mfxExtAV1BitstreamParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used by AV1 encoder with more parameter control to encode frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_RESOLUTION_PARAM. */ + + mfxU32 FrameWidth; /*!< Width of the coded frame in pixels, default value is from mfxFrameInfo. */ + mfxU32 FrameHeight; /*!< Height of the coded frame in pixels, default value is from mfxFrameInfo. */ + + mfxU32 reserved[6]; +} mfxExtAV1ResolutionParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() + /*! The structure is used by AV1 encoder with more parameter control to encode frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_TILE_PARAM. */ + + mfxU16 NumTileRows; /*!< Number of tile rows, default value is 1. */ + mfxU16 NumTileColumns; /*!< Number of tile columns, default value is 1. */ + mfxU16 NumTileGroups; /*!< Number of tile groups, it will be ignored if the tile groups num is invalid, default value is 1. */ + + mfxU16 reserved[5]; +} mfxExtAV1TileParam; +MFX_PACK_END() + +/*! + The AV1 SegmentIdBlockSize enumerator indicates the block size represented by each segment_id in segmentation map. + These values are used with the mfxExtAV1Segmentation::SegmentIdBlockSize parameter. +*/ +typedef enum { + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_UNSPECIFIED = 0, /*!< Unspecified block size. */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_4x4 = 4, /*!< block size 4x4 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_8x8 = 8, /*!< block size 8x8 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_16x16 = 16, /*!< block size 16x16 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_32x32 = 32, /*!< block size 32x32 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_64x64 = 64, /*!< block size 64x64 */ + MFX_AV1_SEGMENT_ID_BLOCK_SIZE_128x128 = 128 /*!< block size 128x128 */ +} mfxAV1SegmentIdBlockSize; + +/*! + The AV1 SegmentFeature enumerator indicates features enabled for the segment. + These values are used with the mfxAV1SegmentParam::FeatureEnabled parameter. +*/ +enum { + MFX_AV1_SEGMENT_FEATURE_ALT_QINDEX = 0x0001, /*!< use alternate Quantizer. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_Y_VERT = 0x0002, /*!< use alternate loop filter value on y plane vertical. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_Y_HORZ = 0x0004, /*!< use alternate loop filter value on y plane horizontal. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_U = 0x0008, /*!< use alternate loop filter value on u plane. */ + MFX_AV1_SEGMENT_FEATURE_ALT_LF_V = 0x0010, /*!< use alternate loop filter value on v plane. */ + MFX_AV1_SEGMENT_FEATURE_REFERENCE = 0x0020, /*!< use segment reference frame. */ + MFX_AV1_SEGMENT_FEATURE_SKIP = 0x0040, /*!< use segment (0,0) + skip mode. */ + MFX_AV1_SEGMENT_FEATURE_GLOBALMV = 0x0080 /*!< use global motion vector. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Contains features and parameters for the segment. +*/ +typedef struct { + mfxU16 FeatureEnabled; /*!< Indicates which features are enabled for the segment. See the AV1 SegmentFeature enumerator for values for + this option. Values from the enumerator can be bit-OR'ed. Support of a particular feature depends on underlying + hardware platform. Application can check which features are supported by calling Query. */ + mfxI16 AltQIndex; /*!< Quantization index delta for the segment. Ignored if MFX_AV1_SEGMENT_FEATURE_ALT_QINDEX isn't set in FeatureEnabled. + Valid range for this parameter is [-255, 255]. If AltQIndex is out of this range, it will be ignored. If AltQIndex + is within valid range, but sum of base quantization index and AltQIndex is out of [0, 255], AltQIndex will be clamped. */ + mfxU16 reserved[30]; +} mfxAV1SegmentParam; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + In the AV1 encoder it is possible to divide a frame into up to 8 segments and apply particular features (like delta for quantization index or for + loop filter level) on a per-segment basis. "Uncompressed header" of every frame indicates if segmentation is enabled for the current frame, + and (if segmentation enabled) contains full information about features applied to every segment. Every "Mode info block" of a coded + frame has segment_id in the range of 0 to 7. + To enable Segmentation, the mfxExtAV1Segmentation structure with correct settings should be passed to the encoder. It can be attached to the + mfxVideoParam structure during initialization or the MFXVideoENCODE_Reset call (static configuration). If the mfxExtAV1Segmentation buffer isn't + attached during initialization, segmentation is disabled for static configuration. If the buffer isn't attached for the Reset call, the encoder + continues to use static configuration for segmentation which was the default before this Reset call. If the mfxExtAV1Segmentation buffer with + NumSegments=0 is provided during initialization or Reset call, segmentation becomes disabled for static configuration. + The buffer can be attached to the mfxEncodeCtrl structure during runtime (dynamic configuration). Dynamic configuration is applied to the + current frame only. After encoding of the current frame, the encoder will switch to the next dynamic configuration or to static configuration if + dynamic configuration is not provided for next frame). + The SegmentIdBlockSize, NumSegmentIdAlloc, and SegmentId parameters represent a segmentation map. Here, the segmentation map is an array of + segment_ids (one byte per segment_id) for blocks of size NxN in raster scan order. The size NxN is specified by the application and is constant + for the whole frame. + If mfxExtAV1Segmentation is attached during initialization and/or during runtime, all three parameters should be set to proper values that do not + conflict with each other and with NumSegments. If any of the parameters are not set or any conflict or error in these parameters is detected by + the library, the segmentation map will be discarded. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_SEGMENTATION. */ + mfxU8 NumSegments; /*!< Number of segments for frame. Value 0 means that segmentation is disabled. Sending 0 for a + particular frame will disable segmentation for this frame only. Sending 0 to the Reset API function will + disable segmentation permanently. Segmentation can be enabled again by a subsequent Reset call. */ + mfxU8 reserved1[3]; + mfxAV1SegmentParam Segment[8]; /*!< Array of mfxAV1SegmentParam structures containing features and parameters for every segment. + Entries with indexes bigger than NumSegments-1 are ignored. See the mfxAV1SegmentParam structure for + definitions of segment features and their parameters. */ + mfxU16 SegmentIdBlockSize;/*!< Size of block (NxN) for segmentation map. See AV1 SegmentIdBlockSize enumerator for values for this + option. An encoded block that is bigger than AV1 SegmentIdBlockSize uses segment_id taken from it's + top-left sub-block from the segmentation map. The application can check if a particular block size is + supported by calling Query. */ + mfxU16 reserved2; + mfxU32 NumSegmentIdAlloc; /*!< Size of buffer allocated for segmentation map (in bytes). Application must assure that + NumSegmentIdAlloc is large enough to cover frame resolution with blocks of size SegmentIdBlockSize. + Otherwise the segmentation map will be discarded. */ + mfxU8 * SegmentIds; /*!< Pointer to the segmentation map buffer which holds the array of segment_ids in raster scan order. The application + is responsible for allocation and release of this memory. The buffer pointed to by SegmentId, provided during + initialization or Reset call should be considered in use until another SegmentId is provided via Reset + call (if any), or until MFXVideoENCODE_Close is called. The buffer pointed to by SegmentId provided with + mfxEncodeCtrl should be considered in use while the input surface is locked by the library. Every segment_id in the + map should be in the range of 0 to NumSegments-1. If some segment_id is out of valid range, the + segmentation map cannot be applied. If the mfxExtAV1Segmentation buffer is attached to the mfxEncodeCtrl structure in + runtime, SegmentId can be zero. In this case, the segmentation map from static configuration will be used. */ + mfxU16 reserved[36]; +} mfxExtAV1Segmentation; +MFX_PACK_END() + +/*! 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. */ + MFX_FILM_GRAIN_APPLY = (1 << 0), /*!< Film grain is added to this frame. */ + MFX_FILM_GRAIN_UPDATE = (1 << 1), /*!< New set of film grain parameters is sent for this frame. */ + MFX_FILM_GRAIN_CHROMA_SCALING_FROM_LUMA = (1 << 2), /*!< Chroma scaling is inferred from luma scaling. */ + MFX_FILM_GRAIN_OVERLAP = (1 << 3), /*!< Overlap between film grain blocks is applied. */ + MFX_FILM_GRAIN_CLIP_TO_RESTRICTED_RANGE = (1 << 4) /*!< Clipping to the restricted (studio) range is applied after adding the film grain. */ +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Defines film grain point. */ +typedef struct { + mfxU8 Value; /*!< The x coordinate for the i-th point of the piece-wise linear scaling function for luma/Cb/Cr component. */ + mfxU8 Scaling; /*!< The scaling (output) value for the i-th point of the piecewise linear scaling function for luma/Cb/Cr component. */ +} mfxAV1FilmGrainPoint; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used by AV-1 decoder to report film grain parameters for decoded frame. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM. */ + + mfxU16 FilmGrainFlags; /*!< Bit map with bit-ORed flags from FilmGrainFlags enum. */ + mfxU16 GrainSeed; /*!< Starting value for pseudo-random numbers used during film grain synthesis. */ + + mfxU8 RefIdx; /*!< Indicate which reference frame contains the film grain parameters to be used for this frame. */ + mfxU8 NumYPoints; /*!< The number of points for the piece-wise linear scaling function of the luma component. */ + mfxU8 NumCbPoints; /*!< The number of points for the piece-wise linear scaling function of the Cb component. */ + mfxU8 NumCrPoints; /*!< The number of points for the piece-wise linear scaling function of the Cr component.*/ + + mfxAV1FilmGrainPoint PointY[14]; /*!< The array of points for luma component. */ + 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 + 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.*/ + + mfxU8 ArCoeffsYPlus128[24]; /*!< Auto-regressive coefficients used for the Y plane. */ + 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 + [-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 .*/ + + mfxU8 CbMult; /*!< The multiplier for the Cb component used in derivation of the input index to the Cb component scaling function.*/ + mfxU8 CbLumaMult; /*!< The multiplier for the average luma component used in derivation of the input index to the Cb component scaling function. */ + mfxU16 CbOffset; /*!< The offset used in derivation of the input index to the Cb component scaling function.*/ + + mfxU8 CrMult; /*!< The multiplier for the Cr component used in derivation of the input index to the Cr component scaling function.*/ + mfxU8 CrLumaMult; /*!< The multiplier for the average luma component used in derivation of the input index to the Cr component scaling function.*/ + mfxU16 CrOffset; /*!< The offset used in derivation of the input index to the Cr component scaling function.*/ + + mfxU16 reserved[43]; +} mfxExtAV1FilmGrainParam; +MFX_PACK_END() + +#define MFX_SURFACEARRAY_VERSION MFX_STRUCT_VERSION(1, 0) + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure is reference counted object to return array of surfaces allocated and processed by the library. */ +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]; + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the mfxSurfaceArray::Release function. + mfxSurfaceArray::AddRef should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + + @param[in] surface Valid mfxSurfaceArray. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxSurfaceArray* surface_array); + /*! @brief + Decrements the internal reference counter of the surface. mfxSurfaceArray::Release should be called after + using the mfxSurfaceArray::AddRef function to add a surface or when allocation logic requires it. + + @param[in] surface_array Valid mfxSurfaceArray. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If surface is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxSurfaceArray* surface_array); + + /*! @brief + Returns current reference counter of mfxSurfaceArray structure. + + @param[in] surface Valid surface_array. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + 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 (MFX_CDECL *GetRefCounter)(struct mfxSurfaceArray* surface_array, mfxU32* counter); + + mfxFrameSurface1** Surfaces; /*!< The array of pointers to mfxFrameSurface1. mfxFrameSurface1 surfaces are allocated by the same + agent who allocates mfxSurfaceArray. */ + mfxU32 NumSurfaces; /*! 0. If the base layer is defined, it must have FrameRateScale = 1. + FrameRateScale of each subsequent layer (if defined) must be a multiple of and greater than the + FrameRateScale value of previous layer. */ + mfxU16 reserved[3]; /*!< Reserved for future use. */ + + union { + /*!< Type of bitrate controls is currently the same across all temporal layers and inherits from common parameters. */ + struct { + mfxU32 InitialDelayInKB;/*!< Initial size of the Video Buffering Verifier (VBV) buffer for the current temporal layer. + @note In this context, KB is 1000 bytes and Kbps is 1000 bps. */ + mfxU32 BufferSizeInKB; /*!< Represents the maximum possible size of any compressed frames for the current temporal layer. */ + mfxU32 TargetKbps; /*!< Target bitrate for the current temporal layer. If RateControlMethod is not CQP, the + application can provide TargetKbps for every defined temporal layer. If TargetKbps per temporal layer is not set then + encoder doesn't apply any special bitrate limitations for the layer. */ + mfxU32 MaxKbps; /*!< The maximum bitrate at which the encoded data enters the Video Buffering Verifier (VBV) buffer for the current temporal layer. */ + + mfxU32 reserved1[16]; /*!< Reserved for future use. */ + + }; + struct { + mfxI32 QPI; /*!< Quantization Parameter (QP) for I-frames for constant QP mode (CQP) for the current temporal layer. Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPI range. + @note Default QPI value is implementation dependent and subject to change without additional notice in this document. */ + mfxI32 QPP; /*!< Quantization Parameter (QP) for P-frames for constant QP mode (CQP) for the current temporal layer. Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPP might be clipped to supported QPI range. + @note Default QPP value is implementation dependent and subject to change without additional notice in this document. */ + mfxI32 QPB; /*!< Quantization Parameter (QP) for B-frames for constant QP mode (CQP) for the current temporal layer. Zero QP is not valid and means that the default value is assigned by the library. + Non-zero QPI might be clipped to supported QPB range. + @note Default QPB value is implementation dependent and subject to change without additional notice in this document. */ + }; + }; + mfxU16 reserved2[4]; /*!< Reserved for future use. */ + +} mfxTemporalLayer; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure is used for universal temporal layers description. */ +typedef struct { + mfxExtBuffer Header; /*! Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_UNIVERSAL_TEMPORAL_LAYERS. */ + mfxU16 NumLayers; /*!< The number of temporal layers. */ + mfxU16 BaseLayerPID; /*!< The priority ID of the base layer. The encoder increases the ID for each temporal layer and writes to the prefix NAL unit for AVC and HEVC. */ + mfxU16 reserved[2]; /*!< Reserved for future use. */ + mfxTemporalLayer *Layers; /*!< The array of temporal layers. */ + + mfxU16 reserved1[8]; /*!< Reserved for future use. */ +} mfxExtTemporalLayers; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The structure is used to configure perceptual encoding prefilter in VPP. */ +typedef struct { + mfxExtBuffer Header; /*! Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_PERC_ENC_PREFILTER. */ + mfxU16 reserved[252]; +} mfxExtVPPPercEncPrefilter; +MFX_PACK_END() +#endif + +#ifdef ONEVPL_EXPERIMENTAL +/*! The TuneQuality enumerator specifies tuning option for encode. Multiple tuning options can be combined using bit mask. */ +enum { + MFX_ENCODE_TUNE_OFF = 0, /*!< Tuning quality is disabled. */ + MFX_ENCODE_TUNE_PSNR = 0x1, /*!< The encoder optimizes quality according to Peak Signal-to-Noise Ratio (PSNR) metric. */ + MFX_ENCODE_TUNE_SSIM = 0x2, /*!< The encoder optimizes quality according to Structural Similarity Index Measure (SSIM) metric. */ + MFX_ENCODE_TUNE_MS_SSIM = 0x4, /*!< The encoder optimizes quality according to Multi-Scale Structural Similarity Index Measure (MS-SSIM) metric. */ + MFX_ENCODE_TUNE_VMAF = 0x8, /*!< The encoder optimizes quality according to Video Multi-Method Assessment Fusion (VMAF) metric. */ + MFX_ENCODE_TUNE_PERCEPTUAL = 0x10, /*!< The encoder makes perceptual quality optimization. */ +}; + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! The structure specifies type of quality optimization used by the encoder. The buffer can also be attached for VPP functions to make correspondent pre-filtering. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_TUNE_ENCODE_QUALITY. */ + mfxU32 TuneQuality; /*!< The control to specify type of encode quality metric(s) to optimize; See correspondent enum. */ + mfxExtBuffer** ExtParam; /*!< Points to an array of pointers to the extra configuration structures; see the ExtendedBufferID enumerator for a list of extended configurations. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to the structure. */ + mfxU16 reserved[11]; +} mfxExtTuneEncodeQuality; +MFX_PACK_END() +#endif + +/*! The mfxAISuperResolutionMode enumerator specifies the mode of AI based super resolution. */ +typedef enum { + MFX_AI_SUPER_RESOLUTION_MODE_DISABLED = 0, /*!< Super Resolution is disabled.*/ + MFX_AI_SUPER_RESOLUTION_MODE_DEFAULT = 1, /*!< Default super resolution mode. The library selects the most appropriate super resolution mode.*/ +#ifdef ONEVPL_EXPERIMENTAL + MFX_AI_SUPER_RESOLUTION_MODE_SHARPEN = 2, /*!< In this mode, super Resolution is optimized or trained to have high sharpness level. This mode is recommended to be used in video conference(camera + noise) or similar usage scenario.*/ + MFX_AI_SUPER_RESOLUTION_MODE_ARTIFACTREMOVAL= 3, /*!< In this mode, Super Resolution is optimized or trained to remove encoding artifacts with medium sharpness level. This mode is recommended to be used in + video surveillance or similar usage scenarios which may have camera noise and encoding artifacts due to limited network bandwidth.*/ +#endif +} mfxAISuperResolutionMode; + +#ifdef ONEVPL_EXPERIMENTAL +typedef enum { + MFX_AI_SUPER_RESOLUTION_ALGORITHM_DEFAULT = 0, /*!< Super Resolution algorithm by default. The library selects the most appropriate super resolution algorithm.*/ + MFX_AI_SUPER_RESOLUTION_ALGORITHM_1 = 1, /*!< Super Resolution algorithm1.*/ + MFX_AI_SUPER_RESOLUTION_ALGORITHM_2 = 2, /*!< Super Resolution algorithm2, MFX_AI_SUPER_RESOLUTION_ALGORITHM_2 video quality is expected to be better than MFX_AI_SUPER_RESOLUTION_ALGORITHM_1.*/ +} mfxAISuperResolutionAlgorithm; +#endif + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + A hint structure that configures AI based super resolution VPP filter. + Super resolution is an AI-powered upscaling feature which converts a low-resolution to high-resolution. + 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 mfxExtVPPAISuperResolution structure directly to the mfxVideoParam structure and + calling the Query API function. If the filter is supported, the function returns a MFX_ERR_NONE status; otherwise, the function returns MFX_ERR_UNSUPPORTED. + If both mfxExtVPPAISuperResolution and mfxExtVPPScaling are attached during initialization, the function will return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM; if both + of them are attached during runtime, the mfxExtVPPAISuperResolution will override the upscaling mode and use super resolution. + If the application needs to switch on and off, the application can set the MFX_AI_SUPER_RESOLUTION_MODE_DISABLED to switch off, MFX_AI_SUPER_RESOLUTION_MODE_DEFAULT + to switch on. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_AI_SUPER_RESOLUTION.*/ + mfxAISuperResolutionMode SRMode; /*!< Indicates Super Resolution Mode. mfxAISuperResolutionMode enumerator.*/ +#ifdef ONEVPL_EXPERIMENTAL + mfxAISuperResolutionAlgorithm SRAlgorithm; /*!< Indicates Super Resolution Algorithm. mfxAISuperResolutionAlgorithm enumerator.*/ + mfxU32 reserved1[15]; /*!< Reserved for future use. */ +#else + mfxU32 reserved1[16]; /*!< Reserved for future use. */ +#endif + mfxHDL reserved2[4]; /*!< Reserved for future use. */ +} mfxExtVPPAISuperResolution; +MFX_PACK_END() + +/* The mfxAIFrameInterpolationMode enumerator specifies the mode of AI based frame interpolation. */ +typedef enum { + MFX_AI_FRAME_INTERPOLATION_MODE_DISABLE = 0, /*!< AI based frame interpolation is disabled. The library duplicates the frame if AI frame interpolation is disabled.*/ + MFX_AI_FRAME_INTERPOLATION_MODE_DEFAULT = 1, /*!< Default AI based frame interpolation mode. The library selects the most appropriate AI based frame interpolation mode.*/ + +#ifdef ONEVPL_EXPERIMENTAL + MFX_AI_FRAME_INTERPOLATION_MODE_BEST_SPEED = 2, /*!< AI based frame interpolation in best speed.*/ + MFX_AI_FRAME_INTERPOLATION_MODE_BEST_QUALITY = 3, /*!< AI based frame interpolation in best quality.*/ +#endif +} mfxAIFrameInterpolationMode; + +/*! + A hint structure that configures AI based frame interpolation VPP filter. + AI powered frame interpolation feature can reconstruct one or more intermediate frames between two consecutive frames by AI method. + 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: + Attaching the mfxExtVPPAIFrameInterpolation structure directly to the mfxVideoParam structure and setting the frame rate of input and output (FrameRateExtN and FrameRateExtD), + then calling the Query API function. If the filter is supported, the Query function returns a MFX_ERR_NONE status; otherwise, the function returns MFX_ERR_UNSUPPORTED. + As a new method of frame interpolation, the application can attach mfxExtVPPAIFrameInterpolation to mfxVideoParam during initialization for frame interpolation, or attach both + mfxExtVPPAIFrameInterpolation and mfxExtVPPFrameRateConversion to mfxVideoParam and use which mfxExtVPPAIFrameInterpolation is regarded as a new algorithm of mfxExtVPPFrameRateConversion + (MFX_FRCALGM_AI_FRAME_INTERPOLATION). + The applications should follow video processing procedures and call the API mfxStatus MFXVideoVPP_RunFrameVPPAsync(Session, Input, Output, Auxdata, Syncp) to process the frames one by one. + The below is detailed explanation of video processing procedures in this AI frame interpolation case. If the application does not follow the below input/output sequence, the application could + get the unexpected output and get an error return value. + Input: Frame0 Frame1 Frame2 Frame3 FrameN + Output: Frame0 Frame0.5 Frame1 Frame1.5 Frame2 Frame2.5 Frame3 FrameX.5 FrameN + #0 API call: Input Frame0, Output Frame0, Return MFX_ERR_NONE. + #1 API call: Input Frame1, Output Frame0.5 and Return MFX_ERR_MORE_SURFACE. + #2 API call: Input Frame1, Output Frame1, Return MFX_ERR_NONE. + #3 API call: Input Frame2, Output Frame1.5, Return MFX_ERR_MORE_SURFACE. + #4 API call: Input Frame2, Output Frame2, Return MFX_ERR_NONE. +*/ +MFX_PACK_BEGIN_STRUCT_W_PTR() +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_AI_FRAME_INTERPOLATION.*/ + mfxAIFrameInterpolationMode FIMode; /*!< Indicates frame interpolation mode. The mfxAIFrameInterpolationMode enumerator.*/ + mfxU16 EnableScd; /*!< Indicates if enabling scene change detection(SCD) of the library. Recommend to enable this flag for + better quality. Value 0 means disable SCD, Value 1 means enable SCD.*/ + + mfxU32 reserved1[24]; /*!< Reserved for future use. */ + mfxHDL reserved2[8]; /*!< Reserved for future use. */ +} mfxExtVPPAIFrameInterpolation; +MFX_PACK_END() + +/*! The mfxQualityInfoMode enumerator specifies the mode of Quality information. */ +typedef enum { + MFX_QUALITY_INFO_DISABLE = 0, /*!< Quality reporting disabled. */ + MFX_QUALITY_INFO_LEVEL_FRAME = 0x1, /*!< Frame level quality report. */ +} mfxQualityInfoMode; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to set quality information report mode for the encoded picture. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_QUALITY_INFO_MODE. */ + mfxQualityInfoMode QualityInfoMode;/*!< See mfxQualityInfoMode enumeration for supported modes. */ + mfxU32 reserved[5]; /*!< Reserved for future use. */ +} mfxExtQualityInfoMode; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Used by the encoder to report quality information about the encoded picture. The application can attach + this buffer to the mfxBitstream structure before calling MFXVideoENCODE_EncodeFrameAsync function. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ENCODED_QUALITY_INFO_OUTPUT. */ + mfxU32 FrameOrder; /*!< Frame display order of encoded picture. */ + mfxU32 MSE[3]; /*!< Frame level mean squared errors (MSE) for Y/U/V channel. + @note MSE is stored in U24.8 format. The calculation formula is: PSNR = 10 * log10(256.0 * (2^bitDepth - 1)^2 / (double)MSE)). */ + mfxU32 reserved1[50]; /*!< Reserved for future use. */ + mfxHDL reserved2[4]; /*!< Reserved for future use. */ +} mfxExtQualityInfoOutput; +MFX_PACK_END() + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to set the screen content tools. + + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AV1_SCREEN_CONTENT_TOOLS. */ + /*! + Set this flag to MFX_CODINGOPTION_ON to enable palette prediction for encoder. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value will be used which can be obtained from the MFXVideoENCODE_GetVideoParam function after encoding initialization. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 Palette; + /*! + Set this flag to MFX_CODINGOPTION_ON to enable intra block copy prediction for encoder. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value will be used which can be obtained from the MFXVideoENCODE_GetVideoParam function after encoding initialization. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 IntraBlockCopy; + mfxU16 reserved[10]; /*!< Reserved for future use. */ +} mfxExtAV1ScreenContentTools; +MFX_PACK_END() + + +/*! The AlphaChannelMode enumerator specifies alpha is straight or pre-multiplied. */ +enum { + /*! + RGB and alpha are independent, then the alpha value specifies how solid it is. + We set it to the default value, i.e., the alpha source data is already pre-multiplied, so that the decoded samples of the associated primary picture + should not be multiplied by the interpretation sample values of the auxiliary coded picture in the display process after output from the decoding process. + */ + MFX_ALPHA_MODE_PREMULTIPLIED = 1, + + /*! + RGB and alpha are linked, then the alpha value specifies how much it obscures whatever is behind it. + Therefore, the decoded samples of the associated primary picture should be multiplied by the interpretation sample values + of the auxiliary coded picture in the display process after output from the decoding process. + */ + MFX_ALPHA_MODE_STRAIGHT = 2 +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Configure the alpha channel encoding. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. BufferId must be equal to MFX_EXTBUFF_ALPHA_CHANNEL_ENC_CTRL. */ + /*! + Set this flag to MFX_CODINGOPTION_ON to enable alpha channel encoding. See the CodingOptionValue enumerator for values of this option. + This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 EnableAlphaChannelEncoding; + /*! + Specifies alpha is straight or pre-multiplied. See the AlphaChannelMode enumerator for details. + Encoder just record this in the SEI for post-decoding rendering. + */ + mfxU16 AlphaChannelMode; + /*! + Indicates the percentage of the auxiliary alpha layer in the total bitrate. Valid range for this parameter is [1, 99]. + We set 25 as the default value, i.e. Alpha(25) : Total(100), then 25% of the bits will be spent on alpha layer encoding whereas the other 75% will be spent on base(YUV) layer. + Affects the following variables: InitialDelayInKB, BufferSizeInKB, TargetKbps, MaxKbps. + */ + mfxU16 AlphaChannelBitrateRatio; + mfxU16 reserved[9]; +} mfxExtAlphaChannelEncCtrl; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Defines the uncompressed frames surface information and data buffers for alpha channel encoding. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. BufferId must be equal to MFX_EXTBUFF_ALPHA_CHANNEL_SURFACE. */ + mfxFrameSurface1* AlphaSurface; /*!< Alpha channel surface. */ + mfxU16 reserved[8]; +} mfxExtAlphaChannelSurface; +MFX_PACK_END() + +#ifdef ONEVPL_EXPERIMENTAL +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! + Used by the encoder to switch to ai assisted encoder solutions. + @note Not all implementations of the encoder support this extended buffer. The application must use query mode 1 to determine if + the functionality is supported. To do this, the application must attach this extended buffer to the mfxVideoParam structure and + call the MFXVideoENCODE_Query function. If the function returns MFX_ERR_NONE then the functionality is supported. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_AI_ENC_CTRL. */ + /*! + Set this flag to MFX_CODINGOPTION_ON to enable saliency encoder solution. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value OFF will be used. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 SaliencyEncoder; + /*! + Set this flag to MFX_CODINGOPTION_ON to enable ML-based adaptive target usage solution. Set this flag to MFX_CODINGOPTION_OFF to disable it. + If this flag is set to any other value, the default value will be used which can be obtained from the MFXVideoENCODE_GetVideoParam function after encoding initialization. + See the CodingOptionValue enumerator for values of this option. This parameter is valid only during initialization. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. + */ + mfxU16 AdaptiveTargetUsage; + mfxU16 reserved[26]; /*!< Reserved for future use. */ +} mfxExtAIEncCtrl; +MFX_PACK_END() +#endif + +#ifdef __cplusplus +} // extern "C" + +#endif + + +#endif diff --git a/third-party/IntelVPL/x64/include/vpl/mfxsurfacepool.h b/third-party/IntelVPL/x64/include/vpl/mfxsurfacepool.h new file mode 100644 index 000000000..48a282d07 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxsurfacepool.h @@ -0,0 +1,184 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFX_SURFACE_POOL_H__ +#define __MFX_SURFACE_POOL_H__ + +#include "mfxstructures.h" + +/*! GUID to obtain mfxSurfacePoolInterface. */ +static const mfxGUID MFX_GUID_SURFACE_POOL = {{0x35, 0x24, 0xf3, 0xda, 0x96, 0x4e, 0x47, 0xf1, 0xaf, 0xb4, 0xec, 0xb1, 0x15, 0x08, 0x06, 0xb1}}; + +/*! Specifies type of pool for VPP component. */ +typedef enum { + MFX_VPP_POOL_IN = 0, /*!< Input pool. */ + MFX_VPP_POOL_OUT = 1 /*!< Output pool. */ +} mfxVPPPoolType; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! The extension buffer specifies surface pool management policy. + Absence of the attached buffer means MFX_ALLOCATION_UNLIMITED policy: + each call of GetSurfaceForXXX leads to surface allocation. +*/ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_ALLOCATION_HINTS. */ + mfxPoolAllocationPolicy AllocationPolicy; /*!< Allocation policy. */ + /*! How many surfaces to allocate during Init. + It's applicable for any polices set by mfxPoolAllocationPolicy::AllocationPolicy + even if the requested number exceeds recommended size of the pool. */ + mfxU32 NumberToPreAllocate; + /*! DeltaToAllocateOnTheFly specifies how many surfaces are allocated + in addition to NumberToPreAllocate in MFX_ALLOCATION_LIMITED mode. + Maximum number of allocated frames will be + NumberToPreAllocate + DeltaToAllocateOnTheFly. + */ + mfxU32 DeltaToAllocateOnTheFly; + union { + mfxVPPPoolType VPPPoolType; /*!< Defines what VPP pool is targeted - input or output. Ignored for other components. */ + mfxU32 reserved; + }; + mfxU32 Wait; /*!< Time in milliseconds for GetSurfaceForXXX() and DecodeFrameAsync functions to wait until surface will be available. */ + mfxU32 reserved1[4]; /*!< Reserved for future use */ +} mfxExtAllocationHints; +MFX_PACK_END() + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! Specifies the surface pool interface. */ +typedef struct mfxSurfacePoolInterface +{ + mfxHDL Context; /*!< The context of the surface pool interface. User should not touch (change, set, null) this pointer. */ + + /*! @brief + Increments the internal reference counter of the mfxSurfacePoolInterface. The mfxSurfacePoolInterface is not destroyed until the + mfxSurfacePoolInterface is destroyed with mfxSurfacePoolInterface::Release function. mfxSurfacePoolInterface::AddRef should be used each time a new link to the + mfxSurfacePoolInterface is created for proper management. + + @param[in] pool Valid pool. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + + */ + mfxStatus (MFX_CDECL *AddRef)(struct mfxSurfacePoolInterface *pool); + /*! @brief + Decrements the internal reference counter of the mfxSurfacePoolInterface. mfxSurfacePoolInterface::Release + should be called after using the mfxSurfacePoolInterface::AddRef function to add a mfxSurfacePoolInterface or when allocation logic requires it. + For example, call mfxSurfacePoolInterface::Release to release a mfxSurfacePoolInterface obtained with + the mfxFrameSurfaceInterface::QueryInterface function. + + @param[in] pool Valid pool. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of mfxSurfacePoolInterface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Release)(struct mfxSurfacePoolInterface *pool); + /*! @brief + Returns current reference counter of mfxSurfacePoolInterface structure. + + @param[in] pool Valid pool. + @param[out] counter Sets counter to the current reference counter value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetRefCounter)(struct mfxSurfacePoolInterface *pool, mfxU32* counter); + /*! @brief + The function should be called by oneAPI Video Processing Library (oneVPL) components or application to specify how many surfaces + it will use concurrently. + Internally, oneVPL allocates surfaces in the shared pool according to the component's policy set by mfxPoolAllocationPolicy. + The exact moment of surfaces allocation is defined by the component and generally independent from that call. + + @param[in] pool Valid pool. + @param[in] num_surfaces The number of surfaces required by the component. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM If pool has MFX_ALLOCATION_UNLIMITED or MFX_ALLOCATION_LIMITED policy. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *SetNumSurfaces)(struct mfxSurfacePoolInterface *pool, mfxU32 num_surfaces); + + /*! @brief + The function should be called by oneVPL components when component is closed or reset and doesn't need to use pool more. It helps + to manage memory accordingly and release redundant memory. Important to specify the same number of surfaces which is requested + during SetNumSurfaces call, otherwise it may lead to the pipeline stalls. + + @param[in] pool Valid pool. + @param[in] num_surfaces The number of surfaces used by the component. + + @return + MFX_ERR_NONE If no error. \n + + MFX_WRN_OUT_OF_RANGE If num_surfaces doesn't equal to num_surfaces requested during SetNumSurfaces call. \n + + MFX_ERR_NULL_PTR If pool is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM If pool has MFX_ALLOCATION_UNLIMITED or MFX_ALLOCATION_LIMITED policy. \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *RevokeSurfaces)(struct mfxSurfacePoolInterface *pool, mfxU32 num_surfaces); + /*! @brief + Returns current allocation policy. + + @param[in] pool Valid pool. + @param[out] policy Sets policy to the current allocation policy value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or policy is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetAllocationPolicy)(struct mfxSurfacePoolInterface *pool, mfxPoolAllocationPolicy *policy); + + /*! @brief + Returns maximum pool size. In case of mfxPoolAllocationPolicy::MFX_ALLOCATION_UNLIMITED policy 0xFFFFFFFF will be returned. + + @param[in] pool Valid pool. + @param[out] size Sets size to the maximum pool size value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or size is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetMaximumPoolSize)(struct mfxSurfacePoolInterface *pool, mfxU32 *size); + + /*! @brief + Returns current pool size. + + @param[in] pool Valid pool. + @param[out] size Sets size to the current pool size value. + + @return + MFX_ERR_NONE If no error. \n + MFX_ERR_NULL_PTR If pool or size is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfacePoolInterface->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *GetCurrentPoolSize)(struct mfxSurfacePoolInterface *pool, mfxU32 *size); + + mfxHDL reserved[4]; /*!< Reserved for future use. */ + +} mfxSurfacePoolInterface; +MFX_PACK_END() + + +#endif /* __MFX_SURFACE_POOL_H__ */ + diff --git a/third-party/IntelVPL/x64/include/vpl/mfxvideo++.h b/third-party/IntelVPL/x64/include/vpl/mfxvideo++.h new file mode 100644 index 000000000..5b01821b4 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxvideo++.h @@ -0,0 +1,594 @@ +/*########################################################################### + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ###########################################################################*/ + +#ifndef __MFXVIDEOPLUSPLUS_H +#define __MFXVIDEOPLUSPLUS_H + +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD +#include "vpl/mfx.h" +#define MFX_IMPL_ACCELMODE(x) (0xff00 & (x)) +#else +#include "mfxvideo.h" +#endif + +class MFXVideoSessionBase { +public: + virtual ~MFXVideoSessionBase() {} + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion* ver) = 0; + virtual mfxStatus InitEx(mfxInitParam par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus QueryIMPL(mfxIMPL* impl) = 0; + virtual mfxStatus QueryVersion(mfxVersion* version) = 0; + + virtual mfxStatus JoinSession(mfxSession child_session) = 0; + virtual mfxStatus DisjoinSession() = 0; + virtual mfxStatus CloneSession(mfxSession* clone) = 0; + virtual mfxStatus SetPriority(mfxPriority priority) = 0; + virtual mfxStatus GetPriority(mfxPriority* priority) = 0; + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator* allocator) = 0; + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) = 0; + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL* hdl) = 0; + virtual mfxStatus QueryPlatform(mfxPlatform* platform) = 0; + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) = 0; + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPP(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) = 0; + + virtual operator mfxSession(void) = 0; +}; + +class MFXVideoENCODEBase { +public: + virtual ~MFXVideoENCODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetEncodeStat(mfxEncodeStat* stat) = 0; + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl* ctrl, + mfxFrameSurface1* surface, + mfxBitstream* bs, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoDECODEBase { +public: + virtual ~MFXVideoDECODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus DecodeHeader(mfxBitstream* bs, mfxVideoParam* par) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + + virtual mfxStatus GetDecodeStat(mfxDecodeStat* stat) = 0; + virtual mfxStatus GetPayload(mfxU64* ts, mfxPayload* payload) = 0; + virtual mfxStatus SetSkipMode(mfxSkipMode mode) = 0; + virtual mfxStatus DecodeFrameAsync(mfxBitstream* bs, + mfxFrameSurface1* surface_work, + mfxFrameSurface1** surface_out, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoVPPBase { +public: + virtual ~MFXVideoVPPBase() {} + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest request[2]) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetVPPStat(mfxVPPStat* stat) = 0; + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1* in, + mfxFrameSurface1* out, + mfxExtVppAuxData* aux, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1* in, mfxFrameSurface1** out) = 0; +}; + +class MFXVideoSession : public MFXVideoSessionBase { +public: + MFXVideoSession(void) { + m_session = (mfxSession)0; +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + m_loader = (mfxLoader)0; +#endif + } + virtual ~MFXVideoSession(void) { + Close(); + } + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion *ver) override { +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + mfxInitParam par = {}; + par.Implementation = impl; + par.Version = *ver; + return InitSession(par); +#else + return MFXInit(impl, ver, &m_session); +#endif + } + virtual mfxStatus InitEx(mfxInitParam par) override { +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + return InitSession(par); +#else + return MFXInitEx(par, &m_session); +#endif + } + virtual mfxStatus Close(void) override { +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + if (m_session) { + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + if (m_loader) { + MFXUnload(m_loader); + m_loader = (mfxLoader)0; + } + return mfxRes; + } + else { + return MFX_ERR_NONE; + } +#else + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + return mfxRes; +#endif + } + + virtual mfxStatus QueryIMPL(mfxIMPL *impl) override { + return MFXQueryIMPL(m_session, impl); + } + virtual mfxStatus QueryVersion(mfxVersion *version) override { + return MFXQueryVersion(m_session, version); + } + + virtual mfxStatus JoinSession(mfxSession child_session) override { + return MFXJoinSession(m_session, child_session); + } + virtual mfxStatus DisjoinSession() override { + return MFXDisjoinSession(m_session); + } + virtual mfxStatus CloneSession(mfxSession *clone) override { + return MFXCloneSession(m_session, clone); + } + virtual mfxStatus SetPriority(mfxPriority priority) override { + return MFXSetPriority(m_session, priority); + } + virtual mfxStatus GetPriority(mfxPriority *priority) override { + return MFXGetPriority(m_session, priority); + } + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator *allocator) override { + return MFXVideoCORE_SetFrameAllocator(m_session, allocator); + } + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) override { + return MFXVideoCORE_SetHandle(m_session, type, hdl); + } + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *hdl) override { + return MFXVideoCORE_GetHandle(m_session, type, hdl); + } + virtual mfxStatus QueryPlatform(mfxPlatform *platform) override { + return MFXVideoCORE_QueryPlatform(m_session, platform); + } + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) override { + return MFXVideoCORE_SyncOperation(m_session, syncp, wait); + } + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPP (mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP (m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual operator mfxSession(void) override { + return m_session; + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session + +#ifdef MFXVIDEO_CPP_ENABLE_MFXLOAD + mfxLoader m_loader; + + inline void InitVariant(mfxVariant *var, mfxU32 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U32; + var->Data.U32 = data; + } + + inline void InitVariant(mfxVariant *var, mfxU16 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U16; + var->Data.U16 = data; + } + + inline void InitVariant(mfxVariant *var, mfxHDL data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_PTR; + var->Data.Ptr = data; + } + + template + mfxStatus CreateConfig(varDataType data, const char *propertyName) { + mfxConfig cfg = MFXCreateConfig(m_loader); + if (cfg == nullptr) + return MFX_ERR_NULL_PTR; + + mfxVariant variant; + InitVariant(&variant, data); + + return MFXSetConfigFilterProperty(cfg, (mfxU8 *)propertyName, variant); + } + + mfxStatus InitSession(mfxInitParam par) { + // already initialized + if (m_session) + return MFX_ERR_NONE; + + m_loader = MFXLoad(); + if (!m_loader) + return MFX_ERR_NOT_FOUND; + + mfxStatus mfxRes = MFX_ERR_NONE; + + mfxU32 implBaseType = MFX_IMPL_BASETYPE(par.Implementation); + + // select implementation type + switch (implBaseType) { + case MFX_IMPL_AUTO: + case MFX_IMPL_AUTO_ANY: + break; + + case MFX_IMPL_SOFTWARE: + mfxRes = CreateConfig(MFX_IMPL_TYPE_SOFTWARE, "mfxImplDescription.Impl"); + break; + + case MFX_IMPL_HARDWARE: + case MFX_IMPL_HARDWARE_ANY: + case MFX_IMPL_HARDWARE2: + case MFX_IMPL_HARDWARE3: + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(MFX_IMPL_TYPE_HARDWARE, "mfxImplDescription.Impl"); + break; + + default: + mfxRes = MFX_ERR_UNSUPPORTED; + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // select adapter index (if specified) + // see notes below about how VendorImplID is interpreted for each acceleration mode + switch (implBaseType) { + case MFX_IMPL_HARDWARE: + mfxRes = CreateConfig(0, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE2: + mfxRes = CreateConfig(1, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE3: + mfxRes = CreateConfig(2, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(3, "mfxImplDescription.VendorImplID"); + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + mfxU32 implAccelMode = MFX_IMPL_ACCELMODE(par.Implementation); + if (implAccelMode == MFX_IMPL_VIA_D3D9) { + // D3D9 - because VendorImplID corresponds to DXGI adapter index (DX11 enumeration), + // this may not map directly to D3D9 index in multi-adapter/multi-monitor configurations + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D9, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_D3D11) { + // D3D11 - VendorImplID corresponds to DXGI adapter index + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D11, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_VAAPI) { + // VAAPI - in general MFXInitEx treats any HARDWAREn the same way (relies on application to pass + // correct VADisplay via SetHandle), but 2.x RT only reports actual number of adapters + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_VAAPI, + "mfxImplDescription.AccelerationMode"); + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set required API level + mfxRes = + CreateConfig(par.Version.Version, "mfxImplDescription.ApiVersion.Version"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set GPUCopy parameter + if (par.GPUCopy) { + mfxRes = CreateConfig(par.GPUCopy, "DeviceCopy"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + + // ExternalThreads was deprecated in API 2.x along with MFXDoWork() + if (par.ExternalThreads) { + return MFX_ERR_UNSUPPORTED; + } + + // pass extBufs + if (par.NumExtParam) { + for (mfxU32 idx = 0; idx < par.NumExtParam; idx++) { + mfxRes = CreateConfig(par.ExtParam[idx], "ExtBuffer"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + } + + // create session with highest priority implementation remaining after filters + mfxRes = MFXCreateSession(m_loader, 0, &m_session); + + return mfxRes; + } +#endif + +private: + MFXVideoSession(const MFXVideoSession &); + void operator=(MFXVideoSession &); +}; + +class MFXVideoENCODE : public MFXVideoENCODEBase { +public: + explicit MFXVideoENCODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoENCODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoENCODE_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoENCODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoENCODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoENCODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoENCODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoENCODE_GetVideoParam(m_session, par); + } + virtual mfxStatus GetEncodeStat(mfxEncodeStat *stat) override { + return MFXVideoENCODE_GetEncodeStat(m_session, stat); + } + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl *ctrl, + mfxFrameSurface1 *surface, + mfxBitstream *bs, + mfxSyncPoint *syncp) override { + return MFXVideoENCODE_EncodeFrameAsync(m_session, ctrl, surface, bs, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoENCODE(const MFXVideoENCODE& other); + MFXVideoENCODE& operator=(const MFXVideoENCODE& other); +}; + +class MFXVideoDECODE : public MFXVideoDECODEBase { +public: + explicit MFXVideoDECODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoDECODE_Query(m_session, in, out); + } + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) override { + return MFXVideoDECODE_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoDECODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoDECODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoDECODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoDECODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoDECODE_GetVideoParam(m_session, par); + } + + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) override { + return MFXVideoDECODE_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) override { + return MFXVideoDECODE_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) override { + return MFXVideoDECODE_SetSkipMode(m_session, mode); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, + mfxFrameSurface1 *surface_work, + mfxFrameSurface1 **surface_out, + mfxSyncPoint *syncp) override { + return MFXVideoDECODE_DecodeFrameAsync(m_session, bs, surface_work, surface_out, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoDECODE(const MFXVideoDECODE& other); + MFXVideoDECODE& operator=(const MFXVideoDECODE& other); +}; + +class MFXVideoVPP : public MFXVideoVPPBase { +public: + explicit MFXVideoVPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoVPP(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoVPP_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2]) override { + return MFXVideoVPP_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoVPP_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoVPP_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoVPP_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoVPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetVPPStat(mfxVPPStat *stat) override { + return MFXVideoVPP_GetVPPStat(m_session, stat); + } + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in, + mfxFrameSurface1 *out, + mfxExtVppAuxData *aux, + mfxSyncPoint *syncp) override { + return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp); + } + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP(m_session, output_surf); + } + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1 *in, mfxFrameSurface1 **out) override { + return MFXVideoVPP_ProcessFrameAsync(m_session, in, out); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoVPP(const MFXVideoVPP& other); + MFXVideoVPP& operator=(const MFXVideoVPP& other); +}; + +class MFXVideoDECODE_VPP +{ +public: + explicit MFXVideoDECODE_VPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE_VPP(void) { + Close(); + } + + virtual mfxStatus Init(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Init(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus Reset(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Reset(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus GetChannelParam(mfxVideoChannelParam *par, mfxU32 channel_id) { + return MFXVideoDECODE_VPP_GetChannelParam(m_session, par, channel_id); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, mfxU32* skip_channels, mfxU32 num_skip_channels, mfxSurfaceArray **surf_array_out) { + return MFXVideoDECODE_VPP_DecodeFrameAsync(m_session, bs, skip_channels, num_skip_channels, surf_array_out); + } + + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) { + return MFXVideoDECODE_VPP_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus Close(void) { + return MFXVideoDECODE_VPP_Close(m_session); + } + virtual mfxStatus GetVideoParam(mfxVideoParam *par) { + return MFXVideoDECODE_VPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) { + return MFXVideoDECODE_VPP_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) { + return MFXVideoDECODE_VPP_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) { + return MFXVideoDECODE_VPP_SetSkipMode(m_session, mode); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +private: + MFXVideoDECODE_VPP(const MFXVideoDECODE_VPP& other); + MFXVideoDECODE_VPP& operator=(const MFXVideoDECODE_VPP& other); +}; + +#endif //__MFXVIDEOPLUSPLUS_H diff --git a/third-party/IntelVPL/x64/include/vpl/mfxvideo.h b/third-party/IntelVPL/x64/include/vpl/mfxvideo.h new file mode 100644 index 000000000..4aab2d87f --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxvideo.h @@ -0,0 +1,1095 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXVIDEO_H__ +#define __MFXVIDEO_H__ +#include "mfxsession.h" +#include "mfxstructures.h" +#include "mfxmemory.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/*! + Describes the API callback functions Alloc, Lock, Unlock, GetHDL, and Free that the + implementation might use for allocating internal frames. Applications that operate on OS-specific video surfaces must + implement these API callback functions. + + Using the default allocator implies that frame data passes in or out of functions through pointers, + as opposed to using memory IDs. + + Behavior is undefined when using an incompletely defined external allocator. + \verbatim embed:rst + See the :ref:`Memory Allocation and External Allocators section ` for additional information. + \endverbatim +*/ +typedef struct { + mfxU32 reserved[4]; + mfxHDL pthis; /*!< Pointer to the allocator object. */ + + /*! + @brief Allocates surface frames. For decoders, MFXVideoDECODE_Init calls Alloc only once. That call + includes all frame allocation requests. For encoders, MFXVideoENCODE_Init calls Alloc twice: once for the + input surfaces and again for the internal reconstructed surfaces. If application also calls this function explicitly, + it should have the logic to avoid duplicated allocation for the same request. + + If two library components must share DirectX* surfaces, this function should pass the pre-allocated surface + chain to the library instead of allocating new DirectX surfaces. + \verbatim embed:rst + See the :ref:`Surface Pool Allocation section ` for additional information. + \endverbatim + + @param[in] pthis Pointer to the allocator object. + @param[in] request Pointer to the mfxFrameAllocRequest structure that specifies the type and number of required frames. + @param[out] response Pointer to the mfxFrameAllocResponse structure that retrieves frames actually allocated. + @return + MFX_ERR_NONE The function successfully allocated the memory block. \n + MFX_ERR_MEMORY_ALLOC The function failed to allocate the video frames. \n + MFX_ERR_UNSUPPORTED The function does not support allocating the specified type of memory. + */ + mfxStatus (MFX_CDECL *Alloc) (mfxHDL pthis, mfxFrameAllocRequest *request, mfxFrameAllocResponse *response); + + /*! + @brief Locks a frame and returns its pointer. + @param[in] pthis Pointer to the allocator object. + @param[in] mid Memory block ID. + @param[out] ptr Pointer to the returned frame structure. + @return + MFX_ERR_NONE The function successfully locked the memory block. \n + MFX_ERR_LOCK_MEMORY This function failed to lock the frame. + */ + mfxStatus (MFX_CDECL *Lock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr); + + /*! + @brief Unlocks a frame and invalidates the specified frame structure. + @param[in] pthis Pointer to the allocator object. + @param[in] mid Memory block ID. + @param[out] ptr Pointer to the frame structure. This pointer can be NULL. + @return + MFX_ERR_NONE The function successfully locked the memory block. + */ + mfxStatus (MFX_CDECL *Unlock) (mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr); + + /*! + @brief Returns the OS-specific handle associated with a video frame. If the handle is a COM interface, + the reference counter must increase. The library will release the interface afterward. + @param[in] pthis Pointer to the allocator object. + @param[in] mid Memory block ID. + @param[out] handle Pointer to the returned OS-specific handle. + @return + MFX_ERR_NONE The function successfully returned the OS-specific handle. \n + MFX_ERR_UNSUPPORTED The function does not support obtaining OS-specific handle.. + @note For D3D11 surfaces, GetHDL should return an mfxHDLPair instead of an mfxHDL. In the mfxHDLPair struct, + mfxHDLPair.first should be is set to the Texture2D address, and mfxHDLPair.second should be set to the array index. + */ + mfxStatus (MFX_CDECL *GetHDL) (mfxHDL pthis, mfxMemId mid, mfxHDL *handle); + + /*! + @brief De-allocates all allocated frames. + MFXClose will call this function. If application also calls this function, it should have logic to avoid double free. + @param[in] pthis Pointer to the allocator object. + @param[in] response Pointer to the mfxFrameAllocResponse structure returned by the Alloc function. + @return + MFX_ERR_NONE The function successfully de-allocated the memory block. + */ + mfxStatus (MFX_CDECL *Free) (mfxHDL pthis, mfxFrameAllocResponse *response); +} mfxFrameAllocator; +MFX_PACK_END() + +/*! + @brief + Sets the external allocator callback structure for frame allocation. + + If the allocator argument is NULL, the library uses the + default allocator, which allocates frames from system memory or hardware devices. The behavior of the API is undefined if it uses this + function while the previous allocator is in use. A general guideline is to set the allocator immediately after initializing the session. + + @param[in] session Session handle. + @param[in] allocator Pointer to the mfxFrameAllocator structure + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_SetFrameAllocator(mfxSession session, mfxFrameAllocator *allocator); + +/*! + @brief + Sets any essential system handle that the library might use. The handle must remain valid until after + the application calls the MFXClose function. + + If the specified system handle is a COM interface, the reference counter of the COM interface will increase. + The counter will decrease when the session closes. + + @param[in] session Session handle. + @param[in] type Handle type + @param[in] hdl Handle to be set + + @returns + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNDEFINED_BEHAVIOR The same handle is redefined. + For example, the function has been called twice with the same handle type or an + internal handle has been created before this function call. + MFX_ERR_DEVICE_FAILED The SDK cannot initialize using the handle. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_SetHandle(mfxSession session, mfxHandleType type, mfxHDL hdl); + +/*! + @brief + Obtains system handles previously set by the MFXVideoCORE_SetHandle function. + + If the handler is a COM interface, the reference counter of the interface increases. + The calling application must release the COM interface. + + @param[in] session Session handle. + @param[in] type Handle type + @param[in] hdl Pointer to the handle to be set + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNDEFINED_BEHAVIOR Specified handle type not found. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_GetHandle(mfxSession session, mfxHandleType type, mfxHDL *hdl); + +/*! + @brief + Returns information about current hardware platform in the Legacy mode. + + @param[in] session Session handle. + @param[out] platform Pointer to the mfxPlatform structure + + @return + MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.19. + + Notes: Deprecated mfxPlatform::CodeName will be filled with MFX_PLATFORM_MAXIMUM for future new platforms. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_QueryPlatform(mfxSession session, mfxPlatform* platform); + +/*! + @brief + Initiates execution of an asynchronous function not already started and returns the status code after the specified asynchronous operation completes. + If wait is zero, the function returns immediately + + @param[in] session Session handle. + @param[in] syncp Sync point + @param[in] wait wait time in milliseconds + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NONE_PARTIAL_OUTPUT The function completed successfully, bitstream contains a portion of the encoded frame according to required granularity. \n + MFX_WRN_IN_EXECUTION The specified asynchronous function is in execution. \n + MFX_ERR_ABORTED The specified asynchronous function aborted due to data dependency on a previous asynchronous function that did not complete. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, mfxU32 wait); + +/*! Maximum allowed length of parameter key and value strings, in bytes. */ +#define MAX_PARAM_STRING_LENGTH 4096 + +/*! The mfxStructureType enumerator specifies the structure type for configuration with the string interface. */ +typedef enum { + MFX_STRUCTURE_TYPE_UNKNOWN = 0, /*!< Unknown structure type. */ + + MFX_STRUCTURE_TYPE_VIDEO_PARAM = 1, /*!< Structure of type mfxVideoParam. */ +} mfxStructureType; + +#define MFX_CONFIGINTERFACE_VERSION MFX_STRUCT_VERSION(1, 0) + +MFX_PACK_BEGIN_STRUCT_W_PTR() +/* Specifies config interface. */ +typedef struct mfxConfigInterface { + mfxHDL Context; /*!< The context of the config interface. User should not touch (change, set, null) this pointer. */ + mfxStructVersion Version; /*!< The version of the structure. */ + + /*! @brief + Sets a parameter to specified value in the current session. If a parameter already has a value, + the new value will overwrite the existing value. + + @param[in] config_interface The valid interface returned by calling MFXQueryInterface(). + @param[in] key Null-terminated string containing parameter to set. The string length must be < MAX_PARAM_STRING_LENGTH bytes. + @param[in] value Null-terminated string containing value to which key should be set. The string length must be < MAX_PARAM_STRING_LENGTH bytes. + value will be converted from a string to the expected data type for the given key, or return an error if conversion fails. + @param[in] struct_type Type of structure pointed to by structure. + @param[out] structure If and only if SetParameter returns MFX_ERR_NONE, the contents of structure (including any attached extension + buffers) will be updated according to the provided key and value. If key modifies a field in an extension buffer + which is not already attached, the function will return MFX_ERR_MORE_EXTBUFFER and fill ext_buffer with the header for + the required mfxExtBuffer type. + @param[out] ext_buffer If and only if SetParameter returns MFX_ERR_MORE_EXTBUFFER, ext_buffer will contain the header for a buffer + of type mfxExtBuffer. The caller should allocate a buffer of the size ext_buffer.BufferSz, copy the header in ext_buffer + to the start of this new buffer, attach this buffer to videoParam, then call SetParameter again. Otherwise, the + contents of ext_buffer will be cleared. + @return + MFX_ERR_NONE The function completed successfully. + MFX_ERR_NULL_PTR If key, value, videoParam, and/or ext_buffer is NULL. + MFX_ERR_NOT_FOUND If key contains an unknown parameter name. + MFX_ERR_UNSUPPORTED If value is of the wrong format for key (for example, a string is provided where an integer is required) + or if value cannot be converted into any valid data type. + MFX_ERR_INVALID_VIDEO_PARAM If length of key or value is >= MAX_PARAM_STRING_LENGTH or is zero (empty string). + MFX_ERR_MORE_EXTBUFFER If key requires modifying a field in an mfxExtBuffer which is not attached. Caller must allocate and attach + the buffer type provided in ext_buffer then call the function again. + + @since This function is available since API version 2.10. + */ + mfxStatus (MFX_CDECL *SetParameter)(struct mfxConfigInterface *config_interface, const mfxU8* key, const mfxU8* value, mfxStructureType struct_type, mfxHDL structure, mfxExtBuffer *ext_buffer); + + mfxHDL reserved[16]; +} mfxConfigInterface; +MFX_PACK_END() + +/*! Alias for returning interface of type mfxConfigInterface. */ +#define MFXGetConfigInterface(session, piface) MFXVideoCORE_GetHandle((session), MFX_HANDLE_CONFIG_INTERFACE, (mfxHDL *)(piface)) + +/* VideoENCODE */ + +/*! + @brief + Works in either of four modes: + + @li If the @p in parameter is zero, the function returns the class configurability in the output structure. The application must set to zero the fields it wants to check for support. If the field is supported, function sets non-zero value to this field, otherwise it would be ignored. It indicates that the SDK implementation can configure the field with Init. + + @li If the @p in parameter is non-zero, the function checks the validity of the fields in the input structure. Then the function returns the corrected values in + the output structure. If there is insufficient information to determine the validity or correction is impossible, the function zeroes the fields. + This feature can verify whether the implementation supports certain profiles, levels or bitrates. + + @li If the @p in parameter is non-zero and mfxExtEncoderResetOption structure is attached to it, the function queries for the outcome of the MFXVideoENCODE_Reset function + and returns it in the mfxExtEncoderResetOption structure attached to out. The query function succeeds if a reset is possible and returns an error otherwise. Unlike other + modes that are independent of the encoder state, this one checks if reset is possible in the present encoder state. + This mode also requires a completely defined mfxVideoParam structure, unlike other modes that support partially defined configurations. + See mfxExtEncoderResetOption description for more details. + + @li If the @p in parameter is non-zero and mfxExtEncoderCapability structure is attached to it, the function returns encoder capability in the mfxExtEncoderCapability structure + attached to out. It is recommended to fill in the mfxVideoParam structure and set the hardware acceleration device handle before calling the function in this mode. + + The application can call this function before or after it initializes the encoder. The ``CodecId`` field of the output structure is a mandated field (to be filled by the + application) to identify the coding standard. + + @param[in] session Session handle. + @param[in] in Pointer to the mfxVideoParam structure as input. + @param[out] out Pointer to the mfxVideoParam structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function failed to identify a specific implementation for the required features. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); + +/*! + @brief + Returns minimum and suggested numbers of the input frame surfaces required for encoding initialization and their type. + + Init will call the external allocator for the required frames with the same set of numbers. + This function does not validate I/O parameters except those used in calculating the number of input surfaces. + + The use of this function is recommended. + \verbatim embed:rst + For more information, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim + + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure as input. + @param[in] request Pointer to the mfxFrameAllocRequest structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); + +/*! + @brief + Allocates memory and prepares tables and necessary structures for encoding. + + This function also does extensive validation to ensure if the + configuration, as specified in the input parameters, is supported. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The function is called twice without a close; + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Init(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Stops the current encoding operation and restores internal structures or parameters for a new encoding operation, possibly with new parameters. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Reset(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Terminates the current encoding operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_Close(mfxSession session); + +/*! + @brief + Retrieves current working parameters to the specified output structure. + + If extended buffers are to be returned, the + application must allocate those extended buffers and attach them as part of the output structure. + The application can retrieve a copy of the bitstream header by attaching the mfxExtCodingOptionSPSPPS structure to the mfxVideoParam structure. + + @param[in] session Session handle. + @param[in] par Pointer to the corresponding parameter structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_GetVideoParam(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Obtains statistics collected during encoding. + + @param[in] session Session handle. + @param[in] stat Pointer to the mfxEncodeStat structure. + + @return MFX_ERR_NONE The function completed successfully. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_GetEncodeStat(mfxSession session, mfxEncodeStat *stat); + +/*! + @brief + Takes a single input frame in either encoded or display order and generates its output bitstream. + + In the case of encoded ordering, the mfxEncodeCtrl + structure must specify the explicit frame type. In the case of display ordering, this function handles frame order shuffling according to the GOP structure + parameters specified during initialization. + + Since encoding may process frames differently from the input order, not every call of the function generates output and the function returns MFX_ERR_MORE_DATA. + If the encoder needs to cache the frame, the function locks the frame. The application should not alter the frame until the encoder unlocks the frame. + If there is output (with return status MFX_ERR_NONE), the return is a frame's worth of bitstream. + + It is the calling application's responsibility to ensure that there is sufficient space in the output buffer. The value ``BufferSizeInKB`` in the + mfxVideoParam structure at encoding initialization specifies the maximum possible size for any compressed frames. This value can also be obtained from the + MFXVideoENCODE_GetVideoParam function after encoding initialization. + + To mark the end of the encoding sequence, call this function with a NULL surface pointer. Repeat the call to drain any remaining internally cached bitstreams + (one frame at a time) until MFX_ERR_MORE_DATA is returned. + + This function is asynchronous. + + @param[in] session Session handle. + @param[in] ctrl Pointer to the mfxEncodeCtrl structure for per-frame encoding control; this parameter is optional (it can be NULL) if the encoder works in the display order mode. + ctrl can be freed right after successful MFXVideoENCODE_EncodeFrameAsync (it is copied inside), but not the ext buffers attached to this ctrl. + If the ext buffers are allocated by the user, do not move, alter or delete unless surface.Data.Locked is zero. + @param[in] surface Pointer to the frame surface structure. + For surfaces allocated by oneAPI Video Processing Library (oneVPL) RT it is safe to call mfxFrameSurface1::FrameInterface->Release after successful MFXVideoENCODE_EncodeFrameAsync. + If it is allocated by user, do not move, alter or delete unless surface.Data.Locked is zero. + @param[out] bs Pointer to the output bitstream. + @param[out] syncp Pointer to the returned sync point associated with this operation. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NOT_ENOUGH_BUFFER The bitstream buffer size is insufficient. \n + MFX_ERR_MORE_DATA The function requires more data to generate any output. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM Inconsistent parameters detected not conforming to Configuration Parameter Constraints. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoENCODE_EncodeFrameAsync(mfxSession session, mfxEncodeCtrl *ctrl, mfxFrameSurface1 *surface, mfxBitstream *bs, mfxSyncPoint *syncp); + +/*! + @brief + Works in one of two modes: + + @li If the @p in parameter is zero, the function returns the class configurability in the output structure. A non-zero value in each field of the output structure + indicates that the field is configurable by the implementation with the MFXVideoDECODE_Init function. + + @li If the @p in parameter is non-zero, the function checks the validity of the fields in the input structure. Then the function returns the corrected values to + the output structure. If there is insufficient information to determine the validity or correction is impossible, the function zeros the fields. This + feature can verify whether the implementation supports certain profiles, levels, or bitrates. + + The application can call this function before or after it initializes the decoder. The ``CodecId`` field of the output structure is a mandated field + (to be filled by the application) to identify the coding standard. + + @param[in] session Session handle. + @param[in] in Pointer to the mfxVideoParam structure as input. + @param[out] out Pointer to the mfxVideoParam structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The function failed to identify a specific implementation for the required features. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The decoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ + +mfxStatus MFX_CDECL MFXVideoDECODE_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); + +/*! + @brief + Parses the input bitstream and fills the mfxVideoParam structure with appropriate values, such as resolution and frame rate, for the Init API function. + + The application can then pass the resulting structure to the MFXVideoDECODE_Init function for decoder initialization. + + An application can call this API function at any time before or after decoder initialization. If the library finds a sequence header in the bitstream, the function + moves the bitstream pointer to the first bit of the sequence header. Otherwise, the function moves the bitstream pointer close to the end of the bitstream buffer but leaves enough data in the buffer to avoid possible loss of start code. + + The ``CodecId`` field of the mfxVideoParam structure is a mandated field (to be filled by the application) to identify the coding standard. + + The application can retrieve a copy of the bitstream header, by attaching the mfxExtCodingOptionSPSPPS structure to the mfxVideoParam structure. + + @param[in] session Session handle. + @param[in] bs Pointer to the bitstream. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + - MFX_ERR_NONE The function successfully filled the structure. It does not mean that the stream can be decoded by the library. + The application should call MFXVideoDECODE_Query function to check if decoding of the stream is supported. \n + - MFX_ERR_MORE_DATA The function requires more bitstream data. \n + - MFX_ERR_UNSUPPORTED ``CodecId`` field of the mfxVideoParam structure indicates some unsupported codec. \n + - MFX_ERR_INVALID_HANDLE Session is not initialized. \n + - MFX_ERR_NULL_PTR @p bs or @p par pointer is NULL. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_DecodeHeader(mfxSession session, mfxBitstream *bs, mfxVideoParam *par); + +/*! + @brief + Returns minimum and suggested numbers of the output frame surfaces required for decoding initialization and their type. + + Init will call the external allocator for the required frames with the same set of numbers. + The use of this function is recommended. + \verbatim embed:rst + For more information, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim + + The ``CodecId`` field of the mfxVideoParam structure is a mandated field (to be filled by the application) to identify the coding standard. + This function does not validate I/O parameters except those used in calculating the number of output surfaces. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure as input. + @param[in] request Pointer to the mfxFrameAllocRequest structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest *request); + +/*! + @brief + Allocates memory and prepares tables and necessary structures for encoding. + + This function also does extensive validation to ensure if the + configuration, as specified in the input parameters, is supported. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The encoding may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The function is called twice without a close. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_Init(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Stops the current decoding operation and restores internal structures or parameters for a new decoding operation. + + Reset serves two purposes: + + @li It recovers the decoder from errors. + @li It restarts decoding from a new position + + The function resets the old sequence header (sequence parameter set in H.264, or sequence header in MPEG-2 and VC-1). The decoder will expect a new sequence header + before it decodes the next frame and will skip any bitstream before encountering the new sequence header. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected that video parameters are wrong or they conflict with initialization parameters. Reset is impossible. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_Reset(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Terminates the current decoding operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_Close(mfxSession session); + +/*! + @brief + Retrieves current working parameters to the specified output structure. + + If extended buffers are to be returned, the + application must allocate those extended buffers and attach them as part of the output structure. + The application can retrieve a copy of the bitstream header, by attaching the mfxExtCodingOptionSPSPPS structure to the mfxVideoParam structure. + + @param[in] session Session handle. + @param[in] par Pointer to the corresponding parameter structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_GetVideoParam(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Obtains statistics collected during decoding. + + @param[in] session Session handle. + @param[in] stat Pointer to the mfxDecodeStat structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_GetDecodeStat(mfxSession session, mfxDecodeStat *stat); + +/*! + @brief + Sets the decoder skip mode. + + The application may use this API function to increase decoding performance by sacrificing output quality. Increasing the skip + level first results in skipping of some decoding operations like deblocking and then leads to frame skipping; first B, then P. Particular details are platform dependent. + + @param[in] session Session handle. + @param[in] mode Decoder skip mode. See the mfxSkipMode enumerator for details. + + @return + MFX_ERR_NONE The function completed successfully and the output surface is ready for decoding \n + MFX_WRN_VALUE_NOT_CHANGED The skip mode is not affected as the maximum or minimum skip range is reached. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_SetSkipMode(mfxSession session, mfxSkipMode mode); + +/*! + @brief + Extracts user data (MPEG-2) or SEI (H.264) messages from the bitstream. + + Internally, the decoder implementation stores encountered user data or + SEI messages. The application may call this API function multiple times to retrieve the user data or SEI messages, one at a time. + + If there is no payload available, the function returns with payload->NumBit=0. + + @param[in] session Session handle. + @param[in] ts Pointer to the user data time stamp in units of 90 KHz; divide ts by 90,000 (90 KHz) to obtain the time in seconds; the time stamp matches the payload + with a specific decoded frame. + @param[in] payload Pointer to the mfxPayload structure; the payload contains user data in MPEG-2 or SEI messages in H.264. + + @return + MFX_ERR_NONE The function completed successfully and the output buffer is ready for decoding. \n + MFX_ERR_NOT_ENOUGH_BUFFER The payload buffer size is insufficient. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_GetPayload(mfxSession session, mfxU64 *ts, mfxPayload *payload); + +/*! + @brief + Decodes the input bitstream to a single output frame. + + The @p surface_work parameter provides a working frame buffer for the decoder. The application should allocate the working frame buffer, which stores decoded frames. + If the function requires caching frames after decoding, it locks the frames and the application must provide a new frame buffer in the next call. + + If, and only if, the function returns MFX_ERR_NONE, the pointer @p surface_out points to the output frame in the display order. If there are no further frames, + the function will reset the pointer to zero and return the appropriate status code. + + Before decoding the first frame, a sequence header (sequence parameter set in H.264 or sequence header in MPEG-2 and VC-1) must be present. The function skips any + bitstreams before it encounters the new sequence header. + + The input bitstream @p bs can be of any size. If there are not enough bits to decode a frame, the function returns MFX_ERR_MORE_DATA, and consumes all input bits except if + a partial start code or sequence header is at the end of the buffer. In this case, the function leaves the last few bytes in the bitstream buffer. + If there is more incoming bitstream, the application should append the incoming bitstream to the bitstream buffer. Otherwise, the application should ignore the + remaining bytes in the bitstream buffer and apply the end of stream procedure described below. + + The application must set @p bs to NULL to signal end of stream. The application may need to call this API function several times to drain any internally cached frames until the + function returns MFX_ERR_MORE_DATA. + + If more than one frame is in the bitstream buffer, the function decodes until the buffer is consumed. The decoding process can be interrupted for events such as if the + decoder needs additional working buffers, is readying a frame for retrieval, or encountering a new header. In these cases, the function returns appropriate status code + and moves the bitstream pointer to the remaining data. + + The decoder may return MFX_ERR_NONE without taking any data from the input bitstream buffer. If the application appends additional data to the bitstream buffer, it + is possible that the bitstream buffer may contain more than one frame. It is recommended that the application invoke the function repeatedly until the function + returns MFX_ERR_MORE_DATA, before appending any more data to the bitstream buffer. + + Starting from API 2.0 it is possible to pass NULL instead of surface_work. In such case runtime will allocate output frames internally. + + This function is asynchronous. + + @param[in] session Session handle. + @param[in] bs Pointer to the input bitstream. + @param[in] surface_work Pointer to the working frame buffer for the decoder. + @param[out] surface_out Pointer to the output frame in the display order. + @param[out] syncp Pointer to the sync point associated with this operation. + + @return + MFX_ERR_NONE The function completed successfully and the output surface is ready for decoding. \n + MFX_ERR_MORE_DATA The function requires more bitstream at input before decoding can proceed. \n + MFX_ERR_MORE_SURFACE The function requires more frame surface at output before decoding can proceed. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_WRN_VIDEO_PARAM_CHANGED The decoder detected a new sequence header in the bitstream. Video parameters may have changed. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The decoder detected incompatible video parameters in the bitstream and failed to follow them. \n + MFX_ERR_REALLOC_SURFACE Bigger surface_work required. May be returned only if mfxInfoMFX::EnableReallocRequest was set to ON during initialization. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED Timeout expired for internal output frame allocation (if set with mfxExtAllocationHints and NULL passed as surface_work). Repeat the call in a few milliseconds or re-initialize decoder with higher surface limit. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxFrameSurface1 *surface_work, mfxFrameSurface1 **surface_out, mfxSyncPoint *syncp); + +/* VideoVPP */ + +/*! + @brief + Works in one of two modes: + + @li If the @p in pointer is zero, the function returns the class configurability in the output structure. A non-zero value in a field indicates that the + implementation can configure it with Init. + + @li If the @p in parameter is non-zero, the function checks the validity of the fields in the input structure. Then the function returns the corrected values to + the output structure. If there is insufficient information to determine the validity or correction is impossible, the function zeroes the fields. + + The application can call this function before or after it initializes the preprocessor. + + @param[in] session Session handle. + @param[in] in Pointer to the mfxVideoParam structure as input. + @param[out] out Pointer to the mfxVideoParam structure as output. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_UNSUPPORTED The implementation does not support the specified configuration. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The video processing may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); + +/*! + @brief + Returns minimum and suggested numbers of the input frame surfaces required for video processing initialization and their type. + + The parameter ``request[0]`` refers to the input requirements; ``request[1]`` refers to output requirements. Init will call the external allocator for the + required frames with the same set of numbers. + This function does not validate I/O parameters except those used in calculating the number of input surfaces. + + The use of this function is recommended. + \verbatim embed:rst + For more information, see the :ref:`Working with Hardware Acceleration section`. + \endverbatim + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure as input. + @param[in] request Pointer to the mfxFrameAllocRequest structure; use ``request[0]`` for input requirements and ``request[1]`` for output requirements for video processing. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The video processing may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_QueryIOSurf(mfxSession session, mfxVideoParam *par, mfxFrameAllocRequest request[2]); + +/*! + @brief + Allocates memory and prepares tables and necessary structures for video processing. + + This function also does extensive validation to ensure if the + configuration, as specified in the input parameters, is supported. + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or the combination of them + resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_PARTIAL_ACCELERATION The underlying hardware does not fully support the specified video parameters. + The video processing may be partially accelerated. Only hardware implementations may return this status code. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The function is called twice without a close. \n + MFX_WRN_FILTER_SKIPPED The VPP skipped one or more filters requested by the application. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Init(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Stops the current video processing operation and restores internal structures or parameters for a new operation + + @param[in] session Session handle. + @param[in] par Pointer to the mfxVideoParam structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected that video parameters are wrong or they conflict with initialization parameters. Reset is impossible. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Reset(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Terminates the current video processing operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return MFX_ERR_NONE + The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_Close(mfxSession session); + +/*! + @brief + Retrieves current working parameters to the specified output structure. + + If extended buffers are to be returned, the + application must allocate those extended buffers and attach them as part of the output structure. + + @param[in] session Session handle. + @param[in] par Pointer to the corresponding parameter structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_GetVideoParam(mfxSession session, mfxVideoParam *par); + +/*! + @brief + Obtains statistics collected during video processing. + + @param[in] session Session handle. + @param[in] stat Pointer to the mfxVPPStat structure. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_GetVPPStat(mfxSession session, mfxVPPStat *stat); + +/*! + @brief + Processes a single input frame to a single output frame. + + Retrieval of the auxiliary data is optional; the encoding process may use it. + The video processing process may not generate an instant output given an input. + \verbatim embed:rst + See the :ref:`Video Processing Procedures section` for details on how to + correctly send input and retrieve output. + \endverbatim + + + At the end of the stream, call this function with the input argument ``in=NULL`` to retrieve any remaining frames, until the function returns MFX_ERR_MORE_DATA. + This function is asynchronous. + + @param[in] session Session handle. + @param[in] in Pointer to the input video surface structure. + @param[out] out Pointer to the output video surface structure. + @param[in] aux Optional pointer to the auxiliary data structure. + @param[out] syncp Pointer to the output sync point. + + @return + MFX_ERR_NONE The output frame is ready after synchronization. \n + MFX_ERR_MORE_DATA Need more input frames before VPP can produce an output. \n + MFX_ERR_MORE_SURFACE The output frame is ready after synchronization. Need more surfaces at output for additional output frames available. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. + + @since This function is available since API version 1.0. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_RunFrameVPPAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 *out, mfxExtVppAuxData *aux, mfxSyncPoint *syncp); + +/*! + @brief + The function processes a single input frame to a single output frame with internal allocation of output frame. + + At the end of the stream, call this function with the input argument ``in=NULL`` to retrieve any remaining frames, until the function returns MFX_ERR_MORE_DATA. + This function is asynchronous. + + @param[in] session Session handle. + @param[in] in Pointer to the input video surface structure. + @param[out] out Pointer to the output video surface structure which is reference counted object allocated by the library. + + @return + MFX_ERR_NONE The output frame is ready after synchronization. \n + MFX_ERR_MORE_DATA Need more input frames before VPP can produce an output. \n + MFX_ERR_MEMORY_ALLOC The function failed to allocate output video frame. \n + + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_WRN_ALLOC_TIMEOUT_EXPIRED Timeout expired for internal output frame allocation (if set with mfxExtAllocationHints). Repeat the call in a few milliseconds or reinitialize VPP with higher surface limit. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoVPP_ProcessFrameAsync(mfxSession session, mfxFrameSurface1 *in, mfxFrameSurface1 **out); + +/*! + @brief + Initialize the SDK in (decode + vpp) mode. The logic of this function is similar to MFXVideoDECODE_Init, + but application has to provide array of pointers to mfxVideoChannelParam and num_channel_param - number of channels. Application is responsible for + memory allocation for mfxVideoChannelParam parameters and for each channel it should specify channel IDs: + mfxVideoChannelParam::mfxFrameInfo::ChannelId. ChannelId should be unique value within one session. ChannelID equals to the 0 + is reserved for the original decoded frame. + The application can attach mfxExtInCrops to mfxVideoChannelParam::ExtParam to annotate input video frame if it wants to enable + letterboxing operation. + @param[in] session SDK session handle. + @param[in] decode_par Pointer to the mfxVideoParam structure which contains initialization parameters for decoder. + @param[in] vpp_par_array Array of pointers to `mfxVideoChannelParam`structures. Each mfxVideoChannelParam contains initialization + parameters for each VPP channel. + @param[in] num_vpp_par Size of array of pointers to mfxVideoChannelParam structures. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected invalid video parameters. These parameters may be out of the valid range, or + the combination of them resulted in incompatibility. Incompatibility not resolved. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility + resolved. \n + MFX_ERR_UNDEFINED_BEHAVIOR The component is already initialized. \n + MFX_WRN_FILTER_SKIPPED The VPP skipped one or more filters requested by the application. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_Init(mfxSession session, mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_vpp_par); + +/*! + @brief + This function is similar to MFXVideoDECODE_DecodeFrameAsync and inherits all bitstream processing logic. As output, + it allocates and returns @p surf_array_out array of processed surfaces according to the chain of filters specified + by application in MFXVideoDECODE_VPP_Init, including original decoded frames. In the @p surf_array_out, the original + decoded frames are returned through surfaces with mfxFrameInfo::ChannelId == 0, followed by each of the subsequent + frame surfaces for each of the requested mfxVideoChannelParam entries provided to the MFXVideoCECODE_VPP_Init + function. At maximum, the number of frame surfaces return is 1 + the value of @p num_vpp_par to the + MFXVideoDECODE_VPP_Init function, but the application must be prepared to the case when some particular filters + are not ready to output surfaces, so the length of @p surf_array_out will be less. Application should use + mfxFrameInfo::ChannelId parameter to match output surface against configured filter. + + An application must synchronize each output surface from the @p surf_array_out surface array independently. + + @param[in] session SDK session handle. + @param[in] bs Pointer to the input bitstream. + @param[in] skip_channels Pointer to the array of `ChannelId`s which specifies channels with skip output frames. Memory for + the array is allocated by application. + @param[in] num_skip_channels Number of channels addressed by skip_channels. + @param[out] surf_array_out The address of a pointer to the structure with frame surfaces. + + @return + MFX_ERR_NONE The function completed successfully and the output surface is ready for decoding. \n + MFX_ERR_MORE_DATA The function requires more bitstream at input before decoding can proceed. \n + MFX_ERR_MORE_SURFACE The function requires more frame surface at output before decoding can proceed. \n + MFX_ERR_DEVICE_LOST Hardware device was lost. + \verbatim embed:rst + See the :ref:`Working with Microsoft* DirectX* Applications section` for further information. + \endverbatim + \n + MFX_WRN_DEVICE_BUSY Hardware device is currently busy. Call this function again after MFXVideoCORE_SyncOperation or in a few milliseconds. \n + MFX_WRN_VIDEO_PARAM_CHANGED The decoder detected a new sequence header in the bitstream. Video parameters may have changed. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The decoder detected incompatible video parameters in the bitstream and failed to follow them. \n + MFX_ERR_NULL_PTR num_skip_channels doesn't equal to 0 when skip_channels is NULL. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_DecodeFrameAsync(mfxSession session, mfxBitstream *bs, mfxU32* skip_channels, mfxU32 num_skip_channels, mfxSurfaceArray **surf_array_out); + +/*! + @brief + This function is similar to MFXVideoDECODE_Reset and stops the current decoding and vpp operation, and restores internal + structures or parameters for a new decoding plus vpp operation. It resets the state of the decoder and/or all initialized vpp + channels. Applications have to care about draining of buffered frames for decode and all vpp channels before call this function. + The application can attach mfxExtInCrops to mfxVideoChannelParam::ExtParam to annotate input video frame if it wants to enable + letterboxing operation. + + @param[in] session Session handle. + @param[in] decode_par Pointer to the `mfxVideoParam` structure which contains new initialization parameters for decoder. Might + be NULL if application wants to Reset only VPP channels. + @param[in] vpp_par_array Array of pointers to mfxVideoChannelParam structures. Each mfxVideoChannelParam contains new + initialization parameters for each VPP channel. + @param[in] num_vpp_par Size of array of pointers to mfxVideoChannelParam structures. + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_INVALID_VIDEO_PARAM The function detected that video parameters are wrong or they conflict with initialization parameters. Reset is impossible. \n + MFX_ERR_INCOMPATIBLE_VIDEO_PARAM The function detected that video parameters provided by the application are incompatible with initialization parameters. + Reset requires additional memory allocation and cannot be executed. The application should close the + component and then reinitialize it. \n + MFX_WRN_INCOMPATIBLE_VIDEO_PARAM The function detected some video parameters were incompatible with others; incompatibility resolved. + MFX_ERR_NULL_PTR Both pointers decode_par and vpp_par_array` equal to zero. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_Reset(mfxSession session, mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_vpp_par); + +/*! + @brief + Returns actual VPP parameters for selected channel which should be specified by application through + mfxVideoChannelParam::mfxFrameInfo::ChannelId. + + @param[in] session Session handle. + @param[in] par Pointer to the `mfxVideoChannelParam` structure which allocated by application + @param[in] channel_id specifies the requested channel's info + + @return + MFX_ERR_NONE The function completed successfully. \n + MFX_ERR_NULL_PTR par pointer is NULL. \n + MFX_ERR_NOT_FOUND the library is not able to find VPP channel with such channel_id. + + @since This function is available since API version 2.1. +*/ +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_GetChannelParam(mfxSession session, mfxVideoChannelParam *par, mfxU32 channel_id); + +/*! + @brief + This function is similar to MFXVideoDECODE_Close. It terminates the current decoding and vpp operation and de-allocates any internal tables or structures. + + @param[in] session Session handle. + + @return + MFX_ERR_NONE The function completed successfully. \n + + @since This function is available since API version 2.1. +*/ + +mfxStatus MFX_CDECL MFXVideoDECODE_VPP_Close(mfxSession session); + +/*! Alias for MFXVideoDECODE_DecodeHeader function. */ +#define MFXVideoDECODE_VPP_DecodeHeader MFXVideoDECODE_DecodeHeader + +/*! Alias for MFXVideoDECODE_GetVideoParam function. */ +#define MFXVideoDECODE_VPP_GetVideoParam MFXVideoDECODE_GetVideoParam + +/*! Alias for MFXVideoDECODE_GetDecodeStat function. */ +#define MFXVideoDECODE_VPP_GetDecodeStat MFXVideoDECODE_GetDecodeStat + +/*! Alias for MFXVideoDECODE_SetSkipMode function. */ +#define MFXVideoDECODE_VPP_SetSkipMode MFXVideoDECODE_SetSkipMode + +/*! Alias for MFXVideoDECODE_GetPayload function. */ +#define MFXVideoDECODE_VPP_GetPayload MFXVideoDECODE_GetPayload + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/third-party/IntelVPL/x64/include/vpl/mfxvp8.h b/third-party/IntelVPL/x64/include/vpl/mfxvp8.h new file mode 100644 index 000000000..d2de824fa --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/mfxvp8.h @@ -0,0 +1,65 @@ +/*############################################################################ + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ + +#ifndef __MFXVP8_H__ +#define __MFXVP8_H__ + +#include "mfxdefs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + MFX_CODEC_VP8 = MFX_MAKEFOURCC('V','P','8',' '), +}; + +/* VP8 CodecProfile*/ +enum { + MFX_PROFILE_VP8_0 = 0+1, + MFX_PROFILE_VP8_1 = 1+1, + MFX_PROFILE_VP8_2 = 2+1, + MFX_PROFILE_VP8_3 = 3+1, +}; + +/* Extended Buffer Ids */ +enum { + /*! + This extended buffer describes VP8 encoder configuration parameters. See the mfxExtVP8CodingOption structure for details. + The application can attach this buffer to the mfxVideoParam structure for encoding initialization. + */ + MFX_EXTBUFF_VP8_CODING_OPTION = MFX_MAKEFOURCC('V','P','8','E'), +}; + +MFX_PACK_BEGIN_USUAL_STRUCT() +/*! Describes VP8 coding options. */ +typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VP8_CODING_OPTION. */ + + mfxU16 Version; /*!< Determines the bitstream version. Corresponds to the same VP8 syntax element in frame_tag. */ + mfxU16 EnableMultipleSegments; /*!< Set this option to ON to enable segmentation. This is tri-state option. See the CodingOptionValue + enumerator for values of this option. */ + mfxU16 LoopFilterType; /*!< Select the type of filter (normal or simple). Corresponds to VP8 syntax element filter_type. */ + mfxU16 LoopFilterLevel[4]; /*!< Controls the filter strength. Corresponds to VP8 syntax element loop_filter_level. */ + mfxU16 SharpnessLevel; /*!< Controls the filter sensitivity. Corresponds to VP8 syntax element sharpness_level. */ + mfxU16 NumTokenPartitions; /*!< Specifies number of token partitions in the coded frame. */ + mfxI16 LoopFilterRefTypeDelta[4]; /*!< Loop filter level delta for reference type (intra, last, golden, altref). */ + mfxI16 LoopFilterMbModeDelta[4]; /*!< Loop filter level delta for MB modes. */ + mfxI16 SegmentQPDelta[4]; /*!< QP delta for segment. */ + mfxI16 CoeffTypeQPDelta[5]; /*!< QP delta for coefficient type (YDC, Y2AC, Y2DC, UVAC, UVDC). */ + mfxU16 WriteIVFHeaders; /*!< Set this option to ON to enable insertion of IVF container headers into bitstream. This is tri-state + option. See the CodingOptionValue enumerator for values of this option */ + mfxU32 NumFramesForIVFHeader; /*!< Specifies number of frames for IVF header when WriteIVFHeaders is ON. */ + mfxU16 reserved[223]; +} mfxExtVP8CodingOption; +MFX_PACK_END() + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/third-party/IntelVPL/x64/include/vpl/preview/README.txt b/third-party/IntelVPL/x64/include/vpl/preview/README.txt new file mode 100644 index 000000000..14311574c --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/preview/README.txt @@ -0,0 +1,2 @@ +The files in this preview folder are provided as a preview of upcoming features. +The content of this folder may be changed or removed without respect for backward compatibility. \ No newline at end of file diff --git a/third-party/IntelVPL/x64/include/vpl/preview/legacy/README.txt b/third-party/IntelVPL/x64/include/vpl/preview/legacy/README.txt new file mode 100644 index 000000000..6944060c7 --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/preview/legacy/README.txt @@ -0,0 +1,25 @@ +The file preview/legacy/mfxvideo++.h is a preview implementation of "class +MFXVideoSession" which takes advantage of API 2.0 functions of the +Intel® Video Processing Library (Intel® VPL) for implementation selection and +session creation. + +Known limitations: + +- The parameter mfxInitParam.ExternalThreads is not supported. + +- The API version returned by MFXVideoSession::QueryVersion() may be different + on platforms for which libmfx-gen is the default runtime implementation. + +- On Windows, accelerators selected using MFX_IMPL_HARDWARE, MFX_IMPL_HARDWARE2, + MFX_IMPL_HARDWARE3, or MFX_IMPL_HARDWARE4 are always enumerated according to + IDXGIFactory::EnumAdapters (i.e. D3D11) indexes, regardless of the + acceleration mode selected. On a multi-monitor or multi-adapter system, D3D9 + and D3D11 adapter indexing may not match. Applications needing to create a + session on a specific D3D9 adapter should instead use the Dispatcher + Configuration Property mfxExtendedDeviceId.DeviceLUID to select the desired + adapter. + +- Identical behavior between the production implementation of mfxvideo++.h and + the preview is not guaranteed. Applications may however define + MFXVIDEO_CPP_USE_DEPRECATED when compiling the preview application to build + with the previous implementation. diff --git a/third-party/IntelVPL/x64/include/vpl/preview/legacy/mfxvideo++.h b/third-party/IntelVPL/x64/include/vpl/preview/legacy/mfxvideo++.h new file mode 100644 index 000000000..0c78d785a --- /dev/null +++ b/third-party/IntelVPL/x64/include/vpl/preview/legacy/mfxvideo++.h @@ -0,0 +1,581 @@ +/*########################################################################### + # Copyright Intel Corporation + # + # SPDX-License-Identifier: MIT + ###########################################################################*/ + +#ifndef __MFXVIDEOPLUSPLUS_H +#define __MFXVIDEOPLUSPLUS_H + +#include "vpl/mfx.h" + +#define MFX_IMPL_ACCELMODE(x) (0xff00 & (x)) + +class MFXVideoSessionBase { +public: + virtual ~MFXVideoSessionBase() {} + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion* ver) = 0; + virtual mfxStatus InitEx(mfxInitParam par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus QueryIMPL(mfxIMPL* impl) = 0; + virtual mfxStatus QueryVersion(mfxVersion* version) = 0; + + virtual mfxStatus JoinSession(mfxSession child_session) = 0; + virtual mfxStatus DisjoinSession() = 0; + virtual mfxStatus CloneSession(mfxSession* clone) = 0; + virtual mfxStatus SetPriority(mfxPriority priority) = 0; + virtual mfxStatus GetPriority(mfxPriority* priority) = 0; + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator* allocator) = 0; + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) = 0; + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL* hdl) = 0; + virtual mfxStatus QueryPlatform(mfxPlatform* platform) = 0; + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) = 0; + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPP(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) = 0; + + virtual operator mfxSession(void) = 0; +}; + +class MFXVideoENCODEBase { +public: + virtual ~MFXVideoENCODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetEncodeStat(mfxEncodeStat* stat) = 0; + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl* ctrl, + mfxFrameSurface1* surface, + mfxBitstream* bs, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoDECODEBase { +public: + virtual ~MFXVideoDECODEBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus DecodeHeader(mfxBitstream* bs, mfxVideoParam* par) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest* request) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + + virtual mfxStatus GetDecodeStat(mfxDecodeStat* stat) = 0; + virtual mfxStatus GetPayload(mfxU64* ts, mfxPayload* payload) = 0; + virtual mfxStatus SetSkipMode(mfxSkipMode mode) = 0; + virtual mfxStatus DecodeFrameAsync(mfxBitstream* bs, + mfxFrameSurface1* surface_work, + mfxFrameSurface1** surface_out, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) = 0; +}; + +class MFXVideoVPPBase { +public: + virtual ~MFXVideoVPPBase() {} + + virtual mfxStatus Query(mfxVideoParam* in, mfxVideoParam* out) = 0; + virtual mfxStatus QueryIOSurf(mfxVideoParam* par, mfxFrameAllocRequest request[2]) = 0; + virtual mfxStatus Init(mfxVideoParam* par) = 0; + virtual mfxStatus Reset(mfxVideoParam* par) = 0; + virtual mfxStatus Close(void) = 0; + + virtual mfxStatus GetVideoParam(mfxVideoParam* par) = 0; + virtual mfxStatus GetVPPStat(mfxVPPStat* stat) = 0; + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1* in, + mfxFrameSurface1* out, + mfxExtVppAuxData* aux, + mfxSyncPoint* syncp) = 0; + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) = 0; + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1* in, mfxFrameSurface1** out) = 0; +}; + +class MFXVideoSession : public MFXVideoSessionBase { +public: + MFXVideoSession(void) { + m_session = (mfxSession)0; +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + m_loader = (mfxLoader)0; +#endif + } + virtual ~MFXVideoSession(void) { + Close(); + } + + virtual mfxStatus Init(mfxIMPL impl, mfxVersion *ver) override { +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + mfxInitParam par = {}; + par.Implementation = impl; + par.Version = *ver; + return InitSession(par); +#else + return MFXInit(impl, ver, &m_session); +#endif + } + virtual mfxStatus InitEx(mfxInitParam par) override { +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + return InitSession(par); +#else + return MFXInitEx(par, &m_session); +#endif + } + virtual mfxStatus Close(void) override { +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + if (m_session) { + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + if (m_loader) { + MFXUnload(m_loader); + m_loader = (mfxLoader)0; + } + return mfxRes; + } + else { + return MFX_ERR_NONE; + } +#else + mfxStatus mfxRes; + mfxRes = MFXClose(m_session); + m_session = (mfxSession)0; + return mfxRes; +#endif + } + + virtual mfxStatus QueryIMPL(mfxIMPL *impl) override { + return MFXQueryIMPL(m_session, impl); + } + virtual mfxStatus QueryVersion(mfxVersion *version) override { + return MFXQueryVersion(m_session, version); + } + + virtual mfxStatus JoinSession(mfxSession child_session) override { + return MFXJoinSession(m_session, child_session); + } + virtual mfxStatus DisjoinSession() override { + return MFXDisjoinSession(m_session); + } + virtual mfxStatus CloneSession(mfxSession *clone) override { + return MFXCloneSession(m_session, clone); + } + virtual mfxStatus SetPriority(mfxPriority priority) override { + return MFXSetPriority(m_session, priority); + } + virtual mfxStatus GetPriority(mfxPriority *priority) override { + return MFXGetPriority(m_session, priority); + } + + virtual mfxStatus SetFrameAllocator(mfxFrameAllocator *allocator) override { + return MFXVideoCORE_SetFrameAllocator(m_session, allocator); + } + virtual mfxStatus SetHandle(mfxHandleType type, mfxHDL hdl) override { + return MFXVideoCORE_SetHandle(m_session, type, hdl); + } + virtual mfxStatus GetHandle(mfxHandleType type, mfxHDL *hdl) override { + return MFXVideoCORE_GetHandle(m_session, type, hdl); + } + virtual mfxStatus QueryPlatform(mfxPlatform *platform) override { + return MFXVideoCORE_QueryPlatform(m_session, platform); + } + + virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) override { + return MFXVideoCORE_SyncOperation(m_session, syncp, wait); + } + + virtual mfxStatus GetSurfaceForEncode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForDecode(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPP (mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP (m_session, output_surf); + } + virtual mfxStatus GetSurfaceForVPPOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual operator mfxSession(void) override { + return m_session; + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session + +#ifndef MFXVIDEO_CPP_USE_DEPRECATED + mfxLoader m_loader; + + inline void InitVariant(mfxVariant *var, mfxU32 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U32; + var->Data.U32 = data; + } + + inline void InitVariant(mfxVariant *var, mfxU16 data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_U16; + var->Data.U16 = data; + } + + inline void InitVariant(mfxVariant *var, mfxHDL data) { + var->Version.Version = (mfxU16)MFX_VARIANT_VERSION; + var->Type = MFX_VARIANT_TYPE_PTR; + var->Data.Ptr = data; + } + + template + mfxStatus CreateConfig(varDataType data, const char *propertyName) { + mfxConfig cfg = MFXCreateConfig(m_loader); + if (cfg == nullptr) + return MFX_ERR_NULL_PTR; + + mfxVariant variant; + InitVariant(&variant, data); + + return MFXSetConfigFilterProperty(cfg, (mfxU8 *)propertyName, variant); + } + + mfxStatus InitSession(mfxInitParam par) { + // already initialized + if (m_session) + return MFX_ERR_NONE; + + m_loader = MFXLoad(); + if (!m_loader) + return MFX_ERR_NOT_FOUND; + + mfxStatus mfxRes = MFX_ERR_NONE; + + mfxU32 implBaseType = MFX_IMPL_BASETYPE(par.Implementation); + + // select implementation type + switch (implBaseType) { + case MFX_IMPL_AUTO: + case MFX_IMPL_AUTO_ANY: + break; + + case MFX_IMPL_SOFTWARE: + mfxRes = CreateConfig(MFX_IMPL_TYPE_SOFTWARE, "mfxImplDescription.Impl"); + break; + + case MFX_IMPL_HARDWARE: + case MFX_IMPL_HARDWARE_ANY: + case MFX_IMPL_HARDWARE2: + case MFX_IMPL_HARDWARE3: + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(MFX_IMPL_TYPE_HARDWARE, "mfxImplDescription.Impl"); + break; + + default: + mfxRes = MFX_ERR_UNSUPPORTED; + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // select adapter index (if specified) + // see notes below about how VendorImplID is interpreted for each acceleration mode + switch (implBaseType) { + case MFX_IMPL_HARDWARE: + mfxRes = CreateConfig(0, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE2: + mfxRes = CreateConfig(1, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE3: + mfxRes = CreateConfig(2, "mfxImplDescription.VendorImplID"); + break; + case MFX_IMPL_HARDWARE4: + mfxRes = CreateConfig(3, "mfxImplDescription.VendorImplID"); + break; + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + mfxU32 implAccelMode = MFX_IMPL_ACCELMODE(par.Implementation); + if (implAccelMode == MFX_IMPL_VIA_D3D9) { + // D3D9 - because VendorImplID corresponds to DXGI adapter index (DX11 enumeration), + // this may not map directly to D3D9 index in multi-adapter/multi-monitor configurations + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D9, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_D3D11) { + // D3D11 - VendorImplID corresponds to DXGI adapter index + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_D3D11, + "mfxImplDescription.AccelerationMode"); + } + else if (implAccelMode == MFX_IMPL_VIA_VAAPI) { + // VAAPI - in general MFXInitEx treats any HARDWAREn the same way (relies on application to pass + // correct VADisplay via SetHandle), but 2.x RT only reports actual number of adapters + mfxRes = CreateConfig(MFX_ACCEL_MODE_VIA_VAAPI, + "mfxImplDescription.AccelerationMode"); + } + + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set required API level + mfxRes = + CreateConfig(par.Version.Version, "mfxImplDescription.ApiVersion.Version"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + + // set GPUCopy parameter + if (par.GPUCopy) { + mfxRes = CreateConfig(par.GPUCopy, "DeviceCopy"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + + // set ExternalThreads parameter + if (par.ExternalThreads) { + // TO DO - need to add this as config filter property and member of mfxInitializationParam + return MFX_ERR_UNSUPPORTED; + } + + // pass extBufs + if (par.NumExtParam) { + for (mfxU32 idx = 0; idx < par.NumExtParam; idx++) { + mfxRes = CreateConfig(par.ExtParam[idx], "ExtBuffer"); + if (MFX_ERR_NONE != mfxRes) + return MFX_ERR_UNSUPPORTED; + } + } + + // create session with highest priority implementation remaining after filters + mfxRes = MFXCreateSession(m_loader, 0, &m_session); + + return mfxRes; + } +#endif + +private: + MFXVideoSession(const MFXVideoSession &); + void operator=(MFXVideoSession &); +}; + +class MFXVideoENCODE : public MFXVideoENCODEBase { +public: + explicit MFXVideoENCODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoENCODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoENCODE_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoENCODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoENCODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoENCODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoENCODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoENCODE_GetVideoParam(m_session, par); + } + virtual mfxStatus GetEncodeStat(mfxEncodeStat *stat) override { + return MFXVideoENCODE_GetEncodeStat(m_session, stat); + } + + virtual mfxStatus EncodeFrameAsync(mfxEncodeCtrl *ctrl, + mfxFrameSurface1 *surface, + mfxBitstream *bs, + mfxSyncPoint *syncp) override { + return MFXVideoENCODE_EncodeFrameAsync(m_session, ctrl, surface, bs, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForEncode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoDECODE : public MFXVideoDECODEBase { +public: + explicit MFXVideoDECODE(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoDECODE_Query(m_session, in, out); + } + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) override { + return MFXVideoDECODE_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { + return MFXVideoDECODE_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoDECODE_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoDECODE_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoDECODE_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoDECODE_GetVideoParam(m_session, par); + } + + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) override { + return MFXVideoDECODE_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) override { + return MFXVideoDECODE_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) override { + return MFXVideoDECODE_SetSkipMode(m_session, mode); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, + mfxFrameSurface1 *surface_work, + mfxFrameSurface1 **surface_out, + mfxSyncPoint *syncp) override { + return MFXVideoDECODE_DecodeFrameAsync(m_session, bs, surface_work, surface_out, syncp); + } + + virtual mfxStatus GetSurface(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForDecode(m_session, output_surf); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoVPP : public MFXVideoVPPBase { +public: + explicit MFXVideoVPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoVPP(void) { + Close(); + } + + virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { + return MFXVideoVPP_Query(m_session, in, out); + } + virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest request[2]) override { + return MFXVideoVPP_QueryIOSurf(m_session, par, request); + } + virtual mfxStatus Init(mfxVideoParam *par) override { + return MFXVideoVPP_Init(m_session, par); + } + virtual mfxStatus Reset(mfxVideoParam *par) override { + return MFXVideoVPP_Reset(m_session, par); + } + virtual mfxStatus Close(void) override { + return MFXVideoVPP_Close(m_session); + } + + virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { + return MFXVideoVPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetVPPStat(mfxVPPStat *stat) override { + return MFXVideoVPP_GetVPPStat(m_session, stat); + } + virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in, + mfxFrameSurface1 *out, + mfxExtVppAuxData *aux, + mfxSyncPoint *syncp) override { + return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp); + } + + virtual mfxStatus GetSurfaceIn(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPP(m_session, output_surf); + } + virtual mfxStatus GetSurfaceOut(mfxFrameSurface1** output_surf) override { + return MFXMemory_GetSurfaceForVPPOut(m_session, output_surf); + } + + virtual mfxStatus ProcessFrameAsync(mfxFrameSurface1 *in, mfxFrameSurface1 **out) override { + return MFXVideoVPP_ProcessFrameAsync(m_session, in, out); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +class MFXVideoDECODE_VPP +{ +public: + explicit MFXVideoDECODE_VPP(mfxSession session) { + m_session = session; + } + virtual ~MFXVideoDECODE_VPP(void) { + Close(); + } + + virtual mfxStatus Init(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Init(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus Reset(mfxVideoParam* decode_par, mfxVideoChannelParam** vpp_par_array, mfxU32 num_channel_par) { + return MFXVideoDECODE_VPP_Reset(m_session, decode_par, vpp_par_array, num_channel_par); + } + virtual mfxStatus GetChannelParam(mfxVideoChannelParam *par, mfxU32 channel_id) { + return MFXVideoDECODE_VPP_GetChannelParam(m_session, par, channel_id); + } + virtual mfxStatus DecodeFrameAsync(mfxBitstream *bs, mfxU32* skip_channels, mfxU32 num_skip_channels, mfxSurfaceArray **surf_array_out) { + return MFXVideoDECODE_VPP_DecodeFrameAsync(m_session, bs, skip_channels, num_skip_channels, surf_array_out); + } + + virtual mfxStatus DecodeHeader(mfxBitstream *bs, mfxVideoParam *par) { + return MFXVideoDECODE_VPP_DecodeHeader(m_session, bs, par); + } + virtual mfxStatus Close(void) { + return MFXVideoDECODE_VPP_Close(m_session); + } + virtual mfxStatus GetVideoParam(mfxVideoParam *par) { + return MFXVideoDECODE_VPP_GetVideoParam(m_session, par); + } + virtual mfxStatus GetDecodeStat(mfxDecodeStat *stat) { + return MFXVideoDECODE_VPP_GetDecodeStat(m_session, stat); + } + virtual mfxStatus GetPayload(mfxU64 *ts, mfxPayload *payload) { + return MFXVideoDECODE_VPP_GetPayload(m_session, ts, payload); + } + virtual mfxStatus SetSkipMode(mfxSkipMode mode) { + return MFXVideoDECODE_VPP_SetSkipMode(m_session, mode); + } + +protected: + mfxSession m_session; // (mfxSession) handle to the owning session +}; + +#endif //__MFXVIDEOPLUSPLUS_H diff --git a/third-party/IntelVPL/x64/lib/cmake/vpl/VPLConfig.cmake b/third-party/IntelVPL/x64/lib/cmake/vpl/VPLConfig.cmake new file mode 100644 index 000000000..e724c5b95 --- /dev/null +++ b/third-party/IntelVPL/x64/lib/cmake/vpl/VPLConfig.cmake @@ -0,0 +1,146 @@ +# ############################################################################## +# Copyright (C) Intel Corporation +# +# SPDX-License-Identifier: MIT +# ############################################################################## + +# * Config file for the VPL package It defines the following variables +# VPL__FOUND VPL_IMPORTED_TARGETS +# +# VPLConfigVersion.cmake defines VPL_VERSION + +option(VPL_SHARED "Use shared instead of static version of dispatcher." + ON) + +# Initialize to default values +set(VPL_INTERFACE_VERSION 2) +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) + +get_filename_component(VPL_LIB_DIR "${_vpl_config_dir}/../../" + ABSOLUTE) +get_filename_component(VPL_INCLUDE_DIR "${_vpl_config_dir}/../../../include" + ABSOLUTE) +get_filename_component(VPL_BIN_DIR "${_vpl_config_dir}/../../../bin" + ABSOLUTE) + +if(CMAKE_SYSTEM_NAME MATCHES Windows) + set(VPL_SHLIB_DIR ${VPL_BIN_DIR}) +else() + set(VPL_SHLIB_DIR ${VPL_LIB_DIR}) +endif() + +if(NOT VPL_IMPORTED_TARGETS) + set(VPL_IMPORTED_TARGETS "") +endif() + +if(NOT VPL_FIND_COMPONENTS) + set(VPL_FIND_COMPONENTS "dispatcher;api") + foreach(_vpl_component ${VPL_FIND_COMPONENTS}) + set(VPL_FIND_REQUIRED_${_vpl_component} 1) + endforeach() +endif() + +# VPL::dispatcher +set(VPL_dispatcher_FOUND 0) + +get_filename_component(_dispatcher_shlib "${VPL_SHLIB_DIR}/libvpl.dll" + ABSOLUTE) +get_filename_component(_dispatcher_debug_shlib + "${VPL_SHLIB_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) +get_filename_component(_dispatcher_implib "${VPL_LIB_DIR}/vpl.lib" + ABSOLUTE) +get_filename_component(_dispatcher_debug_implib + "${VPL_LIB_DIR}/vpld.lib" ABSOLUTE) + +if(TARGET VPL::dispatcher) + list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) + set(VPL_dispatcher_FOUND 1) +else() + if(VPL_SHARED) + if(EXISTS "${_dispatcher_shlib}" OR EXISTS "${_dispatcher_debug_shlib}") + list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) + set(VPL_dispatcher_FOUND 1) + + add_library(VPL::dispatcher SHARED IMPORTED) + set_target_properties( + VPL::dispatcher + PROPERTIES IMPORTED_LOCATION_RELEASE ${_dispatcher_shlib} + IMPORTED_LOCATION_RELWITHDEBINFO ${_dispatcher_shlib} + IMPORTED_LOCATION_MINSIZEREL ${_dispatcher_shlib} + IMPORTED_LOCATION_DEBUG ${_dispatcher_debug_shlib} + IMPORTED_LOCATION_RELWITHDEBRT ${_dispatcher_debug_shlib}) + if(CMAKE_SYSTEM_NAME MATCHES Windows) + set_target_properties( + VPL::dispatcher + PROPERTIES IMPORTED_IMPLIB_RELEASE ${_dispatcher_implib} + IMPORTED_IMPLIB_RELWITHDEBINFO ${_dispatcher_implib} + IMPORTED_IMPLIB_MINSIZEREL ${_dispatcher_implib} + IMPORTED_IMPLIB_DEBUG ${_dispatcher_debug_implib} + IMPORTED_IMPLIB_RELWITHDEBRT ${_dispatcher_debug_implib}) + endif() + elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher) + message(STATUS "Unable to find required VPL component: dispatcher") + set(VPL_FOUND FALSE) + endif() + else() + if(EXISTS "${_dispatcher_lib}" OR EXISTS "${_dispatcher_debug_lib}") + list(APPEND VPL_IMPORTED_TARGETS VPL::dispatcher) + set(VPL_dispatcher_FOUND 1) + add_library(VPL::dispatcher STATIC IMPORTED) + set_target_properties( + VPL::dispatcher + PROPERTIES IMPORTED_LOCATION_RELEASE ${_dispatcher_lib} + IMPORTED_LOCATION_RELWITHDEBINFO ${_dispatcher_lib} + IMPORTED_LOCATION_MINSIZEREL ${_dispatcher_lib} + IMPORTED_LOCATION_DEBUG ${_dispatcher_debug_lib} + IMPORTED_LOCATION_RELWITHDEBRT ${_dispatcher_debug_lib}) + if(UNIX) + # require pthreads for loading legacy MSDK runtimes + set(CMAKE_THREAD_PREFER_PTHREAD TRUE) + set(THREADS_PREFER_PTHREAD_FLAG TRUE) + find_package(Threads REQUIRED) + target_link_libraries(VPL::dispatcher INTERFACE Threads::Threads) + endif() + target_link_libraries(VPL::dispatcher INTERFACE ${CMAKE_DL_LIBS}) + elseif(VPL_FIND_REQUIRED AND VPL_FIND_REQUIRED_dispatcher) + message(STATUS "Unable to find required VPL component: dispatcher") + set(VPL_FOUND FALSE) + endif() + endif() + set_target_properties(VPL::dispatcher PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${VPL_INCLUDE_DIR}") +endif() + +unset(_dispatcher_shlib) + +# VPL::api +set(VPL_api_FOUND 0) +if(EXISTS ${VPL_INCLUDE_DIR}) + if(NOT TARGET VPL::api) + add_library(VPL::api INTERFACE IMPORTED) + set_target_properties(VPL::api PROPERTIES INTERFACE_INCLUDE_DIRECTORIES + "${VPL_INCLUDE_DIR}") + endif() + 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/third-party/IntelVPL/x64/lib/cmake/vpl/VPLConfigVersion.cmake b/third-party/IntelVPL/x64/lib/cmake/vpl/VPLConfigVersion.cmake new file mode 100644 index 000000000..4c86e69ca --- /dev/null +++ b/third-party/IntelVPL/x64/lib/cmake/vpl/VPLConfigVersion.cmake @@ -0,0 +1,17 @@ +# ############################################################################## +# Copyright (C) Intel Corporation +# +# SPDX-License-Identifier: MIT +# ############################################################################## + +set(PACKAGE_VERSION "2.16") + +# Check whether the requested PACKAGE_FIND_VERSION is compatible +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/third-party/IntelVPL/x64/lib/pkgconfig/vpl.pc b/third-party/IntelVPL/x64/lib/pkgconfig/vpl.pc new file mode 100644 index 000000000..c58ed5256 --- /dev/null +++ b/third-party/IntelVPL/x64/lib/pkgconfig/vpl.pc @@ -0,0 +1,12 @@ +prefix=${pcfiledir}/../../ +libdir=${pcfiledir}/../ +includedir=${pcfiledir}/../../include + +Name: Intel(R) Video Processing Library +Description: Accelerated video decode, encode, and frame processing capabilities on Intel(R) GPUs +Version: 2.16 +URL: https://github.com/intel/libvpl + +Libs: -L${libdir} -lvpl +Libs.private: +Cflags: -I${includedir} -I${includedir}/vpl diff --git a/third-party/IntelVPL/x64/lib/vpl.lib b/third-party/IntelVPL/x64/lib/vpl.lib new file mode 100644 index 000000000..35208facc Binary files /dev/null and b/third-party/IntelVPL/x64/lib/vpl.lib differ diff --git a/third-party/NVIDIAImageScaling b/third-party/NVIDIAImageScaling new file mode 160000 index 000000000..35e13ba31 --- /dev/null +++ b/third-party/NVIDIAImageScaling @@ -0,0 +1 @@ +Subproject commit 35e13ba316c98eeecf16f37eae70ce88019911f6 diff --git a/third-party/RTX_Video_SDK/NVIDIA_RTX_Video_SDK_License.pdf b/third-party/RTX_Video_SDK/NVIDIA_RTX_Video_SDK_License.pdf new file mode 100644 index 000000000..130768c40 Binary files /dev/null and b/third-party/RTX_Video_SDK/NVIDIA_RTX_Video_SDK_License.pdf differ diff --git a/third-party/RTX_Video_SDK/bin/Windows/arm64/rel/nvngx_truehdr.dll b/third-party/RTX_Video_SDK/bin/Windows/arm64/rel/nvngx_truehdr.dll new file mode 100644 index 000000000..60de6e8cd Binary files /dev/null and b/third-party/RTX_Video_SDK/bin/Windows/arm64/rel/nvngx_truehdr.dll differ diff --git a/third-party/RTX_Video_SDK/bin/Windows/arm64/rel/nvngx_vsr.dll b/third-party/RTX_Video_SDK/bin/Windows/arm64/rel/nvngx_vsr.dll new file mode 100644 index 000000000..d45894fbd Binary files /dev/null and b/third-party/RTX_Video_SDK/bin/Windows/arm64/rel/nvngx_vsr.dll differ diff --git a/third-party/RTX_Video_SDK/bin/Windows/x64/dev/nvngx_truehdr.dll b/third-party/RTX_Video_SDK/bin/Windows/x64/dev/nvngx_truehdr.dll new file mode 100644 index 000000000..0e0ce577a Binary files /dev/null and b/third-party/RTX_Video_SDK/bin/Windows/x64/dev/nvngx_truehdr.dll differ diff --git a/third-party/RTX_Video_SDK/bin/Windows/x64/dev/nvngx_vsr.dll b/third-party/RTX_Video_SDK/bin/Windows/x64/dev/nvngx_vsr.dll new file mode 100644 index 000000000..d4c649077 Binary files /dev/null and b/third-party/RTX_Video_SDK/bin/Windows/x64/dev/nvngx_vsr.dll differ diff --git a/third-party/RTX_Video_SDK/bin/Windows/x64/rel/nvngx_truehdr.dll b/third-party/RTX_Video_SDK/bin/Windows/x64/rel/nvngx_truehdr.dll new file mode 100644 index 000000000..e0bf7d560 Binary files /dev/null and b/third-party/RTX_Video_SDK/bin/Windows/x64/rel/nvngx_truehdr.dll differ diff --git a/third-party/RTX_Video_SDK/bin/Windows/x64/rel/nvngx_vsr.dll b/third-party/RTX_Video_SDK/bin/Windows/x64/rel/nvngx_vsr.dll new file mode 100644 index 000000000..d3c0af614 Binary files /dev/null and b/third-party/RTX_Video_SDK/bin/Windows/x64/rel/nvngx_vsr.dll differ diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx.h new file mode 100644 index 000000000..506e9bde5 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx.h @@ -0,0 +1,501 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +/* +* HOW TO USE: +* +* IMPORTANT: FOR DLSS/DLISP PLEASE SEE THE PROGRAMMING GUIDE +* +* IMPORTANT: Methods in this library are NOT thread safe. It is up to the +* client to ensure that thread safety is enforced as needed. +* +* 1) Call NVSDK_CONV NVSDK_NGX_D3D11/D3D12/CUDA_Init and pass your app Id +* and other parameters. This will initialize SDK or return an error code +* if SDK cannot run on target machine. Depending on error user might +* need to update drivers. Please note that application Id is provided +* by NVIDIA so if you do not have one please contact us. +* +* 2) Call NVSDK_NGX_D3D11/D3D12/CUDA_GetCapabilityParameters to obtain pointer to +* interface used to pass parameters to SDK. Interface instance is +* allocated and released by SDK so there is no need to do any memory +* management on client side. +* +* 3) Set key parameters for the feature you want to use. For example, +* width and height are required for all features and they can be +* set like this: +* Params->Set(NVSDK_NGX_Parameter_Width,MY_WIDTH); +* Params->Set(NVSDK_NGX_Parameter_Height,MY_HEIGHT); +* +* You can also provide hints like NVSDK_NGX_Parameter_Hint_HDR to tell +* SDK that it should expect HDR color space is needed. Please refer to +* samples since different features need different parameters and hints. +* +* 4) Call NVSDK_NGX_D3D11/D3D12/CUDA_GetScratchBufferSize to obtain size of +* the scratch buffer needed by specific feature. This D3D or CUDA buffer +* should be allocated by client and passed as: +* Params->Set(NVSDK_NGX_Parameter_Scratch,MY_SCRATCH_POINTER) +* Params->Set(NVSDK_NGX_Parameter_Scratch_SizeInBytes,MY_SCRATCH_SIZE_IN_BYTES) +* NOTE: Returned size can be 0 if feature does not use any scratch buffer. +* It is OK to use bigger buffer or reuse buffers across features as long +* as minimum size requirement is met. +* +* 5) Call NVSDK_NGX_D3D11/D3D12/CUDA_CreateFeature to create feature you need. +* On success SDK will return a handle which must be used in any successive +* calls to SDK which require feature handle. SDK will use all parameters +* and hints provided by client to generate feature. If feature with the same +* parameters already exists and error code will be returned. +* +* 6) Call NVSDK_NGX_D3D11/D3D12/CUDA_EvaluateFeature to invoke execution of +* specific feature. Before feature can be evaluated input parameters must +* be specified (like for example color/albedo buffer, motion vectors etc) +* +* 6) Call NVSDK_NGX_D3D11/D3D12/CUDA_ReleaseFeature when feature is no longer +* needed. After this call feature handle becomes invalid and cannot be used. +* +* 7) Call NVSDK_NGX_D3D11/D3D12/CUDA_Shutdown when SDK is no longer needed to +* release all resources. + +* Contact: ngxsupport@nvidia.com +*/ + + +#ifndef NVSDK_NGX_H +#define NVSDK_NGX_H + +#include // For size_t + +#include "nvsdk_ngx_defs.h" +#include "nvsdk_ngx_params.h" +#ifndef __cplusplus +#include +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct IUnknown IUnknown; + +typedef struct IDXGIAdapter IDXGIAdapter; +typedef struct ID3D11Device ID3D11Device; +typedef struct ID3D11Resource ID3D11Resource; +typedef struct ID3D11DeviceContext ID3D11DeviceContext; +typedef struct D3D11_TEXTURE2D_DESC D3D11_TEXTURE2D_DESC; +typedef struct D3D11_BUFFER_DESC D3D11_BUFFER_DESC; +typedef struct ID3D11Buffer ID3D11Buffer; +typedef struct ID3D11Texture2D ID3D11Texture2D; + +typedef struct ID3D12Device ID3D12Device; +typedef struct ID3D12Resource ID3D12Resource; +typedef struct ID3D12GraphicsCommandList ID3D12GraphicsCommandList; +typedef struct D3D12_RESOURCE_DESC D3D12_RESOURCE_DESC; +typedef struct CD3DX12_HEAP_PROPERTIES CD3DX12_HEAP_PROPERTIES; + +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_D3D12_ResourceAllocCallback)(D3D12_RESOURCE_DESC *InDesc, int InState, CD3DX12_HEAP_PROPERTIES *InHeap, ID3D12Resource **OutResource); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_D3D11_BufferAllocCallback)(D3D11_BUFFER_DESC *InDesc, ID3D11Buffer **OutResource); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_D3D11_Tex2DAllocCallback)(D3D11_TEXTURE2D_DESC *InDesc, ID3D11Texture2D **OutResource); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_ResourceReleaseCallback)(IUnknown *InResource); + +typedef unsigned long long CUtexObject; + +// NOTE: Functions under the same name and different function signatures exist +// between the NGX SDK, NGX Core (driver), and NGX Snippets. To discern the +// different signatures here we check if NGX_SNIPPET_BUILD is defined. When that +// is the case we know that the function signature in-use should be that of +// between NGX Core and the Snippet. Otherwise the signature should be between +// NGX SDK and NGX Core. +// +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Init +// ------------------------------------- +// +// InApplicationId: +// Unique Id provided by NVIDIA +// +// InApplicationDataPath: +// Folder to store logs and other temporary files (write access required), +// Normally this would be a location in Documents or ProgramData. +// +// InDevice: [d3d11/12 only] +// DirectX device to use +// +// InFeatureInfo: +// Contains information common to all features, presently only a list of all paths +// feature dlls can be located in, other than the default path - application directory. +// +// DESCRIPTION: +// Initializes new SDK instance. +// +#if defined(NGX_SNIPPET_BUILD) +#ifdef __cplusplus +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init_Ext(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API, const NVSDK_NGX_Parameter* InParameters = nullptr); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API, const NVSDK_NGX_Parameter* InParameters = nullptr); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init_Ext(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API, const NVSDK_NGX_Parameter* InParameters = nullptr); +#else +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init_Ext(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, NVSDK_NGX_Version InSDKVersion, const NVSDK_NGX_Parameter* InParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init_Ext(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, NVSDK_NGX_Version InSDKVersion, const NVSDK_NGX_Parameter* InParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init_Ext(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, NVSDK_NGX_Version InSDKVersion, const NVSDK_NGX_Parameter* InParameters); +#endif +#else +#ifdef __cplusplus +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +#else +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +#endif +#endif // defined(NGX_SNIPPET_BUILD) + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Init_with_ProjectID +// ------------------------------------- +// +// InProjectId: +// Unique Id provided by the rendering engine used +// +// InEngineType: +// Rendering engine used by the application / plugin. +// Use NVSDK_NGX_ENGINE_TYPE_CUSTOM if the specific engine type is not supported explicitly +// +// InEngineVersion: +// Version number of the rendering engine used by the application / plugin. +// +// InApplicationDataPath: +// Folder to store logs and other temporary files (write access required), +// Normally this would be a location in Documents or ProgramData. +// +// InDevice: [d3d11/12 only] +// DirectX device to use +// +// InFeatureInfo: +// Contains information common to all features, presently only a list of all paths +// feature dlls can be located in, other than the default path - application directory. +// +// DESCRIPTION: +// Initializes new SDK instance. +// +#if defined(NGX_SNIPPET_BUILD) +// No NGX Core <---> Snippet interfaces +#else +#ifdef __cplusplus +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +#else +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, ID3D11Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, ID3D12Device *InDevice, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +#endif +#endif // defined(NGX_SNIPPET_BUILD) + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Shutdown +// ------------------------------------- +// +// DESCRIPTION: +// Shuts down the current SDK instance and releases all resources. +// Shutdown1(Device) only affects specified device +// Shutdown1(nullptr) = Shutdown() and shuts down all devices +// +#ifdef NGX_ENABLE_DEPRECATED_SHUTDOWN +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Shutdown(void); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Shutdown(void); +#endif +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_Shutdown1(ID3D11Device *InDevice); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_Shutdown1(ID3D12Device *InDevice); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_Shutdown(void); + +#ifdef NGX_ENABLE_DEPRECATED_GET_PARAMETERS +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetParameters +// ---------------------------------------------------------- +// +// OutParameters: +// Parameters interface used to set any parameter needed by the SDK +// +// DESCRIPTION: +// This interface allows simple parameter setup using named fields. +// For example one can set width by calling Set(NVSDK_NGX_Parameter_Denoiser_Width,100) or +// provide CUDA buffer pointer by calling Set(NVSDK_NGX_Parameter_Denoiser_Color,cudaBuffer) +// For more details please see sample code. Please note that allocated memory +// will be freed by NGX so free/delete operator should NOT be called. +// Parameter maps output by NVSDK_NGX_GetParameters are also pre-populated +// with NGX capabilities and available features. +// Unlike with NVSDK_NGX_AllocateParameters, parameter maps output by NVSDK_NGX_GetParameters +// have their lifetimes managed by NGX, and must not +// be destroyed by the app using NVSDK_NGX_DestroyParameters. +// NVSDK_NGX_GetParameters is deprecated and apps should move to using +// NVSDK_NGX_AllocateParameters and NVSDK_NGX_GetCapabilityParameters when possible. +// Nevertheless, due to the possibility that the user will be using an older driver version, +// NVSDK_NGX_GetParameters may still be used as a fallback if NVSDK_NGX_AllocateParameters +// or NVSDK_NGX_GetCapabilityParameters return NVSDK_NGX_Result_FAIL_OutOfDate. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_GetParameters(NVSDK_NGX_Parameter **OutParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_GetParameters(NVSDK_NGX_Parameter **OutParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_GetParameters(NVSDK_NGX_Parameter **OutParameters); +#endif // NGX_ENABLE_DEPRECATED_GET_PARAMETERS + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_AllocateParameters +// ---------------------------------------------------------- +// +// OutParameters: +// Parameters interface used to set any parameter needed by the SDK +// +// DESCRIPTION: +// This interface allows allocating a simple parameter setup using named fields, whose +// lifetime the app must manage. +// For example one can set width by calling Set(NVSDK_NGX_Parameter_Denoiser_Width,100) or +// provide CUDA buffer pointer by calling Set(NVSDK_NGX_Parameter_Denoiser_Color,cudaBuffer) +// For more details please see sample code. +// Parameter maps output by NVSDK_NGX_AllocateParameters must NOT be freed using +// the free/delete operator; to free a parameter map +// output by NVSDK_NGX_AllocateParameters, NVSDK_NGX_DestroyParameters should be used. +// Unlike with NVSDK_NGX_GetParameters, parameter maps allocated with NVSDK_NGX_AllocateParameters +// must be destroyed by the app using NVSDK_NGX_DestroyParameters. +// Also unlike with NVSDK_NGX_GetParameters, parameter maps output by NVSDK_NGX_AllocateParameters +// do not come pre-populated with NGX capabilities and available features. +// To create a new parameter map pre-populated with such information, NVSDK_NGX_GetCapabilityParameters +// should be used. +// This function may return NVSDK_NGX_Result_FAIL_OutOfDate if an older driver, which +// does not support this API call is being used. In such a case, NVSDK_NGX_GetParameters +// may be used as a fallback. +// This function may only be called after a successful call into NVSDK_NGX_Init. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_AllocateParameters(NVSDK_NGX_Parameter** OutParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_AllocateParameters(NVSDK_NGX_Parameter** OutParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_AllocateParameters(NVSDK_NGX_Parameter** OutParameters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetCapabilityParameters +// ---------------------------------------------------------- +// +// OutParameters: +// The parameters interface populated with NGX and feature capabilities +// +// DESCRIPTION: +// This interface allows the app to create a new parameter map +// pre-populated with NGX capabilities and available features. +// The output parameter map can also be used for any purpose +// parameter maps output by NVSDK_NGX_AllocateParameters can be used for +// but it is not recommended to use NVSDK_NGX_GetCapabilityParameters +// unless querying NGX capabilities and available features +// due to the overhead associated with pre-populating the parameter map. +// Parameter maps output by NVSDK_NGX_GetCapabilityParameters must NOT be freed using +// the free/delete operator; to free a parameter map +// output by NVSDK_NGX_GetCapabilityParameters, NVSDK_NGX_DestroyParameters should be used. +// Unlike with NVSDK_NGX_GetParameters, parameter maps allocated with NVSDK_NGX_GetCapabilityParameters +// must be destroyed by the app using NVSDK_NGX_DestroyParameters. +// This function may return NVSDK_NGX_Result_FAIL_OutOfDate if an older driver, which +// does not support this API call is being used. This function may only be called +// after a successful call into NVSDK_NGX_Init. +// If NVSDK_NGX_GetCapabilityParameters fails with NVSDK_NGX_Result_FAIL_OutOfDate, +// NVSDK_NGX_GetParameters may be used as a fallback, to get a parameter map pre-populated +// with NGX capabilities and available features. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_DestroyParameters +// ---------------------------------------------------------- +// +// InParameters: +// The parameters interface to be destroyed +// +// DESCRIPTION: +// This interface allows the app to destroy the parameter map passed in. Once +// NVSDK_NGX_DestroyParameters is called on a parameter map, it +// must not be used again. +// NVSDK_NGX_DestroyParameters must not be called on any parameter map returned +// by NVSDK_NGX_GetParameters; NGX will manage the lifetime of those +// parameter maps. +// This function may return NVSDK_NGX_Result_FAIL_OutOfDate if an older driver, which +// does not support this API call is being used. This function may only be called +// after a successful call into NVSDK_NGX_Init. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_DestroyParameters(NVSDK_NGX_Parameter* InParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_DestroyParameters(NVSDK_NGX_Parameter* InParameters); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_DestroyParameters(NVSDK_NGX_Parameter* InParameters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetScratchBufferSize +// ---------------------------------------------------------- +// +// InFeatureId: +// AI feature in question +// +// InParameters: +// Parameters used by the feature to help estimate scratch buffer size +// +// OutSizeInBytes: +// Number of bytes needed for the scratch buffer for the specified feature. +// +// DESCRIPTION: +// SDK needs a buffer of a certain size provided by the client in +// order to initialize AI feature. Once feature is no longer +// needed buffer can be released. It is safe to reuse the same +// scratch buffer for different features as long as minimum size +// requirement is met for all features. Please note that some +// features might not need a scratch buffer so return size of 0 +// is completely valid. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, const NVSDK_NGX_Parameter *InParameters, size_t *OutSizeInBytes); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, const NVSDK_NGX_Parameter *InParameters, size_t *OutSizeInBytes); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, const NVSDK_NGX_Parameter *InParameters, size_t *OutSizeInBytes); + +///////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_CreateFeature +// ------------------------------------- +// +// InCmdList:[d3d12 only] +// Command list to use to execute GPU commands. Must be: +// - Open and recording +// - With node mask including the device provided in NVSDK_NGX_D3D12_Init +// - Execute on non-copy command queue. +// InDevCtx: [d3d11 only] +// Device context to use to execute GPU commands +// +// InFeatureID: +// AI feature to initialize +// +// InParameters: +// List of parameters +// +// OutHandle: +// Handle which uniquely identifies the feature. If feature with +// provided parameters already exists the "already exists" error code is returned. +// +// DESCRIPTION: +// Each feature needs to be created before it can be used. +// Refer to the sample code to find out which input parameters +// are needed to create specific feature. +// +#if defined(NGX_SNIPPET_BUILD) +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_CreateFeature(ID3D11DeviceContext *InDevCtx, NVSDK_NGX_Feature InFeatureID, const NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsCommandList *InCmdList, NVSDK_NGX_Feature InFeatureID, const NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_CreateFeature(NVSDK_NGX_Feature InFeatureID, const NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); +#else +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_CreateFeature(ID3D11DeviceContext *InDevCtx, NVSDK_NGX_Feature InFeatureID, NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_CreateFeature(ID3D12GraphicsCommandList *InCmdList, NVSDK_NGX_Feature InFeatureID, NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_CreateFeature(NVSDK_NGX_Feature InFeatureID, const NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); + +#endif // defined(NGX_SNIPPET_BUILD) + +///////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Release +// ------------------------------------- +// +// InHandle: +// Handle to feature to be released +// +// DESCRIPTION: +// Releases feature with a given handle. +// Handles are not reference counted so +// after this call it is invalid to use provided handle. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_ReleaseFeature(NVSDK_NGX_Handle *InHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_ReleaseFeature(NVSDK_NGX_Handle *InHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_ReleaseFeature(NVSDK_NGX_Handle *InHandle); + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetFeatureRequirements +// ------------------------------------- +// Adapter: +// Physical adapter Information +// +// FeatureDiscoveryInfo: +// Contains information common to all NGX Features - required for Feature discovery, Initialization and Logging. +// +// DESCRIPTION: +// Utility function used to identify system requirements to support a given NGX Feature +// on a system given its display device subsytem adapter information that will be subsequently used for creating the graphics device. +// The output parameter OutSupported will be populated with requirements and are valid if and only if NVSDK_NGX_Result_Success is returned: +// OutSupported::FeatureSupported: bitfield of bit shifted values specified in NVSDK_NGX_Feature_Support_Result. 0 if Feature is Supported. +// OutSupported::MinHWArchitecture: Returned HW Architecture value corresponding to NV_GPU_ARCHITECTURE_ID values defined in NvAPI GPU Framework. +// OutSupported::MinOSVersion: Value corresponding to minimum OS version required for NGX Feature Support +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_GetFeatureRequirements(IDXGIAdapter *Adapter, + const NVSDK_NGX_FeatureDiscoveryInfo *FeatureDiscoveryInfo, + NVSDK_NGX_FeatureRequirement *OutSupported); + +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_GetFeatureRequirements(IDXGIAdapter *Adapter, + const NVSDK_NGX_FeatureDiscoveryInfo *FeatureDiscoveryInfo, + NVSDK_NGX_FeatureRequirement *OutSupported); + +///////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_EvaluateFeature +// ------------------------------------- +// +// InCmdList:[d3d12 only] +// Command list to use to execute GPU commands. Must be: +// - Open and recording +// - With node mask including the device provided in NVSDK_NGX_D3D12_Init +// - Execute on non-copy command queue. +// InDevCtx: [d3d11 only] +// Device context to use to execute GPU commands +// +// InFeatureHandle: +// Handle representing feature to be evaluated +// +// InParameters: +// List of parameters required to evaluate feature +// +// InCallback: +// Optional callback for features which might take longer +// to execute. If specified SDK will call it with progress +// values in range 0.0f - 1.0f +// +// DESCRIPTION: +// Evaluates given feature using the provided parameters and +// pre-trained NN. Please note that for most features +// it can be beneficial to pass as many input buffers and parameters +// as possible (for example provide all render targets like color, albedo, normals, depth etc) +// + +#ifdef __cplusplus +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_ProgressCallback)(float InCurrentProgress, bool &OutShouldCancel); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_EvaluateFeature(ID3D11DeviceContext *InDevCtx, const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback InCallback = NULL); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_EvaluateFeature(ID3D12GraphicsCommandList *InCmdList, const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback InCallback = NULL); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_EvaluateFeature(const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback InCallback = NULL); +#endif + +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_ProgressCallback_C)(float InCurrentProgress, bool *OutShouldCancel); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D11_EvaluateFeature_C(ID3D11DeviceContext *InDevCtx, const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback_C InCallback); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_D3D12_EvaluateFeature_C(ID3D12GraphicsCommandList *InCmdList, const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback_C InCallback); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_CUDA_EvaluateFeature_C(const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback_C InCallback); + +#if defined(NGX_SNIPPET_BUILD) +// No NGX Core <---> Snippet interfaces +#else +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_UpdateFeature(const NVSDK_NGX_Application_Identifier *ApplicationId, const NVSDK_NGX_Feature FeatureID); +#endif // defined(NGX_SNIPPET_BUILD) + +// NGX return-code conversion-to-string utility only as a helper for debugging/logging - not for official use. +const wchar_t* NVSDK_CONV GetNGXResultAsString(NVSDK_NGX_Result InNGXResult); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #define NVSDK_NGX_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs.h new file mode 100644 index 000000000..d3ce3f582 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs.h @@ -0,0 +1,792 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2018-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_DEFS_H +#define NVSDK_NGX_DEFS_H +#pragma once + +#ifndef __cplusplus +#include // For size_t +#include +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +#ifdef __cplusplus +#if defined(NVSDK_NGX) && defined(_WIN32) +#define NVSDK_NGX_API extern "C" __declspec(dllexport) +#else +#define NVSDK_NGX_API extern "C" +#endif +#else +#if defined(NVSDK_NGX) && defined(_WIN32) +#define NVSDK_NGX_API __declspec(dllexport) +#else +#define NVSDK_NGX_API +#endif +#endif + +#ifdef __GNUC__ +#define NVSDK_CONV +#else +#define NVSDK_CONV __cdecl +#endif + +#define NVSDK_NGX_ARRAY_LEN(a) (sizeof(a) / sizeof((a)[0])) + +// Version Notes: +// Version 0x0000014: +// * Added a logging callback that the app may pass in on init +// * Added ability for the app to override the logging level +// Version 0x0000015: +// * Support multiple GPUs (bug 3270533) +#define NVSDK_NGX_VERSION_API_MACRO 0x0000015 // NGX_VERSION_DOT 1.5.0 + +typedef unsigned long long AppId; + +typedef enum NVSDK_NGX_DLSS_Hint_Render_Preset +{ + NVSDK_NGX_DLSS_Hint_Render_Preset_Default, // default behavior, may or may not change after OTA + NVSDK_NGX_DLSS_Hint_Render_Preset_A, + NVSDK_NGX_DLSS_Hint_Render_Preset_B, + NVSDK_NGX_DLSS_Hint_Render_Preset_C, + NVSDK_NGX_DLSS_Hint_Render_Preset_D, + NVSDK_NGX_DLSS_Hint_Render_Preset_E, + NVSDK_NGX_DLSS_Hint_Render_Preset_F, + NVSDK_NGX_DLSS_Hint_Render_Preset_G, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_H_Reserved, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_I_Reserved, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_J, + NVSDK_NGX_DLSS_Hint_Render_Preset_K, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_L, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_M, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_N, // do not use, reverts to default behavior + NVSDK_NGX_DLSS_Hint_Render_Preset_O, // do not use, reverts to default behavior +} NVSDK_NGX_DLSS_Hint_Render_Preset; + +typedef struct NVSDK_NGX_FeatureCommonInfo_Internal NVSDK_NGX_FeatureCommonInfo_Internal; + +typedef enum NVSDK_NGX_Version { NVSDK_NGX_Version_API = NVSDK_NGX_VERSION_API_MACRO } NVSDK_NGX_Version; + +typedef enum NVSDK_NGX_Result +{ + NVSDK_NGX_Result_Success = 0x1, + + NVSDK_NGX_Result_Fail = 0xBAD00000, + + // Feature is not supported on current hardware + NVSDK_NGX_Result_FAIL_FeatureNotSupported = NVSDK_NGX_Result_Fail | 1, + + // Platform error - for example - check d3d12 debug layer log for more information + NVSDK_NGX_Result_FAIL_PlatformError = NVSDK_NGX_Result_Fail | 2, + + // Feature with given parameters already exists + NVSDK_NGX_Result_FAIL_FeatureAlreadyExists = NVSDK_NGX_Result_Fail | 3, + + // Feature with provided handle does not exist + NVSDK_NGX_Result_FAIL_FeatureNotFound = NVSDK_NGX_Result_Fail | 4, + + // Invalid parameter was provided + NVSDK_NGX_Result_FAIL_InvalidParameter = NVSDK_NGX_Result_Fail | 5, + + // Provided buffer is too small, please use size provided by NVSDK_NGX_GetScratchBufferSize + NVSDK_NGX_Result_FAIL_ScratchBufferTooSmall = NVSDK_NGX_Result_Fail | 6, + + // SDK was not initialized properly + NVSDK_NGX_Result_FAIL_NotInitialized = NVSDK_NGX_Result_Fail | 7, + + // Unsupported format used for input/output buffers + NVSDK_NGX_Result_FAIL_UnsupportedInputFormat = NVSDK_NGX_Result_Fail | 8, + + // Feature input/output needs RW access (UAV) (d3d11/d3d12 specific) + NVSDK_NGX_Result_FAIL_RWFlagMissing = NVSDK_NGX_Result_Fail | 9, + + // Feature was created with specific input but none is provided at evaluation + NVSDK_NGX_Result_FAIL_MissingInput = NVSDK_NGX_Result_Fail | 10, + + // Feature is not available on the system + NVSDK_NGX_Result_FAIL_UnableToInitializeFeature = NVSDK_NGX_Result_Fail | 11, + + // NGX system libraries are old and need an update + NVSDK_NGX_Result_FAIL_OutOfDate = NVSDK_NGX_Result_Fail | 12, + + // Feature requires more GPU memory than it is available on system + NVSDK_NGX_Result_FAIL_OutOfGPUMemory = NVSDK_NGX_Result_Fail | 13, + + // Format used in input buffer(s) is not supported by feature + NVSDK_NGX_Result_FAIL_UnsupportedFormat = NVSDK_NGX_Result_Fail | 14, + + // Path provided in InApplicationDataPath cannot be written to + NVSDK_NGX_Result_FAIL_UnableToWriteToAppDataPath = NVSDK_NGX_Result_Fail | 15, + + // Unsupported parameter was provided (e.g. specific scaling factor is unsupported) + NVSDK_NGX_Result_FAIL_UnsupportedParameter = NVSDK_NGX_Result_Fail | 16, + + // The feature or application was denied (contact NVIDIA for further details) + NVSDK_NGX_Result_FAIL_Denied = NVSDK_NGX_Result_Fail | 17, + + // The feature or functionality is not implemented + NVSDK_NGX_Result_FAIL_NotImplemented = NVSDK_NGX_Result_Fail | 18, +} NVSDK_NGX_Result; + +#define NVSDK_NGX_SUCCEED(value) (((value) & 0xFFF00000) != NVSDK_NGX_Result_Fail) +#define NVSDK_NGX_FAILED(value) (((value) & 0xFFF00000) == NVSDK_NGX_Result_Fail) + +typedef enum NVSDK_NGX_Feature +{ + NVSDK_NGX_Feature_Reserved0 = 0, + + NVSDK_NGX_Feature_SuperSampling = 1, + + NVSDK_NGX_Feature_InPainting = 2, + + NVSDK_NGX_Feature_ImageSuperResolution = 3, + + NVSDK_NGX_Feature_SlowMotion = 4, + + NVSDK_NGX_Feature_VideoSuperResolution = 5, + + NVSDK_NGX_Feature_Reserved1 = 6, + + NVSDK_NGX_Feature_Reserved2 = 7, + + NVSDK_NGX_Feature_Reserved3 = 8, + + NVSDK_NGX_Feature_ImageSignalProcessing = 9, + + NVSDK_NGX_Feature_DeepResolve = 10, + + NVSDK_NGX_Feature_FrameGeneration = 11, + + NVSDK_NGX_Feature_DeepDVC = 12, + + NVSDK_NGX_Feature_RayReconstruction = 13, + + NVSDK_NGX_Feature_Reserved14 = 14, + + NVSDK_NGX_Feature_Reserved15 = 15, + + NVSDK_NGX_Feature_Reserved16 = 16, + + // New features go here + NVSDK_NGX_Feature_Count, + + // These members are not strictly NGX features, but are + // components of the NGX system, and it may sometimes + // be useful to identify them using the same enum + NVSDK_NGX_Feature_Reserved_SDK = 32764, + + NVSDK_NGX_Feature_Reserved_Core = 32765, + + NVSDK_NGX_Feature_Reserved_Unknown = 32766 +} NVSDK_NGX_Feature; + +//TODO create grayscale format (R32F?) +typedef enum NVSDK_NGX_Buffer_Format +{ + NVSDK_NGX_Buffer_Format_Unknown, + NVSDK_NGX_Buffer_Format_RGB8UI, + NVSDK_NGX_Buffer_Format_RGB16F, + NVSDK_NGX_Buffer_Format_RGB32F, + NVSDK_NGX_Buffer_Format_RGBA8UI, + NVSDK_NGX_Buffer_Format_RGBA16F, + NVSDK_NGX_Buffer_Format_RGBA32F, +} NVSDK_NGX_Buffer_Format; + +typedef enum NVSDK_NGX_PerfQuality_Value +{ + NVSDK_NGX_PerfQuality_Value_MaxPerf, + NVSDK_NGX_PerfQuality_Value_Balanced, + NVSDK_NGX_PerfQuality_Value_MaxQuality, + // Extended PerfQuality modes + NVSDK_NGX_PerfQuality_Value_UltraPerformance, + NVSDK_NGX_PerfQuality_Value_UltraQuality, + NVSDK_NGX_PerfQuality_Value_DLAA, +} NVSDK_NGX_PerfQuality_Value; + +typedef enum NVSDK_NGX_RTX_Value +{ + NVSDK_NGX_RTX_Value_Off, + NVSDK_NGX_RTX_Value_On, +} NVSDK_NGX_RTX_Value; + +typedef enum NVSDK_NGX_DLSS_Mode +{ + NVSDK_NGX_DLSS_Mode_Off, // use existing in-engine AA + upscale solution + NVSDK_NGX_DLSS_Mode_DLSS_DLISP, + NVSDK_NGX_DLSS_Mode_DLISP_Only, // use existing in-engine AA solution + NVSDK_NGX_DLSS_Mode_DLSS, // DLSS will apply AA and upsample at the same time +} NVSDK_NGX_DLSS_Mode; + +typedef struct NVSDK_NGX_Handle { unsigned int Id; } NVSDK_NGX_Handle; + +typedef enum NVSDK_NGX_GPU_Arch +{ + NVSDK_NGX_GPU_Arch_NotSupported = 0, + + // Match NvAPI's NV_GPU_ARCHITECTURE_ID values for GV100 and TU100 for + // backwards compatibility with snippets built against NvAPI + NVSDK_NGX_GPU_Arch_Volta = 0x0140, + NVSDK_NGX_GPU_Arch_Turing = 0x0160, + NVSDK_NGX_GPU_Arch_Ampere = 0x0170, + NVSDK_NGX_GPU_Arch_Ada = 0x0190, + NVSDK_NGX_GPU_Arch_Hopper = 0x0180, + NVSDK_NGX_GPU_Arch_Blackwell = 0x01A0, + NVSDK_NGX_GPU_Arch_Blackwell2 = 0x01B0, + + // Presumably something newer + NVSDK_NGX_GPU_Arch_Unknown = 0x7FFFFFF +} NVSDK_NGX_GPU_Arch; + +typedef enum NVSDK_NGX_DLSS_Feature_Flags +{ + NVSDK_NGX_DLSS_Feature_Flags_IsInvalid = 1 << 31, + + NVSDK_NGX_DLSS_Feature_Flags_None = 0, + NVSDK_NGX_DLSS_Feature_Flags_IsHDR = 1 << 0, + NVSDK_NGX_DLSS_Feature_Flags_MVLowRes = 1 << 1, + NVSDK_NGX_DLSS_Feature_Flags_MVJittered = 1 << 2, + NVSDK_NGX_DLSS_Feature_Flags_DepthInverted = 1 << 3, + NVSDK_NGX_DLSS_Feature_Flags_Reserved_0 = 1 << 4, + NVSDK_NGX_DLSS_Feature_Flags_DoSharpening = 1 << 5, + NVSDK_NGX_DLSS_Feature_Flags_AutoExposure = 1 << 6, + NVSDK_NGX_DLSS_Feature_Flags_AlphaUpscaling = 1 << 7, +} NVSDK_NGX_DLSS_Feature_Flags; + +typedef enum NVSDK_NGX_ToneMapperType +{ + NVSDK_NGX_TONEMAPPER_STRING = 0, + NVSDK_NGX_TONEMAPPER_REINHARD, + NVSDK_NGX_TONEMAPPER_ONEOVERLUMA, + NVSDK_NGX_TONEMAPPER_ACES, + NVSDK_NGX_TONEMAPPERTYPE_NUM +} NVSDK_NGX_ToneMapperType; + +typedef enum NVSDK_NGX_GBufferType +{ + NVSDK_NGX_GBUFFER_ALBEDO = 0, + NVSDK_NGX_GBUFFER_ROUGHNESS, + NVSDK_NGX_GBUFFER_METALLIC, + NVSDK_NGX_GBUFFER_SPECULAR, + NVSDK_NGX_GBUFFER_SUBSURFACE, + NVSDK_NGX_GBUFFER_NORMALS, + NVSDK_NGX_GBUFFER_SHADINGMODELID, /* unique identifier for drawn object or how the object is drawn */ + NVSDK_NGX_GBUFFER_MATERIALID, /* unique identifier for material */ + NVSDK_NGX_GBUFFER_SPECULAR_ALBEDO, + NVSDK_NGX_GBUFFER_INDIRECT_ALBEDO, + NVSDK_NGX_GBUFFER_SPECULAR_MVEC, + NVSDK_NGX_GBUFFER_DISOCCL_MASK, + NVSDK_NGX_GBUFFER_EMISSIVE, + NVSDK_NGX_GBUFFERTYPE_NUM = 16 +} NVSDK_NGX_GBufferType; + +typedef struct NVSDK_NGX_Coordinates +{ + unsigned int X; + unsigned int Y; +} NVSDK_NGX_Coordinates; + +typedef struct NVSDK_NGX_Dimensions +{ + unsigned int Width; + unsigned int Height; +} NVSDK_NGX_Dimensions; + +typedef struct NVSDK_NGX_PrecisionInfo +{ + // 1 if and only if the associated resource buffer is considered low-precision + unsigned int IsLowPrecision; + + // Bias and Scale values, such that `hi = lo * Scale + Bias` + float Bias; + float Scale; +} NVSDK_NGX_PrecisionInfo; + +typedef struct NVSDK_NGX_PathListInfo +{ + // Pointer to a const string + wchar_t const* const* Path; + // Path-list length + unsigned int Length; +} NVSDK_NGX_PathListInfo; + +typedef enum NVSDK_NGX_Logging_Level +{ + NVSDK_NGX_LOGGING_LEVEL_OFF = 0, + NVSDK_NGX_LOGGING_LEVEL_ON, + NVSDK_NGX_LOGGING_LEVEL_VERBOSE, + NVSDK_NGX_LOGGING_LEVEL_NUM +} NVSDK_NGX_Logging_Level; + +// A logging callback provided by the app to allow piping log lines back to the app. +// Please take careful note of the signature and calling convention. +// The callback must be able to be called from any thread. +// It must also be fully thread-safe and any number of threads may call into it concurrently. +// It must fully process message by the time it returns, and there is no guarantee that +// message will still be valid or allocated after it returns. +// message will be a null-terminated string and may contain multibyte characters. +#if defined(__GNUC__) || defined(__clang__) +typedef void NVSDK_CONV(*NVSDK_NGX_AppLogCallback)(const char* message, NVSDK_NGX_Logging_Level loggingLevel, NVSDK_NGX_Feature sourceComponent); +#else +typedef void(NVSDK_CONV* NVSDK_NGX_AppLogCallback)(const char* message, NVSDK_NGX_Logging_Level loggingLevel, NVSDK_NGX_Feature sourceComponent); +#endif + +typedef struct NVSDK_NGX_LoggingInfo +{ + // Fields below were introduced in SDK version 0x0000014 + + // App-provided logging callback + NVSDK_NGX_AppLogCallback LoggingCallback; + + // The minimum logging level to use. If this is higher + // than the logging level otherwise configured, this will override + // that logging level. Otherwise, that logging level will be used. + NVSDK_NGX_Logging_Level MinimumLoggingLevel; + + // Whether or not to disable writing log lines to sinks other than the app log callback. This + // may be useful if the app provides a logging callback. LoggingCallback must be non-null and point + // to a valid logging callback if this is set to true. + bool DisableOtherLoggingSinks; + +} NVSDK_NGX_LoggingInfo; + +typedef struct NVSDK_NGX_FeatureCommonInfo +{ + // List of all paths in descending order of search sequence to locate a feature dll in, other than the default path - application folder. + NVSDK_NGX_PathListInfo PathListInfo; + // Used internally by NGX + NVSDK_NGX_FeatureCommonInfo_Internal* InternalData; // Introduced in SDK version 0x0000013 + + // Fields below were introduced in SDK version 0x0000014 + NVSDK_NGX_LoggingInfo LoggingInfo; +} NVSDK_NGX_FeatureCommonInfo; + +typedef enum NVSDK_NGX_Resource_VK_Type +{ + NVSDK_NGX_RESOURCE_VK_TYPE_VK_IMAGEVIEW, + NVSDK_NGX_RESOURCE_VK_TYPE_VK_BUFFER +} NVSDK_NGX_Resource_VK_Type; + +typedef enum NVSDK_NGX_Opt_Level +{ + NVSDK_NGX_OPT_LEVEL_UNDEFINED = 0, + NVSDK_NGX_OPT_LEVEL_DEBUG = 20, + NVSDK_NGX_OPT_LEVEL_DEVELOP = 30, + NVSDK_NGX_OPT_LEVEL_RELEASE = 40 +} NVSDK_NGX_Opt_Level; + +typedef enum NVSDK_NGX_EngineType +{ + NVSDK_NGX_ENGINE_TYPE_CUSTOM = 0, + NVSDK_NGX_ENGINE_TYPE_UNREAL, + NVSDK_NGX_ENGINE_TYPE_UNITY, + NVSDK_NGX_ENGINE_TYPE_OMNIVERSE, + NVSDK_NGX_ENGINE_COUNT +} NVSDK_NGX_EngineType; + +typedef enum NVSDK_NGX_Feature_Support_Result +{ + NVSDK_NGX_FeatureSupportResult_Supported = 0, + NVSDK_NGX_FeatureSupportResult_CheckNotPresent = 1, + NVSDK_NGX_FeatureSupportResult_DriverVersionUnsupported = 2, + NVSDK_NGX_FeatureSupportResult_AdapterUnsupported = 4, + NVSDK_NGX_FeatureSupportResult_OSVersionBelowMinimumSupported = 8, + NVSDK_NGX_FeatureSupportResult_NotImplemented = 16 +} NVSDK_NGX_Feature_Support_Result; + +typedef enum NVSDK_NGX_Application_Identifier_Type +{ + NVSDK_NGX_Application_Identifier_Type_Application_Id = 0, + NVSDK_NGX_Application_Identifier_Type_Project_Id = 1, +} NVSDK_NGX_Application_Identifier_Type; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_ProjectIdDescription +// ------------------------------------- +// Contains information to identify an application built using a common rendering engine (list of supported rendering engines is defined in NVSDK_NGX_EngineType). +// Should only be used by plugins for the supported rendering engines, unless using NVSDK_NGX_ENGINE_TYPE_CUSTOM as the engine type. +// +// ProjectId +// Unique Id provided by the rendering engine used +// +// EngineType +// Rendering engine used by the application / plugin. +// Use NVSDK_NGX_ENGINE_TYPE_CUSTOM if the specific engine type is not supported explicitly +// +// EngineVersion +// Version number of the rendering engine used by the application / plugin. +// +// DESCRIPTION: +// Contains information to identify an application built using a common rendering engine (list of supported rendering engines is defined in NVSDK_NGX_EngineType). +// Should only be used by plugins for the supported rendering engines, unless using NVSDK_NGX_ENGINE_TYPE_CUSTOM as the engine type. +// +typedef struct NVSDK_NGX_ProjectIdDescription +{ + const char* ProjectId; + NVSDK_NGX_EngineType EngineType; + const char* EngineVersion; +} NVSDK_NGX_ProjectIdDescription; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Application_Identifier +// ------------------------------------- +// Identifier for each application. Required for over the air updates (both optional and mandatory) +// as well as for app-specific customizations for features like DLSS-SR +// +// IdentifierType: +// Whether using a NVSDK_NGX_ProjectIdDescription or an Unique Application Identifier +// +// ProjectDesc: +// If using NVSDK_NGX_ProjectIdDescription, this contains the project ID and engine info required to identify this app +// +// ApplicationIdentifier: +// If not using NVSDK_NGX_ProjectIdDescription, this contains an ID provided by NVIDIA for this app +// If your NVIDIA contact did not provide you an ID for this purpose, use ProjectDesc with NVSDK_NGX_ENGINE_TYPE_CUSTOM as the engine type +// +typedef struct NVSDK_NGX_Application_Identifier +{ + NVSDK_NGX_Application_Identifier_Type IdentifierType; + union v { + NVSDK_NGX_ProjectIdDescription ProjectDesc; + unsigned long long ApplicationId; + } v; +} NVSDK_NGX_Application_Identifier; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_FeatureDiscoveryInfo +// ------------------------------------- +// Contains information common to all features, used by NGX in determining requested Feature availability +// +// InSDKVersion: +// API Struct version number +// +// FeatureID +// Valid NVSDK_NGX_Feature enum corresponding to DLSS v3 Feature which is being queried for availability +// +// ApplicationId +// Unique Id provided by NVIDIA corresponding to a particular Application or alternatively custom Id set by Engine +// +// InApplicationDataPath: +// Folder to store logs and other temporary files (write access required), +// Normally this would be a location in Documents or ProgramData. +// +// FeatureInfo: +// Contains information common to all features, presently only a list of all paths +// feature dlls can be located in, other than the default path - application directory. +// +typedef struct NVSDK_NGX_FeatureDiscoveryInfo +{ + NVSDK_NGX_Version SDKVersion; + NVSDK_NGX_Feature FeatureID; + NVSDK_NGX_Application_Identifier Identifier; + const wchar_t* ApplicationDataPath; + const NVSDK_NGX_FeatureCommonInfo* FeatureInfo; +} NVSDK_NGX_FeatureDiscoveryInfo; + +typedef struct NVSDK_NGX_FeatureRequirement +{ + // Bitfield of bit shifted values specified in NVSDK_NGX_Feature_Support_Result. 0 if Feature is Supported. + NVSDK_NGX_Feature_Support_Result FeatureSupported; + + // Returned HW Architecture value corresponding to NV_GPU_ARCHITECTURE_ID values defined in NvAPI GPU Framework. + unsigned int MinHWArchitecture; + + // Value corresponding to minimum OS version required for NGX Feature Support + char MinOSVersion[255]; +} NVSDK_NGX_FeatureRequirement; + +// Read-only parameters provided by NGX +#define NVSDK_NGX_EParameter_Reserved00 "#\x00" +#define NVSDK_NGX_EParameter_SuperSampling_Available "#\x01" +#define NVSDK_NGX_EParameter_InPainting_Available "#\x02" +#define NVSDK_NGX_EParameter_ImageSuperResolution_Available "#\x03" +#define NVSDK_NGX_EParameter_SlowMotion_Available "#\x04" +#define NVSDK_NGX_EParameter_VideoSuperResolution_Available "#\x05" +#define NVSDK_NGX_EParameter_Reserved06 "#\x06" +#define NVSDK_NGX_EParameter_Reserved07 "#\x07" +#define NVSDK_NGX_EParameter_Reserved08 "#\x08" +#define NVSDK_NGX_EParameter_ImageSignalProcessing_Available "#\x09" +#define NVSDK_NGX_EParameter_ImageSuperResolution_ScaleFactor_2_1 "#\x0a" +#define NVSDK_NGX_EParameter_ImageSuperResolution_ScaleFactor_3_1 "#\x0b" +#define NVSDK_NGX_EParameter_ImageSuperResolution_ScaleFactor_3_2 "#\x0c" +#define NVSDK_NGX_EParameter_ImageSuperResolution_ScaleFactor_4_3 "#\x0d" +#define NVSDK_NGX_EParameter_NumFrames "#\x0e" +#define NVSDK_NGX_EParameter_Scale "#\x0f" +#define NVSDK_NGX_EParameter_Width "#\x10" +#define NVSDK_NGX_EParameter_Height "#\x11" +#define NVSDK_NGX_EParameter_OutWidth "#\x12" +#define NVSDK_NGX_EParameter_OutHeight "#\x13" +#define NVSDK_NGX_EParameter_Sharpness "#\x14" +#define NVSDK_NGX_EParameter_Scratch "#\x15" +#define NVSDK_NGX_EParameter_Scratch_SizeInBytes "#\x16" +#define NVSDK_NGX_EParameter_EvaluationNode "#\x17" // valid since API 0x13 (replaced a deprecated param) +#define NVSDK_NGX_EParameter_Input1 "#\x18" +#define NVSDK_NGX_EParameter_Input1_Format "#\x19" +#define NVSDK_NGX_EParameter_Input1_SizeInBytes "#\x1a" +#define NVSDK_NGX_EParameter_Input2 "#\x1b" +#define NVSDK_NGX_EParameter_Input2_Format "#\x1c" +#define NVSDK_NGX_EParameter_Input2_SizeInBytes "#\x1d" +#define NVSDK_NGX_EParameter_Color "#\x1e" +#define NVSDK_NGX_EParameter_Color_Format "#\x1f" +#define NVSDK_NGX_EParameter_Color_SizeInBytes "#\x20" +#define NVSDK_NGX_EParameter_Albedo "#\x21" +#define NVSDK_NGX_EParameter_Output "#\x22" +#define NVSDK_NGX_EParameter_Output_Format "#\x23" +#define NVSDK_NGX_EParameter_Output_SizeInBytes "#\x24" +#define NVSDK_NGX_EParameter_Reset "#\x25" +#define NVSDK_NGX_EParameter_BlendFactor "#\x26" +#define NVSDK_NGX_EParameter_MotionVectors "#\x27" +#define NVSDK_NGX_EParameter_Rect_X "#\x28" +#define NVSDK_NGX_EParameter_Rect_Y "#\x29" +#define NVSDK_NGX_EParameter_Rect_W "#\x2a" +#define NVSDK_NGX_EParameter_Rect_H "#\x2b" +#define NVSDK_NGX_EParameter_MV_Scale_X "#\x2c" +#define NVSDK_NGX_EParameter_MV_Scale_Y "#\x2d" +#define NVSDK_NGX_EParameter_Model "#\x2e" +#define NVSDK_NGX_EParameter_Format "#\x2f" +#define NVSDK_NGX_EParameter_SizeInBytes "#\x30" +#define NVSDK_NGX_EParameter_ResourceAllocCallback "#\x31" +#define NVSDK_NGX_EParameter_BufferAllocCallback "#\x32" +#define NVSDK_NGX_EParameter_Tex2DAllocCallback "#\x33" +#define NVSDK_NGX_EParameter_ResourceReleaseCallback "#\x34" +#define NVSDK_NGX_EParameter_CreationNodeMask "#\x35" +#define NVSDK_NGX_EParameter_VisibilityNodeMask "#\x36" +#define NVSDK_NGX_EParameter_PreviousOutput "#\x37" +#define NVSDK_NGX_EParameter_MV_Offset_X "#\x38" +#define NVSDK_NGX_EParameter_MV_Offset_Y "#\x39" +#define NVSDK_NGX_EParameter_Hint_UseFireflySwatter "#\x3a" +#define NVSDK_NGX_EParameter_Resource_Width "#\x3b" +#define NVSDK_NGX_EParameter_Resource_Height "#\x3c" +#define NVSDK_NGX_EParameter_Depth "#\x3d" +#define NVSDK_NGX_EParameter_DLSSOptimalSettingsCallback "#\x3e" +#define NVSDK_NGX_EParameter_PerfQualityValue "#\x3f" +#define NVSDK_NGX_EParameter_RTXValue "#\x40" +#define NVSDK_NGX_EParameter_DLSSMode "#\x41" +#define NVSDK_NGX_EParameter_DeepResolve_Available "#\x42" +#define NVSDK_NGX_EParameter_Deprecated_43 "#\x43" +#define NVSDK_NGX_EParameter_OptLevel "#\x44" +#define NVSDK_NGX_EParameter_IsDevSnippetBranch "#\x45" +#define NVSDK_NGX_EParameter_DeepDVC_Available "#\x46" +#define NVSDK_NGX_EParameter_Graphics_API "#\x47" +#define NVSDK_NGX_EParameter_Reserved_48 "#\x48" +#define NVSDK_NGX_EParameter_Reserved_49 "#\x49" + +#define NVSDK_NGX_Parameter_OptLevel "Snippet.OptLevel" +#define NVSDK_NGX_Parameter_IsDevSnippetBranch "Snippet.IsDevBranch" +#define NVSDK_NGX_Parameter_SuperSampling_ScaleFactor "SuperSampling.ScaleFactor" +#define NVSDK_NGX_Parameter_ImageSignalProcessing_ScaleFactor "ImageSignalProcessing.ScaleFactor" +#define NVSDK_NGX_Parameter_SuperSampling_Available "SuperSampling.Available" +#define NVSDK_NGX_Parameter_InPainting_Available "InPainting.Available" +#define NVSDK_NGX_Parameter_ImageSuperResolution_Available "ImageSuperResolution.Available" +#define NVSDK_NGX_Parameter_SlowMotion_Available "SlowMotion.Available" +#define NVSDK_NGX_Parameter_VideoSuperResolution_Available "VideoSuperResolution.Available" +#define NVSDK_NGX_Parameter_ImageSignalProcessing_Available "ImageSignalProcessing.Available" +#define NVSDK_NGX_Parameter_DeepResolve_Available "DeepResolve.Available" +#define NVSDK_NGX_Parameter_SuperSampling_NeedsUpdatedDriver "SuperSampling.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_InPainting_NeedsUpdatedDriver "InPainting.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_ImageSuperResolution_NeedsUpdatedDriver "ImageSuperResolution.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_SlowMotion_NeedsUpdatedDriver "SlowMotion.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_VideoSuperResolution_NeedsUpdatedDriver "VideoSuperResolution.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_ImageSignalProcessing_NeedsUpdatedDriver "ImageSignalProcessing.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_DeepResolve_NeedsUpdatedDriver "DeepResolve.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_FrameInterpolation_NeedsUpdatedDriver "FrameInterpolation.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMajor "SuperSampling.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_InPainting_MinDriverVersionMajor "InPainting.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_ImageSuperResolution_MinDriverVersionMajor "ImageSuperResolution.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_SlowMotion_MinDriverVersionMajor "SlowMotion.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_VideoSuperResolution_MinDriverVersionMajor "VideoSuperResolution.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_ImageSignalProcessing_MinDriverVersionMajor "ImageSignalProcessing.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_DeepResolve_MinDriverVersionMajor "DeepResolve.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_FrameInterpolation_MinDriverVersionMajor "FrameInterpolation.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_SuperSampling_MinDriverVersionMinor "SuperSampling.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_InPainting_MinDriverVersionMinor "InPainting.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_ImageSuperResolution_MinDriverVersionMinor "ImageSuperResolution.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_SlowMotion_MinDriverVersionMinor "SlowMotion.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_VideoSuperResolution_MinDriverVersionMinor "VideoSuperResolution.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_ImageSignalProcessing_MinDriverVersionMinor "ImageSignalProcessing.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_DeepResolve_MinDriverVersionMinor "DeepResolve.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_SuperSampling_FeatureInitResult "SuperSampling.FeatureInitResult" +#define NVSDK_NGX_Parameter_InPainting_FeatureInitResult "InPainting.FeatureInitResult" +#define NVSDK_NGX_Parameter_ImageSuperResolution_FeatureInitResult "ImageSuperResolution.FeatureInitResult" +#define NVSDK_NGX_Parameter_SlowMotion_FeatureInitResult "SlowMotion.FeatureInitResult" +#define NVSDK_NGX_Parameter_VideoSuperResolution_FeatureInitResult "VideoSuperResolution.FeatureInitResult" +#define NVSDK_NGX_Parameter_ImageSignalProcessing_FeatureInitResult "ImageSignalProcessing.FeatureInitResult" +#define NVSDK_NGX_Parameter_DeepResolve_FeatureInitResult "DeepResolve.FeatureInitResult" +#define NVSDK_NGX_Parameter_FrameInterpolation_FeatureInitResult "FrameInterpolation.FeatureInitResult" +#define NVSDK_NGX_Parameter_ImageSuperResolution_ScaleFactor_2_1 "ImageSuperResolution.ScaleFactor.2.1" +#define NVSDK_NGX_Parameter_ImageSuperResolution_ScaleFactor_3_1 "ImageSuperResolution.ScaleFactor.3.1" +#define NVSDK_NGX_Parameter_ImageSuperResolution_ScaleFactor_3_2 "ImageSuperResolution.ScaleFactor.3.2" +#define NVSDK_NGX_Parameter_ImageSuperResolution_ScaleFactor_4_3 "ImageSuperResolution.ScaleFactor.4.3" +#define NVSDK_NGX_Parameter_NumFrames "NumFrames" +#define NVSDK_NGX_Parameter_Scale "Scale" +#define NVSDK_NGX_Parameter_Width "Width" +#define NVSDK_NGX_Parameter_Height "Height" +#define NVSDK_NGX_Parameter_OutWidth "OutWidth" +#define NVSDK_NGX_Parameter_OutHeight "OutHeight" +#define NVSDK_NGX_Parameter_Sharpness "Sharpness" +#define NVSDK_NGX_Parameter_Scratch "Scratch" +#define NVSDK_NGX_Parameter_Scratch_SizeInBytes "Scratch.SizeInBytes" +#define NVSDK_NGX_Parameter_Input1 "Input1" +#define NVSDK_NGX_Parameter_Input1_Format "Input1.Format" +#define NVSDK_NGX_Parameter_Input1_SizeInBytes "Input1.SizeInBytes" +#define NVSDK_NGX_Parameter_Input2 "Input2" +#define NVSDK_NGX_Parameter_Input2_Format "Input2.Format" +#define NVSDK_NGX_Parameter_Input2_SizeInBytes "Input2.SizeInBytes" +#define NVSDK_NGX_Parameter_Color "Color" +#define NVSDK_NGX_Parameter_Color_Format "Color.Format" +#define NVSDK_NGX_Parameter_Color_SizeInBytes "Color.SizeInBytes" +#define NVSDK_NGX_Parameter_FI_Color1 "Color1" +#define NVSDK_NGX_Parameter_FI_Color2 "Color2" +#define NVSDK_NGX_Parameter_Albedo "Albedo" +#define NVSDK_NGX_Parameter_Output "Output" +#define NVSDK_NGX_Parameter_Output_Format "Output.Format" +#define NVSDK_NGX_Parameter_Output_SizeInBytes "Output.SizeInBytes" +#define NVSDK_NGX_Parameter_FI_Output1 "Output1" +#define NVSDK_NGX_Parameter_FI_Output2 "Output2" +#define NVSDK_NGX_Parameter_FI_Output3 "Output3" +#define NVSDK_NGX_Parameter_Reset "Reset" +#define NVSDK_NGX_Parameter_BlendFactor "BlendFactor" +#define NVSDK_NGX_Parameter_MotionVectors "MotionVectors" +#define NVSDK_NGX_Parameter_FI_MotionVectors1 "MotionVectors1" +#define NVSDK_NGX_Parameter_FI_MotionVectors2 "MotionVectors2" +#define NVSDK_NGX_Parameter_Rect_X "Rect.X" +#define NVSDK_NGX_Parameter_Rect_Y "Rect.Y" +#define NVSDK_NGX_Parameter_Rect_W "Rect.W" +#define NVSDK_NGX_Parameter_Rect_H "Rect.H" +#define NVSDK_NGX_Parameter_OutRect_X "OutRect.X" +#define NVSDK_NGX_Parameter_OutRect_Y "OutRect.Y" +#define NVSDK_NGX_Parameter_OutRect_W "OutRect.W" +#define NVSDK_NGX_Parameter_OutRect_H "OutRect.H" +#define NVSDK_NGX_Parameter_MV_Scale_X "MV.Scale.X" +#define NVSDK_NGX_Parameter_MV_Scale_Y "MV.Scale.Y" +#define NVSDK_NGX_Parameter_Model "Model" +#define NVSDK_NGX_Parameter_Format "Format" +#define NVSDK_NGX_Parameter_SizeInBytes "SizeInBytes" +#define NVSDK_NGX_Parameter_ResourceAllocCallback "ResourceAllocCallback" +#define NVSDK_NGX_Parameter_BufferAllocCallback "BufferAllocCallback" +#define NVSDK_NGX_Parameter_Tex2DAllocCallback "Tex2DAllocCallback" +#define NVSDK_NGX_Parameter_ResourceReleaseCallback "ResourceReleaseCallback" +#define NVSDK_NGX_Parameter_CreationNodeMask "CreationNodeMask" +#define NVSDK_NGX_Parameter_VisibilityNodeMask "VisibilityNodeMask" +#define NVSDK_NGX_Parameter_MV_Offset_X "MV.Offset.X" +#define NVSDK_NGX_Parameter_MV_Offset_Y "MV.Offset.Y" +#define NVSDK_NGX_Parameter_Hint_UseFireflySwatter "Hint.UseFireflySwatter" +#define NVSDK_NGX_Parameter_Resource_Width "ResourceWidth" +#define NVSDK_NGX_Parameter_Resource_Height "ResourceHeight" +#define NVSDK_NGX_Parameter_Resource_OutWidth "ResourceOutWidth" +#define NVSDK_NGX_Parameter_Resource_OutHeight "ResourceOutHeight" +#define NVSDK_NGX_Parameter_Depth "Depth" +#define NVSDK_NGX_Parameter_FI_Depth1 "Depth1" +#define NVSDK_NGX_Parameter_FI_Depth2 "Depth2" +#define NVSDK_NGX_Parameter_DLSSOptimalSettingsCallback "DLSSOptimalSettingsCallback" +#define NVSDK_NGX_Parameter_DLSSGetStatsCallback "DLSSGetStatsCallback" +#define NVSDK_NGX_Parameter_PerfQualityValue "PerfQualityValue" +#define NVSDK_NGX_Parameter_RTXValue "RTXValue" +#define NVSDK_NGX_Parameter_DLSSMode "DLSSMode" +#define NVSDK_NGX_Parameter_FI_Mode "FIMode" +#define NVSDK_NGX_Parameter_FI_OF_Preset "FIOFPreset" +#define NVSDK_NGX_Parameter_FI_OF_GridSize "FIOFGridSize" +#define NVSDK_NGX_Parameter_Jitter_Offset_X "Jitter.Offset.X" +#define NVSDK_NGX_Parameter_Jitter_Offset_Y "Jitter.Offset.Y" +#define NVSDK_NGX_Parameter_Denoise "Denoise" +#define NVSDK_NGX_Parameter_TransparencyMask "TransparencyMask" +#define NVSDK_NGX_Parameter_ExposureTexture "ExposureTexture" // a 1x1 texture containing the final exposure scale +#define NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags "DLSS.Feature.Create.Flags" +#define NVSDK_NGX_Parameter_DLSS_Checkerboard_Jitter_Hack "DLSS.Checkerboard.Jitter.Hack" +#define NVSDK_NGX_Parameter_GBuffer_Normals "GBuffer.Normals" +#define NVSDK_NGX_Parameter_GBuffer_Albedo "GBuffer.Albedo" +#define NVSDK_NGX_Parameter_GBuffer_Roughness "GBuffer.Roughness" +#define NVSDK_NGX_Parameter_GBuffer_DiffuseAlbedo "GBuffer.DiffuseAlbedo" +#define NVSDK_NGX_Parameter_GBuffer_SpecularAlbedo "GBuffer.SpecularAlbedo" +#define NVSDK_NGX_Parameter_GBuffer_IndirectAlbedo "GBuffer.IndirectAlbedo" +#define NVSDK_NGX_Parameter_GBuffer_SpecularMvec "GBuffer.SpecularMvec" +#define NVSDK_NGX_Parameter_GBuffer_DisocclusionMask "GBuffer.DisocclusionMask" +#define NVSDK_NGX_Parameter_GBuffer_Metallic "GBuffer.Metallic" +#define NVSDK_NGX_Parameter_GBuffer_Specular "GBuffer.Specular" +#define NVSDK_NGX_Parameter_GBuffer_Subsurface "GBuffer.Subsurface" +#define NVSDK_NGX_Parameter_GBuffer_ShadingModelId "GBuffer.ShadingModelId" +#define NVSDK_NGX_Parameter_GBuffer_MaterialId "GBuffer.MaterialId" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_8 "GBuffer.Attrib.8" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_9 "GBuffer.Attrib.9" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_10 "GBuffer.Attrib.10" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_11 "GBuffer.Attrib.11" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_12 "GBuffer.Attrib.12" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_13 "GBuffer.Attrib.13" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_14 "GBuffer.Attrib.14" +#define NVSDK_NGX_Parameter_GBuffer_Atrrib_15 "GBuffer.Attrib.15" +#define NVSDK_NGX_Parameter_TonemapperType "TonemapperType" +#define NVSDK_NGX_Parameter_FreeMemOnReleaseFeature "FreeMemOnReleaseFeature" +#define NVSDK_NGX_Parameter_MotionVectors3D "MotionVectors3D" +#define NVSDK_NGX_Parameter_IsParticleMask "IsParticleMask" +#define NVSDK_NGX_Parameter_AnimatedTextureMask "AnimatedTextureMask" +#define NVSDK_NGX_Parameter_DepthHighRes "DepthHighRes" +#define NVSDK_NGX_Parameter_Position_ViewSpace "Position.ViewSpace" +#define NVSDK_NGX_Parameter_FrameTimeDeltaInMsec "FrameTimeDeltaInMsec" +#define NVSDK_NGX_Parameter_RayTracingHitDistance "RayTracingHitDistance" +#define NVSDK_NGX_Parameter_MotionVectorsReflection "MotionVectorsReflection" +#define NVSDK_NGX_Parameter_DLSS_Enable_Output_Subrects "DLSS.Enable.Output.Subrects" +#define NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_X "DLSS.Input.Color.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_Y "DLSS.Input.Color.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_X "DLSS.Input.Depth.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_Y "DLSS.Input.Depth.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_X "DLSS.Input.MV.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_Y "DLSS.Input.MV.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_X "DLSS.Input.Translucency.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_Y "DLSS.Input.Translucency.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_X "DLSS.Output.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_Y "DLSS.Output.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width "DLSS.Render.Subrect.Dimensions.Width" +#define NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height "DLSS.Render.Subrect.Dimensions.Height" +#define NVSDK_NGX_Parameter_DLSS_Pre_Exposure "DLSS.Pre.Exposure" +#define NVSDK_NGX_Parameter_DLSS_Exposure_Scale "DLSS.Exposure.Scale" +#define NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask "DLSS.Input.Bias.Current.Color.Mask" +#define NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_X "DLSS.Input.Bias.Current.Color.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_Y "DLSS.Input.Bias.Current.Color.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_Indicator_Invert_Y_Axis "DLSS.Indicator.Invert.Y.Axis" +#define NVSDK_NGX_Parameter_DLSS_Indicator_Invert_X_Axis "DLSS.Indicator.Invert.X.Axis" +#define NVSDK_NGX_Parameter_DLSS_INV_VIEW_PROJECTION_MATRIX "InvViewProjectionMatrix" +#define NVSDK_NGX_Parameter_DLSS_CLIP_TO_PREV_CLIP_MATRIX "ClipToPrevClipMatrix" + +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayer "DLSS.TransparencyLayer" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayer_Subrect_Base_X "DLSS.TransparencyLayer.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayer_Subrect_Base_Y "DLSS.TransparencyLayer.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayerOpacity "DLSS.TransparencyLayerOpacity" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayerOpacity_Subrect_Base_X "DLSS.TransparencyLayerOpacity.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayerOpacity_Subrect_Base_Y "DLSS.TransparencyLayerOpacity.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayerMvecs "DLSS.TransparencyLayerMvecs" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayerMvecs_Subrect_Base_X "DLSS.TransparencyLayerMvecs.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_TransparencyLayerMvecs_Subrect_Base_Y "DLSS.TransparencyLayerMvecs.Subrect.Base.Y" +#define NVSDK_NGX_Parameter_DLSS_DisocclusionMask "DLSS.DisocclusionMask" +#define NVSDK_NGX_Parameter_DLSS_DisocclusionMask_Subrect_Base_X "DLSS.DisocclusionMask.Subrect.Base.X" +#define NVSDK_NGX_Parameter_DLSS_DisocclusionMask_Subrect_Base_Y "DLSS.DisocclusionMask.Subrect.Base.Y" + +#define NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Max_Render_Width "DLSS.Get.Dynamic.Max.Render.Width" +#define NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Max_Render_Height "DLSS.Get.Dynamic.Max.Render.Height" +#define NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Min_Render_Width "DLSS.Get.Dynamic.Min.Render.Width" +#define NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Min_Render_Height "DLSS.Get.Dynamic.Min.Render.Height" + +#define NVSDK_NGX_Parameter_DLSS_Hint_Render_Preset_DLAA "DLSS.Hint.Render.Preset.DLAA" +#define NVSDK_NGX_Parameter_DLSS_Hint_Render_Preset_Quality "DLSS.Hint.Render.Preset.Quality" +#define NVSDK_NGX_Parameter_DLSS_Hint_Render_Preset_Balanced "DLSS.Hint.Render.Preset.Balanced" +#define NVSDK_NGX_Parameter_DLSS_Hint_Render_Preset_Performance "DLSS.Hint.Render.Preset.Performance" +#define NVSDK_NGX_Parameter_DLSS_Hint_Render_Preset_UltraPerformance "DLSS.Hint.Render.Preset.UltraPerformance" +#define NVSDK_NGX_Parameter_DLSS_Hint_Render_Preset_UltraQuality "DLSS.Hint.Render.Preset.UltraQuality" + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs_truehdr.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs_truehdr.h new file mode 100644 index 000000000..d9e494dce --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs_truehdr.h @@ -0,0 +1,42 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_DEFS_TRUEHDR_H +#define NVSDK_NGX_DEFS_TRUEHDR_H +#pragma once + +#include "nvsdk_ngx_defs.h" + +#define NVSDK_NGX_EParameter_TrueHDR_Avalilable NVSDK_NGX_EParameter_Reserved_48 + +constexpr NVSDK_NGX_Feature NVSDK_NGX_Feature_TrueHDR = NVSDK_NGX_Feature_Reserved14; + +#define NVSDK_NGX_Parameter_TrueHDR_Available "TrueHDR.Available" +#define NVSDK_NGX_Parameter_TrueHDR_NeedsUpdatedDriver "TrueHDR.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_TrueHDR_MinDriverVersionMajor "TrueHDR.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_TrueHDR_MinDriverVersionMinor "TrueHDR.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_TrueHDR_FeatureInitResult "TrueHDR.FeatureInitResult" + +#define NVSDK_NGX_Parameter_TrueHDR_InLeft "TrueHDR.InLeft" // Input left pixel for source rect +#define NVSDK_NGX_Parameter_TrueHDR_InTop "TrueHDR.InTop" // Input top pixel for source rect +#define NVSDK_NGX_Parameter_TrueHDR_InRight "TrueHDR.InRight" // Input right pixel for source rect +#define NVSDK_NGX_Parameter_TrueHDR_InBottom "TrueHDR.InBottom" // Input bottom pixel for source rect +#define NVSDK_NGX_Parameter_TrueHDR_OutLeft "TrueHDR.OutLeft" // Output left pixel for dest rect +#define NVSDK_NGX_Parameter_TrueHDR_OutTop "TrueHDR.OutTop" // Output top pixel for dest rect +#define NVSDK_NGX_Parameter_TrueHDR_OutRight "TrueHDR.OutRight" // Output right pixel for dest rect +#define NVSDK_NGX_Parameter_TrueHDR_OutBottom "TrueHDR.OutBottom" // Output bottom pixel for dest rect +#define NVSDK_NGX_Parameter_TrueHDR_Contrast "TrueHDR.Contrast" // 0 to 200 for HDR Contrast +#define NVSDK_NGX_Parameter_TrueHDR_Saturation "TrueHDR.Saturation" // 0 to 200 for HDR Saturation +#define NVSDK_NGX_Parameter_TrueHDR_MiddleGray "TrueHDR.MiddleGray" // 10 to 100 for HDR MiddleGray +#define NVSDK_NGX_Parameter_TrueHDR_MaxLuminance "TrueHDR.MaxLuminance" // 400 to 2000 for Monitor MaxLuminance + +#endif // NVSDK_NGX_DEFS_TRUEHDR_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs_vsr.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs_vsr.h new file mode 100644 index 000000000..1f1086e93 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_defs_vsr.h @@ -0,0 +1,39 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_DEFS_VSR_H +#define NVSDK_NGX_DEFS_VSR_H +#pragma once + +#include "nvsdk_ngx_defs.h" + +#define NVSDK_NGX_EParameter_VSR_Available NVSDK_NGX_EParameter_Reserved_49 + +constexpr NVSDK_NGX_Feature NVSDK_NGX_Feature_VSR = NVSDK_NGX_Feature_Reserved16; + +typedef enum NVSDK_NGX_VSR_QualityLevel +{ + NVSDK_NGX_VSR_Quality_Bicubic = 0, + NVSDK_NGX_VSR_Quality_Low = 1, + NVSDK_NGX_VSR_Quality_Medium = 2, + NVSDK_NGX_VSR_Quality_High = 3, + NVSDK_NGX_VSR_Quality_Ultra = 4, +} NVSDK_NGX_VSR_QualityLevel; + +#define NVSDK_NGX_Parameter_VSR_Available "VSR.Available" +#define NVSDK_NGX_Parameter_VSR_NeedsUpdatedDriver "VSR.NeedsUpdatedDriver" +#define NVSDK_NGX_Parameter_VSR_MinDriverVersionMajor "VSR.MinDriverVersionMajor" +#define NVSDK_NGX_Parameter_VSR_MinDriverVersionMinor "VSR.MinDriverVersionMinor" +#define NVSDK_NGX_Parameter_VSR_FeatureInitResult "VSR.FeatureInitResult" +#define NVSDK_NGX_Parameter_VSR_QualityLevel "VSR.QualityLevel" + +#endif // NVSDK_NGX_DEFS_VSR_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers.h new file mode 100644 index 000000000..5bb1fb722 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers.h @@ -0,0 +1,627 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2019-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_HELPERS_H +#define NVSDK_NGX_HELPERS_H +#pragma once + +#include "nvsdk_ngx.h" +#include "nvsdk_ngx_defs.h" + +typedef NVSDK_NGX_Result(NVSDK_CONV *PFN_NVSDK_NGX_DLSS_GetStatsCallback)(NVSDK_NGX_Parameter *InParams); + +static inline NVSDK_NGX_Result NGX_DLSS_GET_STATS_2( + NVSDK_NGX_Parameter *pInParams, + unsigned long long *pVRAMAllocatedBytes, + unsigned int *pOptLevel, unsigned int *IsDevSnippetBranch) +{ + void *Callback = NULL; + NVSDK_NGX_Parameter_GetVoidPointer(pInParams, NVSDK_NGX_Parameter_DLSSGetStatsCallback, &Callback); + if (!Callback) + { + // Possible reasons for this: + // - Installed DLSS is out of date and does not support the feature we need + // - You used NVSDK_NGX_AllocateParameters() for creating InParams. Try using NVSDK_NGX_GetCapabilityParameters() instead + return NVSDK_NGX_Result_FAIL_OutOfDate; + } + + NVSDK_NGX_Result Res = NVSDK_NGX_Result_Success; + PFN_NVSDK_NGX_DLSS_GetStatsCallback PFNCallback = (PFN_NVSDK_NGX_DLSS_GetStatsCallback)Callback; + Res = PFNCallback(pInParams); + if (NVSDK_NGX_FAILED(Res)) + { + return Res; + } + NVSDK_NGX_Parameter_GetULL(pInParams, NVSDK_NGX_Parameter_SizeInBytes, pVRAMAllocatedBytes); + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_EParameter_OptLevel, pOptLevel); + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_EParameter_IsDevSnippetBranch, IsDevSnippetBranch); + return Res; +} + +static inline NVSDK_NGX_Result NGX_DLSS_GET_STATS_1( + NVSDK_NGX_Parameter *pInParams, + unsigned long long *pVRAMAllocatedBytes, + unsigned int *pOptLevel) +{ + unsigned int dummy = 0; + return NGX_DLSS_GET_STATS_2(pInParams, pVRAMAllocatedBytes, pOptLevel, &dummy); +} + +static inline NVSDK_NGX_Result NGX_DLSS_GET_STATS( + NVSDK_NGX_Parameter *pInParams, + unsigned long long *pVRAMAllocatedBytes) +{ + unsigned int dummy = 0; + return NGX_DLSS_GET_STATS_2(pInParams, pVRAMAllocatedBytes, &dummy, &dummy); +} + +typedef NVSDK_NGX_Result(NVSDK_CONV *PFN_NVSDK_NGX_DLSS_GetOptimalSettingsCallback)(NVSDK_NGX_Parameter *InParams); + +static inline NVSDK_NGX_Result NGX_DLSS_GET_OPTIMAL_SETTINGS( + NVSDK_NGX_Parameter *pInParams, + unsigned int InUserSelectedWidth, + unsigned int InUserSelectedHeight, + NVSDK_NGX_PerfQuality_Value InPerfQualityValue, + unsigned int *pOutRenderOptimalWidth, + unsigned int *pOutRenderOptimalHeight, + unsigned int *pOutRenderMaxWidth, + unsigned int *pOutRenderMaxHeight, + unsigned int *pOutRenderMinWidth, + unsigned int *pOutRenderMinHeight, + float *pOutSharpness) +{ + void *Callback = NULL; + NVSDK_NGX_Parameter_GetVoidPointer(pInParams, NVSDK_NGX_Parameter_DLSSOptimalSettingsCallback, &Callback); + if (!Callback) + { + // Possible reasons for this: + // - Installed DLSS is out of date and does not support the feature we need + // - You used NVSDK_NGX_AllocateParameters() for creating InParams. Try using NVSDK_NGX_GetCapabilityParameters() instead + return NVSDK_NGX_Result_FAIL_OutOfDate; + } + + // These are selections made by user in UI + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, InUserSelectedWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, InUserSelectedHeight); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_PerfQualityValue, InPerfQualityValue); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_RTXValue, false); // Some older DLSS dlls still expect this value to be set + + NVSDK_NGX_Result Res = NVSDK_NGX_Result_Success; + PFN_NVSDK_NGX_DLSS_GetOptimalSettingsCallback PFNCallback = (PFN_NVSDK_NGX_DLSS_GetOptimalSettingsCallback)Callback; + Res = PFNCallback(pInParams); + if (NVSDK_NGX_FAILED(Res)) + { + return Res; + } + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pOutRenderOptimalWidth); + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pOutRenderOptimalHeight); + // If we have an older DLSS Dll those might need to be set to the optimal dimensions instead + *pOutRenderMaxWidth = *pOutRenderOptimalWidth; + *pOutRenderMaxHeight = *pOutRenderOptimalHeight; + *pOutRenderMinWidth = *pOutRenderOptimalWidth; + *pOutRenderMinHeight = *pOutRenderOptimalHeight; + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Max_Render_Width, pOutRenderMaxWidth); + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Max_Render_Height, pOutRenderMaxHeight); + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Min_Render_Width, pOutRenderMinWidth); + NVSDK_NGX_Parameter_GetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Get_Dynamic_Min_Render_Height, pOutRenderMinHeight); + NVSDK_NGX_Parameter_GetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pOutSharpness); + return Res; +} + +/*** D3D11 ***/ +typedef struct NVSDK_NGX_D3D11_Feature_Eval_Params +{ + ID3D11Resource* pInColor; + ID3D11Resource* pInOutput; + /*** OPTIONAL for DLSS ***/ + float InSharpness; +} NVSDK_NGX_D3D11_Feature_Eval_Params; + +typedef struct NVSDK_NGX_CUDA_Feature_Eval_Params +{ + CUtexObject* pInColor; + CUtexObject* pInOutput; + /*** OPTIONAL for DLSS ***/ + float InSharpness; +} NVSDK_NGX_CUDA_Feature_Eval_Params; + +typedef struct NVSDK_NGX_D3D11_GBuffer +{ + ID3D11Resource* pInAttrib[NVSDK_NGX_GBUFFERTYPE_NUM]; +} NVSDK_NGX_D3D11_GBuffer; + +typedef struct NVSDK_NGX_D3D11_DLSS_Eval_Params +{ + NVSDK_NGX_D3D11_Feature_Eval_Params Feature; + ID3D11Resource* pInDepth; + ID3D11Resource* pInMotionVectors; + float InJitterOffsetX; /* Jitter offset must be in input/render pixel space */ + float InJitterOffsetY; + NVSDK_NGX_Dimensions InRenderSubrectDimensions; + /*** OPTIONAL - leave to 0/0.0f if unused ***/ + int InReset; /* Set to 1 when scene changes completely (new level etc) */ + float InMVScaleX; /* If MVs need custom scaling to convert to pixel space */ + float InMVScaleY; + ID3D11Resource* pInTransparencyMask; /* Unused/Reserved for future use */ + ID3D11Resource* pInExposureTexture; + ID3D11Resource* pInBiasCurrentColorMask; + NVSDK_NGX_Coordinates InColorSubrectBase; + NVSDK_NGX_Coordinates InDepthSubrectBase; + NVSDK_NGX_Coordinates InMVSubrectBase; + NVSDK_NGX_Coordinates InTranslucencySubrectBase; + NVSDK_NGX_Coordinates InBiasCurrentColorSubrectBase; + NVSDK_NGX_Coordinates InOutputSubrectBase; + float InPreExposure; + float InExposureScale; + int InIndicatorInvertXAxis; + int InIndicatorInvertYAxis; + /*** OPTIONAL - only for research purposes ***/ + NVSDK_NGX_D3D11_GBuffer GBufferSurface; + NVSDK_NGX_ToneMapperType InToneMapperType; + ID3D11Resource* pInMotionVectors3D; + ID3D11Resource* pInIsParticleMask; /* to identify which pixels contains particles, essentially that are not drawn as part of base pass */ + ID3D11Resource* pInAnimatedTextureMask; /* a binary mask covering pixels occupied by animated textures */ + ID3D11Resource* pInDepthHighRes; + ID3D11Resource* pInPositionViewSpace; + float InFrameTimeDeltaInMsec; /* helps in determining the amount to denoise or anti-alias based on the speed of the object from motion vector magnitudes and fps as determined by this delta */ + ID3D11Resource* pInRayTracingHitDistance; /* for each effect - approximation to the amount of noise in a ray-traced color */ + ID3D11Resource* pInMotionVectorsReflections; /* motion vectors of reflected objects like for mirrored surfaces */ +} NVSDK_NGX_D3D11_DLSS_Eval_Params; + +typedef struct NVSDK_NGX_D3D11_DLISP_Eval_Params +{ + NVSDK_NGX_D3D11_Feature_Eval_Params Feature; + /*** OPTIONAL - leave to 0/0.0f if unused ***/ + unsigned int InRectX; + unsigned int InRectY; + unsigned int InRectW; + unsigned int InRectH; + float InDenoise; +} NVSDK_NGX_D3D11_DLISP_Eval_Params; + +typedef struct NVSDK_NGX_CUDA_DLISP_Eval_Params +{ + NVSDK_NGX_CUDA_Feature_Eval_Params Feature; + /*** OPTIONAL - leave to 0/0.0f if unused ***/ + unsigned int InRectX; + unsigned int InRectY; + unsigned int InRectW; + unsigned int InRectH; + float InDenoise; +} NVSDK_NGX_CUDA_DLISP_Eval_Params; + + +static inline NVSDK_NGX_Result NGX_D3D11_CREATE_DLSS_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_DLSS_Create_Params *pInDlssCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pInDlssCreateParams->Feature.InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pInDlssCreateParams->Feature.InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pInDlssCreateParams->Feature.InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pInDlssCreateParams->Feature.InTargetHeight); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_PerfQualityValue, pInDlssCreateParams->Feature.InPerfQualityValue); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, pInDlssCreateParams->InFeatureCreateFlags); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Enable_Output_Subrects, pInDlssCreateParams->InEnableOutputSubrects ? 1 : 0); + + return NVSDK_NGX_D3D11_CreateFeature(pInCtx, NVSDK_NGX_Feature_SuperSampling, pInParams, ppOutHandle); +} + + +static inline NVSDK_NGX_Result NGX_D3D11_EVALUATE_DLSS_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D11_DLSS_Eval_Params *pInDlssEvalParams) +{ + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Color, pInDlssEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Output, pInDlssEvalParams->Feature.pInOutput); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Depth, pInDlssEvalParams->pInDepth); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_MotionVectors, pInDlssEvalParams->pInMotionVectors); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Jitter_Offset_X, pInDlssEvalParams->InJitterOffsetX); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Jitter_Offset_Y, pInDlssEvalParams->InJitterOffsetY); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pInDlssEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_Reset, pInDlssEvalParams->InReset); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_MV_Scale_X, pInDlssEvalParams->InMVScaleX == 0.0f ? 1.0f : pInDlssEvalParams->InMVScaleX); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_MV_Scale_Y, pInDlssEvalParams->InMVScaleY == 0.0f ? 1.0f : pInDlssEvalParams->InMVScaleY); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_TransparencyMask, pInDlssEvalParams->pInTransparencyMask); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_ExposureTexture, pInDlssEvalParams->pInExposureTexture); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, pInDlssEvalParams->pInBiasCurrentColorMask); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Albedo, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_ALBEDO]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Roughness, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_ROUGHNESS]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Metallic, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_METALLIC]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Specular, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SPECULAR]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Subsurface, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SUBSURFACE]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Normals, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_NORMALS]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_ShadingModelId, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SHADINGMODELID]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_MaterialId, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_MATERIALID]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_8, pInDlssEvalParams->GBufferSurface.pInAttrib[8]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_9, pInDlssEvalParams->GBufferSurface.pInAttrib[9]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_10, pInDlssEvalParams->GBufferSurface.pInAttrib[10]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_11, pInDlssEvalParams->GBufferSurface.pInAttrib[11]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_12, pInDlssEvalParams->GBufferSurface.pInAttrib[12]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_13, pInDlssEvalParams->GBufferSurface.pInAttrib[13]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_14, pInDlssEvalParams->GBufferSurface.pInAttrib[14]); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_15, pInDlssEvalParams->GBufferSurface.pInAttrib[15]); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TonemapperType, pInDlssEvalParams->InToneMapperType); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_MotionVectors3D, pInDlssEvalParams->pInMotionVectors3D); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_IsParticleMask, pInDlssEvalParams->pInIsParticleMask); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_AnimatedTextureMask, pInDlssEvalParams->pInAnimatedTextureMask); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_DepthHighRes, pInDlssEvalParams->pInDepthHighRes); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Position_ViewSpace, pInDlssEvalParams->pInPositionViewSpace); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, pInDlssEvalParams->InFrameTimeDeltaInMsec); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_RayTracingHitDistance, pInDlssEvalParams->pInRayTracingHitDistance); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_MotionVectorsReflection, pInDlssEvalParams->pInMotionVectorsReflections); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_X, pInDlssEvalParams->InColorSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_Y, pInDlssEvalParams->InColorSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_X, pInDlssEvalParams->InDepthSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_Y, pInDlssEvalParams->InDepthSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_X, pInDlssEvalParams->InMVSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_Y, pInDlssEvalParams->InMVSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_X, pInDlssEvalParams->InTranslucencySubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_Y, pInDlssEvalParams->InTranslucencySubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_X, pInDlssEvalParams->InBiasCurrentColorSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_Y, pInDlssEvalParams->InBiasCurrentColorSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_X, pInDlssEvalParams->InOutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_Y, pInDlssEvalParams->InOutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width , pInDlssEvalParams->InRenderSubrectDimensions.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height, pInDlssEvalParams->InRenderSubrectDimensions.Height); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_DLSS_Pre_Exposure, pInDlssEvalParams->InPreExposure == 0.0f ? 1.0f : pInDlssEvalParams->InPreExposure); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_DLSS_Exposure_Scale, pInDlssEvalParams->InExposureScale == 0.0f ? 1.0f : pInDlssEvalParams->InExposureScale); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_X_Axis, pInDlssEvalParams->InIndicatorInvertXAxis); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_Y_Axis, pInDlssEvalParams->InIndicatorInvertYAxis); + + return NVSDK_NGX_D3D11_EvaluateFeature_C(pInCtx, pInHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_D3D11_CREATE_DLISP_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pDlispCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pDlispCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pDlispCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pDlispCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pDlispCreateParams->InTargetHeight); + + return NVSDK_NGX_D3D11_CreateFeature(pInCtx, NVSDK_NGX_Feature_ImageSignalProcessing, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_CUDA_CREATE_DLISP_EXT( + NVSDK_NGX_Handle** ppOutHandle, + NVSDK_NGX_Parameter* pInParams, + NVSDK_NGX_Feature_Create_Params* pDlispCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pDlispCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pDlispCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pDlispCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pDlispCreateParams->InTargetHeight); + + return NVSDK_NGX_CUDA_CreateFeature(NVSDK_NGX_Feature_ImageSignalProcessing, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D11_EVALUATE_DLISP_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D11_DLISP_Eval_Params *pDlispEvalParams) +{ + if (pDlispEvalParams->Feature.InSharpness < 0.0f || pDlispEvalParams->Feature.InSharpness > 1.0f || pDlispEvalParams->InDenoise < 0.0f || pDlispEvalParams->InDenoise > 1.0f) + { + return NVSDK_NGX_Result_FAIL_InvalidParameter; + } + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Color, pDlispEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Output, pDlispEvalParams->Feature.pInOutput); + // Both sharpness and denoise in range [0.0f,1.0f] + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pDlispEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Denoise, pDlispEvalParams->InDenoise); + // If input is atlas - use RECT to upscale only the required area + if (pDlispEvalParams->InRectW) + { + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pDlispEvalParams->InRectX); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pDlispEvalParams->InRectY); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pDlispEvalParams->InRectW); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pDlispEvalParams->InRectH); + } + + return NVSDK_NGX_D3D11_EvaluateFeature_C(pInCtx, pInHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_CUDA_EVALUATE_DLISP_EXT( + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_CUDA_DLISP_Eval_Params *pDlispEvalParams) +{ + if (pDlispEvalParams->Feature.InSharpness < 0.0f || pDlispEvalParams->Feature.InSharpness > 1.0f || pDlispEvalParams->InDenoise < 0.0f || pDlispEvalParams->InDenoise > 1.0f) + { + return NVSDK_NGX_Result_FAIL_InvalidParameter; + } + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Color, pDlispEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pDlispEvalParams->Feature.pInOutput); + // Both sharpness and denoise in range [0.0f,1.0f] + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pDlispEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Denoise, pDlispEvalParams->InDenoise); + // If input is atlas - use RECT to upscale only the required area + if (pDlispEvalParams->InRectW) + { + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pDlispEvalParams->InRectX); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pDlispEvalParams->InRectY); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pDlispEvalParams->InRectW); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pDlispEvalParams->InRectH); + } + + return NVSDK_NGX_CUDA_EvaluateFeature_C(pInHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_D3D11_CREATE_DLRESOLVE_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pDlresolveCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pDlresolveCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pDlresolveCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pDlresolveCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pDlresolveCreateParams->InTargetHeight); + + return NVSDK_NGX_D3D11_CreateFeature(pInCtx, NVSDK_NGX_Feature_DeepResolve, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D11_EVALUATE_DLRESOLVE_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle *InHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D11_Feature_Eval_Params *pDlresolveEvalParams) +{ + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Color, pDlresolveEvalParams->pInColor); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Output, pDlresolveEvalParams->pInOutput); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pDlresolveEvalParams->InSharpness); + + return NVSDK_NGX_D3D11_EvaluateFeature_C(pInCtx, InHandle, pInParams, NULL); +} + +/*** D3D12 ***/ +typedef struct NVSDK_NGX_D3D12_Feature_Eval_Params +{ + ID3D12Resource* pInColor; + ID3D12Resource* pInOutput; + /*** OPTIONAL for DLSS ***/ + float InSharpness; +} NVSDK_NGX_D3D12_Feature_Eval_Params; + +typedef struct NVSDK_NGX_D3D12_GBuffer +{ + ID3D12Resource* pInAttrib[NVSDK_NGX_GBUFFERTYPE_NUM]; +} NVSDK_NGX_D3D12_GBuffer; + +typedef struct NVSDK_NGX_D3D12_DLSS_Eval_Params +{ + NVSDK_NGX_D3D12_Feature_Eval_Params Feature; + ID3D12Resource* pInDepth; + ID3D12Resource* pInMotionVectors; + float InJitterOffsetX; /* Jitter offset must be in input/render pixel space */ + float InJitterOffsetY; + NVSDK_NGX_Dimensions InRenderSubrectDimensions; + /*** OPTIONAL - leave to 0/0.0f if unused ***/ + int InReset; /* Set to 1 when scene changes completely (new level etc) */ + float InMVScaleX; /* If MVs need custom scaling to convert to pixel space */ + float InMVScaleY; + ID3D12Resource* pInTransparencyMask; /* Unused/Reserved for future use */ + ID3D12Resource* pInExposureTexture; + ID3D12Resource* pInBiasCurrentColorMask; + NVSDK_NGX_Coordinates InColorSubrectBase; + NVSDK_NGX_Coordinates InDepthSubrectBase; + NVSDK_NGX_Coordinates InMVSubrectBase; + NVSDK_NGX_Coordinates InTranslucencySubrectBase; + NVSDK_NGX_Coordinates InBiasCurrentColorSubrectBase; + NVSDK_NGX_Coordinates InOutputSubrectBase; + float InPreExposure; + float InExposureScale; + int InIndicatorInvertXAxis; + int InIndicatorInvertYAxis; + /*** OPTIONAL - only for research purposes ***/ + NVSDK_NGX_D3D12_GBuffer GBufferSurface; + NVSDK_NGX_ToneMapperType InToneMapperType; + ID3D12Resource* pInMotionVectors3D; + ID3D12Resource* pInIsParticleMask; /* to identify which pixels contains particles, essentially that are not drawn as part of base pass */ + ID3D12Resource* pInAnimatedTextureMask; /* a binary mask covering pixels occupied by animated textures */ + ID3D12Resource* pInDepthHighRes; + ID3D12Resource* pInPositionViewSpace; + float InFrameTimeDeltaInMsec; /* helps in determining the amount to denoise or anti-alias based on the speed of the object from motion vector magnitudes and fps as determined by this delta */ + ID3D12Resource* pInRayTracingHitDistance; /* for each effect - approximation to the amount of noise in a ray-traced color */ + ID3D12Resource* pInMotionVectorsReflections; /* motion vectors of reflected objects like for mirrored surfaces */ +} NVSDK_NGX_D3D12_DLSS_Eval_Params; + +typedef struct NVSDK_NGX_D3D12_DLISP_Eval_Params +{ + NVSDK_NGX_D3D12_Feature_Eval_Params Feature; + /*** OPTIONAL ***/ + unsigned int InRectX; + unsigned int InRectY; + unsigned int InRectW; + unsigned int InRectH; + float InDenoise; +} NVSDK_NGX_D3D12_DLISP_Eval_Params; + + +static inline NVSDK_NGX_Result NGX_D3D12_CREATE_DLSS_EXT( + ID3D12GraphicsCommandList *pInCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_DLSS_Create_Params *pInDlssCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pInDlssCreateParams->Feature.InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pInDlssCreateParams->Feature.InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pInDlssCreateParams->Feature.InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pInDlssCreateParams->Feature.InTargetHeight); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_PerfQualityValue, pInDlssCreateParams->Feature.InPerfQualityValue); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, pInDlssCreateParams->InFeatureCreateFlags); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Enable_Output_Subrects, pInDlssCreateParams->InEnableOutputSubrects ? 1 : 0); + + return NVSDK_NGX_D3D12_CreateFeature(pInCmdList, NVSDK_NGX_Feature_SuperSampling, pInParams, ppOutHandle); +} + + +static inline NVSDK_NGX_Result NGX_D3D12_EVALUATE_DLSS_EXT( + ID3D12GraphicsCommandList *pInCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D12_DLSS_Eval_Params *pInDlssEvalParams) +{ + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Color, pInDlssEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Output, pInDlssEvalParams->Feature.pInOutput); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Depth, pInDlssEvalParams->pInDepth); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_MotionVectors, pInDlssEvalParams->pInMotionVectors); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Jitter_Offset_X, pInDlssEvalParams->InJitterOffsetX); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Jitter_Offset_Y, pInDlssEvalParams->InJitterOffsetY); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pInDlssEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_Reset, pInDlssEvalParams->InReset); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_MV_Scale_X, pInDlssEvalParams->InMVScaleX == 0.0f ? 1.0f : pInDlssEvalParams->InMVScaleX); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_MV_Scale_Y, pInDlssEvalParams->InMVScaleY == 0.0f ? 1.0f : pInDlssEvalParams->InMVScaleY); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_TransparencyMask, pInDlssEvalParams->pInTransparencyMask); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_ExposureTexture, pInDlssEvalParams->pInExposureTexture); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, pInDlssEvalParams->pInBiasCurrentColorMask); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Albedo, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_ALBEDO]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Roughness, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_ROUGHNESS]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Metallic, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_METALLIC]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Specular, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SPECULAR]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Subsurface, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SUBSURFACE]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Normals, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_NORMALS]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_ShadingModelId, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SHADINGMODELID]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_MaterialId, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_MATERIALID]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_8, pInDlssEvalParams->GBufferSurface.pInAttrib[8]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_9, pInDlssEvalParams->GBufferSurface.pInAttrib[9]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_10, pInDlssEvalParams->GBufferSurface.pInAttrib[10]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_11, pInDlssEvalParams->GBufferSurface.pInAttrib[11]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_12, pInDlssEvalParams->GBufferSurface.pInAttrib[12]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_13, pInDlssEvalParams->GBufferSurface.pInAttrib[13]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_14, pInDlssEvalParams->GBufferSurface.pInAttrib[14]); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_15, pInDlssEvalParams->GBufferSurface.pInAttrib[15]); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TonemapperType, pInDlssEvalParams->InToneMapperType); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_MotionVectors3D, pInDlssEvalParams->pInMotionVectors3D); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_IsParticleMask, pInDlssEvalParams->pInIsParticleMask); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_AnimatedTextureMask, pInDlssEvalParams->pInAnimatedTextureMask); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_DepthHighRes, pInDlssEvalParams->pInDepthHighRes); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Position_ViewSpace, pInDlssEvalParams->pInPositionViewSpace); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, pInDlssEvalParams->InFrameTimeDeltaInMsec); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_RayTracingHitDistance, pInDlssEvalParams->pInRayTracingHitDistance); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_MotionVectorsReflection, pInDlssEvalParams->pInMotionVectorsReflections); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_X, pInDlssEvalParams->InColorSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_Y, pInDlssEvalParams->InColorSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_X, pInDlssEvalParams->InDepthSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_Y, pInDlssEvalParams->InDepthSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_X, pInDlssEvalParams->InMVSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_Y, pInDlssEvalParams->InMVSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_X, pInDlssEvalParams->InTranslucencySubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_Y, pInDlssEvalParams->InTranslucencySubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_X, pInDlssEvalParams->InBiasCurrentColorSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_Y, pInDlssEvalParams->InBiasCurrentColorSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_X, pInDlssEvalParams->InOutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_Y, pInDlssEvalParams->InOutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width , pInDlssEvalParams->InRenderSubrectDimensions.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height, pInDlssEvalParams->InRenderSubrectDimensions.Height); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_DLSS_Pre_Exposure, pInDlssEvalParams->InPreExposure == 0.0f ? 1.0f : pInDlssEvalParams->InPreExposure); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_DLSS_Exposure_Scale, pInDlssEvalParams->InExposureScale == 0.0f ? 1.0f : pInDlssEvalParams->InExposureScale); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_X_Axis, pInDlssEvalParams->InIndicatorInvertXAxis); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_Y_Axis, pInDlssEvalParams->InIndicatorInvertYAxis); + + return NVSDK_NGX_D3D12_EvaluateFeature_C(pInCmdList, pInHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_D3D12_CREATE_DLISP_EXT( + ID3D12GraphicsCommandList *InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pDlispCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pDlispCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pDlispCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pDlispCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pDlispCreateParams->InTargetHeight); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_PerfQualityValue, pDlispCreateParams->InPerfQualityValue); + + return NVSDK_NGX_D3D12_CreateFeature(InCmdList, NVSDK_NGX_Feature_ImageSignalProcessing, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D12_EVALUATE_DLISP_EXT( + ID3D12GraphicsCommandList *pInCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D12_DLISP_Eval_Params *pDlispEvalParams) +{ + if (pDlispEvalParams->Feature.InSharpness < 0.0f || pDlispEvalParams->Feature.InSharpness > 1.0f || pDlispEvalParams->InDenoise < 0.0f || pDlispEvalParams->InDenoise > 1.0f) + { + return NVSDK_NGX_Result_FAIL_InvalidParameter; + } + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Color, pDlispEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Output, pDlispEvalParams->Feature.pInOutput); + // Both sharpness and denoise in range [0.0f,1.0f] + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pDlispEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Denoise, pDlispEvalParams->InDenoise); + // If input is atlas - use RECT to upscale only the required area + if (pDlispEvalParams->InRectW) + { + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pDlispEvalParams->InRectX); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pDlispEvalParams->InRectY); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pDlispEvalParams->InRectW); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pDlispEvalParams->InRectH); + } + return NVSDK_NGX_D3D12_EvaluateFeature_C(pInCmdList, pInHandle, pInParams, NULL); +} + + +static inline NVSDK_NGX_Result NGX_D3D12_CREATE_DLRESOLVE_EXT( + ID3D12GraphicsCommandList *pInCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pDlresolveCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pDlresolveCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pDlresolveCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pDlresolveCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pDlresolveCreateParams->InTargetHeight); + + return NVSDK_NGX_D3D12_CreateFeature(pInCmdList, NVSDK_NGX_Feature_DeepResolve, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D12_EVALUATE_DLRESOLVE_EXT( + ID3D12GraphicsCommandList *pInCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D12_Feature_Eval_Params *pDlresolveEvalParams) +{ + // This call to NVSDK_NGX_Parameter_SetXXX() is equivalent to the Params->Set below functionally + // but to work around the lack of virtual functions and polymorphism in a C only project + // we introduced this new way to set params. + // The test should enforce that both paths work. + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Color, pDlresolveEvalParams->pInColor); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Output, pDlresolveEvalParams->pInOutput); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pDlresolveEvalParams->InSharpness); + + return NVSDK_NGX_D3D12_EvaluateFeature_C(pInCmdList, pInHandle, pInParams, NULL); +} + +#endif diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_truehdr.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_truehdr.h new file mode 100644 index 000000000..6843e4b0c --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_truehdr.h @@ -0,0 +1,170 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_HELPERS_TRUEHDR_H +#define NVSDK_NGX_HELPERS_TRUEHDR_H +#pragma once + +#include "nvsdk_ngx_helpers.h" +#include "nvsdk_ngx_defs_truehdr.h" + +typedef struct NVSDK_NGX_D3D11_TRUEHDR_Eval_Params +{ + ID3D11Resource* pInput; + ID3D11Resource* pOutput; + NVSDK_NGX_Coordinates InputSubrectTL; + NVSDK_NGX_Dimensions InputSubrectBR; + NVSDK_NGX_Coordinates OutputSubrectTL; + NVSDK_NGX_Dimensions OutputSubrectBR; + unsigned int Contrast; + unsigned int Saturation; + unsigned int MiddleGray; + unsigned int MaxLuminance; +} NVSDK_NGX_D3D11_TRUEHDR_Eval_Params; + +typedef struct NVSDK_NGX_D3D12_TRUEHDR_Eval_Params +{ + ID3D12Resource* pInput; + ID3D12Resource* pOutput; + NVSDK_NGX_Coordinates InputSubrectTL; + NVSDK_NGX_Dimensions InputSubrectBR; + NVSDK_NGX_Coordinates OutputSubrectTL; + NVSDK_NGX_Dimensions OutputSubrectBR; + unsigned int Contrast; + unsigned int Saturation; + unsigned int MiddleGray; + unsigned int MaxLuminance; +} NVSDK_NGX_D3D12_TRUEHDR_Eval_Params; + +typedef struct NVSDK_NGX_CUDA_TRUEHDR_Create_Params +{ + NVSDK_NGX_Feature_Create_Params Feature; + void* InCUContext; + void* InCUStream; +} NVSDK_NGX_CUDA_TRUEHDR_Create_Params; + +typedef struct NVSDK_NGX_CUDA_TRUEHDR_Eval_Params +{ + void* pInput; + void* pOutput; + NVSDK_NGX_Coordinates InputSubrectTL; + NVSDK_NGX_Dimensions InputSubrectBR; + NVSDK_NGX_Coordinates OutputSubrectTL; + NVSDK_NGX_Dimensions OutputSubrectBR; + unsigned int Contrast; + unsigned int Saturation; + unsigned int MiddleGray; + unsigned int MaxLuminance; +} NVSDK_NGX_CUDA_TRUEHDR_Eval_Params; + +static inline NVSDK_NGX_Result NGX_D3D11_CREATE_TRUEHDR_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pTrueHDRCreateParams) +{ + return NVSDK_NGX_D3D11_CreateFeature(pInCtx, NVSDK_NGX_Feature_TrueHDR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D12_CREATE_TRUEHDR_EXT( + ID3D12GraphicsCommandList* InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle** ppOutHandle, + NVSDK_NGX_Parameter* pInParams, + NVSDK_NGX_Feature_Create_Params* pTrueHDRCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + return NVSDK_NGX_D3D12_CreateFeature(InCmdList, NVSDK_NGX_Feature_TrueHDR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_CUDA_CREATE_TRUEHDR( + NVSDK_NGX_Handle** ppOutHandle, + NVSDK_NGX_Parameter* pInParams, + NVSDK_NGX_CUDA_TRUEHDR_Create_Params* pTrueHDRCreateParams) +{ + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input1, pTrueHDRCreateParams->InCUContext); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input2, pTrueHDRCreateParams->InCUStream); + return NVSDK_NGX_CUDA_CreateFeature(NVSDK_NGX_Feature_TrueHDR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D11_EVALUATE_TRUEHDR_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D11_TRUEHDR_Eval_Params *pTrueHDREvalParams) +{ + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Input1, pTrueHDREvalParams->pInput); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Output, pTrueHDREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InLeft, pTrueHDREvalParams->InputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InTop, pTrueHDREvalParams->InputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InRight, pTrueHDREvalParams->InputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InBottom, pTrueHDREvalParams->InputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutLeft, pTrueHDREvalParams->OutputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutTop, pTrueHDREvalParams->OutputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutRight, pTrueHDREvalParams->OutputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutBottom, pTrueHDREvalParams->OutputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Contrast, pTrueHDREvalParams->Contrast); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Saturation, pTrueHDREvalParams->Saturation); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MiddleGray, pTrueHDREvalParams->MiddleGray); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MaxLuminance, pTrueHDREvalParams->MaxLuminance); + return NVSDK_NGX_D3D11_EvaluateFeature_C(pInCtx, pInHandle, pInParams, NULL); +} + + +static inline NVSDK_NGX_Result NGX_D3D12_EVALUATE_TRUEHDR_EXT( + ID3D12GraphicsCommandList *pInCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D12_TRUEHDR_Eval_Params *pTrueHDREvalParams) +{ + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Input1, pTrueHDREvalParams->pInput); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Output, pTrueHDREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InLeft, pTrueHDREvalParams->InputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InTop, pTrueHDREvalParams->InputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InRight, pTrueHDREvalParams->InputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InBottom, pTrueHDREvalParams->InputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutLeft, pTrueHDREvalParams->OutputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutTop, pTrueHDREvalParams->OutputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutRight, pTrueHDREvalParams->OutputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutBottom, pTrueHDREvalParams->OutputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Contrast, pTrueHDREvalParams->Contrast); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Saturation, pTrueHDREvalParams->Saturation); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MiddleGray, pTrueHDREvalParams->MiddleGray); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MaxLuminance, pTrueHDREvalParams->MaxLuminance); + return NVSDK_NGX_D3D12_EvaluateFeature_C(pInCmdList, pInHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_CUDA_EVALUATE_TRUEHDR( + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_CUDA_TRUEHDR_Eval_Params *pTrueHDREvalParams) +{ + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input1, pTrueHDREvalParams->pInput); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pTrueHDREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InLeft, pTrueHDREvalParams->InputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InTop, pTrueHDREvalParams->InputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InRight, pTrueHDREvalParams->InputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InBottom, pTrueHDREvalParams->InputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutLeft, pTrueHDREvalParams->OutputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutTop, pTrueHDREvalParams->OutputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutRight, pTrueHDREvalParams->OutputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutBottom, pTrueHDREvalParams->OutputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Contrast, pTrueHDREvalParams->Contrast); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Saturation, pTrueHDREvalParams->Saturation); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MiddleGray, pTrueHDREvalParams->MiddleGray); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MaxLuminance, pTrueHDREvalParams->MaxLuminance); + return NVSDK_NGX_CUDA_EvaluateFeature_C(pInHandle, pInParams, NULL); +} + +#endif // NVSDK_NGX_HELPERS_TRUEHDR_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_truehdr_vk.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_truehdr_vk.h new file mode 100644 index 000000000..b4a6b4a43 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_truehdr_vk.h @@ -0,0 +1,82 @@ +#pragma once +/* +* Copyright (c) 2021 NVIDIA CORPORATION. All rights reserved. +* +* NVIDIA Corporation and its licensors retain all intellectual property and proprietary +* rights in and to this software, related documentation and any modifications thereto. +* Any use, reproduction, disclosure or distribution of this software and related +* documentation without an express license agreement from NVIDIA Corporation is strictly +* prohibited. +* +* TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THIS SOFTWARE IS PROVIDED *AS IS* +* AND NVIDIA AND ITS SUPPLIERS DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, +* INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +* PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS BE LIABLE FOR ANY +* SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER (INCLUDING, WITHOUT +* LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF +* BUSINESS INFORMATION, OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR +* INABILITY TO USE THIS SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY OF +* SUCH DAMAGES. +*/ + + +#ifndef NVSDK_NGX_TRUEHDR_VK_H +#define NVSDK_NGX_TRUEHDR_VK_H + +#include "nvsdk_ngx_defs_truehdr.h" +#include "nvsdk_ngx_helpers_vk.h" + +typedef struct NVSDK_NGX_VK_TRUEHDR_Eval_Params +{ + NVSDK_NGX_Resource_VK* pInput; + NVSDK_NGX_Resource_VK* pOutput; + NVSDK_NGX_Coordinates InputSubrectTL; + NVSDK_NGX_Dimensions InputSubrectBR; + NVSDK_NGX_Coordinates OutputSubrectTL; + NVSDK_NGX_Dimensions OutputSubrectBR; + unsigned int Contrast; + unsigned int Saturation; + unsigned int MiddleGray; + unsigned int MaxLuminance; +} NVSDK_NGX_VK_TRUEHDR_Eval_Params; + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_TRUEHDR_EXT1( + VkDevice InDevice, + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pTrueHDRCreateParams) +{ + + if (InDevice) return NVSDK_NGX_VULKAN_CreateFeature1(InDevice, InCmdList, NVSDK_NGX_Feature_TrueHDR, pInParams, ppOutHandle); + else return NVSDK_NGX_VULKAN_CreateFeature(InCmdList, NVSDK_NGX_Feature_TrueHDR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_EVALUATE_TRUEHDR_EXT1( + VkCommandBuffer InCmdList, + NVSDK_NGX_Handle* pInHandle, + NVSDK_NGX_Parameter* pInParams, + NVSDK_NGX_VK_TRUEHDR_Eval_Params* pTrueHDREvalParams) +{ + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input1, pTrueHDREvalParams->pInput); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pTrueHDREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InLeft, pTrueHDREvalParams->InputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InTop, pTrueHDREvalParams->InputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InRight, pTrueHDREvalParams->InputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_InBottom, pTrueHDREvalParams->InputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutLeft, pTrueHDREvalParams->OutputSubrectTL.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutTop, pTrueHDREvalParams->OutputSubrectTL.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutRight, pTrueHDREvalParams->OutputSubrectBR.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_OutBottom, pTrueHDREvalParams->OutputSubrectBR.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Contrast, pTrueHDREvalParams->Contrast); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_Saturation, pTrueHDREvalParams->Saturation); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MiddleGray, pTrueHDREvalParams->MiddleGray); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TrueHDR_MaxLuminance, pTrueHDREvalParams->MaxLuminance); + + return NVSDK_NGX_VULKAN_EvaluateFeature_C(InCmdList, pInHandle, pInParams, NULL); +} + + +#endif // NVSDK_NGX_TRUEHDR_VK_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vk.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vk.h new file mode 100644 index 000000000..d64bd8373 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vk.h @@ -0,0 +1,310 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2019-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_HELPERS_VK_H +#define NVSDK_NGX_HELPERS_VK_H +#pragma once + +#include "nvsdk_ngx_vk.h" + +#define NVSDK_NGX_ENSURE_VK_IMAGEVIEW(InResource) if ((InResource) && (InResource)->Type != NVSDK_NGX_RESOURCE_VK_TYPE_VK_IMAGEVIEW) { return NVSDK_NGX_Result_FAIL_InvalidParameter; } + +static inline NVSDK_NGX_Resource_VK NVSDK_NGX_Create_ImageView_Resource_VK(VkImageView imageView, VkImage image, VkImageSubresourceRange subresourceRange, VkFormat format, unsigned int width, unsigned int height, bool readWrite) +{ + NVSDK_NGX_Resource_VK resourceVK = {}; + resourceVK.Type = NVSDK_NGX_RESOURCE_VK_TYPE_VK_IMAGEVIEW; + resourceVK.Resource.ImageViewInfo.ImageView = imageView; + resourceVK.Resource.ImageViewInfo.Image = image; + resourceVK.Resource.ImageViewInfo.SubresourceRange = subresourceRange; + resourceVK.Resource.ImageViewInfo.Height = height; + resourceVK.Resource.ImageViewInfo.Width = width; + resourceVK.Resource.ImageViewInfo.Format = format; + resourceVK.ReadWrite = readWrite; + return resourceVK; +} + +static inline NVSDK_NGX_Resource_VK NVSDK_NGX_Create_Buffer_Resource_VK(VkBuffer buffer, unsigned int sizeInBytes, bool readWrite) +{ + NVSDK_NGX_Resource_VK resourceVK = {}; + resourceVK.Type = NVSDK_NGX_RESOURCE_VK_TYPE_VK_BUFFER; + resourceVK.Resource.BufferInfo.Buffer = buffer; + resourceVK.Resource.BufferInfo.SizeInBytes = sizeInBytes; + resourceVK.ReadWrite = readWrite; + return resourceVK; +} + +typedef struct NVSDK_NGX_VK_Feature_Eval_Params +{ + NVSDK_NGX_Resource_VK *pInColor; + NVSDK_NGX_Resource_VK *pInOutput; + /*** OPTIONAL for DLSS ***/ + float InSharpness; +} NVSDK_NGX_VK_Feature_Eval_Params; + +typedef struct NVSDK_NGX_VK_GBuffer +{ + NVSDK_NGX_Resource_VK *pInAttrib[NVSDK_NGX_GBUFFERTYPE_NUM]; +} NVSDK_NGX_VK_GBuffer; + +typedef struct NVSDK_NGX_Coordinates_VK +{ + unsigned int X; + unsigned int Y; +} NVSDK_NGX_Coordinates_VK; + +typedef struct NVSDK_NGX_VK_DLSS_Eval_Params +{ + NVSDK_NGX_VK_Feature_Eval_Params Feature; + NVSDK_NGX_Resource_VK * pInDepth; + NVSDK_NGX_Resource_VK * pInMotionVectors; + float InJitterOffsetX; /* Jitter offset must be in input/render pixel space */ + float InJitterOffsetY; + NVSDK_NGX_Dimensions InRenderSubrectDimensions; + /*** OPTIONAL - leave to 0/0.0f if unused ***/ + int InReset; /* Set to 1 when scene changes completely (new level etc) */ + float InMVScaleX; /* If MVs need custom scaling to convert to pixel space */ + float InMVScaleY; + NVSDK_NGX_Resource_VK * pInTransparencyMask; /* Unused/Reserved for future use */ + NVSDK_NGX_Resource_VK * pInExposureTexture; + NVSDK_NGX_Resource_VK * pInBiasCurrentColorMask; + NVSDK_NGX_Coordinates InColorSubrectBase; + NVSDK_NGX_Coordinates InDepthSubrectBase; + NVSDK_NGX_Coordinates InMVSubrectBase; + NVSDK_NGX_Coordinates InTranslucencySubrectBase; + NVSDK_NGX_Coordinates InBiasCurrentColorSubrectBase; + NVSDK_NGX_Coordinates InOutputSubrectBase; + float InPreExposure; + float InExposureScale; + int InIndicatorInvertXAxis; + int InIndicatorInvertYAxis; + /*** OPTIONAL - only for research purposes ***/ + NVSDK_NGX_VK_GBuffer GBufferSurface; + NVSDK_NGX_ToneMapperType InToneMapperType; + NVSDK_NGX_Resource_VK * pInMotionVectors3D; + NVSDK_NGX_Resource_VK * pInIsParticleMask; /* to identify which pixels contains particles, essentially that are not drawn as part of base pass */ + NVSDK_NGX_Resource_VK * pInAnimatedTextureMask; /* a binary mask covering pixels occupied by animated textures */ + NVSDK_NGX_Resource_VK * pInDepthHighRes; + NVSDK_NGX_Resource_VK * pInPositionViewSpace; + float InFrameTimeDeltaInMsec; /* helps in determining the amount to denoise or anti-alias based on the speed of the object from motion vector magnitudes and fps as determined by this delta */ + NVSDK_NGX_Resource_VK * pInRayTracingHitDistance; /* for each effect - approximation to the amount of noise in a ray-traced color */ + NVSDK_NGX_Resource_VK * pInMotionVectorsReflections; /* motion vectors of reflected objects like for mirrored surfaces */ +} NVSDK_NGX_VK_DLSS_Eval_Params; + +typedef struct NVSDK_NGX_VK_DLISP_Eval_Params +{ + NVSDK_NGX_VK_Feature_Eval_Params Feature; + /*** OPTIONAL - leave to 0/0.0f if unused ***/ + unsigned int InRectX; + unsigned int InRectY; + unsigned int InRectW; + unsigned int InRectH; + float InDenoise; +} NVSDK_NGX_VK_DLISP_Eval_Params; + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_DLSS_EXT1( + VkDevice InDevice, + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_DLSS_Create_Params *pInDlssCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pInDlssCreateParams->Feature.InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pInDlssCreateParams->Feature.InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pInDlssCreateParams->Feature.InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pInDlssCreateParams->Feature.InTargetHeight); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_PerfQualityValue, pInDlssCreateParams->Feature.InPerfQualityValue); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Feature_Create_Flags, pInDlssCreateParams->InFeatureCreateFlags); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Enable_Output_Subrects, pInDlssCreateParams->InEnableOutputSubrects ? 1 : 0); + + if (InDevice) return NVSDK_NGX_VULKAN_CreateFeature1(InDevice, InCmdList, NVSDK_NGX_Feature_SuperSampling, pInParams, ppOutHandle); + else return NVSDK_NGX_VULKAN_CreateFeature(InCmdList, NVSDK_NGX_Feature_SuperSampling, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_DLSS_EXT( + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_DLSS_Create_Params *pInDlssCreateParams) +{ + return NGX_VULKAN_CREATE_DLSS_EXT1(NULL, InCmdList, InCreationNodeMask, InVisibilityNodeMask, ppOutHandle, pInParams, pInDlssCreateParams); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_EVALUATE_DLSS_EXT( + VkCommandBuffer InCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_VK_DLSS_Eval_Params *pInDlssEvalParams) +{ + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->Feature.pInColor); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInMotionVectors); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->Feature.pInOutput); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInDepth); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInTransparencyMask); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInExposureTexture); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInBiasCurrentColorMask); + for (size_t i = 0; i <= 15; i++) + { + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->GBufferSurface.pInAttrib[i]); + } + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInMotionVectors3D); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInIsParticleMask); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInAnimatedTextureMask); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInDepthHighRes); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInPositionViewSpace); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInRayTracingHitDistance); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlssEvalParams->pInMotionVectorsReflections); + + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Color, pInDlssEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pInDlssEvalParams->Feature.pInOutput); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Depth, pInDlssEvalParams->pInDepth); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_MotionVectors, pInDlssEvalParams->pInMotionVectors); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Jitter_Offset_X, pInDlssEvalParams->InJitterOffsetX); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Jitter_Offset_Y, pInDlssEvalParams->InJitterOffsetY); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pInDlssEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_Reset, pInDlssEvalParams->InReset); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_MV_Scale_X, pInDlssEvalParams->InMVScaleX == 0.0f ? 1.0f : pInDlssEvalParams->InMVScaleX); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_MV_Scale_Y, pInDlssEvalParams->InMVScaleY == 0.0f ? 1.0f : pInDlssEvalParams->InMVScaleY); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_TransparencyMask, pInDlssEvalParams->pInTransparencyMask); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_ExposureTexture, pInDlssEvalParams->pInExposureTexture); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_Mask, pInDlssEvalParams->pInBiasCurrentColorMask); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Albedo, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_ALBEDO]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Roughness, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_ROUGHNESS]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Metallic, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_METALLIC]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Specular, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SPECULAR]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Subsurface, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SUBSURFACE]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Normals, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_NORMALS]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_ShadingModelId, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_SHADINGMODELID]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_MaterialId, pInDlssEvalParams->GBufferSurface.pInAttrib[NVSDK_NGX_GBUFFER_MATERIALID]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_8, pInDlssEvalParams->GBufferSurface.pInAttrib[8]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_9, pInDlssEvalParams->GBufferSurface.pInAttrib[9]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_10, pInDlssEvalParams->GBufferSurface.pInAttrib[10]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_11, pInDlssEvalParams->GBufferSurface.pInAttrib[11]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_12, pInDlssEvalParams->GBufferSurface.pInAttrib[12]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_13, pInDlssEvalParams->GBufferSurface.pInAttrib[13]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_14, pInDlssEvalParams->GBufferSurface.pInAttrib[14]); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_GBuffer_Atrrib_15, pInDlssEvalParams->GBufferSurface.pInAttrib[15]); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_TonemapperType, pInDlssEvalParams->InToneMapperType); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_MotionVectors3D, pInDlssEvalParams->pInMotionVectors3D); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_IsParticleMask, pInDlssEvalParams->pInIsParticleMask); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_AnimatedTextureMask, pInDlssEvalParams->pInAnimatedTextureMask); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_DepthHighRes, pInDlssEvalParams->pInDepthHighRes); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Position_ViewSpace, pInDlssEvalParams->pInPositionViewSpace); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_FrameTimeDeltaInMsec, pInDlssEvalParams->InFrameTimeDeltaInMsec); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_RayTracingHitDistance, pInDlssEvalParams->pInRayTracingHitDistance); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_MotionVectorsReflection, pInDlssEvalParams->pInMotionVectorsReflections); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_X, pInDlssEvalParams->InColorSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Color_Subrect_Base_Y, pInDlssEvalParams->InColorSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_X, pInDlssEvalParams->InDepthSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Depth_Subrect_Base_Y, pInDlssEvalParams->InDepthSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_X, pInDlssEvalParams->InMVSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_MV_SubrectBase_Y, pInDlssEvalParams->InMVSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_X, pInDlssEvalParams->InTranslucencySubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Translucency_SubrectBase_Y, pInDlssEvalParams->InTranslucencySubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_X, pInDlssEvalParams->InBiasCurrentColorSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Input_Bias_Current_Color_SubrectBase_Y, pInDlssEvalParams->InBiasCurrentColorSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_X, pInDlssEvalParams->InOutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Output_Subrect_Base_Y, pInDlssEvalParams->InOutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Width , pInDlssEvalParams->InRenderSubrectDimensions.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_DLSS_Render_Subrect_Dimensions_Height, pInDlssEvalParams->InRenderSubrectDimensions.Height); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_DLSS_Pre_Exposure, pInDlssEvalParams->InPreExposure == 0.0f ? 1.0f : pInDlssEvalParams->InPreExposure); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_DLSS_Exposure_Scale, pInDlssEvalParams->InExposureScale == 0.0f ? 1.0f : pInDlssEvalParams->InExposureScale); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_X_Axis, pInDlssEvalParams->InIndicatorInvertXAxis); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_DLSS_Indicator_Invert_Y_Axis, pInDlssEvalParams->InIndicatorInvertYAxis); + + return NVSDK_NGX_VULKAN_EvaluateFeature_C(InCmdList, pInHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_DLISP_EXT( + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pInDlispCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pInDlispCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pInDlispCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pInDlispCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pInDlispCreateParams->InTargetHeight); + NVSDK_NGX_Parameter_SetI(pInParams, NVSDK_NGX_Parameter_PerfQualityValue, pInDlispCreateParams->InPerfQualityValue); + + return NVSDK_NGX_VULKAN_CreateFeature(InCmdList, NVSDK_NGX_Feature_ImageSignalProcessing, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_EVALUATE_DLISP_EXT( + VkCommandBuffer InCmdList, + NVSDK_NGX_Handle *InHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_VK_DLISP_Eval_Params *pInDlispEvalParams) +{ + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlispEvalParams->Feature.pInColor); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlispEvalParams->Feature.pInOutput); + + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Color, pInDlispEvalParams->Feature.pInColor); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pInDlispEvalParams->Feature.pInOutput); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pInDlispEvalParams->Feature.InSharpness); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Denoise, pInDlispEvalParams->InDenoise); + // If input is atlas - use RECT to upscale only the required area + if (pInDlispEvalParams->InRectW) + { + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pInDlispEvalParams->InRectX); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pInDlispEvalParams->InRectY); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pInDlispEvalParams->InRectW); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pInDlispEvalParams->InRectH); + } + + return NVSDK_NGX_VULKAN_EvaluateFeature_C(InCmdList, InHandle, pInParams, NULL); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_DLRESOLVE_EXT( + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pInDlresolveCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Width, pInDlresolveCreateParams->InWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Height, pInDlresolveCreateParams->InHeight); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutWidth, pInDlresolveCreateParams->InTargetWidth); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutHeight, pInDlresolveCreateParams->InTargetHeight); + + return NVSDK_NGX_VULKAN_CreateFeature(InCmdList, NVSDK_NGX_Feature_DeepResolve, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_EVALUATE_DLRESOLVE_EXT( + VkCommandBuffer InCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_VK_Feature_Eval_Params *pInDlresolveEvalParams) +{ + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlresolveEvalParams->pInColor); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInDlresolveEvalParams->pInOutput); + + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Color, pInDlresolveEvalParams->pInColor); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pInDlresolveEvalParams->pInOutput); + NVSDK_NGX_Parameter_SetF(pInParams, NVSDK_NGX_Parameter_Sharpness, pInDlresolveEvalParams->InSharpness); + + return NVSDK_NGX_VULKAN_EvaluateFeature_C(InCmdList, pInHandle, pInParams, NULL); +} + +#endif // NVSDK_NGX_HELPERS_VK_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vsr.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vsr.h new file mode 100644 index 000000000..409fb08d9 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vsr.h @@ -0,0 +1,151 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_HELPERS_VSR_H +#define NVSDK_NGX_HELPERS_VSR_H +#pragma once + +#include "nvsdk_ngx_defs_vsr.h" +#include "nvsdk_ngx_helpers.h" + +typedef struct NVSDK_NGX_D3D11_VSR_Eval_Params +{ + ID3D11Resource* pInput; + ID3D11Resource* pOutput; + NVSDK_NGX_Coordinates InputSubrectBase; + NVSDK_NGX_Dimensions InputSubrectSize; + NVSDK_NGX_Coordinates OutputSubrectBase; + NVSDK_NGX_Dimensions OutputSubrectSize; + NVSDK_NGX_VSR_QualityLevel QualityLevel; +} NVSDK_NGX_D3D11_VSR_Eval_Params; + +static inline NVSDK_NGX_Result NGX_D3D11_CREATE_VSR_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pInVSRCreateParams) +{ + return NVSDK_NGX_D3D11_CreateFeature(pInCtx, NVSDK_NGX_Feature_VSR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_D3D11_EVALUATE_VSR_EXT( + ID3D11DeviceContext *pInCtx, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D11_VSR_Eval_Params *pInVSREvalParams) +{ + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Input1, pInVSREvalParams->pInput); + NVSDK_NGX_Parameter_SetD3d11Resource(pInParams, NVSDK_NGX_Parameter_Output, pInVSREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pInVSREvalParams->InputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pInVSREvalParams->InputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pInVSREvalParams->InputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pInVSREvalParams->InputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_X, pInVSREvalParams->OutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_Y, pInVSREvalParams->OutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_W, pInVSREvalParams->OutputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_H, pInVSREvalParams->OutputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VSR_QualityLevel, pInVSREvalParams->QualityLevel); + return NVSDK_NGX_D3D11_EvaluateFeature_C(pInCtx, pInHandle, pInParams, NULL); +} + +typedef struct NVSDK_NGX_D3D12_VSR_Eval_Params +{ + ID3D12Resource* pInput; + ID3D12Resource* pOutput; + NVSDK_NGX_Coordinates InputSubrectBase; + NVSDK_NGX_Dimensions InputSubrectSize; + NVSDK_NGX_Coordinates OutputSubrectBase; + NVSDK_NGX_Dimensions OutputSubrectSize; + NVSDK_NGX_VSR_QualityLevel QualityLevel; +} NVSDK_NGX_D3D12_VSR_Eval_Params; + +static inline NVSDK_NGX_Result NGX_D3D12_CREATE_VSR_EXT( + ID3D12GraphicsCommandList *InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pInVSRCreateParams) +{ + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_CreationNodeMask, InCreationNodeMask); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VisibilityNodeMask, InVisibilityNodeMask); + return NVSDK_NGX_D3D12_CreateFeature(InCmdList, NVSDK_NGX_Feature_VSR, pInParams, ppOutHandle); +} +static inline NVSDK_NGX_Result NGX_D3D12_EVALUATE_VSR_EXT( + ID3D12GraphicsCommandList *pInCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_D3D12_VSR_Eval_Params *pInVSREvalParams) +{ + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Input1, pInVSREvalParams->pInput); + NVSDK_NGX_Parameter_SetD3d12Resource(pInParams, NVSDK_NGX_Parameter_Output, pInVSREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pInVSREvalParams->InputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pInVSREvalParams->InputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pInVSREvalParams->InputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pInVSREvalParams->InputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_X, pInVSREvalParams->OutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_Y, pInVSREvalParams->OutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_W, pInVSREvalParams->OutputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_H, pInVSREvalParams->OutputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VSR_QualityLevel, pInVSREvalParams->QualityLevel); + return NVSDK_NGX_D3D12_EvaluateFeature_C(pInCmdList, pInHandle, pInParams, NULL); +} + + +typedef struct NVSDK_NGX_CUDA_VSR_Create_Params +{ + NVSDK_NGX_Feature_Create_Params Feature; + void* InCUContext; + void* InCUStream; +} NVSDK_NGX_CUDA_VSRCreate_Params; + +typedef struct NVSDK_NGX_CUDA_VSR_Eval_Params +{ + void* pInput; + void* pOutput; + NVSDK_NGX_Coordinates InputSubrectBase; + NVSDK_NGX_Dimensions InputSubrectSize; + NVSDK_NGX_Coordinates OutputSubrectBase; + NVSDK_NGX_Dimensions OutputSubrectSize; + NVSDK_NGX_VSR_QualityLevel QualityLevel; +} NVSDK_NGX_CUDA_VSR_Eval_Params; + +static inline NVSDK_NGX_Result NGX_CUDA_CREATE_VSR( + NVSDK_NGX_Handle** ppOutHandle, + NVSDK_NGX_Parameter* pInParams, + NVSDK_NGX_CUDA_VSRCreate_Params* pInVSRCreateParams) +{ + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input1, pInVSRCreateParams->InCUContext); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input2, pInVSRCreateParams->InCUStream); + return NVSDK_NGX_CUDA_CreateFeature(NVSDK_NGX_Feature_VSR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_CUDA_EVALUATE_VSR( + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_CUDA_VSR_Eval_Params *pInVSREvalParams) +{ + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input1, pInVSREvalParams->pInput); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pInVSREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pInVSREvalParams->InputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pInVSREvalParams->InputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pInVSREvalParams->InputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pInVSREvalParams->InputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_X, pInVSREvalParams->OutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_Y, pInVSREvalParams->OutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_W, pInVSREvalParams->OutputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_H, pInVSREvalParams->OutputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VSR_QualityLevel, pInVSREvalParams->QualityLevel); + return NVSDK_NGX_CUDA_EvaluateFeature_C(pInHandle, pInParams, NULL); +} + +#endif // NVSDK_NGX_HELPERS_VSR_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vsr_vk.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vsr_vk.h new file mode 100644 index 000000000..aa58b90bd --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_helpers_vsr_vk.h @@ -0,0 +1,79 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +#ifndef NVSDK_NGX_HELPERS_VSR_VK_H +#define NVSDK_NGX_HELPERS_VSR_VK_H +#pragma once + +#include "nvsdk_ngx_defs_vsr.h" +#include "nvsdk_ngx_helpers_vk.h" + +typedef struct NVSDK_NGX_VK_VSR_Eval_Params +{ + NVSDK_NGX_Resource_VK* pInput; + NVSDK_NGX_Resource_VK* pOutput; + NVSDK_NGX_Coordinates InputSubrectBase; + NVSDK_NGX_Dimensions InputSubrectSize; + NVSDK_NGX_Coordinates OutputSubrectBase; + NVSDK_NGX_Dimensions OutputSubrectSize; + NVSDK_NGX_VSR_QualityLevel QualityLevel; +} NVSDK_NGX_VK_VSR_Eval_Params; + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_VSR_EXT1( + VkDevice InDevice, + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pInVSRCreateParams) +{ + + if (InDevice) return NVSDK_NGX_VULKAN_CreateFeature1(InDevice, InCmdList, NVSDK_NGX_Feature_VSR, pInParams, ppOutHandle); + else return NVSDK_NGX_VULKAN_CreateFeature(InCmdList, NVSDK_NGX_Feature_VSR, pInParams, ppOutHandle); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_CREATE_VSR_EXT( + VkCommandBuffer InCmdList, + unsigned int InCreationNodeMask, + unsigned int InVisibilityNodeMask, + NVSDK_NGX_Handle **ppOutHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_Feature_Create_Params *pInVSRCreateParams) +{ + return NGX_VULKAN_CREATE_VSR_EXT1(NULL, InCmdList, InCreationNodeMask, InVisibilityNodeMask, ppOutHandle, pInParams, pInVSRCreateParams); +} + +static inline NVSDK_NGX_Result NGX_VULKAN_EVALUATE_VSR_EXT( + VkCommandBuffer InCmdList, + NVSDK_NGX_Handle *pInHandle, + NVSDK_NGX_Parameter *pInParams, + NVSDK_NGX_VK_VSR_Eval_Params *pInVSREvalParams) +{ + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInVSREvalParams->pInput); + NVSDK_NGX_ENSURE_VK_IMAGEVIEW(pInVSREvalParams->pOutput); + + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Input1, pInVSREvalParams->pInput); + NVSDK_NGX_Parameter_SetVoidPointer(pInParams, NVSDK_NGX_Parameter_Output, pInVSREvalParams->pOutput); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_X, pInVSREvalParams->InputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_Y, pInVSREvalParams->InputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_W, pInVSREvalParams->InputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_Rect_H, pInVSREvalParams->InputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_X, pInVSREvalParams->OutputSubrectBase.X); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_Y, pInVSREvalParams->OutputSubrectBase.Y); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_W, pInVSREvalParams->OutputSubrectSize.Width); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_OutRect_H, pInVSREvalParams->OutputSubrectSize.Height); + NVSDK_NGX_Parameter_SetUI(pInParams, NVSDK_NGX_Parameter_VSR_QualityLevel, pInVSREvalParams->QualityLevel); + return NVSDK_NGX_VULKAN_EvaluateFeature_C(InCmdList, pInHandle, pInParams, NULL); +} + +#endif // NVSDK_NGX_HELPERS_VSR_VK_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_params.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_params.h new file mode 100644 index 000000000..6774bce70 --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_params.h @@ -0,0 +1,116 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + + +#ifndef NVSDK_NGX_PARAMS_H +#define NVSDK_NGX_PARAMS_H + +#include "nvsdk_ngx_defs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct ID3D11Resource ID3D11Resource; +typedef struct ID3D12Resource ID3D12Resource; + +typedef struct NVSDK_NGX_Feature_Create_Params +{ + unsigned int InWidth; + unsigned int InHeight; + unsigned int InTargetWidth; + unsigned int InTargetHeight; + /*** OPTIONAL ***/ + NVSDK_NGX_PerfQuality_Value InPerfQualityValue; +} NVSDK_NGX_Feature_Create_Params; + +typedef struct NVSDK_NGX_DLSS_Create_Params +{ + NVSDK_NGX_Feature_Create_Params Feature; + /*** OPTIONAL ***/ + int InFeatureCreateFlags; + bool InEnableOutputSubrects; +} NVSDK_NGX_DLSS_Create_Params; + +typedef struct NVSDK_NGX_DLDenoise_Create_Params +{ + NVSDK_NGX_Feature_Create_Params Feature; + /*** OPTIONAL ***/ + int InFeatureCreateFlags; +} NVSDK_NGX_DLDenoise_Create_Params; + +#ifdef __cplusplus +typedef struct NVSDK_NGX_Parameter +{ + virtual void Set(const char * InName, unsigned long long InValue) = 0; + virtual void Set(const char * InName, float InValue) = 0; + virtual void Set(const char * InName, double InValue) = 0; + virtual void Set(const char * InName, unsigned int InValue) = 0; + virtual void Set(const char * InName, int InValue) = 0; + virtual void Set(const char * InName, ID3D11Resource *InValue) = 0; + virtual void Set(const char * InName, ID3D12Resource *InValue) = 0; + virtual void Set(const char * InName, void *InValue) = 0; + + virtual NVSDK_NGX_Result Get(const char * InName, unsigned long long *OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, float *OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, double *OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, unsigned int *OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, int *OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, ID3D11Resource **OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, ID3D12Resource **OutValue) const = 0; + virtual NVSDK_NGX_Result Get(const char * InName, void **OutValue) const = 0; + + virtual void Reset() = 0; +} NVSDK_NGX_Parameter; +#else +typedef struct NVSDK_NGX_Parameter NVSDK_NGX_Parameter; +#endif // _cplusplus + +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetULL)(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned long long InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetULL(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned long long InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetF)(NVSDK_NGX_Parameter *InParameter, const char * InName, float InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetF(NVSDK_NGX_Parameter *InParameter, const char * InName, float InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetD)(NVSDK_NGX_Parameter *InParameter, const char * InName, double InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetD(NVSDK_NGX_Parameter *InParameter, const char * InName, double InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetUI)(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned int InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetUI(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned int InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetI)(NVSDK_NGX_Parameter *InParameter, const char * InName, int InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetI(NVSDK_NGX_Parameter *InParameter, const char * InName, int InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetD3d11Resource)(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D11Resource *InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetD3d11Resource(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D11Resource *InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetD3d12Resource)(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D12Resource *InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetD3d12Resource(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D12Resource *InValue); +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_SetVoidPointer)(NVSDK_NGX_Parameter *InParameter, const char * InName, void *InValue); +NVSDK_NGX_API void NVSDK_CONV NVSDK_NGX_Parameter_SetVoidPointer(NVSDK_NGX_Parameter *InParameter, const char * InName, void *InValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetULL)(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned long long *OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetULL(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned long long *OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetF)(NVSDK_NGX_Parameter *InParameter, const char * InName, float *OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetF(NVSDK_NGX_Parameter *InParameter, const char * InName, float *OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetD)(NVSDK_NGX_Parameter *InParameter, const char * InName, double *OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetD(NVSDK_NGX_Parameter *InParameter, const char * InName, double *OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetUI)(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned int *OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetUI(NVSDK_NGX_Parameter *InParameter, const char * InName, unsigned int *OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetI)(NVSDK_NGX_Parameter *InParameter, const char * InName, int *OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetI(NVSDK_NGX_Parameter *InParameter, const char * InName, int *OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetD3d11Resource)(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D11Resource **OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetD3d11Resource(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D11Resource **OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetD3d12Resource)(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D12Resource **OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetD3d12Resource(NVSDK_NGX_Parameter *InParameter, const char * InName, ID3D12Resource **OutValue); +typedef NVSDK_NGX_Result (NVSDK_CONV *PFN_NVSDK_NGX_Parameter_GetVoidPointer)(NVSDK_NGX_Parameter *InParameter, const char * InName, void **OutValue); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_Parameter_GetVoidPointer(NVSDK_NGX_Parameter *InParameter, const char * InName, void **OutValue); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #define NVSDK_NGX_PARAMS_H diff --git a/third-party/RTX_Video_SDK/include/nvsdk_ngx_vk.h b/third-party/RTX_Video_SDK/include/nvsdk_ngx_vk.h new file mode 100644 index 000000000..3f682d02e --- /dev/null +++ b/third-party/RTX_Video_SDK/include/nvsdk_ngx_vk.h @@ -0,0 +1,553 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: LicenseRef-NvidiaProprietary + * + * NVIDIA CORPORATION, its affiliates and licensors retain all intellectual + * property and proprietary rights in and to this material, related + * documentation and any modifications thereto. Any use, reproduction, + * disclosure or distribution of this material and related documentation + * without an express license agreement from NVIDIA CORPORATION or + * its affiliates is strictly prohibited. + */ + +/* +* HOW TO USE: +* +* IMPORTANT: Methods in this library are NOT thread safe. It is up to the +* client to ensure that thread safety is enforced as needed. +* +* 1) Call NVSDK_CONV NVSDK_NGX_D3D11/D3D12/CUDA_Init and pass your app Id +* and other parameters. This will initialize SDK or return an error code +* if SDK cannot run on target machine. Depending on error user might +* need to update drivers. Please note that application Id is provided +* by NVIDIA so if you do not have one please contact us. +* +* 2) Call NVSDK_NGX_D3D11/D3D12/CUDA_GetParameters to obtain pointer to +* interface used to pass parameters to SDK. Interface instance is +* allocated and released by SDK so there is no need to do any memory +* management on client side. +* +* 3) Set key parameters for the feature you want to use. For example, +* width and height are required for all features and they can be +* set like this: +* Params->Set(NVSDK_NGX_Parameter_Width,MY_WIDTH); +* Params->Set(NVSDK_NGX_Parameter_Height,MY_HEIGHT); +* +* You can also provide hints like NVSDK_NGX_Parameter_Hint_HDR to tell +* SDK that it should expect HDR color space is needed. Please refer to +* samples since different features need different parameters and hints. +* +* 4) Call NVSDK_NGX_D3D11/D3D12/CUDA_GetScratchBufferSize to obtain size of +* the scratch buffer needed by specific feature. This D3D or CUDA buffer +* should be allocated by client and passed as: +* Params->Set(NVSDK_NGX_Parameter_Scratch,MY_SCRATCH_POINTER) +* Params->Set(NVSDK_NGX_Parameter_Scratch_SizeInBytes,MY_SCRATCH_SIZE_IN_BYTES) +* NOTE: Returned size can be 0 if feature does not use any scratch buffer. +* It is OK to use bigger buffer or reuse buffers across features as long +* as minimum size requirement is met. +* +* 5) Call NVSDK_NGX_D3D11/D3D12/CUDA_CreateFeature to create feature you need. +* On success SDK will return a handle which must be used in any successive +* calls to SDK which require feature handle. SDK will use all parameters +* and hints provided by client to generate feature. If feature with the same +* parameters already exists and error code will be returned. +* +* 6) Call NVSDK_NGX_D3D11/D3D12/CUDA_EvaluateFeature to invoke execution of +* specific feature. Before feature can be evaluated input parameters must +* be specified (like for example color/albedo buffer, motion vectors etc) +* +* 6) Call NVSDK_NGX_D3D11/D3D12/CUDA_ReleaseFeature when feature is no longer +* needed. After this call feature handle becomes invalid and cannot be used. +* +* 7) Call NVSDK_NGX_D3D11/D3D12/CUDA_Shutdown when SDK is no longer needed to +* release all resources. + +* Contact: ngxsupport@nvidia.com +*/ + + +#ifndef NVSDK_NGX_VK_H +#define NVSDK_NGX_VK_H + +#include "nvsdk_ngx_defs.h" +#include "nvsdk_ngx_params.h" +#ifndef __cplusplus +#include +#include +#endif + +#ifdef __cplusplus +extern "C" +{ +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_ImageViewInfo_VK [Vulkan only] +// Contains ImageView-specific metadata. +// ImageView: +// The VkImageView resource. +// +// Image: +// The VkImage associated to this VkImageView. +// +// SubresourceRange: +// The VkImageSubresourceRange associated to this VkImageView. +// +// Format: +// The format of the resource. +// +// Width: +// The width of the resource. +// +// Height: +// The height of the resource. +// +typedef struct NVSDK_NGX_ImageViewInfo_VK { + VkImageView ImageView; + VkImage Image; + VkImageSubresourceRange SubresourceRange; + VkFormat Format; + unsigned int Width; + unsigned int Height; +} NVSDK_NGX_ImageViewInfo_VK; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_BufferInfo_VK [Vulkan only] +// Contains Buffer-specific metadata. +// Buffer +// The VkBuffer resource. +// +// SizeInBytes: +// The size of the resource (in bytes). +// +typedef struct NVSDK_NGX_BufferInfo_VK { + VkBuffer Buffer; + unsigned int SizeInBytes; +} NVSDK_NGX_BufferInfo_VK; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Resource_VK [Vulkan only] +// +// ImageViewInfo: +// The VkImageView resource, and VkImageView-specific metadata. A NVSDK_NGX_Resource_VK can only have one of ImageViewInfo or BufferInfo. +// +// BufferInfo: +// The VkBuffer Resource, and VkBuffer-specific metadata. A NVSDK_NGX_Resource_VK can only have one of ImageViewInfo or BufferInfo. +// +// Type: +// Whether or this resource is a VkImageView or a VkBuffer. +// +// ReadWrite: +// True if the resource is available for read and write access. +// For VkBuffer resources: VkBufferUsageFlags includes VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT or VK_BUFFER_USAGE_STORAGE_BUFFER_BIT +// For VkImage resources: VkImageUsageFlags for associated VkImage includes VK_IMAGE_USAGE_STORAGE_BIT +// +typedef struct NVSDK_NGX_Resource_VK { + union { + NVSDK_NGX_ImageViewInfo_VK ImageViewInfo; + NVSDK_NGX_BufferInfo_VK BufferInfo; + } Resource; + NVSDK_NGX_Resource_VK_Type Type; + bool ReadWrite; +} NVSDK_NGX_Resource_VK; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// DEPRECATED, use NVSDK_NGX_VULKAN_GetFeatureInstanceExtensionRequirements() and NVSDK_NGX_VULKAN_GetFeatureRequirements() instead +// NVSDK_NGX_RequiredExtensions [Vulkan only] +// +// OutInstanceExtCount: +// Returns the number of instance extensions NGX requires +// +// OutInstanceExts: +// Returns a pointer to *OutInstanceExtCount strings of instance extensions +// +// OutDeviceExtCount: +// Returns the number of device extensions NGX requires +// +// OutDeviceExts: +// Returns a pointer to *OutDeviceExtCount strings of device extensions +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_RequiredExtensions(unsigned int *OutInstanceExtCount, const char ***OutInstanceExts, unsigned int *OutDeviceExtCount, const char ***OutDeviceExts); + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Init +// ------------------------------------- +// +// InApplicationId: +// Unique Id provided by NVIDIA +// +// InApplicationDataPath: +// Folder to store logs and other temporary files (write access required), +// Normally this would be a location in Documents or ProgramData. +// +// InInstance/InPD/InDevice: [vk only] +// Vulkan Instance, PhysicalDevice, and Device to use +// +// InGIPA/InGDPA: [vk only] +// Optional Vulkan function pointers to vkGetInstanceProcAddr and vkGetDeviceProcAddr +// +// DESCRIPTION: +// Initializes new SDK instance. +// +#ifdef __cplusplus +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice, PFN_vkGetInstanceProcAddr InGIPA = nullptr, PFN_vkGetDeviceProcAddr InGDPA = nullptr, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +#else +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_Init(unsigned long long InApplicationId, const wchar_t *InApplicationDataPath, VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice, PFN_vkGetInstanceProcAddr InGIPA, PFN_vkGetDeviceProcAddr InGDPA, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Init_with_ProjectID +// ------------------------------------- +// +// InParojectId: +// Unique Id provided by the rendering engine used +// +// InEngineType: +// Rendering engine used by the application / plugin. +// Use NVSDK_NGX_ENGINE_TYPE_CUSTOM if the specific engine type is not supported explicitly +// +// InEngineVersion: +// Version number of the rendering engine used by the application / plugin. +// +// InApplicationDataPath: +// Folder to store logs and other temporary files (write access required), +// Normally this would be a location in Documents or ProgramData. +// +// InInstance/InPD/InDevice: [vk only] +// Vulkan Instance, PhysicalDevice, and Device to use +// +// InGIPA/InGDPA: [vk only] +// Optional Vulkan function pointers to vkGetInstanceProcAddr and vkGetDeviceProcAddr +// +// InFeatureInfo: +// Contains information common to all features, presently only a list of all paths +// feature dlls can be located in, other than the default path - application directory. +// +// DESCRIPTION: +// Initializes new SDK instance. +// +#ifdef __cplusplus +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice, PFN_vkGetInstanceProcAddr InGIPA = nullptr, PFN_vkGetDeviceProcAddr InGDPA = nullptr, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo = nullptr, NVSDK_NGX_Version InSDKVersion = NVSDK_NGX_Version_API); +#else +NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_Init_with_ProjectID(const char *InProjectId, NVSDK_NGX_EngineType InEngineType, const char *InEngineVersion, const wchar_t *InApplicationDataPath, VkInstance InInstance, VkPhysicalDevice InPD, VkDevice InDevice, PFN_vkGetInstanceProcAddr InGIPA, PFN_vkGetDeviceProcAddr InGDPA, const NVSDK_NGX_FeatureCommonInfo *InFeatureInfo, NVSDK_NGX_Version InSDKVersion); +#endif + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Shutdown +// ------------------------------------- +// +// DESCRIPTION: +// Shuts down the current SDK instance and releases all resources. +// Shutdown1(Device) only affects specified device +// Shutdown1(nullptr) = Shutdown() and shuts down all devices +// +#ifdef NGX_ENABLE_DEPRECATED_SHUTDOWN +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_Shutdown(void); +#endif +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_Shutdown1(VkDevice InDevice); + +#ifdef NGX_ENABLE_DEPRECATED_GET_PARAMETERS +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetParameters +// ---------------------------------------------------------- +// +// OutParameters: +// Parameters interface used to set any parameter needed by the SDK +// +// DESCRIPTION: +// This interface allows simple parameter setup using named fields. +// For example one can set width by calling Set(NVSDK_NGX_Parameter_Denoiser_Width,100) or +// provide CUDA buffer pointer by calling Set(NVSDK_NGX_Parameter_Denoiser_Color,cudaBuffer) +// For more details please see sample code. Please note that allocated memory +// will be freed by NGX so free/delete operator should NOT be called. +// Parameter maps output by NVSDK_NGX_GetParameters are also pre-populated +// with NGX capabilities and available features. +// Unlike with NVSDK_NGX_AllocateParameters, parameter maps output by NVSDK_NGX_GetParameters +// have their lifetimes managed by NGX, and must not +// be destroyed by the app using NVSDK_NGX_DestroyParameters. +// NVSDK_NGX_GetParameters is deprecated and apps should move to using +// NVSDK_NGX_AllocateParameters and NVSDK_NGX_GetCapabilityParameters when possible. +// Nevertheless, due to the possibility that the user will be using an older driver version, +// NVSDK_NGX_GetParameters may still be used as a fallback if NVSDK_NGX_AllocateParameters +// or NVSDK_NGX_GetCapabilityParameters return NVSDK_NGX_Result_FAIL_OutOfDate. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_GetParameters(NVSDK_NGX_Parameter **OutParameters); +#endif // NGX_ENABLE_DEPRECATED_GET_PARAMETERS + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_AllocateParameters +// ---------------------------------------------------------- +// +// OutParameters: +// Parameters interface used to set any parameter needed by the SDK +// +// DESCRIPTION: +// This interface allows allocating a simple parameter setup using named fields, whose +// lifetime the app must manage. +// For example one can set width by calling Set(NVSDK_NGX_Parameter_Denoiser_Width,100) or +// provide CUDA buffer pointer by calling Set(NVSDK_NGX_Parameter_Denoiser_Color,cudaBuffer) +// For more details please see sample code. +// Parameter maps output by NVSDK_NGX_AllocateParameters must NOT be freed using +// the free/delete operator; to free a parameter map +// output by NVSDK_NGX_AllocateParameters, NVSDK_NGX_DestroyParameters should be used. +// Unlike with NVSDK_NGX_GetParameters, parameter maps allocated with NVSDK_NGX_AllocateParameters +// must be destroyed by the app using NVSDK_NGX_DestroyParameters. +// Also unlike with NVSDK_NGX_GetParameters, parameter maps output by NVSDK_NGX_AllocateParameters +// do not come pre-populated with NGX capabilities and available features. +// To create a new parameter map pre-populated with such information, NVSDK_NGX_GetCapabilityParameters +// should be used. +// This function may return NVSDK_NGX_Result_FAIL_OutOfDate if an older driver, which +// does not support this API call is being used. In such a case, NVSDK_NGX_GetParameters +// may be used as a fallback. +// This function may only be called after a successful call into NVSDK_NGX_Init. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_AllocateParameters(NVSDK_NGX_Parameter** OutParameters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetCapabilityParameters +// ---------------------------------------------------------- +// +// OutParameters: +// The parameters interface populated with NGX and feature capabilities +// +// DESCRIPTION: +// This interface allows the app to create a new parameter map +// pre-populated with NGX capabilities and available features. +// The output parameter map can also be used for any purpose +// parameter maps output by NVSDK_NGX_AllocateParameters can be used for +// but it is not recommended to use NVSDK_NGX_GetCapabilityParameters +// unless querying NGX capabilities and available features +// due to the overhead associated with pre-populating the parameter map. +// Parameter maps output by NVSDK_NGX_GetCapabilityParameters must NOT be freed using +// the free/delete operator; to free a parameter map +// output by NVSDK_NGX_GetCapabilityParameters, NVSDK_NGX_DestroyParameters should be used. +// Unlike with NVSDK_NGX_GetParameters, parameter maps allocated with NVSDK_NGX_GetCapabilityParameters +// must be destroyed by the app using NVSDK_NGX_DestroyParameters. +// This function may return NVSDK_NGX_Result_FAIL_OutOfDate if an older driver, which +// does not support this API call is being used. This function may only be called +// after a successful call into NVSDK_NGX_Init. +// If NVSDK_NGX_GetCapabilityParameters fails with NVSDK_NGX_Result_FAIL_OutOfDate, +// NVSDK_NGX_GetParameters may be used as a fallback, to get a parameter map pre-populated +// with NGX capabilities and available features. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_GetCapabilityParameters(NVSDK_NGX_Parameter** OutParameters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_DestroyParameters +// ---------------------------------------------------------- +// +// InParameters: +// The parameters interface to be destroyed +// +// DESCRIPTION: +// This interface allows the app to destroy the parameter map passed in. Once +// NVSDK_NGX_DestroyParameters is called on a parameter map, it +// must not be used again. +// NVSDK_NGX_DestroyParameters must not be called on any parameter map returned +// by NVSDK_NGX_GetParameters; NGX will manage the lifetime of those +// parameter maps. +// This function may return NVSDK_NGX_Result_FAIL_OutOfDate if an older driver, which +// does not support this API call is being used. This function may only be called +// after a successful call into NVSDK_NGX_Init. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_DestroyParameters(NVSDK_NGX_Parameter* InParameters); + +//////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetScratchBufferSize +// ---------------------------------------------------------- +// +// InFeatureId: +// AI feature in question +// +// InParameters: +// Parameters used by the feature to help estimate scratch buffer size +// +// OutSizeInBytes: +// Number of bytes needed for the scratch buffer for the specified feature. +// +// DESCRIPTION: +// SDK needs a buffer of a certain size provided by the client in +// order to initialize AI feature. Once feature is no longer +// needed buffer can be released. It is safe to reuse the same +// scratch buffer for different features as long as minimum size +// requirement is met for all features. Please note that some +// features might not need a scratch buffer so return size of 0 +// is completely valid. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_GetScratchBufferSize(NVSDK_NGX_Feature InFeatureId, const NVSDK_NGX_Parameter *InParameters, size_t *OutSizeInBytes); + +///////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_CreateFeature +// ------------------------------------- +// +// InCmdBuffer: +// Command buffer to use to execute GPU commands. Must be: +// - Open and recording + +// InFeatureID: +// AI feature to initialize +// +// InParameters: +// List of parameters +// +// OutHandle: +// Handle which uniquely identifies the feature. If feature with +// provided parameters already exists the "already exists" error code is returned. +// +// DESCRIPTION: +// Each feature needs to be created before it can be used. +// Refer to the sample code to find out which input parameters +// are needed to create specific feature. +// CreateFeature() creates feature on single existing Device +// CreateFeature1() creates feature on the specified Device +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_CreateFeature(VkCommandBuffer InCmdBuffer, NVSDK_NGX_Feature InFeatureID, NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_CreateFeature1(VkDevice InDevice, VkCommandBuffer InCmdList, NVSDK_NGX_Feature InFeatureID, NVSDK_NGX_Parameter *InParameters, NVSDK_NGX_Handle **OutHandle); + +///////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_Release +// ------------------------------------- +// +// InHandle: +// Handle to feature to be released +// +// DESCRIPTION: +// Releases feature with a given handle. +// Handles are not reference counted so +// after this call it is invalid to use provided handle. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_ReleaseFeature(NVSDK_NGX_Handle *InHandle); + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_GetFeatureRequirements +// ------------------------------------- +// Instance: +// VkInstance +// +// InPhysicalDevice: +// VkPhysicalDevice +// +// FeatureDiscoveryInfo: +// Contains information common to all NGX Features - required for Feature discovery, Initialization and Logging. +// +// DESCRIPTION: +// Utility function used to identify system requirements to support a given NGX Feature +// on a system given its display device subsytem adapter information that will be subsequently used for creating the graphics device. +// The output parameter OutSupported will be populated with requirements and are valid if and only if NVSDK_NGX_Result_Success is returned: +// OutSupported::FeatureSupported: bitfield of bit shifted values specified in NVSDK_NGX_Feature_Support_Result. 0 if Feature is Supported. +// OutSupported::MinHWArchitecture: Returned HW Architecture value corresponding to NV_GPU_ARCHITECTURE_ID values defined in NvAPI GPU Framework. +// OutSupported::MinOSVersion: Value corresponding to minimum OS version required for NGX Feature Support +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_GetFeatureRequirements(const VkInstance Instance, + const VkPhysicalDevice PhysicalDevice, + const NVSDK_NGX_FeatureDiscoveryInfo *FeatureDiscoveryInfo, + NVSDK_NGX_FeatureRequirement *OutSupported); + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// GetFeatureInstanceExtensionRequirements +// -------------------------------------------- +// +// FeatureDiscoveryInfo: +// Contains information common to all NGX Features - required for Feature discovery, Initialization and Logging. +// +// OutExtensionCount: +// A pointer to an integer related to the number of extension properties required or queried, as described below. +// +// OutExtensionProperties: +// Either NULL or a pointer to a pointer to an array of VkExtensionProperties structures. +// +// DESCRIPTION: +// Utility function used to identify Vulkan Instance Extensions required for NGX Feature support identified by its FeatureID. +// +// OutExtensionCount will be populated with the number of extensions +// required by the NGX Feature specified in FeatureID. +// OutExtensionProperties will be populated with a pointer to a +// OutExtensionCount sized array of VkExtensionProperties structures. +// +// The returned extension list is valid if NVSDK_NGX_Result_Success is returned. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_GetFeatureInstanceExtensionRequirements(const NVSDK_NGX_FeatureDiscoveryInfo *FeatureDiscoveryInfo, + uint32_t *OutExtensionCount, + VkExtensionProperties **OutExtensionProperties); + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// GetFeatureDeviceExtensionRequirements +// -------------------------------------- +// Instance: +// VkInstance +// +// InPhysicalDevice: +// VkPhysicalDevice +// +// FeatureDiscoveryInfo: +// Contains information common to all NGX Features - required for Feature discovery, Initialization and Logging. +// +// OutExtensionCount: +// A pointer to an integer related to the number of extension properties required or queried, as described below. +// +// OutExtensionProperties: +// Either NULL or a pointer to a pointer to an array of VkExtensionProperties structures. +// +// DESCRIPTION: +// Utility function used to identify Vulkan Device Extensions required for NGX Feature support identified by its FeatureID, +// VkInstance, and VkPhysicalDevice. +// +// OutExtensionCount will be populated with the number of extensions +// required by the NGX Feature specified in FeatureID. +// OutExtensionProperties will be populated with a pointer to a +// OutExtensionCount sized array of VkExtensionProperties structures. +// +// The returned extension list is valid if NVSDK_NGX_Result_Success is returned. +// +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_GetFeatureDeviceExtensionRequirements(VkInstance Instance, + VkPhysicalDevice PhysicalDevice, + const NVSDK_NGX_FeatureDiscoveryInfo *FeatureDiscoveryInfo, + uint32_t *OutExtensionCount, + VkExtensionProperties **OutExtensionProperties); + +///////////////////////////////////////////////////////////////////////// +// NVSDK_NGX_EvaluateFeature +// ------------------------------------- +// +// InCmdList:[d3d12 only] +// Command list to use to execute GPU commands. Must be: +// - Open and recording +// - With node mask including the device provided in NVSDK_NGX_D3D12_Init +// - Execute on non-copy command queue. +// InDevCtx: [d3d11 only] +// Device context to use to execute GPU commands +// +// InFeatureHandle: +// Handle representing feature to be evaluated +// +// InParameters: +// List of parameters required to evaluate feature +// +// InCallback: +// Optional callback for features which might take longer +// to execture. If specified SDK will call it with progress +// values in range 0.0f - 1.0f +// +// DESCRIPTION: +// Evaluates given feature using the provided parameters and +// pre-trained NN. Please note that for most features +// it can be benefitials to pass as many input buffers and parameters +// as possible (for example provide all render targets like color, albedo, normals, depth etc) +// + +#ifdef __cplusplus +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_ProgressCallback)(float InCurrentProgress, bool &OutShouldCancel); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_EvaluateFeature(VkCommandBuffer InCmdList, const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback InCallback = NULL); +#endif +typedef void (NVSDK_CONV *PFN_NVSDK_NGX_ProgressCallback_C)(float InCurrentProgress, bool *OutShouldCancel); +NVSDK_NGX_API NVSDK_NGX_Result NVSDK_CONV NVSDK_NGX_VULKAN_EvaluateFeature_C(VkCommandBuffer InCmdList, const NVSDK_NGX_Handle *InFeatureHandle, const NVSDK_NGX_Parameter *InParameters, PFN_NVSDK_NGX_ProgressCallback_C InCallback); + +// NGX return-code conversion-to-string utility only as a helper for debugging/logging - not for official use. +const wchar_t* NVSDK_CONV GetNGXResultAsString(NVSDK_NGX_Result InNGXResult); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // #define NVSDK_NGX_VK_H diff --git a/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_d.lib b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_d.lib new file mode 100644 index 000000000..704548ef3 Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_d.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_d_dbg.lib b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_d_dbg.lib new file mode 100644 index 000000000..e7e92eaa2 Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_d_dbg.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_s.lib b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_s.lib new file mode 100644 index 000000000..f68ef99dc Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_s.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_s_dbg.lib b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_s_dbg.lib new file mode 100644 index 000000000..edc9b7237 Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/arm64/nvsdk_ngx_s_dbg.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_d.lib b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_d.lib new file mode 100644 index 000000000..bd14e6094 Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_d.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_d_dbg.lib b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_d_dbg.lib new file mode 100644 index 000000000..2eefbcfc0 Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_d_dbg.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_s.lib b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_s.lib new file mode 100644 index 000000000..7c3f606be Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_s.lib differ diff --git a/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_s_dbg.lib b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_s_dbg.lib new file mode 100644 index 000000000..49a55a7ae Binary files /dev/null and b/third-party/RTX_Video_SDK/lib/Windows/x64/nvsdk_ngx_s_dbg.lib differ diff --git a/third-party/libvpl b/third-party/libvpl new file mode 160000 index 000000000..778a66d6c --- /dev/null +++ b/third-party/libvpl @@ -0,0 +1 @@ +Subproject commit 778a66d6c6537f08eabb91955dbbf1bce3812894 diff --git a/third-party/stb_image/stb_image.h b/third-party/stb_image/stb_image.h new file mode 100644 index 000000000..9eedabedc --- /dev/null +++ b/third-party/stb_image/stb_image.h @@ -0,0 +1,7988 @@ +/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb + no warranty implied; use at your own risk + + Do this: + #define STB_IMAGE_IMPLEMENTATION + before you include this file in *one* C or C++ file to create the implementation. + + // i.e. it should look like this: + #include ... + #include ... + #include ... + #define STB_IMAGE_IMPLEMENTATION + #include "stb_image.h" + + You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. + And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free + + + QUICK NOTES: + Primarily of interest to game developers and other people who can + avoid problematic images and only need the trivial interface + + JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) + PNG 1/2/4/8/16-bit-per-channel + + TGA (not sure what subset, if a subset) + BMP non-1bpp, non-RLE + PSD (composited view only, no extra channels, 8/16 bit-per-channel) + + GIF (*comp always reports as 4-channel) + HDR (radiance rgbE format) + PIC (Softimage PIC) + PNM (PPM and PGM binary only) + + Animated GIF still needs a proper API, but here's one way to do it: + http://gist.github.com/urraka/685d9a6340b26b830d49 + + - decode from memory or through FILE (define STBI_NO_STDIO to remove code) + - decode from arbitrary I/O callbacks + - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) + + Full documentation under "DOCUMENTATION" below. + + +LICENSE + + See end of file for license information. + +RECENT REVISION HISTORY: + + 2.30 (2024-05-31) avoid erroneous gcc warning + 2.29 (2023-05-xx) optimizations + 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff + 2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes + 2.26 (2020-07-13) many minor fixes + 2.25 (2020-02-02) fix warnings + 2.24 (2020-02-02) fix warnings; thread-local failure_reason and flip_vertically + 2.23 (2019-08-11) fix clang static analysis warning + 2.22 (2019-03-04) gif fixes, fix warnings + 2.21 (2019-02-25) fix typo in comment + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) bugfix, 1-bit BMP, 16-bitness query, fix warnings + 2.16 (2017-07-23) all functions have 16-bit variants; optimizations; bugfixes + 2.15 (2017-03-18) fix png-1,2,4; all Imagenet JPGs; no runtime SSE detection on GCC + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-12-04) experimental 16-bit API, only for PNG so far; fixes + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) 16-bit PNGS; enable SSE2 in non-gcc x64 + RGB-format JPEG; remove white matting in PSD; + allocate large structures on the stack; + correct channel count for PNG & BMP + 2.10 (2016-01-22) avoid warning introduced in 2.09 + 2.09 (2016-01-16) 16-bit TGA; comments in PNM files; STBI_REALLOC_SIZED + + See end of file for full revision history. + + + ============================ Contributors ========================= + + Image formats Extensions, features + Sean Barrett (jpeg, png, bmp) Jetro Lauha (stbi_info) + Nicolas Schulz (hdr, psd) Martin "SpartanJ" Golini (stbi_info) + Jonathan Dummer (tga) James "moose2000" Brown (iPhone PNG) + Jean-Marc Lienher (gif) Ben "Disch" Wenger (io callbacks) + Tom Seddon (pic) Omar Cornut (1/2/4-bit PNG) + Thatcher Ulrich (psd) Nicolas Guillemot (vertical flip) + Ken Miller (pgm, ppm) Richard Mitton (16-bit PSD) + github:urraka (animated gif) Junggon Kim (PNM comments) + Christopher Forseth (animated gif) Daniel Gibson (16-bit TGA) + socks-the-fox (16-bit PNG) + Jeremy Sawicki (handle all ImageNet JPGs) + Optimizations & bugfixes Mikhail Morozov (1-bit BMP) + Fabian "ryg" Giesen Anael Seghezzi (is-16-bit query) + Arseny Kapoulkine Simon Breuss (16-bit PNM) + John-Mark Allen + Carmelo J Fdez-Aguera + + Bug & warning fixes + Marc LeBlanc David Woo Guillaume George Martins Mozeiko + Christpher Lloyd Jerry Jansson Joseph Thomson Blazej Dariusz Roszkowski + Phil Jordan Dave Moore Roy Eltham + Hayaki Saito Nathan Reed Won Chun + Luke Graham Johan Duparc Nick Verigakis the Horde3D community + Thomas Ruf Ronny Chevalier github:rlyeh + Janez Zemva John Bartholomew Michal Cichon github:romigrou + Jonathan Blow Ken Hamada Tero Hanninen github:svdijk + Eugene Golushkov Laurent Gomila Cort Stratton github:snagar + Aruelien Pocheville Sergio Gonzalez Thibault Reuille github:Zelex + Cass Everitt Ryamond Barbiero github:grim210 + Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw + Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus + Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo + Julian Raschke Gregory Mullen Christian Floisand github:darealshinji + Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007 + Brad Weinberger Matvey Cherevko github:mosra + Luca Sas Alexander Veselov Zack Middleton [reserved] + Ryan C. Gordon [reserved] [reserved] + DO NOT ADD YOUR NAME HERE + + Jacko Dirks + + To add your name to the credits, pick a random blank space in the middle and fill it. + 80% of merge conflicts on stb PRs are due to people adding their name at the end + of the credits. +*/ + +#ifndef STBI_INCLUDE_STB_IMAGE_H +#define STBI_INCLUDE_STB_IMAGE_H + +// DOCUMENTATION +// +// Limitations: +// - no 12-bit-per-channel JPEG +// - no JPEGs with arithmetic coding +// - GIF always returns *comp=4 +// +// Basic usage (see HDR discussion below for HDR usage): +// int x,y,n; +// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); +// // ... process data if not NULL ... +// // ... x = width, y = height, n = # 8-bit components per pixel ... +// // ... replace '0' with '1'..'4' to force that many components per pixel +// // ... but 'n' will always be the number that it would have been if you said 0 +// stbi_image_free(data); +// +// Standard parameters: +// int *x -- outputs image width in pixels +// int *y -- outputs image height in pixels +// int *channels_in_file -- outputs # of image components in image file +// int desired_channels -- if non-zero, # of image components requested in result +// +// The return value from an image loader is an 'unsigned char *' which points +// to the pixel data, or NULL on an allocation failure or if the image is +// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, +// with each pixel consisting of N interleaved 8-bit components; the first +// pixel pointed to is top-left-most in the image. There is no padding between +// image scanlines or between pixels, regardless of format. The number of +// components N is 'desired_channels' if desired_channels is non-zero, or +// *channels_in_file otherwise. If desired_channels is non-zero, +// *channels_in_file has the number of components that _would_ have been +// output otherwise. E.g. if you set desired_channels to 4, you will always +// get RGBA output, but you can check *channels_in_file to see if it's trivially +// opaque because e.g. there were only 3 channels in the source image. +// +// An output image with N components has the following components interleaved +// in this order in each pixel: +// +// N=#comp components +// 1 grey +// 2 grey, alpha +// 3 red, green, blue +// 4 red, green, blue, alpha +// +// If image loading fails for any reason, the return value will be NULL, +// and *x, *y, *channels_in_file will be unchanged. The function +// stbi_failure_reason() can be queried for an extremely brief, end-user +// unfriendly explanation of why the load failed. Define STBI_NO_FAILURE_STRINGS +// to avoid compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly +// more user-friendly ones. +// +// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. +// +// To query the width, height and component count of an image without having to +// decode the full file, you can use the stbi_info family of functions: +// +// int x,y,n,ok; +// ok = stbi_info(filename, &x, &y, &n); +// // returns ok=1 and sets x, y, n if image is a supported format, +// // 0 otherwise. +// +// Note that stb_image pervasively uses ints in its public API for sizes, +// including sizes of memory buffers. This is now part of the API and thus +// hard to change without causing breakage. As a result, the various image +// loaders all have certain limits on image size; these differ somewhat +// by format but generally boil down to either just under 2GB or just under +// 1GB. When the decoded image would be larger than this, stb_image decoding +// will fail. +// +// Additionally, stb_image will reject image files that have any of their +// dimensions set to a larger value than the configurable STBI_MAX_DIMENSIONS, +// which defaults to 2**24 = 16777216 pixels. Due to the above memory limit, +// the only way to have an image with such dimensions load correctly +// is for it to have a rather extreme aspect ratio. Either way, the +// assumption here is that such larger images are likely to be malformed +// or malicious. If you do need to load an image with individual dimensions +// larger than that, and it still fits in the overall size limit, you can +// #define STBI_MAX_DIMENSIONS on your own to be something larger. +// +// =========================================================================== +// +// UNICODE: +// +// If compiling for Windows and you wish to use Unicode filenames, compile +// with +// #define STBI_WINDOWS_UTF8 +// and pass utf8-encoded filenames. Call stbi_convert_wchar_to_utf8 to convert +// Windows wchar_t filenames to utf8. +// +// =========================================================================== +// +// Philosophy +// +// stb libraries are designed with the following priorities: +// +// 1. easy to use +// 2. easy to maintain +// 3. good performance +// +// Sometimes I let "good performance" creep up in priority over "easy to maintain", +// and for best performance I may provide less-easy-to-use APIs that give higher +// performance, in addition to the easy-to-use ones. Nevertheless, it's important +// to keep in mind that from the standpoint of you, a client of this library, +// all you care about is #1 and #3, and stb libraries DO NOT emphasize #3 above all. +// +// Some secondary priorities arise directly from the first two, some of which +// provide more explicit reasons why performance can't be emphasized. +// +// - Portable ("ease of use") +// - Small source code footprint ("easy to maintain") +// - No dependencies ("ease of use") +// +// =========================================================================== +// +// I/O callbacks +// +// I/O callbacks allow you to read from arbitrary sources, like packaged +// files or some other source. Data read from callbacks are processed +// through a small internal buffer (currently 128 bytes) to try to reduce +// overhead. +// +// The three functions you must define are "read" (reads some bytes of data), +// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). +// +// =========================================================================== +// +// SIMD support +// +// The JPEG decoder will try to automatically use SIMD kernels on x86 when +// supported by the compiler. For ARM Neon support, you must explicitly +// request it. +// +// (The old do-it-yourself SIMD API is no longer supported in the current +// code.) +// +// On x86, SSE2 will automatically be used when available based on a run-time +// test; if not, the generic C versions are used as a fall-back. On ARM targets, +// the typical path is to have separate builds for NEON and non-NEON devices +// (at least this is true for iOS and Android). Therefore, the NEON support is +// toggled by a build flag: define STBI_NEON to get NEON loops. +// +// If for some reason you do not want to use any of SIMD code, or if +// you have issues compiling it, you can disable it entirely by +// defining STBI_NO_SIMD. +// +// =========================================================================== +// +// HDR image support (disable by defining STBI_NO_HDR) +// +// stb_image supports loading HDR images in general, and currently the Radiance +// .HDR file format specifically. You can still load any file through the existing +// interface; if you attempt to load an HDR file, it will be automatically remapped +// to LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; +// both of these constants can be reconfigured through this interface: +// +// stbi_hdr_to_ldr_gamma(2.2f); +// stbi_hdr_to_ldr_scale(1.0f); +// +// (note, do not use _inverse_ constants; stbi_image will invert them +// appropriately). +// +// Additionally, there is a new, parallel interface for loading files as +// (linear) floats to preserve the full dynamic range: +// +// float *data = stbi_loadf(filename, &x, &y, &n, 0); +// +// If you load LDR images through this interface, those images will +// be promoted to floating point values, run through the inverse of +// constants corresponding to the above: +// +// stbi_ldr_to_hdr_scale(1.0f); +// stbi_ldr_to_hdr_gamma(2.2f); +// +// Finally, given a filename (or an open file or memory block--see header +// file for details) containing image data, you can query for the "most +// appropriate" interface to use (that is, whether the image is HDR or +// not), using: +// +// stbi_is_hdr(char *filename); +// +// =========================================================================== +// +// iPhone PNG support: +// +// We optionally support converting iPhone-formatted PNGs (which store +// premultiplied BGRA) back to RGB, even though they're internally encoded +// differently. To enable this conversion, call +// stbi_convert_iphone_png_to_rgb(1). +// +// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per +// pixel to remove any premultiplied alpha *only* if the image file explicitly +// says there's premultiplied data (currently only happens in iPhone images, +// and only if iPhone convert-to-rgb processing is on). +// +// =========================================================================== +// +// ADDITIONAL CONFIGURATION +// +// - You can suppress implementation of any of the decoders to reduce +// your code footprint by #defining one or more of the following +// symbols before creating the implementation. +// +// STBI_NO_JPEG +// STBI_NO_PNG +// STBI_NO_BMP +// STBI_NO_PSD +// STBI_NO_TGA +// STBI_NO_GIF +// STBI_NO_HDR +// STBI_NO_PIC +// STBI_NO_PNM (.ppm and .pgm) +// +// - You can request *only* certain decoders and suppress all other ones +// (this will be more forward-compatible, as addition of new decoders +// doesn't require you to disable them explicitly): +// +// STBI_ONLY_JPEG +// STBI_ONLY_PNG +// STBI_ONLY_BMP +// STBI_ONLY_PSD +// STBI_ONLY_TGA +// STBI_ONLY_GIF +// STBI_ONLY_HDR +// STBI_ONLY_PIC +// STBI_ONLY_PNM (.ppm and .pgm) +// +// - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still +// want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB +// +// - If you define STBI_MAX_DIMENSIONS, stb_image will reject images greater +// than that size (in either width or height) without further processing. +// This is to let programs in the wild set an upper bound to prevent +// denial-of-service attacks on untrusted data, as one could generate a +// valid image of gigantic dimensions and force stb_image to allocate a +// huge block of memory and spend disproportionate time decoding it. By +// default this is set to (1 << 24), which is 16777216, but that's still +// very big. + +#ifndef STBI_NO_STDIO +#include +#endif // STBI_NO_STDIO + +#define STBI_VERSION 1 + +enum +{ + STBI_default = 0, // only used for desired_channels + + STBI_grey = 1, + STBI_grey_alpha = 2, + STBI_rgb = 3, + STBI_rgb_alpha = 4 +}; + +#include +typedef unsigned char stbi_uc; +typedef unsigned short stbi_us; + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef STBIDEF +#ifdef STB_IMAGE_STATIC +#define STBIDEF static +#else +#define STBIDEF extern +#endif +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// PRIMARY API - works on images of any type +// + +// +// load image by filename, open file, or memory buffer +// + +typedef struct +{ + int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read + void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative + int (*eof) (void *user); // returns nonzero if we are at end of file/data +} stbi_io_callbacks; + +//////////////////////////////////// +// +// 8-bits-per-channel interface +// + +STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +// for stbi_load_from_file, file pointer is left pointing immediately after image +#endif + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +#endif + +#ifdef STBI_WINDOWS_UTF8 +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif + +//////////////////////////////////// +// +// 16-bits-per-channel interface +// + +STBIDEF stbi_us *stbi_load_16_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + +#ifndef STBI_NO_STDIO +STBIDEF stbi_us *stbi_load_16 (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); +STBIDEF stbi_us *stbi_load_from_file_16(FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); +#endif + +//////////////////////////////////// +// +// float-per-channel interface +// +#ifndef STBI_NO_LINEAR + STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels); + + #ifndef STBI_NO_STDIO + STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *channels_in_file, int desired_channels); + STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *channels_in_file, int desired_channels); + #endif +#endif + +#ifndef STBI_NO_HDR + STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); + STBIDEF void stbi_hdr_to_ldr_scale(float scale); +#endif // STBI_NO_HDR + +#ifndef STBI_NO_LINEAR + STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); + STBIDEF void stbi_ldr_to_hdr_scale(float scale); +#endif // STBI_NO_LINEAR + +// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename); +STBIDEF int stbi_is_hdr_from_file(FILE *f); +#endif // STBI_NO_STDIO + + +// get a VERY brief reason for failure +// on most compilers (and ALL modern mainstream compilers) this is threadsafe +STBIDEF const char *stbi_failure_reason (void); + +// free the loaded image -- this is just free() +STBIDEF void stbi_image_free (void *retval_from_stbi_load); + +// get image dimensions & components without fully decoding +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len); +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *clbk, void *user); + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); +STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); +STBIDEF int stbi_is_16_bit (char const *filename); +STBIDEF int stbi_is_16_bit_from_file(FILE *f); +#endif + + + +// for image formats that explicitly notate that they have premultiplied alpha, +// we just return the colors as stored in the file. set this flag to force +// unpremultiplication. results are undefined if the unpremultiply overflow. +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); + +// indicate whether we should process iphone images back to canonical format, +// or just pass them through "as-is" +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); + +// flip the image vertically, so the first pixel in the output array is the bottom left +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); + +// as above, but only applies to images loaded on the thread that calls the function +// this function is only available if your compiler supports thread-local variables; +// calling it will fail to link if your compiler doesn't +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply); +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert); +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip); + +// ZLIB client - used by PNG, available for other purposes + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); +STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + +STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); + + +#ifdef __cplusplus +} +#endif + +// +// +//// end header file ///////////////////////////////////////////////////// +#endif // STBI_INCLUDE_STB_IMAGE_H + +#ifdef STB_IMAGE_IMPLEMENTATION + +#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ + || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ + || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ + || defined(STBI_ONLY_ZLIB) + #ifndef STBI_ONLY_JPEG + #define STBI_NO_JPEG + #endif + #ifndef STBI_ONLY_PNG + #define STBI_NO_PNG + #endif + #ifndef STBI_ONLY_BMP + #define STBI_NO_BMP + #endif + #ifndef STBI_ONLY_PSD + #define STBI_NO_PSD + #endif + #ifndef STBI_ONLY_TGA + #define STBI_NO_TGA + #endif + #ifndef STBI_ONLY_GIF + #define STBI_NO_GIF + #endif + #ifndef STBI_ONLY_HDR + #define STBI_NO_HDR + #endif + #ifndef STBI_ONLY_PIC + #define STBI_NO_PIC + #endif + #ifndef STBI_ONLY_PNM + #define STBI_NO_PNM + #endif +#endif + +#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) +#define STBI_NO_ZLIB +#endif + + +#include +#include // ptrdiff_t on osx +#include +#include +#include + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) +#include // ldexp, pow +#endif + +#ifndef STBI_NO_STDIO +#include +#endif + +#ifndef STBI_ASSERT +#include +#define STBI_ASSERT(x) assert(x) +#endif + +#ifdef __cplusplus +#define STBI_EXTERN extern "C" +#else +#define STBI_EXTERN extern +#endif + + +#ifndef _MSC_VER + #ifdef __cplusplus + #define stbi_inline inline + #else + #define stbi_inline + #endif +#else + #define stbi_inline __forceinline +#endif + +#ifndef STBI_NO_THREAD_LOCALS + #if defined(__cplusplus) && __cplusplus >= 201103L + #define STBI_THREAD_LOCAL thread_local + #elif defined(__GNUC__) && __GNUC__ < 5 + #define STBI_THREAD_LOCAL __thread + #elif defined(_MSC_VER) + #define STBI_THREAD_LOCAL __declspec(thread) + #elif defined (__STDC_VERSION__) && __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__) + #define STBI_THREAD_LOCAL _Thread_local + #endif + + #ifndef STBI_THREAD_LOCAL + #if defined(__GNUC__) + #define STBI_THREAD_LOCAL __thread + #endif + #endif +#endif + +#if defined(_MSC_VER) || defined(__SYMBIAN32__) +typedef unsigned short stbi__uint16; +typedef signed short stbi__int16; +typedef unsigned int stbi__uint32; +typedef signed int stbi__int32; +#else +#include +typedef uint16_t stbi__uint16; +typedef int16_t stbi__int16; +typedef uint32_t stbi__uint32; +typedef int32_t stbi__int32; +#endif + +// should produce compiler error if size is wrong +typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; + +#ifdef _MSC_VER +#define STBI_NOTUSED(v) (void)(v) +#else +#define STBI_NOTUSED(v) (void)sizeof(v) +#endif + +#ifdef _MSC_VER +#define STBI_HAS_LROTL +#endif + +#ifdef STBI_HAS_LROTL + #define stbi_lrot(x,y) _lrotl(x,y) +#else + #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (-(y) & 31))) +#endif + +#if defined(STBI_MALLOC) && defined(STBI_FREE) && (defined(STBI_REALLOC) || defined(STBI_REALLOC_SIZED)) +// ok +#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) && !defined(STBI_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC (or STBI_REALLOC_SIZED)." +#endif + +#ifndef STBI_MALLOC +#define STBI_MALLOC(sz) malloc(sz) +#define STBI_REALLOC(p,newsz) realloc(p,newsz) +#define STBI_FREE(p) free(p) +#endif + +#ifndef STBI_REALLOC_SIZED +#define STBI_REALLOC_SIZED(p,oldsz,newsz) STBI_REALLOC(p,newsz) +#endif + +// x86/x64 detection +#if defined(__x86_64__) || defined(_M_X64) +#define STBI__X64_TARGET +#elif defined(__i386) || defined(_M_IX86) +#define STBI__X86_TARGET +#endif + +#if defined(__GNUC__) && defined(STBI__X86_TARGET) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) +// gcc doesn't support sse2 intrinsics unless you compile with -msse2, +// which in turn means it gets to use SSE2 everywhere. This is unfortunate, +// but previous attempts to provide the SSE2 functions with runtime +// detection caused numerous issues. The way architecture extensions are +// exposed in GCC/Clang is, sadly, not really suited for one-file libs. +// New behavior: if compiled with -msse2, we use SSE2 without any +// detection; if not, we don't use it at all. +#define STBI_NO_SIMD +#endif + +#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) +// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET +// +// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the +// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. +// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not +// simultaneously enabling "-mstackrealign". +// +// See https://github.com/nothings/stb/issues/81 for more information. +// +// So default to no SSE2 on 32-bit MinGW. If you've read this far and added +// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. +#define STBI_NO_SIMD +#endif + +#if !defined(STBI_NO_SIMD) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) +#define STBI_SSE2 +#include + +#ifdef _MSC_VER + +#if _MSC_VER >= 1400 // not VC6 +#include // __cpuid +static int stbi__cpuid3(void) +{ + int info[4]; + __cpuid(info,1); + return info[3]; +} +#else +static int stbi__cpuid3(void) +{ + int res; + __asm { + mov eax,1 + cpuid + mov res,edx + } + return res; +} +#endif + +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + int info3 = stbi__cpuid3(); + return ((info3 >> 26) & 1) != 0; +} +#endif + +#else // assume GCC-style if not VC++ +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) + +#if !defined(STBI_NO_JPEG) && defined(STBI_SSE2) +static int stbi__sse2_available(void) +{ + // If we're even attempting to compile this on GCC/Clang, that means + // -msse2 is on, which means the compiler is allowed to use SSE2 + // instructions at will, and so are we. + return 1; +} +#endif + +#endif +#endif + +// ARM NEON +#if defined(STBI_NO_SIMD) && defined(STBI_NEON) +#undef STBI_NEON +#endif + +#ifdef STBI_NEON +#include +#ifdef _MSC_VER +#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name +#else +#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) +#endif +#endif + +#ifndef STBI_SIMD_ALIGN +#define STBI_SIMD_ALIGN(type, name) type name +#endif + +#ifndef STBI_MAX_DIMENSIONS +#define STBI_MAX_DIMENSIONS (1 << 24) +#endif + +/////////////////////////////////////////////// +// +// stbi__context struct and start_xxx functions + +// stbi__context structure is our basic context used by all images, so it +// contains all the IO context, plus some basic image information +typedef struct +{ + stbi__uint32 img_x, img_y; + int img_n, img_out_n; + + stbi_io_callbacks io; + void *io_user_data; + + int read_from_callbacks; + int buflen; + stbi_uc buffer_start[128]; + int callback_already_read; + + stbi_uc *img_buffer, *img_buffer_end; + stbi_uc *img_buffer_original, *img_buffer_original_end; +} stbi__context; + + +static void stbi__refill_buffer(stbi__context *s); + +// initialize a memory-decode context +static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) +{ + s->io.read = NULL; + s->read_from_callbacks = 0; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; + s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; +} + +// initialize a callback-based context +static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) +{ + s->io = *c; + s->io_user_data = user; + s->buflen = sizeof(s->buffer_start); + s->read_from_callbacks = 1; + s->callback_already_read = 0; + s->img_buffer = s->img_buffer_original = s->buffer_start; + stbi__refill_buffer(s); + s->img_buffer_original_end = s->img_buffer_end; +} + +#ifndef STBI_NO_STDIO + +static int stbi__stdio_read(void *user, char *data, int size) +{ + return (int) fread(data,1,size,(FILE*) user); +} + +static void stbi__stdio_skip(void *user, int n) +{ + int ch; + fseek((FILE*) user, n, SEEK_CUR); + ch = fgetc((FILE*) user); /* have to read a byte to reset feof()'s flag */ + if (ch != EOF) { + ungetc(ch, (FILE *) user); /* push byte back onto stream if valid. */ + } +} + +static int stbi__stdio_eof(void *user) +{ + return feof((FILE*) user) || ferror((FILE *) user); +} + +static stbi_io_callbacks stbi__stdio_callbacks = +{ + stbi__stdio_read, + stbi__stdio_skip, + stbi__stdio_eof, +}; + +static void stbi__start_file(stbi__context *s, FILE *f) +{ + stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); +} + +//static void stop_file(stbi__context *s) { } + +#endif // !STBI_NO_STDIO + +static void stbi__rewind(stbi__context *s) +{ + // conceptually rewind SHOULD rewind to the beginning of the stream, + // but we just rewind to the beginning of the initial buffer, because + // we only use it after doing 'test', which only ever looks at at most 92 bytes + s->img_buffer = s->img_buffer_original; + s->img_buffer_end = s->img_buffer_original_end; +} + +enum +{ + STBI_ORDER_RGB, + STBI_ORDER_BGR +}; + +typedef struct +{ + int bits_per_channel; + int num_channels; + int channel_order; +} stbi__result_info; + +#ifndef STBI_NO_JPEG +static int stbi__jpeg_test(stbi__context *s); +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNG +static int stbi__png_test(stbi__context *s); +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__png_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_BMP +static int stbi__bmp_test(stbi__context *s); +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_TGA +static int stbi__tga_test(stbi__context *s); +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s); +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc); +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__psd_is16(stbi__context *s); +#endif + +#ifndef STBI_NO_HDR +static int stbi__hdr_test(stbi__context *s); +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_test(stbi__context *s); +static void *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_GIF +static int stbi__gif_test(stbi__context *s); +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp); +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); +#endif + +#ifndef STBI_NO_PNM +static int stbi__pnm_test(stbi__context *s); +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri); +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); +static int stbi__pnm_is16(stbi__context *s); +#endif + +static +#ifdef STBI_THREAD_LOCAL +STBI_THREAD_LOCAL +#endif +const char *stbi__g_failure_reason; + +STBIDEF const char *stbi_failure_reason(void) +{ + return stbi__g_failure_reason; +} + +#ifndef STBI_NO_FAILURE_STRINGS +static int stbi__err(const char *str) +{ + stbi__g_failure_reason = str; + return 0; +} +#endif + +static void *stbi__malloc(size_t size) +{ + return STBI_MALLOC(size); +} + +// stb_image uses ints pervasively, including for offset calculations. +// therefore the largest decoded image size we can support with the +// current code, even on 64-bit targets, is INT_MAX. this is not a +// significant limitation for the intended use case. +// +// we do, however, need to make sure our size calculations don't +// overflow. hence a few helper functions for size calculations that +// multiply integers together, making sure that they're non-negative +// and no overflow occurs. + +// return 1 if the sum is valid, 0 on overflow. +// negative terms are considered invalid. +static int stbi__addsizes_valid(int a, int b) +{ + if (b < 0) return 0; + // now 0 <= b <= INT_MAX, hence also + // 0 <= INT_MAX - b <= INTMAX. + // And "a + b <= INT_MAX" (which might overflow) is the + // same as a <= INT_MAX - b (no overflow) + return a <= INT_MAX - b; +} + +// returns 1 if the product is valid, 0 on overflow. +// negative factors are considered invalid. +static int stbi__mul2sizes_valid(int a, int b) +{ + if (a < 0 || b < 0) return 0; + if (b == 0) return 1; // mul-by-0 is always safe + // portable way to check for no overflows in a*b + return a <= INT_MAX/b; +} + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// returns 1 if "a*b + add" has no negative terms/factors and doesn't overflow +static int stbi__mad2sizes_valid(int a, int b, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__addsizes_valid(a*b, add); +} +#endif + +// returns 1 if "a*b*c + add" has no negative terms/factors and doesn't overflow +static int stbi__mad3sizes_valid(int a, int b, int c, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__addsizes_valid(a*b*c, add); +} + +// returns 1 if "a*b*c*d + add" has no negative terms/factors and doesn't overflow +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static int stbi__mad4sizes_valid(int a, int b, int c, int d, int add) +{ + return stbi__mul2sizes_valid(a, b) && stbi__mul2sizes_valid(a*b, c) && + stbi__mul2sizes_valid(a*b*c, d) && stbi__addsizes_valid(a*b*c*d, add); +} +#endif + +#if !defined(STBI_NO_JPEG) || !defined(STBI_NO_PNG) || !defined(STBI_NO_TGA) || !defined(STBI_NO_HDR) +// mallocs with size overflow checking +static void *stbi__malloc_mad2(int a, int b, int add) +{ + if (!stbi__mad2sizes_valid(a, b, add)) return NULL; + return stbi__malloc(a*b + add); +} +#endif + +static void *stbi__malloc_mad3(int a, int b, int c, int add) +{ + if (!stbi__mad3sizes_valid(a, b, c, add)) return NULL; + return stbi__malloc(a*b*c + add); +} + +#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) || !defined(STBI_NO_PNM) +static void *stbi__malloc_mad4(int a, int b, int c, int d, int add) +{ + if (!stbi__mad4sizes_valid(a, b, c, d, add)) return NULL; + return stbi__malloc(a*b*c*d + add); +} +#endif + +// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow. +static int stbi__addints_valid(int a, int b) +{ + if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow + if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0. + return a <= INT_MAX - b; +} + +// returns 1 if the product of two ints fits in a signed short, 0 on overflow. +static int stbi__mul2shorts_valid(int a, int b) +{ + if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow + if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid + if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN + return a >= SHRT_MIN / b; +} + +// stbi__err - error +// stbi__errpf - error returning pointer to float +// stbi__errpuc - error returning pointer to unsigned char + +#ifdef STBI_NO_FAILURE_STRINGS + #define stbi__err(x,y) 0 +#elif defined(STBI_FAILURE_USERMSG) + #define stbi__err(x,y) stbi__err(y) +#else + #define stbi__err(x,y) stbi__err(x) +#endif + +#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) +#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) + +STBIDEF void stbi_image_free(void *retval_from_stbi_load) +{ + STBI_FREE(retval_from_stbi_load); +} + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); +#endif + +#ifndef STBI_NO_HDR +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); +#endif + +static int stbi__vertically_flip_on_load_global = 0; + +STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_global = flag_true_if_should_flip; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__vertically_flip_on_load stbi__vertically_flip_on_load_global +#else +static STBI_THREAD_LOCAL int stbi__vertically_flip_on_load_local, stbi__vertically_flip_on_load_set; + +STBIDEF void stbi_set_flip_vertically_on_load_thread(int flag_true_if_should_flip) +{ + stbi__vertically_flip_on_load_local = flag_true_if_should_flip; + stbi__vertically_flip_on_load_set = 1; +} + +#define stbi__vertically_flip_on_load (stbi__vertically_flip_on_load_set \ + ? stbi__vertically_flip_on_load_local \ + : stbi__vertically_flip_on_load_global) +#endif // STBI_THREAD_LOCAL + +static void *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + memset(ri, 0, sizeof(*ri)); // make sure it's initialized if we add new fields + ri->bits_per_channel = 8; // default is 8 so most paths don't have to be changed + ri->channel_order = STBI_ORDER_RGB; // all current input & output are this, but this is here so we can add BGR order + ri->num_channels = 0; + + // test the formats with a very explicit header first (at least a FOURCC + // or distinctive magic number first) + #ifndef STBI_NO_PNG + if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_BMP + if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_GIF + if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PSD + if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp, ri, bpc); + #else + STBI_NOTUSED(bpc); + #endif + #ifndef STBI_NO_PIC + if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp, ri); + #endif + + // then the formats that can end up attempting to load with just 1 or 2 + // bytes matching expectations; these are prone to false positives, so + // try them later + #ifndef STBI_NO_JPEG + if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp, ri); + #endif + #ifndef STBI_NO_PNM + if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp, ri); + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + float *hdr = stbi__hdr_load(s, x,y,comp,req_comp, ri); + return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); + } + #endif + + #ifndef STBI_NO_TGA + // test tga last because it's a crappy test! + if (stbi__tga_test(s)) + return stbi__tga_load(s,x,y,comp,req_comp, ri); + #endif + + return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); +} + +static stbi_uc *stbi__convert_16_to_8(stbi__uint16 *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi_uc *reduced; + + reduced = (stbi_uc *) stbi__malloc(img_len); + if (reduced == NULL) return stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + reduced[i] = (stbi_uc)((orig[i] >> 8) & 0xFF); // top half of each byte is sufficient approx of 16->8 bit scaling + + STBI_FREE(orig); + return reduced; +} + +static stbi__uint16 *stbi__convert_8_to_16(stbi_uc *orig, int w, int h, int channels) +{ + int i; + int img_len = w * h * channels; + stbi__uint16 *enlarged; + + enlarged = (stbi__uint16 *) stbi__malloc(img_len*2); + if (enlarged == NULL) return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + + for (i = 0; i < img_len; ++i) + enlarged[i] = (stbi__uint16)((orig[i] << 8) + orig[i]); // replicate to high and low byte, maps 0->0, 255->0xffff + + STBI_FREE(orig); + return enlarged; +} + +static void stbi__vertical_flip(void *image, int w, int h, int bytes_per_pixel) +{ + int row; + size_t bytes_per_row = (size_t)w * bytes_per_pixel; + stbi_uc temp[2048]; + stbi_uc *bytes = (stbi_uc *)image; + + for (row = 0; row < (h>>1); row++) { + stbi_uc *row0 = bytes + row*bytes_per_row; + stbi_uc *row1 = bytes + (h - row - 1)*bytes_per_row; + // swap row0 with row1 + size_t bytes_left = bytes_per_row; + while (bytes_left) { + size_t bytes_copy = (bytes_left < sizeof(temp)) ? bytes_left : sizeof(temp); + memcpy(temp, row0, bytes_copy); + memcpy(row0, row1, bytes_copy); + memcpy(row1, temp, bytes_copy); + row0 += bytes_copy; + row1 += bytes_copy; + bytes_left -= bytes_copy; + } + } +} + +#ifndef STBI_NO_GIF +static void stbi__vertical_flip_slices(void *image, int w, int h, int z, int bytes_per_pixel) +{ + int slice; + int slice_size = w * h * bytes_per_pixel; + + stbi_uc *bytes = (stbi_uc *)image; + for (slice = 0; slice < z; ++slice) { + stbi__vertical_flip(bytes, w, h, bytes_per_pixel); + bytes += slice_size; + } +} +#endif + +static unsigned char *stbi__load_and_postprocess_8bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 8); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 8) { + result = stbi__convert_16_to_8((stbi__uint16 *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 8; + } + + // @TODO: move stbi__convert_format to here + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi_uc)); + } + + return (unsigned char *) result; +} + +static stbi__uint16 *stbi__load_and_postprocess_16bit(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + stbi__result_info ri; + void *result = stbi__load_main(s, x, y, comp, req_comp, &ri, 16); + + if (result == NULL) + return NULL; + + // it is the responsibility of the loaders to make sure we get either 8 or 16 bit. + STBI_ASSERT(ri.bits_per_channel == 8 || ri.bits_per_channel == 16); + + if (ri.bits_per_channel != 16) { + result = stbi__convert_8_to_16((stbi_uc *) result, *x, *y, req_comp == 0 ? *comp : req_comp); + ri.bits_per_channel = 16; + } + + // @TODO: move stbi__convert_format16 to here + // @TODO: special case RGB-to-Y (and RGBA-to-YA) for 8-bit-to-16-bit case to keep more precision + + if (stbi__vertically_flip_on_load) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(stbi__uint16)); + } + + return (stbi__uint16 *) result; +} + +#if !defined(STBI_NO_HDR) && !defined(STBI_NO_LINEAR) +static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) +{ + if (stbi__vertically_flip_on_load && result != NULL) { + int channels = req_comp ? req_comp : *comp; + stbi__vertical_flip(result, *x, *y, channels * sizeof(float)); + } +} +#endif + +#ifndef STBI_NO_STDIO + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBI_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBI_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); +#endif + +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) +STBIDEF int stbi_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbi__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBI_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + + +STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + unsigned char *result; + if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi__uint16 *stbi_load_from_file_16(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__uint16 *result; + stbi__context s; + stbi__start_file(&s,f); + result = stbi__load_and_postprocess_16bit(&s,x,y,comp,req_comp); + if (result) { + // need to 'unget' all the characters in the IO buffer + fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); + } + return result; +} + +STBIDEF stbi_us *stbi_load_16(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + stbi__uint16 *result; + if (!f) return (stbi_us *) stbi__errpuc("can't fopen", "Unable to open file"); + result = stbi_load_from_file_16(f,x,y,comp,req_comp); + fclose(f); + return result; +} + + +#endif //!STBI_NO_STDIO + +STBIDEF stbi_us *stbi_load_16_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_us *stbi_load_16_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *channels_in_file, int desired_channels) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *)clbk, user); + return stbi__load_and_postprocess_16bit(&s,x,y,channels_in_file,desired_channels); +} + +STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__load_and_postprocess_8bit(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_GIF +STBIDEF stbi_uc *stbi_load_gif_from_memory(stbi_uc const *buffer, int len, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + unsigned char *result; + stbi__context s; + stbi__start_mem(&s,buffer,len); + + result = (unsigned char*) stbi__load_gif_main(&s, delays, x, y, z, comp, req_comp); + if (stbi__vertically_flip_on_load) { + stbi__vertical_flip_slices( result, *x, *y, *z, *comp ); + } + + return result; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) +{ + unsigned char *data; + #ifndef STBI_NO_HDR + if (stbi__hdr_test(s)) { + stbi__result_info ri; + float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp, &ri); + if (hdr_data) + stbi__float_postprocess(hdr_data,x,y,comp,req_comp); + return hdr_data; + } + #endif + data = stbi__load_and_postprocess_8bit(s, x, y, comp, req_comp); + if (data) + return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); + return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); +} + +STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} + +#ifndef STBI_NO_STDIO +STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) +{ + float *result; + FILE *f = stbi__fopen(filename, "rb"); + if (!f) return stbi__errpf("can't fopen", "Unable to open file"); + result = stbi_loadf_from_file(f,x,y,comp,req_comp); + fclose(f); + return result; +} + +STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) +{ + stbi__context s; + stbi__start_file(&s,f); + return stbi__loadf_main(&s,x,y,comp,req_comp); +} +#endif // !STBI_NO_STDIO + +#endif // !STBI_NO_LINEAR + +// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is +// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always +// reports false! + +STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(buffer); + STBI_NOTUSED(len); + return 0; + #endif +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_is_hdr (char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result=0; + if (f) { + result = stbi_is_hdr_from_file(f); + fclose(f); + } + return result; +} + +STBIDEF int stbi_is_hdr_from_file(FILE *f) +{ + #ifndef STBI_NO_HDR + long pos = ftell(f); + int res; + stbi__context s; + stbi__start_file(&s,f); + res = stbi__hdr_test(&s); + fseek(f, pos, SEEK_SET); + return res; + #else + STBI_NOTUSED(f); + return 0; + #endif +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) +{ + #ifndef STBI_NO_HDR + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); + return stbi__hdr_test(&s); + #else + STBI_NOTUSED(clbk); + STBI_NOTUSED(user); + return 0; + #endif +} + +#ifndef STBI_NO_LINEAR +static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; + +STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } +STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } +#endif + +static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; + +STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } +STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } + + +////////////////////////////////////////////////////////////////////////////// +// +// Common code used by all image loaders +// + +enum +{ + STBI__SCAN_load=0, + STBI__SCAN_type, + STBI__SCAN_header +}; + +static void stbi__refill_buffer(stbi__context *s) +{ + int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); + s->callback_already_read += (int) (s->img_buffer - s->img_buffer_original); + if (n == 0) { + // at end of file, treat same as if from memory, but need to handle case + // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file + s->read_from_callbacks = 0; + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start+1; + *s->img_buffer = 0; + } else { + s->img_buffer = s->buffer_start; + s->img_buffer_end = s->buffer_start + n; + } +} + +stbi_inline static stbi_uc stbi__get8(stbi__context *s) +{ + if (s->img_buffer < s->img_buffer_end) + return *s->img_buffer++; + if (s->read_from_callbacks) { + stbi__refill_buffer(s); + return *s->img_buffer++; + } + return 0; +} + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_HDR) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +stbi_inline static int stbi__at_eof(stbi__context *s) +{ + if (s->io.read) { + if (!(s->io.eof)(s->io_user_data)) return 0; + // if feof() is true, check if buffer = end + // special case: we've only got the special 0 character at the end + if (s->read_from_callbacks == 0) return 1; + } + + return s->img_buffer >= s->img_buffer_end; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) +// nothing +#else +static void stbi__skip(stbi__context *s, int n) +{ + if (n == 0) return; // already there! + if (n < 0) { + s->img_buffer = s->img_buffer_end; + return; + } + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + s->img_buffer = s->img_buffer_end; + (s->io.skip)(s->io_user_data, n - blen); + return; + } + } + s->img_buffer += n; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_TGA) && defined(STBI_NO_HDR) && defined(STBI_NO_PNM) +// nothing +#else +static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) +{ + if (s->io.read) { + int blen = (int) (s->img_buffer_end - s->img_buffer); + if (blen < n) { + int res, count; + + memcpy(buffer, s->img_buffer, blen); + + count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); + res = (count == (n-blen)); + s->img_buffer = s->img_buffer_end; + return res; + } + } + + if (s->img_buffer+n <= s->img_buffer_end) { + memcpy(buffer, s->img_buffer, n); + s->img_buffer += n; + return 1; + } else + return 0; +} +#endif + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static int stbi__get16be(stbi__context *s) +{ + int z = stbi__get8(s); + return (z << 8) + stbi__get8(s); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) && defined(STBI_NO_PIC) +// nothing +#else +static stbi__uint32 stbi__get32be(stbi__context *s) +{ + stbi__uint32 z = stbi__get16be(s); + return (z << 16) + stbi__get16be(s); +} +#endif + +#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) +// nothing +#else +static int stbi__get16le(stbi__context *s) +{ + int z = stbi__get8(s); + return z + (stbi__get8(s) << 8); +} +#endif + +#ifndef STBI_NO_BMP +static stbi__uint32 stbi__get32le(stbi__context *s) +{ + stbi__uint32 z = stbi__get16le(s); + z += (stbi__uint32)stbi__get16le(s) << 16; + return z; +} +#endif + +#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings + +#if defined(STBI_NO_JPEG) && defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +////////////////////////////////////////////////////////////////////////////// +// +// generic converter from built-in img_n to req_comp +// individual types do this automatically as much as possible (e.g. jpeg +// does all cases internally since it needs to colorspace convert anyway, +// and it never has alpha, so very few cases ). png can automatically +// interleave an alpha=255 channel, but falls back to this for other cases +// +// assume data buffer is malloced, so malloc a new one and free that one +// only failure mode is malloc failing + +static stbi_uc stbi__compute_y(int r, int g, int b) +{ + return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_BMP) && defined(STBI_NO_PSD) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) && defined(STBI_NO_PIC) && defined(STBI_NO_PNM) +// nothing +#else +static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + unsigned char *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (unsigned char *) stbi__malloc_mad3(req_comp, x, y, 0); + if (good == NULL) { + STBI_FREE(data); + return stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + unsigned char *src = data + j * x * img_n ; + unsigned char *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=255; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=255; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=255; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = 255; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 stbi__compute_y_16(int r, int g, int b) +{ + return (stbi__uint16) (((r*77) + (g*150) + (29*b)) >> 8); +} +#endif + +#if defined(STBI_NO_PNG) && defined(STBI_NO_PSD) +// nothing +#else +static stbi__uint16 *stbi__convert_format16(stbi__uint16 *data, int img_n, int req_comp, unsigned int x, unsigned int y) +{ + int i,j; + stbi__uint16 *good; + + if (req_comp == img_n) return data; + STBI_ASSERT(req_comp >= 1 && req_comp <= 4); + + good = (stbi__uint16 *) stbi__malloc(req_comp * x * y * 2); + if (good == NULL) { + STBI_FREE(data); + return (stbi__uint16 *) stbi__errpuc("outofmem", "Out of memory"); + } + + for (j=0; j < (int) y; ++j) { + stbi__uint16 *src = data + j * x * img_n ; + stbi__uint16 *dest = good + j * x * req_comp; + + #define STBI__COMBO(a,b) ((a)*8+(b)) + #define STBI__CASE(a,b) case STBI__COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) + // convert source image with img_n components to one with req_comp components; + // avoid switch per pixel, so use switch per scanline and massive macros + switch (STBI__COMBO(img_n, req_comp)) { + STBI__CASE(1,2) { dest[0]=src[0]; dest[1]=0xffff; } break; + STBI__CASE(1,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(1,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=0xffff; } break; + STBI__CASE(2,1) { dest[0]=src[0]; } break; + STBI__CASE(2,3) { dest[0]=dest[1]=dest[2]=src[0]; } break; + STBI__CASE(2,4) { dest[0]=dest[1]=dest[2]=src[0]; dest[3]=src[1]; } break; + STBI__CASE(3,4) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2];dest[3]=0xffff; } break; + STBI__CASE(3,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(3,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = 0xffff; } break; + STBI__CASE(4,1) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); } break; + STBI__CASE(4,2) { dest[0]=stbi__compute_y_16(src[0],src[1],src[2]); dest[1] = src[3]; } break; + STBI__CASE(4,3) { dest[0]=src[0];dest[1]=src[1];dest[2]=src[2]; } break; + default: STBI_ASSERT(0); STBI_FREE(data); STBI_FREE(good); return (stbi__uint16*) stbi__errpuc("unsupported", "Unsupported format conversion"); + } + #undef STBI__CASE + } + + STBI_FREE(data); + return good; +} +#endif + +#ifndef STBI_NO_LINEAR +static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) +{ + int i,k,n; + float *output; + if (!data) return NULL; + output = (float *) stbi__malloc_mad4(x, y, comp, sizeof(float), 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); + } + } + if (n < comp) { + for (i=0; i < x*y; ++i) { + output[i*comp + n] = data[i*comp + n]/255.0f; + } + } + STBI_FREE(data); + return output; +} +#endif + +#ifndef STBI_NO_HDR +#define stbi__float2int(x) ((int) (x)) +static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) +{ + int i,k,n; + stbi_uc *output; + if (!data) return NULL; + output = (stbi_uc *) stbi__malloc_mad3(x, y, comp, 0); + if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } + // compute number of non-alpha components + if (comp & 1) n = comp; else n = comp-1; + for (i=0; i < x*y; ++i) { + for (k=0; k < n; ++k) { + float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + if (k < comp) { + float z = data[i*comp+k] * 255 + 0.5f; + if (z < 0) z = 0; + if (z > 255) z = 255; + output[i*comp + k] = (stbi_uc) stbi__float2int(z); + } + } + STBI_FREE(data); + return output; +} +#endif + +////////////////////////////////////////////////////////////////////////////// +// +// "baseline" JPEG/JFIF decoder +// +// simple implementation +// - doesn't support delayed output of y-dimension +// - simple interface (only one output format: 8-bit interleaved RGB) +// - doesn't try to recover corrupt jpegs +// - doesn't allow partial loading, loading multiple at once +// - still fast on x86 (copying globals into locals doesn't help x86) +// - allocates lots of intermediate memory (full size of all components) +// - non-interleaved case requires this anyway +// - allows good upsampling (see next) +// high-quality +// - upsampled channels are bilinearly interpolated, even across blocks +// - quality integer IDCT derived from IJG's 'slow' +// performance +// - fast huffman; reasonable integer IDCT +// - some SIMD kernels for common paths on targets with SSE2/NEON +// - uses a lot of intermediate memory, could cache poorly + +#ifndef STBI_NO_JPEG + +// huffman decoding acceleration +#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache + +typedef struct +{ + stbi_uc fast[1 << FAST_BITS]; + // weirdly, repacking this into AoS is a 10% speed loss, instead of a win + stbi__uint16 code[256]; + stbi_uc values[256]; + stbi_uc size[257]; + unsigned int maxcode[18]; + int delta[17]; // old 'firstsymbol' - old 'firstcode' +} stbi__huffman; + +typedef struct +{ + stbi__context *s; + stbi__huffman huff_dc[4]; + stbi__huffman huff_ac[4]; + stbi__uint16 dequant[4][64]; + stbi__int16 fast_ac[4][1 << FAST_BITS]; + +// sizes for components, interleaved MCUs + int img_h_max, img_v_max; + int img_mcu_x, img_mcu_y; + int img_mcu_w, img_mcu_h; + +// definition of jpeg image component + struct + { + int id; + int h,v; + int tq; + int hd,ha; + int dc_pred; + + int x,y,w2,h2; + stbi_uc *data; + void *raw_data, *raw_coeff; + stbi_uc *linebuf; + short *coeff; // progressive only + int coeff_w, coeff_h; // number of 8x8 coefficient blocks + } img_comp[4]; + + stbi__uint32 code_buffer; // jpeg entropy-coded buffer + int code_bits; // number of valid bits + unsigned char marker; // marker seen while filling entropy buffer + int nomore; // flag if we saw a marker so must stop + + int progressive; + int spec_start; + int spec_end; + int succ_high; + int succ_low; + int eob_run; + int jfif; + int app14_color_transform; // Adobe APP14 tag + int rgb; + + int scan_n, order[4]; + int restart_interval, todo; + +// kernels + void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); + void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); + stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); +} stbi__jpeg; + +static int stbi__build_huffman(stbi__huffman *h, int *count) +{ + int i,j,k=0; + unsigned int code; + // build size list for each symbol (from JPEG spec) + for (i=0; i < 16; ++i) { + for (j=0; j < count[i]; ++j) { + h->size[k++] = (stbi_uc) (i+1); + if(k >= 257) return stbi__err("bad size list","Corrupt JPEG"); + } + } + h->size[k] = 0; + + // compute actual symbols (from jpeg spec) + code = 0; + k = 0; + for(j=1; j <= 16; ++j) { + // compute delta to add to code to compute symbol id + h->delta[j] = k - code; + if (h->size[k] == j) { + while (h->size[k] == j) + h->code[k++] = (stbi__uint16) (code++); + if (code-1 >= (1u << j)) return stbi__err("bad code lengths","Corrupt JPEG"); + } + // compute largest code + 1 for this size, preshifted as needed later + h->maxcode[j] = code << (16-j); + code <<= 1; + } + h->maxcode[j] = 0xffffffff; + + // build non-spec acceleration table; 255 is flag for not-accelerated + memset(h->fast, 255, 1 << FAST_BITS); + for (i=0; i < k; ++i) { + int s = h->size[i]; + if (s <= FAST_BITS) { + int c = h->code[i] << (FAST_BITS-s); + int m = 1 << (FAST_BITS-s); + for (j=0; j < m; ++j) { + h->fast[c+j] = (stbi_uc) i; + } + } + } + return 1; +} + +// build a table that decodes both magnitude and value of small ACs in +// one go. +static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) +{ + int i; + for (i=0; i < (1 << FAST_BITS); ++i) { + stbi_uc fast = h->fast[i]; + fast_ac[i] = 0; + if (fast < 255) { + int rs = h->values[fast]; + int run = (rs >> 4) & 15; + int magbits = rs & 15; + int len = h->size[fast]; + + if (magbits && len + magbits <= FAST_BITS) { + // magnitude code followed by receive_extend code + int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); + int m = 1 << (magbits - 1); + if (k < m) k += (~0U << magbits) + 1; + // if the result is small enough, we can fit it in fast_ac table + if (k >= -128 && k <= 127) + fast_ac[i] = (stbi__int16) ((k * 256) + (run * 16) + (len + magbits)); + } + } + } +} + +static void stbi__grow_buffer_unsafe(stbi__jpeg *j) +{ + do { + unsigned int b = j->nomore ? 0 : stbi__get8(j->s); + if (b == 0xff) { + int c = stbi__get8(j->s); + while (c == 0xff) c = stbi__get8(j->s); // consume fill bytes + if (c != 0) { + j->marker = (unsigned char) c; + j->nomore = 1; + return; + } + } + j->code_buffer |= b << (24 - j->code_bits); + j->code_bits += 8; + } while (j->code_bits <= 24); +} + +// (1 << n) - 1 +static const stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; + +// decode a jpeg huffman value from the bitstream +stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) +{ + unsigned int temp; + int c,k; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + // look at the top FAST_BITS and determine what symbol ID it is, + // if the code is <= FAST_BITS + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + k = h->fast[c]; + if (k < 255) { + int s = h->size[k]; + if (s > j->code_bits) + return -1; + j->code_buffer <<= s; + j->code_bits -= s; + return h->values[k]; + } + + // naive test is to shift the code_buffer down so k bits are + // valid, then test against maxcode. To speed this up, we've + // preshifted maxcode left so that it has (16-k) 0s at the + // end; in other words, regardless of the number of bits, it + // wants to be compared against something shifted to have 16; + // that way we don't need to shift inside the loop. + temp = j->code_buffer >> 16; + for (k=FAST_BITS+1 ; ; ++k) + if (temp < h->maxcode[k]) + break; + if (k == 17) { + // error! code not found + j->code_bits -= 16; + return -1; + } + + if (k > j->code_bits) + return -1; + + // convert the huffman code to the symbol id + c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; + if(c < 0 || c >= 256) // symbol id out of bounds! + return -1; + STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); + + // convert the id to a symbol + j->code_bits -= k; + j->code_buffer <<= k; + return h->values[c]; +} + +// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + + sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative) + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k + (stbi__jbias[n] & (sgn - 1)); +} + +// get some unsigned bits +stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) +{ + unsigned int k; + if (j->code_bits < n) stbi__grow_buffer_unsafe(j); + if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing + k = stbi_lrot(j->code_buffer, n); + j->code_buffer = k & ~stbi__bmask[n]; + k &= stbi__bmask[n]; + j->code_bits -= n; + return k; +} + +stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) +{ + unsigned int k; + if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); + if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing + k = j->code_buffer; + j->code_buffer <<= 1; + --j->code_bits; + return k & 0x80000000; +} + +// given a value that's at position X in the zigzag stream, +// where does it appear in the 8x8 matrix coded as row-major? +static const stbi_uc stbi__jpeg_dezigzag[64+15] = +{ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63, + // let corrupt input sample past end + 63, 63, 63, 63, 63, 63, 63, 63, + 63, 63, 63, 63, 63, 63, 63 +}; + +// decode one 64-entry block-- +static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi__uint16 *dequant) +{ + int diff,dc,k; + int t; + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("bad huffman code","Corrupt JPEG"); + + // 0 all the ac values now so we can do it 32-bits at a time + memset(data,0,64*sizeof(data[0])); + + diff = t ? stbi__extend_receive(j, t) : 0; + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * dequant[0]); + + // decode AC components, see JPEG spec + k = 1; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * dequant[zig]); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (rs != 0xf0) break; // end block + k += 16; + } else { + k += r; + // decode into unzigzag'd location + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); + } + } + } while (k < 64); + return 1; +} + +static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) +{ + int diff,dc; + int t; + if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + + if (j->succ_high == 0) { + // first scan for DC coefficient, must be first + memset(data,0,64*sizeof(data[0])); // 0 all the ac values now + t = stbi__jpeg_huff_decode(j, hdc); + if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + diff = t ? stbi__extend_receive(j, t) : 0; + + if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG"); + dc = j->img_comp[b].dc_pred + diff; + j->img_comp[b].dc_pred = dc; + if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + data[0] = (short) (dc * (1 << j->succ_low)); + } else { + // refinement scan for DC coefficient + if (stbi__jpeg_get_bit(j)) + data[0] += (short) (1 << j->succ_low); + } + return 1; +} + +// @OPTIMIZE: store non-zigzagged during the decode passes, +// and only de-zigzag when dequantizing +static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) +{ + int k; + if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); + + if (j->succ_high == 0) { + int shift = j->succ_low; + + if (j->eob_run) { + --j->eob_run; + return 1; + } + + k = j->spec_start; + do { + unsigned int zig; + int c,r,s; + if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); + c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); + r = fac[c]; + if (r) { // fast-AC path + k += (r >> 4) & 15; // run + s = r & 15; // combined length + if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available"); + j->code_buffer <<= s; + j->code_bits -= s; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) ((r >> 8) * (1 << shift)); + } else { + int rs = stbi__jpeg_huff_decode(j, hac); + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r); + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + --j->eob_run; + break; + } + k += 16; + } else { + k += r; + zig = stbi__jpeg_dezigzag[k++]; + data[zig] = (short) (stbi__extend_receive(j,s) * (1 << shift)); + } + } + } while (k <= j->spec_end); + } else { + // refinement scan for these AC coefficients + + short bit = (short) (1 << j->succ_low); + + if (j->eob_run) { + --j->eob_run; + for (k = j->spec_start; k <= j->spec_end; ++k) { + short *p = &data[stbi__jpeg_dezigzag[k]]; + if (*p != 0) + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } + } else { + k = j->spec_start; + do { + int r,s; + int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh + if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); + s = rs & 15; + r = rs >> 4; + if (s == 0) { + if (r < 15) { + j->eob_run = (1 << r) - 1; + if (r) + j->eob_run += stbi__jpeg_get_bits(j, r); + r = 64; // force end of block + } else { + // r=15 s=0 should write 16 0s, so we just do + // a run of 15 0s and then write s (which is 0), + // so we don't have to do anything special here + } + } else { + if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); + // sign bit + if (stbi__jpeg_get_bit(j)) + s = bit; + else + s = -bit; + } + + // advance by r + while (k <= j->spec_end) { + short *p = &data[stbi__jpeg_dezigzag[k++]]; + if (*p != 0) { + if (stbi__jpeg_get_bit(j)) + if ((*p & bit)==0) { + if (*p > 0) + *p += bit; + else + *p -= bit; + } + } else { + if (r == 0) { + *p = (short) s; + break; + } + --r; + } + } + } while (k <= j->spec_end); + } + } + return 1; +} + +// take a -128..127 value and stbi__clamp it and convert to 0..255 +stbi_inline static stbi_uc stbi__clamp(int x) +{ + // trick to use a single test to catch both cases + if ((unsigned int) x > 255) { + if (x < 0) return 0; + if (x > 255) return 255; + } + return (stbi_uc) x; +} + +#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) +#define stbi__fsh(x) ((x) * 4096) + +// derived from jidctint -- DCT_ISLOW +#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ + int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ + p2 = s2; \ + p3 = s6; \ + p1 = (p2+p3) * stbi__f2f(0.5411961f); \ + t2 = p1 + p3*stbi__f2f(-1.847759065f); \ + t3 = p1 + p2*stbi__f2f( 0.765366865f); \ + p2 = s0; \ + p3 = s4; \ + t0 = stbi__fsh(p2+p3); \ + t1 = stbi__fsh(p2-p3); \ + x0 = t0+t3; \ + x3 = t0-t3; \ + x1 = t1+t2; \ + x2 = t1-t2; \ + t0 = s7; \ + t1 = s5; \ + t2 = s3; \ + t3 = s1; \ + p3 = t0+t2; \ + p4 = t1+t3; \ + p1 = t0+t3; \ + p2 = t1+t2; \ + p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ + t0 = t0*stbi__f2f( 0.298631336f); \ + t1 = t1*stbi__f2f( 2.053119869f); \ + t2 = t2*stbi__f2f( 3.072711026f); \ + t3 = t3*stbi__f2f( 1.501321110f); \ + p1 = p5 + p1*stbi__f2f(-0.899976223f); \ + p2 = p5 + p2*stbi__f2f(-2.562915447f); \ + p3 = p3*stbi__f2f(-1.961570560f); \ + p4 = p4*stbi__f2f(-0.390180644f); \ + t3 += p1+p4; \ + t2 += p2+p3; \ + t1 += p2+p4; \ + t0 += p1+p3; + +static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) +{ + int i,val[64],*v=val; + stbi_uc *o; + short *d = data; + + // columns + for (i=0; i < 8; ++i,++d, ++v) { + // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing + if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 + && d[40]==0 && d[48]==0 && d[56]==0) { + // no shortcut 0 seconds + // (1|2|3|4|5|6|7)==0 0 seconds + // all separate -0.047 seconds + // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds + int dcterm = d[0]*4; + v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; + } else { + STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) + // constants scaled things up by 1<<12; let's bring them back + // down, but keep 2 extra bits of precision + x0 += 512; x1 += 512; x2 += 512; x3 += 512; + v[ 0] = (x0+t3) >> 10; + v[56] = (x0-t3) >> 10; + v[ 8] = (x1+t2) >> 10; + v[48] = (x1-t2) >> 10; + v[16] = (x2+t1) >> 10; + v[40] = (x2-t1) >> 10; + v[24] = (x3+t0) >> 10; + v[32] = (x3-t0) >> 10; + } + } + + for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { + // no fast case since the first 1D IDCT spread components out + STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) + // constants scaled things up by 1<<12, plus we had 1<<2 from first + // loop, plus horizontal and vertical each scale by sqrt(8) so together + // we've got an extra 1<<3, so 1<<17 total we need to remove. + // so we want to round that, which means adding 0.5 * 1<<17, + // aka 65536. Also, we'll end up with -128 to 127 that we want + // to encode as 0..255 by adding 128, so we'll add that before the shift + x0 += 65536 + (128<<17); + x1 += 65536 + (128<<17); + x2 += 65536 + (128<<17); + x3 += 65536 + (128<<17); + // tried computing the shifts into temps, or'ing the temps to see + // if any were out of range, but that was slower + o[0] = stbi__clamp((x0+t3) >> 17); + o[7] = stbi__clamp((x0-t3) >> 17); + o[1] = stbi__clamp((x1+t2) >> 17); + o[6] = stbi__clamp((x1-t2) >> 17); + o[2] = stbi__clamp((x2+t1) >> 17); + o[5] = stbi__clamp((x2-t1) >> 17); + o[3] = stbi__clamp((x3+t0) >> 17); + o[4] = stbi__clamp((x3-t0) >> 17); + } +} + +#ifdef STBI_SSE2 +// sse2 integer IDCT. not the fastest possible implementation but it +// produces bit-identical results to the generic C version so it's +// fully "transparent". +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + // This is constructed to match our regular (generic) integer IDCT exactly. + __m128i row0, row1, row2, row3, row4, row5, row6, row7; + __m128i tmp; + + // dot product constant: even elems=x, odd elems=y + #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) + + // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) + // out(1) = c1[even]*x + c1[odd]*y + #define dct_rot(out0,out1, x,y,c0,c1) \ + __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ + __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ + __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ + __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ + __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ + __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) + + // out = in << 12 (in 16-bit, out 32-bit) + #define dct_widen(out, in) \ + __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ + __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) + + // wide add + #define dct_wadd(out, a, b) \ + __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_add_epi32(a##_h, b##_h) + + // wide sub + #define dct_wsub(out, a, b) \ + __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ + __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) + + // butterfly a/b, add bias, then shift by "s" and pack + #define dct_bfly32o(out0, out1, a,b,bias,s) \ + { \ + __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ + __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ + dct_wadd(sum, abiased, b); \ + dct_wsub(dif, abiased, b); \ + out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ + out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ + } + + // 8-bit interleave step (for transposes) + #define dct_interleave8(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi8(a, b); \ + b = _mm_unpackhi_epi8(tmp, b) + + // 16-bit interleave step (for transposes) + #define dct_interleave16(a, b) \ + tmp = a; \ + a = _mm_unpacklo_epi16(a, b); \ + b = _mm_unpackhi_epi16(tmp, b) + + #define dct_pass(bias,shift) \ + { \ + /* even part */ \ + dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ + __m128i sum04 = _mm_add_epi16(row0, row4); \ + __m128i dif04 = _mm_sub_epi16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ + dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ + __m128i sum17 = _mm_add_epi16(row1, row7); \ + __m128i sum35 = _mm_add_epi16(row3, row5); \ + dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ + dct_wadd(x4, y0o, y4o); \ + dct_wadd(x5, y1o, y5o); \ + dct_wadd(x6, y2o, y5o); \ + dct_wadd(x7, y3o, y4o); \ + dct_bfly32o(row0,row7, x0,x7,bias,shift); \ + dct_bfly32o(row1,row6, x1,x6,bias,shift); \ + dct_bfly32o(row2,row5, x2,x5,bias,shift); \ + dct_bfly32o(row3,row4, x3,x4,bias,shift); \ + } + + __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); + __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); + __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); + __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); + __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); + __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); + __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); + __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); + + // rounding biases in column/row passes, see stbi__idct_block for explanation. + __m128i bias_0 = _mm_set1_epi32(512); + __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); + + // load + row0 = _mm_load_si128((const __m128i *) (data + 0*8)); + row1 = _mm_load_si128((const __m128i *) (data + 1*8)); + row2 = _mm_load_si128((const __m128i *) (data + 2*8)); + row3 = _mm_load_si128((const __m128i *) (data + 3*8)); + row4 = _mm_load_si128((const __m128i *) (data + 4*8)); + row5 = _mm_load_si128((const __m128i *) (data + 5*8)); + row6 = _mm_load_si128((const __m128i *) (data + 6*8)); + row7 = _mm_load_si128((const __m128i *) (data + 7*8)); + + // column pass + dct_pass(bias_0, 10); + + { + // 16bit 8x8 transpose pass 1 + dct_interleave16(row0, row4); + dct_interleave16(row1, row5); + dct_interleave16(row2, row6); + dct_interleave16(row3, row7); + + // transpose pass 2 + dct_interleave16(row0, row2); + dct_interleave16(row1, row3); + dct_interleave16(row4, row6); + dct_interleave16(row5, row7); + + // transpose pass 3 + dct_interleave16(row0, row1); + dct_interleave16(row2, row3); + dct_interleave16(row4, row5); + dct_interleave16(row6, row7); + } + + // row pass + dct_pass(bias_1, 17); + + { + // pack + __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 + __m128i p1 = _mm_packus_epi16(row2, row3); + __m128i p2 = _mm_packus_epi16(row4, row5); + __m128i p3 = _mm_packus_epi16(row6, row7); + + // 8bit 8x8 transpose pass 1 + dct_interleave8(p0, p2); // a0e0a1e1... + dct_interleave8(p1, p3); // c0g0c1g1... + + // transpose pass 2 + dct_interleave8(p0, p1); // a0c0e0g0... + dct_interleave8(p2, p3); // b0d0f0h0... + + // transpose pass 3 + dct_interleave8(p0, p2); // a0b0c0d0... + dct_interleave8(p1, p3); // a4b4c4d4... + + // store + _mm_storel_epi64((__m128i *) out, p0); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p2); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p1); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; + _mm_storel_epi64((__m128i *) out, p3); out += out_stride; + _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); + } + +#undef dct_const +#undef dct_rot +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_interleave8 +#undef dct_interleave16 +#undef dct_pass +} + +#endif // STBI_SSE2 + +#ifdef STBI_NEON + +// NEON integer IDCT. should produce bit-identical +// results to the generic C version. +static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) +{ + int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; + + int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); + int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); + int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); + int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); + int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); + int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); + int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); + int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); + int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); + int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); + int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); + int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); + +#define dct_long_mul(out, inq, coeff) \ + int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) + +#define dct_long_mac(out, acc, inq, coeff) \ + int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ + int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) + +#define dct_widen(out, inq) \ + int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ + int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) + +// wide add +#define dct_wadd(out, a, b) \ + int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vaddq_s32(a##_h, b##_h) + +// wide sub +#define dct_wsub(out, a, b) \ + int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ + int32x4_t out##_h = vsubq_s32(a##_h, b##_h) + +// butterfly a/b, then shift using "shiftop" by "s" and pack +#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ + { \ + dct_wadd(sum, a, b); \ + dct_wsub(dif, a, b); \ + out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ + out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ + } + +#define dct_pass(shiftop, shift) \ + { \ + /* even part */ \ + int16x8_t sum26 = vaddq_s16(row2, row6); \ + dct_long_mul(p1e, sum26, rot0_0); \ + dct_long_mac(t2e, p1e, row6, rot0_1); \ + dct_long_mac(t3e, p1e, row2, rot0_2); \ + int16x8_t sum04 = vaddq_s16(row0, row4); \ + int16x8_t dif04 = vsubq_s16(row0, row4); \ + dct_widen(t0e, sum04); \ + dct_widen(t1e, dif04); \ + dct_wadd(x0, t0e, t3e); \ + dct_wsub(x3, t0e, t3e); \ + dct_wadd(x1, t1e, t2e); \ + dct_wsub(x2, t1e, t2e); \ + /* odd part */ \ + int16x8_t sum15 = vaddq_s16(row1, row5); \ + int16x8_t sum17 = vaddq_s16(row1, row7); \ + int16x8_t sum35 = vaddq_s16(row3, row5); \ + int16x8_t sum37 = vaddq_s16(row3, row7); \ + int16x8_t sumodd = vaddq_s16(sum17, sum35); \ + dct_long_mul(p5o, sumodd, rot1_0); \ + dct_long_mac(p1o, p5o, sum17, rot1_1); \ + dct_long_mac(p2o, p5o, sum35, rot1_2); \ + dct_long_mul(p3o, sum37, rot2_0); \ + dct_long_mul(p4o, sum15, rot2_1); \ + dct_wadd(sump13o, p1o, p3o); \ + dct_wadd(sump24o, p2o, p4o); \ + dct_wadd(sump23o, p2o, p3o); \ + dct_wadd(sump14o, p1o, p4o); \ + dct_long_mac(x4, sump13o, row7, rot3_0); \ + dct_long_mac(x5, sump24o, row5, rot3_1); \ + dct_long_mac(x6, sump23o, row3, rot3_2); \ + dct_long_mac(x7, sump14o, row1, rot3_3); \ + dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ + dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ + dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ + dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ + } + + // load + row0 = vld1q_s16(data + 0*8); + row1 = vld1q_s16(data + 1*8); + row2 = vld1q_s16(data + 2*8); + row3 = vld1q_s16(data + 3*8); + row4 = vld1q_s16(data + 4*8); + row5 = vld1q_s16(data + 5*8); + row6 = vld1q_s16(data + 6*8); + row7 = vld1q_s16(data + 7*8); + + // add DC bias + row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); + + // column pass + dct_pass(vrshrn_n_s32, 10); + + // 16bit 8x8 transpose + { +// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. +// whether compilers actually get this is another story, sadly. +#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } +#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } + + // pass 1 + dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 + dct_trn16(row2, row3); + dct_trn16(row4, row5); + dct_trn16(row6, row7); + + // pass 2 + dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 + dct_trn32(row1, row3); + dct_trn32(row4, row6); + dct_trn32(row5, row7); + + // pass 3 + dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 + dct_trn64(row1, row5); + dct_trn64(row2, row6); + dct_trn64(row3, row7); + +#undef dct_trn16 +#undef dct_trn32 +#undef dct_trn64 + } + + // row pass + // vrshrn_n_s32 only supports shifts up to 16, we need + // 17. so do a non-rounding shift of 16 first then follow + // up with a rounding shift by 1. + dct_pass(vshrn_n_s32, 16); + + { + // pack and round + uint8x8_t p0 = vqrshrun_n_s16(row0, 1); + uint8x8_t p1 = vqrshrun_n_s16(row1, 1); + uint8x8_t p2 = vqrshrun_n_s16(row2, 1); + uint8x8_t p3 = vqrshrun_n_s16(row3, 1); + uint8x8_t p4 = vqrshrun_n_s16(row4, 1); + uint8x8_t p5 = vqrshrun_n_s16(row5, 1); + uint8x8_t p6 = vqrshrun_n_s16(row6, 1); + uint8x8_t p7 = vqrshrun_n_s16(row7, 1); + + // again, these can translate into one instruction, but often don't. +#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } +#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } +#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } + + // sadly can't use interleaved stores here since we only write + // 8 bytes to each scan line! + + // 8x8 8-bit transpose pass 1 + dct_trn8_8(p0, p1); + dct_trn8_8(p2, p3); + dct_trn8_8(p4, p5); + dct_trn8_8(p6, p7); + + // pass 2 + dct_trn8_16(p0, p2); + dct_trn8_16(p1, p3); + dct_trn8_16(p4, p6); + dct_trn8_16(p5, p7); + + // pass 3 + dct_trn8_32(p0, p4); + dct_trn8_32(p1, p5); + dct_trn8_32(p2, p6); + dct_trn8_32(p3, p7); + + // store + vst1_u8(out, p0); out += out_stride; + vst1_u8(out, p1); out += out_stride; + vst1_u8(out, p2); out += out_stride; + vst1_u8(out, p3); out += out_stride; + vst1_u8(out, p4); out += out_stride; + vst1_u8(out, p5); out += out_stride; + vst1_u8(out, p6); out += out_stride; + vst1_u8(out, p7); + +#undef dct_trn8_8 +#undef dct_trn8_16 +#undef dct_trn8_32 + } + +#undef dct_long_mul +#undef dct_long_mac +#undef dct_widen +#undef dct_wadd +#undef dct_wsub +#undef dct_bfly32o +#undef dct_pass +} + +#endif // STBI_NEON + +#define STBI__MARKER_none 0xff +// if there's a pending marker from the entropy stream, return that +// otherwise, fetch from the stream and get a marker. if there's no +// marker, return 0xff, which is never a valid marker value +static stbi_uc stbi__get_marker(stbi__jpeg *j) +{ + stbi_uc x; + if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } + x = stbi__get8(j->s); + if (x != 0xff) return STBI__MARKER_none; + while (x == 0xff) + x = stbi__get8(j->s); // consume repeated 0xff fill bytes + return x; +} + +// in each scan, we'll have scan_n components, and the order +// of the components is specified by order[] +#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) + +// after a restart interval, stbi__jpeg_reset the entropy decoder and +// the dc prediction +static void stbi__jpeg_reset(stbi__jpeg *j) +{ + j->code_bits = 0; + j->code_buffer = 0; + j->nomore = 0; + j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = j->img_comp[3].dc_pred = 0; + j->marker = STBI__MARKER_none; + j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; + j->eob_run = 0; + // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, + // since we don't even allow 1<<30 pixels +} + +static int stbi__parse_entropy_coded_data(stbi__jpeg *z) +{ + stbi__jpeg_reset(z); + if (!z->progressive) { + if (z->scan_n == 1) { + int i,j; + STBI_SIMD_ALIGN(short, data[64]); + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + // if it's NOT a restart, then just bail, so we get corrupt data + // rather than no data + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + STBI_SIMD_ALIGN(short, data[64]); + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x)*8; + int y2 = (j*z->img_comp[n].v + y)*8; + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } else { + if (z->scan_n == 1) { + int i,j; + int n = z->order[0]; + // non-interleaved data, we just need to process one block at a time, + // in trivial scanline order + // number of blocks to do just depends on how many actual "pixels" this + // component has, independent of interleaved MCU blocking and such + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + if (z->spec_start == 0) { + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } else { + int ha = z->img_comp[n].ha; + if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) + return 0; + } + // every data block is an MCU, so countdown the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } else { // interleaved + int i,j,k,x,y; + for (j=0; j < z->img_mcu_y; ++j) { + for (i=0; i < z->img_mcu_x; ++i) { + // scan an interleaved mcu... process scan_n components in order + for (k=0; k < z->scan_n; ++k) { + int n = z->order[k]; + // scan out an mcu's worth of this component; that's just determined + // by the basic H and V specified for the component + for (y=0; y < z->img_comp[n].v; ++y) { + for (x=0; x < z->img_comp[n].h; ++x) { + int x2 = (i*z->img_comp[n].h + x); + int y2 = (j*z->img_comp[n].v + y); + short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); + if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) + return 0; + } + } + } + // after all interleaved components, that's an interleaved MCU, + // so now count down the restart interval + if (--z->todo <= 0) { + if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); + if (!STBI__RESTART(z->marker)) return 1; + stbi__jpeg_reset(z); + } + } + } + return 1; + } + } +} + +static void stbi__jpeg_dequantize(short *data, stbi__uint16 *dequant) +{ + int i; + for (i=0; i < 64; ++i) + data[i] *= dequant[i]; +} + +static void stbi__jpeg_finish(stbi__jpeg *z) +{ + if (z->progressive) { + // dequantize and idct the data + int i,j,n; + for (n=0; n < z->s->img_n; ++n) { + int w = (z->img_comp[n].x+7) >> 3; + int h = (z->img_comp[n].y+7) >> 3; + for (j=0; j < h; ++j) { + for (i=0; i < w; ++i) { + short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); + stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); + z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); + } + } + } + } +} + +static int stbi__process_marker(stbi__jpeg *z, int m) +{ + int L; + switch (m) { + case STBI__MARKER_none: // no marker found + return stbi__err("expected marker","Corrupt JPEG"); + + case 0xDD: // DRI - specify restart interval + if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); + z->restart_interval = stbi__get16be(z->s); + return 1; + + case 0xDB: // DQT - define quantization table + L = stbi__get16be(z->s)-2; + while (L > 0) { + int q = stbi__get8(z->s); + int p = q >> 4, sixteen = (p != 0); + int t = q & 15,i; + if (p != 0 && p != 1) return stbi__err("bad DQT type","Corrupt JPEG"); + if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); + + for (i=0; i < 64; ++i) + z->dequant[t][stbi__jpeg_dezigzag[i]] = (stbi__uint16)(sixteen ? stbi__get16be(z->s) : stbi__get8(z->s)); + L -= (sixteen ? 129 : 65); + } + return L==0; + + case 0xC4: // DHT - define huffman table + L = stbi__get16be(z->s)-2; + while (L > 0) { + stbi_uc *v; + int sizes[16],i,n=0; + int q = stbi__get8(z->s); + int tc = q >> 4; + int th = q & 15; + if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); + for (i=0; i < 16; ++i) { + sizes[i] = stbi__get8(z->s); + n += sizes[i]; + } + if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values! + L -= 17; + if (tc == 0) { + if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; + v = z->huff_dc[th].values; + } else { + if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; + v = z->huff_ac[th].values; + } + for (i=0; i < n; ++i) + v[i] = stbi__get8(z->s); + if (tc != 0) + stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); + L -= n; + } + return L==0; + } + + // check for comment block or APP blocks + if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { + L = stbi__get16be(z->s); + if (L < 2) { + if (m == 0xFE) + return stbi__err("bad COM len","Corrupt JPEG"); + else + return stbi__err("bad APP len","Corrupt JPEG"); + } + L -= 2; + + if (m == 0xE0 && L >= 5) { // JFIF APP0 segment + static const unsigned char tag[5] = {'J','F','I','F','\0'}; + int ok = 1; + int i; + for (i=0; i < 5; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 5; + if (ok) + z->jfif = 1; + } else if (m == 0xEE && L >= 12) { // Adobe APP14 segment + static const unsigned char tag[6] = {'A','d','o','b','e','\0'}; + int ok = 1; + int i; + for (i=0; i < 6; ++i) + if (stbi__get8(z->s) != tag[i]) + ok = 0; + L -= 6; + if (ok) { + stbi__get8(z->s); // version + stbi__get16be(z->s); // flags0 + stbi__get16be(z->s); // flags1 + z->app14_color_transform = stbi__get8(z->s); // color transform + L -= 6; + } + } + + stbi__skip(z->s, L); + return 1; + } + + return stbi__err("unknown marker","Corrupt JPEG"); +} + +// after we see SOS +static int stbi__process_scan_header(stbi__jpeg *z) +{ + int i; + int Ls = stbi__get16be(z->s); + z->scan_n = stbi__get8(z->s); + if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); + if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); + for (i=0; i < z->scan_n; ++i) { + int id = stbi__get8(z->s), which; + int q = stbi__get8(z->s); + for (which = 0; which < z->s->img_n; ++which) + if (z->img_comp[which].id == id) + break; + if (which == z->s->img_n) return 0; // no match + z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); + z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); + z->order[i] = which; + } + + { + int aa; + z->spec_start = stbi__get8(z->s); + z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 + aa = stbi__get8(z->s); + z->succ_high = (aa >> 4); + z->succ_low = (aa & 15); + if (z->progressive) { + if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) + return stbi__err("bad SOS", "Corrupt JPEG"); + } else { + if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); + if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); + z->spec_end = 63; + } + } + + return 1; +} + +static int stbi__free_jpeg_components(stbi__jpeg *z, int ncomp, int why) +{ + int i; + for (i=0; i < ncomp; ++i) { + if (z->img_comp[i].raw_data) { + STBI_FREE(z->img_comp[i].raw_data); + z->img_comp[i].raw_data = NULL; + z->img_comp[i].data = NULL; + } + if (z->img_comp[i].raw_coeff) { + STBI_FREE(z->img_comp[i].raw_coeff); + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].coeff = 0; + } + if (z->img_comp[i].linebuf) { + STBI_FREE(z->img_comp[i].linebuf); + z->img_comp[i].linebuf = NULL; + } + } + return why; +} + +static int stbi__process_frame_header(stbi__jpeg *z, int scan) +{ + stbi__context *s = z->s; + int Lf,p,i,q, h_max=1,v_max=1,c; + Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG + p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline + s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG + s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + c = stbi__get8(s); + if (c != 3 && c != 1 && c != 4) return stbi__err("bad component count","Corrupt JPEG"); + s->img_n = c; + for (i=0; i < c; ++i) { + z->img_comp[i].data = NULL; + z->img_comp[i].linebuf = NULL; + } + + if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); + + z->rgb = 0; + for (i=0; i < s->img_n; ++i) { + static const unsigned char rgb[3] = { 'R', 'G', 'B' }; + z->img_comp[i].id = stbi__get8(s); + if (s->img_n == 3 && z->img_comp[i].id == rgb[i]) + ++z->rgb; + q = stbi__get8(s); + z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); + z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); + z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); + } + + if (scan != STBI__SCAN_load) return 1; + + if (!stbi__mad3sizes_valid(s->img_x, s->img_y, s->img_n, 0)) return stbi__err("too large", "Image too large to decode"); + + for (i=0; i < s->img_n; ++i) { + if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; + if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; + } + + // check that plane subsampling factors are integer ratios; our resamplers can't deal with fractional ratios + // and I've never seen a non-corrupted JPEG file actually use them + for (i=0; i < s->img_n; ++i) { + if (h_max % z->img_comp[i].h != 0) return stbi__err("bad H","Corrupt JPEG"); + if (v_max % z->img_comp[i].v != 0) return stbi__err("bad V","Corrupt JPEG"); + } + + // compute interleaved mcu info + z->img_h_max = h_max; + z->img_v_max = v_max; + z->img_mcu_w = h_max * 8; + z->img_mcu_h = v_max * 8; + // these sizes can't be more than 17 bits + z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; + z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; + + for (i=0; i < s->img_n; ++i) { + // number of effective pixels (e.g. for non-interleaved MCU) + z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; + z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; + // to simplify generation, we'll allocate enough memory to decode + // the bogus oversized data from using interleaved MCUs and their + // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't + // discard the extra data until colorspace conversion + // + // img_mcu_x, img_mcu_y: <=17 bits; comp[i].h and .v are <=4 (checked earlier) + // so these muls can't overflow with 32-bit ints (which we require) + z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; + z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; + z->img_comp[i].coeff = 0; + z->img_comp[i].raw_coeff = 0; + z->img_comp[i].linebuf = NULL; + z->img_comp[i].raw_data = stbi__malloc_mad2(z->img_comp[i].w2, z->img_comp[i].h2, 15); + if (z->img_comp[i].raw_data == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + // align blocks for idct using mmx/sse + z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); + if (z->progressive) { + // w2, h2 are multiples of 8 (see above) + z->img_comp[i].coeff_w = z->img_comp[i].w2 / 8; + z->img_comp[i].coeff_h = z->img_comp[i].h2 / 8; + z->img_comp[i].raw_coeff = stbi__malloc_mad3(z->img_comp[i].w2, z->img_comp[i].h2, sizeof(short), 15); + if (z->img_comp[i].raw_coeff == NULL) + return stbi__free_jpeg_components(z, i+1, stbi__err("outofmem", "Out of memory")); + z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); + } + } + + return 1; +} + +// use comparisons since in some cases we handle more than one case (e.g. SOF) +#define stbi__DNL(x) ((x) == 0xdc) +#define stbi__SOI(x) ((x) == 0xd8) +#define stbi__EOI(x) ((x) == 0xd9) +#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) +#define stbi__SOS(x) ((x) == 0xda) + +#define stbi__SOF_progressive(x) ((x) == 0xc2) + +static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) +{ + int m; + z->jfif = 0; + z->app14_color_transform = -1; // valid values are 0,1,2 + z->marker = STBI__MARKER_none; // initialize cached marker to empty + m = stbi__get_marker(z); + if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); + if (scan == STBI__SCAN_type) return 1; + m = stbi__get_marker(z); + while (!stbi__SOF(m)) { + if (!stbi__process_marker(z,m)) return 0; + m = stbi__get_marker(z); + while (m == STBI__MARKER_none) { + // some files have extra padding after their blocks, so ok, we'll scan + if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); + m = stbi__get_marker(z); + } + } + z->progressive = stbi__SOF_progressive(m); + if (!stbi__process_frame_header(z, scan)) return 0; + return 1; +} + +static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j) +{ + // some JPEGs have junk at end, skip over it but if we find what looks + // like a valid marker, resume there + while (!stbi__at_eof(j->s)) { + stbi_uc x = stbi__get8(j->s); + while (x == 0xff) { // might be a marker + if (stbi__at_eof(j->s)) return STBI__MARKER_none; + x = stbi__get8(j->s); + if (x != 0x00 && x != 0xff) { + // not a stuffed zero or lead-in to another marker, looks + // like an actual marker, return it + return x; + } + // stuffed zero has x=0 now which ends the loop, meaning we go + // back to regular scan loop. + // repeated 0xff keeps trying to read the next byte of the marker. + } + } + return STBI__MARKER_none; +} + +// decode image to YCbCr format +static int stbi__decode_jpeg_image(stbi__jpeg *j) +{ + int m; + for (m = 0; m < 4; m++) { + j->img_comp[m].raw_data = NULL; + j->img_comp[m].raw_coeff = NULL; + } + j->restart_interval = 0; + if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; + m = stbi__get_marker(j); + while (!stbi__EOI(m)) { + if (stbi__SOS(m)) { + if (!stbi__process_scan_header(j)) return 0; + if (!stbi__parse_entropy_coded_data(j)) return 0; + if (j->marker == STBI__MARKER_none ) { + j->marker = stbi__skip_jpeg_junk_at_end(j); + // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 + } + m = stbi__get_marker(j); + if (STBI__RESTART(m)) + m = stbi__get_marker(j); + } else if (stbi__DNL(m)) { + int Ld = stbi__get16be(j->s); + stbi__uint32 NL = stbi__get16be(j->s); + if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG"); + if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG"); + m = stbi__get_marker(j); + } else { + if (!stbi__process_marker(j, m)) return 1; + m = stbi__get_marker(j); + } + } + if (j->progressive) + stbi__jpeg_finish(j); + return 1; +} + +// static jfif-centered resampling (across block boundaries) + +typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, + int w, int hs); + +#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) + +static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + STBI_NOTUSED(out); + STBI_NOTUSED(in_far); + STBI_NOTUSED(w); + STBI_NOTUSED(hs); + return in_near; +} + +static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples vertically for every one in input + int i; + STBI_NOTUSED(hs); + for (i=0; i < w; ++i) + out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); + return out; +} + +static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate two samples horizontally for every one in input + int i; + stbi_uc *input = in_near; + + if (w == 1) { + // if only one sample, can't do any interpolation + out[0] = out[1] = input[0]; + return out; + } + + out[0] = input[0]; + out[1] = stbi__div4(input[0]*3 + input[1] + 2); + for (i=1; i < w-1; ++i) { + int n = 3*input[i]+2; + out[i*2+0] = stbi__div4(n+input[i-1]); + out[i*2+1] = stbi__div4(n+input[i+1]); + } + out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); + out[i*2+1] = input[w-1]; + + STBI_NOTUSED(in_far); + STBI_NOTUSED(hs); + + return out; +} + +#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) + +static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i,t0,t1; + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + out[0] = stbi__div4(t1+2); + for (i=1; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // need to generate 2x2 samples for every one in input + int i=0,t0,t1; + + if (w == 1) { + out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); + return out; + } + + t1 = 3*in_near[0] + in_far[0]; + // process groups of 8 pixels for as long as we can. + // note we can't handle the last pixel in a row in this loop + // because we need to handle the filter boundary conditions. + for (; i < ((w-1) & ~7); i += 8) { +#if defined(STBI_SSE2) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + __m128i zero = _mm_setzero_si128(); + __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); + __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); + __m128i farw = _mm_unpacklo_epi8(farb, zero); + __m128i nearw = _mm_unpacklo_epi8(nearb, zero); + __m128i diff = _mm_sub_epi16(farw, nearw); + __m128i nears = _mm_slli_epi16(nearw, 2); + __m128i curr = _mm_add_epi16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + __m128i prv0 = _mm_slli_si128(curr, 2); + __m128i nxt0 = _mm_srli_si128(curr, 2); + __m128i prev = _mm_insert_epi16(prv0, t1, 0); + __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + __m128i bias = _mm_set1_epi16(8); + __m128i curs = _mm_slli_epi16(curr, 2); + __m128i prvd = _mm_sub_epi16(prev, curr); + __m128i nxtd = _mm_sub_epi16(next, curr); + __m128i curb = _mm_add_epi16(curs, bias); + __m128i even = _mm_add_epi16(prvd, curb); + __m128i odd = _mm_add_epi16(nxtd, curb); + + // interleave even and odd pixels, then undo scaling. + __m128i int0 = _mm_unpacklo_epi16(even, odd); + __m128i int1 = _mm_unpackhi_epi16(even, odd); + __m128i de0 = _mm_srli_epi16(int0, 4); + __m128i de1 = _mm_srli_epi16(int1, 4); + + // pack and write output + __m128i outv = _mm_packus_epi16(de0, de1); + _mm_storeu_si128((__m128i *) (out + i*2), outv); +#elif defined(STBI_NEON) + // load and perform the vertical filtering pass + // this uses 3*x + y = 4*x + (y - x) + uint8x8_t farb = vld1_u8(in_far + i); + uint8x8_t nearb = vld1_u8(in_near + i); + int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); + int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); + int16x8_t curr = vaddq_s16(nears, diff); // current row + + // horizontal filter works the same based on shifted vers of current + // row. "prev" is current row shifted right by 1 pixel; we need to + // insert the previous pixel value (from t1). + // "next" is current row shifted left by 1 pixel, with first pixel + // of next block of 8 pixels added in. + int16x8_t prv0 = vextq_s16(curr, curr, 7); + int16x8_t nxt0 = vextq_s16(curr, curr, 1); + int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); + int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); + + // horizontal filter, polyphase implementation since it's convenient: + // even pixels = 3*cur + prev = cur*4 + (prev - cur) + // odd pixels = 3*cur + next = cur*4 + (next - cur) + // note the shared term. + int16x8_t curs = vshlq_n_s16(curr, 2); + int16x8_t prvd = vsubq_s16(prev, curr); + int16x8_t nxtd = vsubq_s16(next, curr); + int16x8_t even = vaddq_s16(curs, prvd); + int16x8_t odd = vaddq_s16(curs, nxtd); + + // undo scaling and round, then store with even/odd phases interleaved + uint8x8x2_t o; + o.val[0] = vqrshrun_n_s16(even, 4); + o.val[1] = vqrshrun_n_s16(odd, 4); + vst2_u8(out + i*2, o); +#endif + + // "previous" value for next iter + t1 = 3*in_near[i+7] + in_far[i+7]; + } + + t0 = t1; + t1 = 3*in_near[i] + in_far[i]; + out[i*2] = stbi__div16(3*t1 + t0 + 8); + + for (++i; i < w; ++i) { + t0 = t1; + t1 = 3*in_near[i]+in_far[i]; + out[i*2-1] = stbi__div16(3*t0 + t1 + 8); + out[i*2 ] = stbi__div16(3*t1 + t0 + 8); + } + out[w*2-1] = stbi__div4(t1+2); + + STBI_NOTUSED(hs); + + return out; +} +#endif + +static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) +{ + // resample with nearest-neighbor + int i,j; + STBI_NOTUSED(in_far); + for (i=0; i < w; ++i) + for (j=0; j < hs; ++j) + out[i*hs+j] = in_near[i]; + return out; +} + +// this is a reduced-precision calculation of YCbCr-to-RGB introduced +// to make sure the code produces the same results in both SIMD and scalar +#define stbi__float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) +static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) +{ + int i; + for (i=0; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + (cr*-stbi__float2fixed(0.71414f)) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} + +#if defined(STBI_SSE2) || defined(STBI_NEON) +static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) +{ + int i = 0; + +#ifdef STBI_SSE2 + // step == 3 is pretty ugly on the final interleave, and i'm not convinced + // it's useful in practice (you wouldn't use it for textures, for example). + // so just accelerate step == 4 case. + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + __m128i signflip = _mm_set1_epi8(-0x80); + __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); + __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); + __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); + __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); + __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); + __m128i xw = _mm_set1_epi16(255); // alpha channel + + for (; i+7 < count; i += 8) { + // load + __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); + __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); + __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); + __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 + __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 + + // unpack to short (and left-shift cr, cb by 8) + __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); + __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); + __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); + + // color transform + __m128i yws = _mm_srli_epi16(yw, 4); + __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); + __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); + __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); + __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); + __m128i rws = _mm_add_epi16(cr0, yws); + __m128i gwt = _mm_add_epi16(cb0, yws); + __m128i bws = _mm_add_epi16(yws, cb1); + __m128i gws = _mm_add_epi16(gwt, cr1); + + // descale + __m128i rw = _mm_srai_epi16(rws, 4); + __m128i bw = _mm_srai_epi16(bws, 4); + __m128i gw = _mm_srai_epi16(gws, 4); + + // back to byte, set up for transpose + __m128i brb = _mm_packus_epi16(rw, bw); + __m128i gxb = _mm_packus_epi16(gw, xw); + + // transpose to interleave channels + __m128i t0 = _mm_unpacklo_epi8(brb, gxb); + __m128i t1 = _mm_unpackhi_epi8(brb, gxb); + __m128i o0 = _mm_unpacklo_epi16(t0, t1); + __m128i o1 = _mm_unpackhi_epi16(t0, t1); + + // store + _mm_storeu_si128((__m128i *) (out + 0), o0); + _mm_storeu_si128((__m128i *) (out + 16), o1); + out += 32; + } + } +#endif + +#ifdef STBI_NEON + // in this version, step=3 support would be easy to add. but is there demand? + if (step == 4) { + // this is a fairly straightforward implementation and not super-optimized. + uint8x8_t signflip = vdup_n_u8(0x80); + int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); + int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); + int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); + int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); + + for (; i+7 < count; i += 8) { + // load + uint8x8_t y_bytes = vld1_u8(y + i); + uint8x8_t cr_bytes = vld1_u8(pcr + i); + uint8x8_t cb_bytes = vld1_u8(pcb + i); + int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); + int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); + + // expand to s16 + int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); + int16x8_t crw = vshll_n_s8(cr_biased, 7); + int16x8_t cbw = vshll_n_s8(cb_biased, 7); + + // color transform + int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); + int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); + int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); + int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); + int16x8_t rws = vaddq_s16(yws, cr0); + int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); + int16x8_t bws = vaddq_s16(yws, cb1); + + // undo scaling, round, convert to byte + uint8x8x4_t o; + o.val[0] = vqrshrun_n_s16(rws, 4); + o.val[1] = vqrshrun_n_s16(gws, 4); + o.val[2] = vqrshrun_n_s16(bws, 4); + o.val[3] = vdup_n_u8(255); + + // store, interleaving r/g/b/a + vst4_u8(out, o); + out += 8*4; + } + } +#endif + + for (; i < count; ++i) { + int y_fixed = (y[i] << 20) + (1<<19); // rounding + int r,g,b; + int cr = pcr[i] - 128; + int cb = pcb[i] - 128; + r = y_fixed + cr* stbi__float2fixed(1.40200f); + g = y_fixed + cr*-stbi__float2fixed(0.71414f) + ((cb*-stbi__float2fixed(0.34414f)) & 0xffff0000); + b = y_fixed + cb* stbi__float2fixed(1.77200f); + r >>= 20; + g >>= 20; + b >>= 20; + if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } + if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } + if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } + out[0] = (stbi_uc)r; + out[1] = (stbi_uc)g; + out[2] = (stbi_uc)b; + out[3] = 255; + out += step; + } +} +#endif + +// set up the kernels +static void stbi__setup_jpeg(stbi__jpeg *j) +{ + j->idct_block_kernel = stbi__idct_block; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; + +#ifdef STBI_SSE2 + if (stbi__sse2_available()) { + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; + } +#endif + +#ifdef STBI_NEON + j->idct_block_kernel = stbi__idct_simd; + j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; + j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; +#endif +} + +// clean up the temporary component buffers +static void stbi__cleanup_jpeg(stbi__jpeg *j) +{ + stbi__free_jpeg_components(j, j->s->img_n, 0); +} + +typedef struct +{ + resample_row_func resample; + stbi_uc *line0,*line1; + int hs,vs; // expansion factor in each axis + int w_lores; // horizontal pixels pre-expansion + int ystep; // how far through vertical expansion we are + int ypos; // which pre-expansion row we're on +} stbi__resample; + +// fast 0..255 * 0..255 => 0..255 rounded multiplication +static stbi_uc stbi__blinn_8x8(stbi_uc x, stbi_uc y) +{ + unsigned int t = x*y + 128; + return (stbi_uc) ((t + (t >>8)) >> 8); +} + +static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) +{ + int n, decode_n, is_rgb; + z->s->img_n = 0; // make stbi__cleanup_jpeg safe + + // validate req_comp + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + + // load a jpeg image from whichever source, but leave in YCbCr format + if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } + + // determine actual number of components to generate + n = req_comp ? req_comp : z->s->img_n >= 3 ? 3 : 1; + + is_rgb = z->s->img_n == 3 && (z->rgb == 3 || (z->app14_color_transform == 0 && !z->jfif)); + + if (z->s->img_n == 3 && n < 3 && !is_rgb) + decode_n = 1; + else + decode_n = z->s->img_n; + + // nothing to do if no components requested; check this now to avoid + // accessing uninitialized coutput[0] later + if (decode_n <= 0) { stbi__cleanup_jpeg(z); return NULL; } + + // resample and color-convert + { + int k; + unsigned int i,j; + stbi_uc *output; + stbi_uc *coutput[4] = { NULL, NULL, NULL, NULL }; + + stbi__resample res_comp[4]; + + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + + // allocate line buffer big enough for upsampling off the edges + // with upsample factor of 4 + z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); + if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + r->hs = z->img_h_max / z->img_comp[k].h; + r->vs = z->img_v_max / z->img_comp[k].v; + r->ystep = r->vs >> 1; + r->w_lores = (z->s->img_x + r->hs-1) / r->hs; + r->ypos = 0; + r->line0 = r->line1 = z->img_comp[k].data; + + if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; + else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; + else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; + else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; + else r->resample = stbi__resample_row_generic; + } + + // can't error after this so, this is safe + output = (stbi_uc *) stbi__malloc_mad3(n, z->s->img_x, z->s->img_y, 1); + if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } + + // now go ahead and resample + for (j=0; j < z->s->img_y; ++j) { + stbi_uc *out = output + n * z->s->img_x * j; + for (k=0; k < decode_n; ++k) { + stbi__resample *r = &res_comp[k]; + int y_bot = r->ystep >= (r->vs >> 1); + coutput[k] = r->resample(z->img_comp[k].linebuf, + y_bot ? r->line1 : r->line0, + y_bot ? r->line0 : r->line1, + r->w_lores, r->hs); + if (++r->ystep >= r->vs) { + r->ystep = 0; + r->line0 = r->line1; + if (++r->ypos < z->img_comp[k].y) + r->line1 += z->img_comp[k].w2; + } + } + if (n >= 3) { + stbi_uc *y = coutput[0]; + if (z->s->img_n == 3) { + if (is_rgb) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = y[i]; + out[1] = coutput[1][i]; + out[2] = coutput[2][i]; + out[3] = 255; + out += n; + } + } else { + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else if (z->s->img_n == 4) { + if (z->app14_color_transform == 0) { // CMYK + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(coutput[0][i], m); + out[1] = stbi__blinn_8x8(coutput[1][i], m); + out[2] = stbi__blinn_8x8(coutput[2][i], m); + out[3] = 255; + out += n; + } + } else if (z->app14_color_transform == 2) { // YCCK + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + out[0] = stbi__blinn_8x8(255 - out[0], m); + out[1] = stbi__blinn_8x8(255 - out[1], m); + out[2] = stbi__blinn_8x8(255 - out[2], m); + out += n; + } + } else { // YCbCr + alpha? Ignore the fourth channel for now + z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); + } + } else + for (i=0; i < z->s->img_x; ++i) { + out[0] = out[1] = out[2] = y[i]; + out[3] = 255; // not used if n==3 + out += n; + } + } else { + if (is_rgb) { + if (n == 1) + for (i=0; i < z->s->img_x; ++i) + *out++ = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + else { + for (i=0; i < z->s->img_x; ++i, out += 2) { + out[0] = stbi__compute_y(coutput[0][i], coutput[1][i], coutput[2][i]); + out[1] = 255; + } + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 0) { + for (i=0; i < z->s->img_x; ++i) { + stbi_uc m = coutput[3][i]; + stbi_uc r = stbi__blinn_8x8(coutput[0][i], m); + stbi_uc g = stbi__blinn_8x8(coutput[1][i], m); + stbi_uc b = stbi__blinn_8x8(coutput[2][i], m); + out[0] = stbi__compute_y(r, g, b); + out[1] = 255; + out += n; + } + } else if (z->s->img_n == 4 && z->app14_color_transform == 2) { + for (i=0; i < z->s->img_x; ++i) { + out[0] = stbi__blinn_8x8(255 - coutput[0][i], coutput[3][i]); + out[1] = 255; + out += n; + } + } else { + stbi_uc *y = coutput[0]; + if (n == 1) + for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; + else + for (i=0; i < z->s->img_x; ++i) { *out++ = y[i]; *out++ = 255; } + } + } + } + stbi__cleanup_jpeg(z); + *out_x = z->s->img_x; + *out_y = z->s->img_y; + if (comp) *comp = z->s->img_n >= 3 ? 3 : 1; // report original components, not output + return output; + } +} + +static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + unsigned char* result; + stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__errpuc("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + STBI_NOTUSED(ri); + j->s = s; + stbi__setup_jpeg(j); + result = load_jpeg_image(j, x,y,comp,req_comp); + STBI_FREE(j); + return result; +} + +static int stbi__jpeg_test(stbi__context *s) +{ + int r; + stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg)); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + stbi__setup_jpeg(j); + r = stbi__decode_jpeg_header(j, STBI__SCAN_type); + stbi__rewind(s); + STBI_FREE(j); + return r; +} + +static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) +{ + if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { + stbi__rewind( j->s ); + return 0; + } + if (x) *x = j->s->img_x; + if (y) *y = j->s->img_y; + if (comp) *comp = j->s->img_n >= 3 ? 3 : 1; + return 1; +} + +static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) +{ + int result; + stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg))); + if (!j) return stbi__err("outofmem", "Out of memory"); + memset(j, 0, sizeof(stbi__jpeg)); + j->s = s; + result = stbi__jpeg_info_raw(j, x, y, comp); + STBI_FREE(j); + return result; +} +#endif + +// public domain zlib decode v0.2 Sean Barrett 2006-11-18 +// simple implementation +// - all input must be provided in an upfront buffer +// - all output is written to a single output buffer (can malloc/realloc) +// performance +// - fast huffman + +#ifndef STBI_NO_ZLIB + +// fast-way is faster to check than jpeg huffman, but slow way is slower +#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables +#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) +#define STBI__ZNSYMS 288 // number of symbols in literal/length alphabet + +// zlib-style huffman encoding +// (jpegs packs from left, zlib from right, so can't share code) +typedef struct +{ + stbi__uint16 fast[1 << STBI__ZFAST_BITS]; + stbi__uint16 firstcode[16]; + int maxcode[17]; + stbi__uint16 firstsymbol[16]; + stbi_uc size[STBI__ZNSYMS]; + stbi__uint16 value[STBI__ZNSYMS]; +} stbi__zhuffman; + +stbi_inline static int stbi__bitreverse16(int n) +{ + n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); + n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); + n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); + n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); + return n; +} + +stbi_inline static int stbi__bit_reverse(int v, int bits) +{ + STBI_ASSERT(bits <= 16); + // to bit reverse n bits, reverse 16 and shift + // e.g. 11 bits, bit reverse and shift away 5 + return stbi__bitreverse16(v) >> (16-bits); +} + +static int stbi__zbuild_huffman(stbi__zhuffman *z, const stbi_uc *sizelist, int num) +{ + int i,k=0; + int code, next_code[16], sizes[17]; + + // DEFLATE spec for generating codes + memset(sizes, 0, sizeof(sizes)); + memset(z->fast, 0, sizeof(z->fast)); + for (i=0; i < num; ++i) + ++sizes[sizelist[i]]; + sizes[0] = 0; + for (i=1; i < 16; ++i) + if (sizes[i] > (1 << i)) + return stbi__err("bad sizes", "Corrupt PNG"); + code = 0; + for (i=1; i < 16; ++i) { + next_code[i] = code; + z->firstcode[i] = (stbi__uint16) code; + z->firstsymbol[i] = (stbi__uint16) k; + code = (code + sizes[i]); + if (sizes[i]) + if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); + z->maxcode[i] = code << (16-i); // preshift for inner loop + code <<= 1; + k += sizes[i]; + } + z->maxcode[16] = 0x10000; // sentinel + for (i=0; i < num; ++i) { + int s = sizelist[i]; + if (s) { + int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; + stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); + z->size [c] = (stbi_uc ) s; + z->value[c] = (stbi__uint16) i; + if (s <= STBI__ZFAST_BITS) { + int j = stbi__bit_reverse(next_code[s],s); + while (j < (1 << STBI__ZFAST_BITS)) { + z->fast[j] = fastv; + j += (1 << s); + } + } + ++next_code[s]; + } + } + return 1; +} + +// zlib-from-memory implementation for PNG reading +// because PNG allows splitting the zlib stream arbitrarily, +// and it's annoying structurally to have PNG call ZLIB call PNG, +// we require PNG read all the IDATs and combine them into a single +// memory buffer + +typedef struct +{ + stbi_uc *zbuffer, *zbuffer_end; + int num_bits; + int hit_zeof_once; + stbi__uint32 code_buffer; + + char *zout; + char *zout_start; + char *zout_end; + int z_expandable; + + stbi__zhuffman z_length, z_distance; +} stbi__zbuf; + +stbi_inline static int stbi__zeof(stbi__zbuf *z) +{ + return (z->zbuffer >= z->zbuffer_end); +} + +stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) +{ + return stbi__zeof(z) ? 0 : *z->zbuffer++; +} + +static void stbi__fill_bits(stbi__zbuf *z) +{ + do { + if (z->code_buffer >= (1U << z->num_bits)) { + z->zbuffer = z->zbuffer_end; /* treat this as EOF so we fail. */ + return; + } + z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; + z->num_bits += 8; + } while (z->num_bits <= 24); +} + +stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) +{ + unsigned int k; + if (z->num_bits < n) stbi__fill_bits(z); + k = z->code_buffer & ((1 << n) - 1); + z->code_buffer >>= n; + z->num_bits -= n; + return k; +} + +static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s,k; + // not resolved by fast table, so compute it the slow way + // use jpeg approach, which requires MSbits at top + k = stbi__bit_reverse(a->code_buffer, 16); + for (s=STBI__ZFAST_BITS+1; ; ++s) + if (k < z->maxcode[s]) + break; + if (s >= 16) return -1; // invalid code! + // code size is s, so: + b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; + if (b >= STBI__ZNSYMS) return -1; // some data was corrupt somewhere! + if (z->size[b] != s) return -1; // was originally an assert, but report failure instead. + a->code_buffer >>= s; + a->num_bits -= s; + return z->value[b]; +} + +stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) +{ + int b,s; + if (a->num_bits < 16) { + if (stbi__zeof(a)) { + if (!a->hit_zeof_once) { + // This is the first time we hit eof, insert 16 extra padding btis + // to allow us to keep going; if we actually consume any of them + // though, that is invalid data. This is caught later. + a->hit_zeof_once = 1; + a->num_bits += 16; // add 16 implicit zero bits + } else { + // We already inserted our extra 16 padding bits and are again + // out, this stream is actually prematurely terminated. + return -1; + } + } else { + stbi__fill_bits(a); + } + } + b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; + if (b) { + s = b >> 9; + a->code_buffer >>= s; + a->num_bits -= s; + return b & 511; + } + return stbi__zhuffman_decode_slowpath(a, z); +} + +static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes +{ + char *q; + unsigned int cur, limit, old_limit; + z->zout = zout; + if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); + cur = (unsigned int) (z->zout - z->zout_start); + limit = old_limit = (unsigned) (z->zout_end - z->zout_start); + if (UINT_MAX - cur < (unsigned) n) return stbi__err("outofmem", "Out of memory"); + while (cur + n > limit) { + if(limit > UINT_MAX / 2) return stbi__err("outofmem", "Out of memory"); + limit *= 2; + } + q = (char *) STBI_REALLOC_SIZED(z->zout_start, old_limit, limit); + STBI_NOTUSED(old_limit); + if (q == NULL) return stbi__err("outofmem", "Out of memory"); + z->zout_start = q; + z->zout = q + cur; + z->zout_end = q + limit; + return 1; +} + +static const int stbi__zlength_base[31] = { + 3,4,5,6,7,8,9,10,11,13, + 15,17,19,23,27,31,35,43,51,59, + 67,83,99,115,131,163,195,227,258,0,0 }; + +static const int stbi__zlength_extra[31]= +{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; + +static const int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, +257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; + +static const int stbi__zdist_extra[32] = +{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +static int stbi__parse_huffman_block(stbi__zbuf *a) +{ + char *zout = a->zout; + for(;;) { + int z = stbi__zhuffman_decode(a, &a->z_length); + if (z < 256) { + if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes + if (zout >= a->zout_end) { + if (!stbi__zexpand(a, zout, 1)) return 0; + zout = a->zout; + } + *zout++ = (char) z; + } else { + stbi_uc *p; + int len,dist; + if (z == 256) { + a->zout = zout; + if (a->hit_zeof_once && a->num_bits < 16) { + // The first time we hit zeof, we inserted 16 extra zero bits into our bit + // buffer so the decoder can just do its speculative decoding. But if we + // actually consumed any of those bits (which is the case when num_bits < 16), + // the stream actually read past the end so it is malformed. + return stbi__err("unexpected end","Corrupt PNG"); + } + return 1; + } + if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data + z -= 257; + len = stbi__zlength_base[z]; + if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); + z = stbi__zhuffman_decode(a, &a->z_distance); + if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data + dist = stbi__zdist_base[z]; + if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); + if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); + if (len > a->zout_end - zout) { + if (!stbi__zexpand(a, zout, len)) return 0; + zout = a->zout; + } + p = (stbi_uc *) (zout - dist); + if (dist == 1) { // run of one byte; common in images. + stbi_uc v = *p; + if (len) { do *zout++ = v; while (--len); } + } else { + if (len) { do *zout++ = *p++; while (--len); } + } + } + } +} + +static int stbi__compute_huffman_codes(stbi__zbuf *a) +{ + static const stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; + stbi__zhuffman z_codelength; + stbi_uc lencodes[286+32+137];//padding for maximum single op + stbi_uc codelength_sizes[19]; + int i,n; + + int hlit = stbi__zreceive(a,5) + 257; + int hdist = stbi__zreceive(a,5) + 1; + int hclen = stbi__zreceive(a,4) + 4; + int ntot = hlit + hdist; + + memset(codelength_sizes, 0, sizeof(codelength_sizes)); + for (i=0; i < hclen; ++i) { + int s = stbi__zreceive(a,3); + codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; + } + if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; + + n = 0; + while (n < ntot) { + int c = stbi__zhuffman_decode(a, &z_codelength); + if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); + if (c < 16) + lencodes[n++] = (stbi_uc) c; + else { + stbi_uc fill = 0; + if (c == 16) { + c = stbi__zreceive(a,2)+3; + if (n == 0) return stbi__err("bad codelengths", "Corrupt PNG"); + fill = lencodes[n-1]; + } else if (c == 17) { + c = stbi__zreceive(a,3)+3; + } else if (c == 18) { + c = stbi__zreceive(a,7)+11; + } else { + return stbi__err("bad codelengths", "Corrupt PNG"); + } + if (ntot - n < c) return stbi__err("bad codelengths", "Corrupt PNG"); + memset(lencodes+n, fill, c); + n += c; + } + } + if (n != ntot) return stbi__err("bad codelengths","Corrupt PNG"); + if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; + return 1; +} + +static int stbi__parse_uncompressed_block(stbi__zbuf *a) +{ + stbi_uc header[4]; + int len,nlen,k; + if (a->num_bits & 7) + stbi__zreceive(a, a->num_bits & 7); // discard + // drain the bit-packed data into header + k = 0; + while (a->num_bits > 0) { + header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check + a->code_buffer >>= 8; + a->num_bits -= 8; + } + if (a->num_bits < 0) return stbi__err("zlib corrupt","Corrupt PNG"); + // now fill header the normal way + while (k < 4) + header[k++] = stbi__zget8(a); + len = header[1] * 256 + header[0]; + nlen = header[3] * 256 + header[2]; + if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); + if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); + if (a->zout + len > a->zout_end) + if (!stbi__zexpand(a, a->zout, len)) return 0; + memcpy(a->zout, a->zbuffer, len); + a->zbuffer += len; + a->zout += len; + return 1; +} + +static int stbi__parse_zlib_header(stbi__zbuf *a) +{ + int cmf = stbi__zget8(a); + int cm = cmf & 15; + /* int cinfo = cmf >> 4; */ + int flg = stbi__zget8(a); + if (stbi__zeof(a)) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec + if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png + if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png + // window = 1 << (8 + cinfo)... but who cares, we fully buffer output + return 1; +} + +static const stbi_uc stbi__zdefault_length[STBI__ZNSYMS] = +{ + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8 +}; +static const stbi_uc stbi__zdefault_distance[32] = +{ + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5 +}; +/* +Init algorithm: +{ + int i; // use <= to match clearly with spec + for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; + for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; + for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; + for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; + + for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; +} +*/ + +static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) +{ + int final, type; + if (parse_header) + if (!stbi__parse_zlib_header(a)) return 0; + a->num_bits = 0; + a->code_buffer = 0; + a->hit_zeof_once = 0; + do { + final = stbi__zreceive(a,1); + type = stbi__zreceive(a,2); + if (type == 0) { + if (!stbi__parse_uncompressed_block(a)) return 0; + } else if (type == 3) { + return 0; + } else { + if (type == 1) { + // use fixed code lengths + if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , STBI__ZNSYMS)) return 0; + if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; + } else { + if (!stbi__compute_huffman_codes(a)) return 0; + } + if (!stbi__parse_huffman_block(a)) return 0; + } + } while (!final); + return 1; +} + +static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) +{ + a->zout_start = obuf; + a->zout = obuf; + a->zout_end = obuf + olen; + a->z_expandable = exp; + + return stbi__parse_zlib(a, parse_header); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) +{ + return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); +} + +STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(initial_size); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer + len; + if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) + return (int) (a.zout - a.zout_start); + else + return -1; +} + +STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) +{ + stbi__zbuf a; + char *p = (char *) stbi__malloc(16384); + if (p == NULL) return NULL; + a.zbuffer = (stbi_uc *) buffer; + a.zbuffer_end = (stbi_uc *) buffer+len; + if (stbi__do_zlib(&a, p, 16384, 1, 0)) { + if (outlen) *outlen = (int) (a.zout - a.zout_start); + return a.zout_start; + } else { + STBI_FREE(a.zout_start); + return NULL; + } +} + +STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) +{ + stbi__zbuf a; + a.zbuffer = (stbi_uc *) ibuffer; + a.zbuffer_end = (stbi_uc *) ibuffer + ilen; + if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) + return (int) (a.zout - a.zout_start); + else + return -1; +} +#endif + +// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 +// simple implementation +// - only 8-bit samples +// - no CRC checking +// - allocates lots of intermediate memory +// - avoids problem of streaming data between subsystems +// - avoids explicit window management +// performance +// - uses stb_zlib, a PD zlib implementation with fast huffman decoding + +#ifndef STBI_NO_PNG +typedef struct +{ + stbi__uint32 length; + stbi__uint32 type; +} stbi__pngchunk; + +static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) +{ + stbi__pngchunk c; + c.length = stbi__get32be(s); + c.type = stbi__get32be(s); + return c; +} + +static int stbi__check_png_header(stbi__context *s) +{ + static const stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; + int i; + for (i=0; i < 8; ++i) + if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); + return 1; +} + +typedef struct +{ + stbi__context *s; + stbi_uc *idata, *expanded, *out; + int depth; +} stbi__png; + + +enum { + STBI__F_none=0, + STBI__F_sub=1, + STBI__F_up=2, + STBI__F_avg=3, + STBI__F_paeth=4, + // synthetic filter used for first scanline to avoid needing a dummy row of 0s + STBI__F_avg_first +}; + +static stbi_uc first_row_filter[5] = +{ + STBI__F_none, + STBI__F_sub, + STBI__F_none, + STBI__F_avg_first, + STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub +}; + +static int stbi__paeth(int a, int b, int c) +{ + // This formulation looks very different from the reference in the PNG spec, but is + // actually equivalent and has favorable data dependencies and admits straightforward + // generation of branch-free code, which helps performance significantly. + int thresh = c*3 - (a + b); + int lo = a < b ? a : b; + int hi = a < b ? b : a; + int t0 = (hi <= thresh) ? lo : c; + int t1 = (thresh <= lo) ? hi : t0; + return t1; +} + +static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; + +// adds an extra all-255 alpha channel +// dest == src is legal +// img_n must be 1 or 3 +static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n) +{ + int i; + // must process data backwards since we allow dest==src + if (img_n == 1) { + for (i=x-1; i >= 0; --i) { + dest[i*2+1] = 255; + dest[i*2+0] = src[i]; + } + } else { + STBI_ASSERT(img_n == 3); + for (i=x-1; i >= 0; --i) { + dest[i*4+3] = 255; + dest[i*4+2] = src[i*3+2]; + dest[i*4+1] = src[i*3+1]; + dest[i*4+0] = src[i*3+0]; + } + } +} + +// create the png data from post-deflated data +static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) +{ + int bytes = (depth == 16 ? 2 : 1); + stbi__context *s = a->s; + stbi__uint32 i,j,stride = x*out_n*bytes; + stbi__uint32 img_len, img_width_bytes; + stbi_uc *filter_buf; + int all_ok = 1; + int k; + int img_n = s->img_n; // copy it into a local for later + + int output_bytes = out_n*bytes; + int filter_bytes = img_n*bytes; + int width = x; + + STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); + a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into + if (!a->out) return stbi__err("outofmem", "Out of memory"); + + // note: error exits here don't need to clean up a->out individually, + // stbi__do_png always does on error. + if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG"); + img_width_bytes = (((img_n * x * depth) + 7) >> 3); + if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG"); + img_len = (img_width_bytes + 1) * y; + + // we used to check for exact match between raw_len and img_len on non-interlaced PNGs, + // but issue #276 reported a PNG in the wild that had extra data at the end (all zeros), + // so just check for raw_len < img_len always. + if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); + + // Allocate two scan lines worth of filter workspace buffer. + filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0); + if (!filter_buf) return stbi__err("outofmem", "Out of memory"); + + // Filtering for low-bit-depth images + if (depth < 8) { + filter_bytes = 1; + width = img_width_bytes; + } + + for (j=0; j < y; ++j) { + // cur/prior filter buffers alternate + stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes; + stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes; + stbi_uc *dest = a->out + stride*j; + int nk = width * filter_bytes; + int filter = *raw++; + + // check filter type + if (filter > 4) { + all_ok = stbi__err("invalid filter","Corrupt PNG"); + break; + } + + // if first row, use special filter that doesn't sample previous row + if (j == 0) filter = first_row_filter[filter]; + + // perform actual filtering + switch (filter) { + case STBI__F_none: + memcpy(cur, raw, nk); + break; + case STBI__F_sub: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); + break; + case STBI__F_up: + for (k = 0; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); + break; + case STBI__F_avg: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); + break; + case STBI__F_paeth: + for (k = 0; k < filter_bytes; ++k) + cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0) + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes])); + break; + case STBI__F_avg_first: + memcpy(cur, raw, filter_bytes); + for (k = filter_bytes; k < nk; ++k) + cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); + break; + } + + raw += nk; + + // expand decoded bits in cur to dest, also adding an extra alpha channel if desired + if (depth < 8) { + stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range + stbi_uc *in = cur; + stbi_uc *out = dest; + stbi_uc inb = 0; + stbi__uint32 nsmp = x*img_n; + + // expand bits to bytes first + if (depth == 4) { + for (i=0; i < nsmp; ++i) { + if ((i & 1) == 0) inb = *in++; + *out++ = scale * (inb >> 4); + inb <<= 4; + } + } else if (depth == 2) { + for (i=0; i < nsmp; ++i) { + if ((i & 3) == 0) inb = *in++; + *out++ = scale * (inb >> 6); + inb <<= 2; + } + } else { + STBI_ASSERT(depth == 1); + for (i=0; i < nsmp; ++i) { + if ((i & 7) == 0) inb = *in++; + *out++ = scale * (inb >> 7); + inb <<= 1; + } + } + + // insert alpha=255 values if desired + if (img_n != out_n) + stbi__create_png_alpha_expand8(dest, dest, x, img_n); + } else if (depth == 8) { + if (img_n == out_n) + memcpy(dest, cur, x*img_n); + else + stbi__create_png_alpha_expand8(dest, cur, x, img_n); + } else if (depth == 16) { + // convert the image data from big-endian to platform-native + stbi__uint16 *dest16 = (stbi__uint16*)dest; + stbi__uint32 nsmp = x*img_n; + + if (img_n == out_n) { + for (i = 0; i < nsmp; ++i, ++dest16, cur += 2) + *dest16 = (cur[0] << 8) | cur[1]; + } else { + STBI_ASSERT(img_n+1 == out_n); + if (img_n == 1) { + for (i = 0; i < x; ++i, dest16 += 2, cur += 2) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = 0xffff; + } + } else { + STBI_ASSERT(img_n == 3); + for (i = 0; i < x; ++i, dest16 += 4, cur += 6) { + dest16[0] = (cur[0] << 8) | cur[1]; + dest16[1] = (cur[2] << 8) | cur[3]; + dest16[2] = (cur[4] << 8) | cur[5]; + dest16[3] = 0xffff; + } + } + } + } + } + + STBI_FREE(filter_buf); + if (!all_ok) return 0; + + return 1; +} + +static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) +{ + int bytes = (depth == 16 ? 2 : 1); + int out_bytes = out_n * bytes; + stbi_uc *final; + int p; + if (!interlaced) + return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); + + // de-interlacing + final = (stbi_uc *) stbi__malloc_mad3(a->s->img_x, a->s->img_y, out_bytes, 0); + if (!final) return stbi__err("outofmem", "Out of memory"); + for (p=0; p < 7; ++p) { + int xorig[] = { 0,4,0,2,0,1,0 }; + int yorig[] = { 0,0,4,0,2,0,1 }; + int xspc[] = { 8,8,4,4,2,2,1 }; + int yspc[] = { 8,8,8,4,4,2,2 }; + int i,j,x,y; + // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 + x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; + y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; + if (x && y) { + stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; + if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { + STBI_FREE(final); + return 0; + } + for (j=0; j < y; ++j) { + for (i=0; i < x; ++i) { + int out_y = j*yspc[p]+yorig[p]; + int out_x = i*xspc[p]+xorig[p]; + memcpy(final + out_y*a->s->img_x*out_bytes + out_x*out_bytes, + a->out + (j*x+i)*out_bytes, out_bytes); + } + } + STBI_FREE(a->out); + image_data += img_len; + image_data_len -= img_len; + } + } + a->out = final; + + return 1; +} + +static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + // compute color-based transparency, assuming we've + // already got 255 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i=0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 255); + p += 2; + } + } else { + for (i=0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__compute_transparency16(stbi__png *z, stbi__uint16 tc[3], int out_n) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi__uint16 *p = (stbi__uint16*) z->out; + + // compute color-based transparency, assuming we've + // already got 65535 as the alpha value in the output + STBI_ASSERT(out_n == 2 || out_n == 4); + + if (out_n == 2) { + for (i = 0; i < pixel_count; ++i) { + p[1] = (p[0] == tc[0] ? 0 : 65535); + p += 2; + } + } else { + for (i = 0; i < pixel_count; ++i) { + if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) + p[3] = 0; + p += 4; + } + } + return 1; +} + +static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) +{ + stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; + stbi_uc *p, *temp_out, *orig = a->out; + + p = (stbi_uc *) stbi__malloc_mad2(pixel_count, pal_img_n, 0); + if (p == NULL) return stbi__err("outofmem", "Out of memory"); + + // between here and free(out) below, exitting would leak + temp_out = p; + + if (pal_img_n == 3) { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p += 3; + } + } else { + for (i=0; i < pixel_count; ++i) { + int n = orig[i]*4; + p[0] = palette[n ]; + p[1] = palette[n+1]; + p[2] = palette[n+2]; + p[3] = palette[n+3]; + p += 4; + } + } + STBI_FREE(a->out); + a->out = temp_out; + + STBI_NOTUSED(len); + + return 1; +} + +static int stbi__unpremultiply_on_load_global = 0; +static int stbi__de_iphone_flag_global = 0; + +STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_global = flag_true_if_should_unpremultiply; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_global = flag_true_if_should_convert; +} + +#ifndef STBI_THREAD_LOCAL +#define stbi__unpremultiply_on_load stbi__unpremultiply_on_load_global +#define stbi__de_iphone_flag stbi__de_iphone_flag_global +#else +static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set; +static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set; + +STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply) +{ + stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply; + stbi__unpremultiply_on_load_set = 1; +} + +STBIDEF void stbi_convert_iphone_png_to_rgb_thread(int flag_true_if_should_convert) +{ + stbi__de_iphone_flag_local = flag_true_if_should_convert; + stbi__de_iphone_flag_set = 1; +} + +#define stbi__unpremultiply_on_load (stbi__unpremultiply_on_load_set \ + ? stbi__unpremultiply_on_load_local \ + : stbi__unpremultiply_on_load_global) +#define stbi__de_iphone_flag (stbi__de_iphone_flag_set \ + ? stbi__de_iphone_flag_local \ + : stbi__de_iphone_flag_global) +#endif // STBI_THREAD_LOCAL + +static void stbi__de_iphone(stbi__png *z) +{ + stbi__context *s = z->s; + stbi__uint32 i, pixel_count = s->img_x * s->img_y; + stbi_uc *p = z->out; + + if (s->img_out_n == 3) { // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 3; + } + } else { + STBI_ASSERT(s->img_out_n == 4); + if (stbi__unpremultiply_on_load) { + // convert bgr to rgb and unpremultiply + for (i=0; i < pixel_count; ++i) { + stbi_uc a = p[3]; + stbi_uc t = p[0]; + if (a) { + stbi_uc half = a / 2; + p[0] = (p[2] * 255 + half) / a; + p[1] = (p[1] * 255 + half) / a; + p[2] = ( t * 255 + half) / a; + } else { + p[0] = p[2]; + p[2] = t; + } + p += 4; + } + } else { + // convert bgr to rgb + for (i=0; i < pixel_count; ++i) { + stbi_uc t = p[0]; + p[0] = p[2]; + p[2] = t; + p += 4; + } + } + } +} + +#define STBI__PNG_TYPE(a,b,c,d) (((unsigned) (a) << 24) + ((unsigned) (b) << 16) + ((unsigned) (c) << 8) + (unsigned) (d)) + +static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) +{ + stbi_uc palette[1024], pal_img_n=0; + stbi_uc has_trans=0, tc[3]={0}; + stbi__uint16 tc16[3]; + stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; + int first=1,k,interlace=0, color=0, is_iphone=0; + stbi__context *s = z->s; + + z->expanded = NULL; + z->idata = NULL; + z->out = NULL; + + if (!stbi__check_png_header(s)) return 0; + + if (scan == STBI__SCAN_type) return 1; + + for (;;) { + stbi__pngchunk c = stbi__get_chunk_header(s); + switch (c.type) { + case STBI__PNG_TYPE('C','g','B','I'): + is_iphone = 1; + stbi__skip(s, c.length); + break; + case STBI__PNG_TYPE('I','H','D','R'): { + int comp,filter; + if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); + first = 0; + if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); + s->img_x = stbi__get32be(s); + s->img_y = stbi__get32be(s); + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + z->depth = stbi__get8(s); if (z->depth != 1 && z->depth != 2 && z->depth != 4 && z->depth != 8 && z->depth != 16) return stbi__err("1/2/4/8/16-bit only","PNG not supported: 1/2/4/8/16-bit only"); + color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3 && z->depth == 16) return stbi__err("bad ctype","Corrupt PNG"); + if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); + comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); + filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); + interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); + if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); + if (!pal_img_n) { + s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); + if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); + } else { + // if paletted, then pal_n is our final components, and + // img_n is # components to decompress/filter. + s->img_n = 1; + if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); + } + // even with SCAN_header, have to scan to see if we have a tRNS + break; + } + + case STBI__PNG_TYPE('P','L','T','E'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); + pal_len = c.length / 3; + if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); + for (i=0; i < pal_len; ++i) { + palette[i*4+0] = stbi__get8(s); + palette[i*4+1] = stbi__get8(s); + palette[i*4+2] = stbi__get8(s); + palette[i*4+3] = 255; + } + break; + } + + case STBI__PNG_TYPE('t','R','N','S'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); + if (pal_img_n) { + if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } + if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); + if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); + pal_img_n = 4; + for (i=0; i < c.length; ++i) + palette[i*4+3] = stbi__get8(s); + } else { + if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); + if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); + has_trans = 1; + // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now. + if (scan == STBI__SCAN_header) { ++s->img_n; return 1; } + if (z->depth == 16) { + for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning + tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is + } else { + for (k = 0; k < s->img_n && k < 3; ++k) + tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger + } + } + break; + } + + case STBI__PNG_TYPE('I','D','A','T'): { + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); + if (scan == STBI__SCAN_header) { + // header scan definitely stops at first IDAT + if (pal_img_n) + s->img_n = pal_img_n; + return 1; + } + if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes"); + if ((int)(ioff + c.length) < (int)ioff) return 0; + if (ioff + c.length > idata_limit) { + stbi__uint32 idata_limit_old = idata_limit; + stbi_uc *p; + if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; + while (ioff + c.length > idata_limit) + idata_limit *= 2; + STBI_NOTUSED(idata_limit_old); + p = (stbi_uc *) STBI_REALLOC_SIZED(z->idata, idata_limit_old, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); + z->idata = p; + } + if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); + ioff += c.length; + break; + } + + case STBI__PNG_TYPE('I','E','N','D'): { + stbi__uint32 raw_len, bpl; + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if (scan != STBI__SCAN_load) return 1; + if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); + // initial guess for decoded data size to avoid unnecessary reallocs + bpl = (s->img_x * z->depth + 7) / 8; // bytes per line, per component + raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; + z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); + if (z->expanded == NULL) return 0; // zlib should set error + STBI_FREE(z->idata); z->idata = NULL; + if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) + s->img_out_n = s->img_n+1; + else + s->img_out_n = s->img_n; + if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, z->depth, color, interlace)) return 0; + if (has_trans) { + if (z->depth == 16) { + if (!stbi__compute_transparency16(z, tc16, s->img_out_n)) return 0; + } else { + if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; + } + } + if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) + stbi__de_iphone(z); + if (pal_img_n) { + // pal_img_n == 3 or 4 + s->img_n = pal_img_n; // record the actual colors we had + s->img_out_n = pal_img_n; + if (req_comp >= 3) s->img_out_n = req_comp; + if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) + return 0; + } else if (has_trans) { + // non-paletted image with tRNS -> source image has (constant) alpha + ++s->img_n; + } + STBI_FREE(z->expanded); z->expanded = NULL; + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + return 1; + } + + default: + // if critical, fail + if (first) return stbi__err("first not IHDR", "Corrupt PNG"); + if ((c.type & (1 << 29)) == 0) { + #ifndef STBI_NO_FAILURE_STRINGS + // not threadsafe + static char invalid_chunk[] = "XXXX PNG chunk not known"; + invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); + invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); + invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); + invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); + #endif + return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); + } + stbi__skip(s, c.length); + break; + } + // end of PNG chunk, read and skip CRC + stbi__get32be(s); + } +} + +static void *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp, stbi__result_info *ri) +{ + void *result=NULL; + if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); + if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { + if (p->depth <= 8) + ri->bits_per_channel = 8; + else if (p->depth == 16) + ri->bits_per_channel = 16; + else + return stbi__errpuc("bad bits_per_channel", "PNG not supported: unsupported color depth"); + result = p->out; + p->out = NULL; + if (req_comp && req_comp != p->s->img_out_n) { + if (ri->bits_per_channel == 8) + result = stbi__convert_format((unsigned char *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + else + result = stbi__convert_format16((stbi__uint16 *) result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); + p->s->img_out_n = req_comp; + if (result == NULL) return result; + } + *x = p->s->img_x; + *y = p->s->img_y; + if (n) *n = p->s->img_n; + } + STBI_FREE(p->out); p->out = NULL; + STBI_FREE(p->expanded); p->expanded = NULL; + STBI_FREE(p->idata); p->idata = NULL; + + return result; +} + +static void *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi__png p; + p.s = s; + return stbi__do_png(&p, x,y,comp,req_comp, ri); +} + +static int stbi__png_test(stbi__context *s) +{ + int r; + r = stbi__check_png_header(s); + stbi__rewind(s); + return r; +} + +static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) +{ + if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { + stbi__rewind( p->s ); + return 0; + } + if (x) *x = p->s->img_x; + if (y) *y = p->s->img_y; + if (comp) *comp = p->s->img_n; + return 1; +} + +static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__png p; + p.s = s; + return stbi__png_info_raw(&p, x, y, comp); +} + +static int stbi__png_is16(stbi__context *s) +{ + stbi__png p; + p.s = s; + if (!stbi__png_info_raw(&p, NULL, NULL, NULL)) + return 0; + if (p.depth != 16) { + stbi__rewind(p.s); + return 0; + } + return 1; +} +#endif + +// Microsoft/Windows BMP image + +#ifndef STBI_NO_BMP +static int stbi__bmp_test_raw(stbi__context *s) +{ + int r; + int sz; + if (stbi__get8(s) != 'B') return 0; + if (stbi__get8(s) != 'M') return 0; + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + stbi__get32le(s); // discard data offset + sz = stbi__get32le(s); + r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); + return r; +} + +static int stbi__bmp_test(stbi__context *s) +{ + int r = stbi__bmp_test_raw(s); + stbi__rewind(s); + return r; +} + + +// returns 0..31 for the highest set bit +static int stbi__high_bit(unsigned int z) +{ + int n=0; + if (z == 0) return -1; + if (z >= 0x10000) { n += 16; z >>= 16; } + if (z >= 0x00100) { n += 8; z >>= 8; } + if (z >= 0x00010) { n += 4; z >>= 4; } + if (z >= 0x00004) { n += 2; z >>= 2; } + if (z >= 0x00002) { n += 1;/* >>= 1;*/ } + return n; +} + +static int stbi__bitcount(unsigned int a) +{ + a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 + a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 + a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits + a = (a + (a >> 8)); // max 16 per 8 bits + a = (a + (a >> 16)); // max 32 per 8 bits + return a & 0xff; +} + +// extract an arbitrarily-aligned N-bit value (N=bits) +// from v, and then make it 8-bits long and fractionally +// extend it to full full range. +static int stbi__shiftsigned(unsigned int v, int shift, int bits) +{ + static unsigned int mul_table[9] = { + 0, + 0xff/*0b11111111*/, 0x55/*0b01010101*/, 0x49/*0b01001001*/, 0x11/*0b00010001*/, + 0x21/*0b00100001*/, 0x41/*0b01000001*/, 0x81/*0b10000001*/, 0x01/*0b00000001*/, + }; + static unsigned int shift_table[9] = { + 0, 0,0,1,0,2,4,6,0, + }; + if (shift < 0) + v <<= -shift; + else + v >>= shift; + STBI_ASSERT(v < 256); + v >>= (8-bits); + STBI_ASSERT(bits >= 0 && bits <= 8); + return (int) ((unsigned) v * mul_table[bits]) >> shift_table[bits]; +} + +typedef struct +{ + int bpp, offset, hsz; + unsigned int mr,mg,mb,ma, all_a; + int extra_read; +} stbi__bmp_data; + +static int stbi__bmp_set_mask_defaults(stbi__bmp_data *info, int compress) +{ + // BI_BITFIELDS specifies masks explicitly, don't override + if (compress == 3) + return 1; + + if (compress == 0) { + if (info->bpp == 16) { + info->mr = 31u << 10; + info->mg = 31u << 5; + info->mb = 31u << 0; + } else if (info->bpp == 32) { + info->mr = 0xffu << 16; + info->mg = 0xffu << 8; + info->mb = 0xffu << 0; + info->ma = 0xffu << 24; + info->all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 + } else { + // otherwise, use defaults, which is all-0 + info->mr = info->mg = info->mb = info->ma = 0; + } + return 1; + } + return 0; // error +} + +static void *stbi__bmp_parse_header(stbi__context *s, stbi__bmp_data *info) +{ + int hsz; + if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); + stbi__get32le(s); // discard filesize + stbi__get16le(s); // discard reserved + stbi__get16le(s); // discard reserved + info->offset = stbi__get32le(s); + info->hsz = hsz = stbi__get32le(s); + info->mr = info->mg = info->mb = info->ma = 0; + info->extra_read = 14; + + if (info->offset < 0) return stbi__errpuc("bad BMP", "bad BMP"); + + if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); + if (hsz == 12) { + s->img_x = stbi__get16le(s); + s->img_y = stbi__get16le(s); + } else { + s->img_x = stbi__get32le(s); + s->img_y = stbi__get32le(s); + } + if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); + info->bpp = stbi__get16le(s); + if (hsz != 12) { + int compress = stbi__get32le(s); + if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); + if (compress >= 4) return stbi__errpuc("BMP JPEG/PNG", "BMP type not supported: unsupported compression"); // this includes PNG/JPEG modes + if (compress == 3 && info->bpp != 16 && info->bpp != 32) return stbi__errpuc("bad BMP", "bad BMP"); // bitfields requires 16 or 32 bits/pixel + stbi__get32le(s); // discard sizeof + stbi__get32le(s); // discard hres + stbi__get32le(s); // discard vres + stbi__get32le(s); // discard colorsused + stbi__get32le(s); // discard max important + if (hsz == 40 || hsz == 56) { + if (hsz == 56) { + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + stbi__get32le(s); + } + if (info->bpp == 16 || info->bpp == 32) { + if (compress == 0) { + stbi__bmp_set_mask_defaults(info, compress); + } else if (compress == 3) { + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->extra_read += 12; + // not documented, but generated by photoshop and handled by mspaint + if (info->mr == info->mg && info->mg == info->mb) { + // ?!?!? + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else + return stbi__errpuc("bad BMP", "bad BMP"); + } + } else { + // V4/V5 header + int i; + if (hsz != 108 && hsz != 124) + return stbi__errpuc("bad BMP", "bad BMP"); + info->mr = stbi__get32le(s); + info->mg = stbi__get32le(s); + info->mb = stbi__get32le(s); + info->ma = stbi__get32le(s); + if (compress != 3) // override mr/mg/mb unless in BI_BITFIELDS mode, as per docs + stbi__bmp_set_mask_defaults(info, compress); + stbi__get32le(s); // discard color space + for (i=0; i < 12; ++i) + stbi__get32le(s); // discard color space parameters + if (hsz == 124) { + stbi__get32le(s); // discard rendering intent + stbi__get32le(s); // discard offset of profile data + stbi__get32le(s); // discard size of profile data + stbi__get32le(s); // discard reserved + } + } + } + return (void *) 1; +} + + +static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + unsigned int mr=0,mg=0,mb=0,ma=0, all_a; + stbi_uc pal[256][4]; + int psize=0,i,j,width; + int flip_vertically, pad, target; + stbi__bmp_data info; + STBI_NOTUSED(ri); + + info.all_a = 255; + if (stbi__bmp_parse_header(s, &info) == NULL) + return NULL; // error code already set + + flip_vertically = ((int) s->img_y) > 0; + s->img_y = abs((int) s->img_y); + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + mr = info.mr; + mg = info.mg; + mb = info.mb; + ma = info.ma; + all_a = info.all_a; + + if (info.hsz == 12) { + if (info.bpp < 24) + psize = (info.offset - info.extra_read - 24) / 3; + } else { + if (info.bpp < 16) + psize = (info.offset - info.extra_read - info.hsz) >> 2; + } + if (psize == 0) { + // accept some number of extra bytes after the header, but if the offset points either to before + // the header ends or implies a large amount of extra data, reject the file as malformed + int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original); + int header_limit = 1024; // max we actually read is below 256 bytes currently. + int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size. + if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) { + return stbi__errpuc("bad header", "Corrupt BMP"); + } + // we established that bytes_read_so_far is positive and sensible. + // the first half of this test rejects offsets that are either too small positives, or + // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn + // ensures the number computed in the second half of the test can't overflow. + if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) { + return stbi__errpuc("bad offset", "Corrupt BMP"); + } else { + stbi__skip(s, info.offset - bytes_read_so_far); + } + } + + if (info.bpp == 24 && ma == 0xff000000) + s->img_n = 3; + else + s->img_n = ma ? 4 : 3; + if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 + target = req_comp; + else + target = s->img_n; // if they want monochrome, we'll post-convert + + // sanity-check size + if (!stbi__mad3sizes_valid(target, s->img_x, s->img_y, 0)) + return stbi__errpuc("too large", "Corrupt BMP"); + + out = (stbi_uc *) stbi__malloc_mad3(target, s->img_x, s->img_y, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (info.bpp < 16) { + int z=0; + if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } + for (i=0; i < psize; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + if (info.hsz != 12) stbi__get8(s); + pal[i][3] = 255; + } + stbi__skip(s, info.offset - info.extra_read - info.hsz - psize * (info.hsz == 12 ? 3 : 4)); + if (info.bpp == 1) width = (s->img_x + 7) >> 3; + else if (info.bpp == 4) width = (s->img_x + 1) >> 1; + else if (info.bpp == 8) width = s->img_x; + else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } + pad = (-width)&3; + if (info.bpp == 1) { + for (j=0; j < (int) s->img_y; ++j) { + int bit_offset = 7, v = stbi__get8(s); + for (i=0; i < (int) s->img_x; ++i) { + int color = (v>>bit_offset)&0x1; + out[z++] = pal[color][0]; + out[z++] = pal[color][1]; + out[z++] = pal[color][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + if((--bit_offset) < 0) { + bit_offset = 7; + v = stbi__get8(s); + } + } + stbi__skip(s, pad); + } + } else { + for (j=0; j < (int) s->img_y; ++j) { + for (i=0; i < (int) s->img_x; i += 2) { + int v=stbi__get8(s),v2=0; + if (info.bpp == 4) { + v2 = v & 15; + v >>= 4; + } + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + if (i+1 == (int) s->img_x) break; + v = (info.bpp == 8) ? stbi__get8(s) : v2; + out[z++] = pal[v][0]; + out[z++] = pal[v][1]; + out[z++] = pal[v][2]; + if (target == 4) out[z++] = 255; + } + stbi__skip(s, pad); + } + } + } else { + int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; + int z = 0; + int easy=0; + stbi__skip(s, info.offset - info.extra_read - info.hsz); + if (info.bpp == 24) width = 3 * s->img_x; + else if (info.bpp == 16) width = 2*s->img_x; + else /* bpp = 32 and pad = 0 */ width=0; + pad = (-width) & 3; + if (info.bpp == 24) { + easy = 1; + } else if (info.bpp == 32) { + if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) + easy = 2; + } + if (!easy) { + if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + // right shift amt to put high bit in position #7 + rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); + gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); + bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); + ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); + if (rcount > 8 || gcount > 8 || bcount > 8 || acount > 8) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } + } + for (j=0; j < (int) s->img_y; ++j) { + if (easy) { + for (i=0; i < (int) s->img_x; ++i) { + unsigned char a; + out[z+2] = stbi__get8(s); + out[z+1] = stbi__get8(s); + out[z+0] = stbi__get8(s); + z += 3; + a = (easy == 2 ? stbi__get8(s) : 255); + all_a |= a; + if (target == 4) out[z++] = a; + } + } else { + int bpp = info.bpp; + for (i=0; i < (int) s->img_x; ++i) { + stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); + unsigned int a; + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); + out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); + a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); + all_a |= a; + if (target == 4) out[z++] = STBI__BYTECAST(a); + } + } + stbi__skip(s, pad); + } + } + + // if alpha channel is all 0s, replace with all 255s + if (target == 4 && all_a == 0) + for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) + out[i] = 255; + + if (flip_vertically) { + stbi_uc t; + for (j=0; j < (int) s->img_y>>1; ++j) { + stbi_uc *p1 = out + j *s->img_x*target; + stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; + for (i=0; i < (int) s->img_x*target; ++i) { + t = p1[i]; p1[i] = p2[i]; p2[i] = t; + } + } + } + + if (req_comp && req_comp != target) { + out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + return out; +} +#endif + +// Targa Truevision - TGA +// by Jonathan Dummer +#ifndef STBI_NO_TGA +// returns STBI_rgb or whatever, 0 on error +static int stbi__tga_get_comp(int bits_per_pixel, int is_grey, int* is_rgb16) +{ + // only RGB or RGBA (incl. 16bit) or grey allowed + if (is_rgb16) *is_rgb16 = 0; + switch(bits_per_pixel) { + case 8: return STBI_grey; + case 16: if(is_grey) return STBI_grey_alpha; + // fallthrough + case 15: if(is_rgb16) *is_rgb16 = 1; + return STBI_rgb; + case 24: // fallthrough + case 32: return bits_per_pixel/8; + default: return 0; + } +} + +static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) +{ + int tga_w, tga_h, tga_comp, tga_image_type, tga_bits_per_pixel, tga_colormap_bpp; + int sz, tga_colormap_type; + stbi__get8(s); // discard Offset + tga_colormap_type = stbi__get8(s); // colormap type + if( tga_colormap_type > 1 ) { + stbi__rewind(s); + return 0; // only RGB or indexed allowed + } + tga_image_type = stbi__get8(s); // image type + if ( tga_colormap_type == 1 ) { // colormapped (paletted) image + if (tga_image_type != 1 && tga_image_type != 9) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) { + stbi__rewind(s); + return 0; + } + stbi__skip(s,4); // skip image x and y origin + tga_colormap_bpp = sz; + } else { // "normal" image w/o colormap - only RGB or grey allowed, +/- RLE + if ( (tga_image_type != 2) && (tga_image_type != 3) && (tga_image_type != 10) && (tga_image_type != 11) ) { + stbi__rewind(s); + return 0; // only RGB or grey allowed, +/- RLE + } + stbi__skip(s,9); // skip colormap specification and image x/y origin + tga_colormap_bpp = 0; + } + tga_w = stbi__get16le(s); + if( tga_w < 1 ) { + stbi__rewind(s); + return 0; // test width + } + tga_h = stbi__get16le(s); + if( tga_h < 1 ) { + stbi__rewind(s); + return 0; // test height + } + tga_bits_per_pixel = stbi__get8(s); // bits per pixel + stbi__get8(s); // ignore alpha bits + if (tga_colormap_bpp != 0) { + if((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16)) { + // when using a colormap, tga_bits_per_pixel is the size of the indexes + // I don't think anything but 8 or 16bit indexes makes sense + stbi__rewind(s); + return 0; + } + tga_comp = stbi__tga_get_comp(tga_colormap_bpp, 0, NULL); + } else { + tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3) || (tga_image_type == 11), NULL); + } + if(!tga_comp) { + stbi__rewind(s); + return 0; + } + if (x) *x = tga_w; + if (y) *y = tga_h; + if (comp) *comp = tga_comp; + return 1; // seems to have passed everything +} + +static int stbi__tga_test(stbi__context *s) +{ + int res = 0; + int sz, tga_color_type; + stbi__get8(s); // discard Offset + tga_color_type = stbi__get8(s); // color type + if ( tga_color_type > 1 ) goto errorEnd; // only RGB or indexed allowed + sz = stbi__get8(s); // image type + if ( tga_color_type == 1 ) { // colormapped (paletted) image + if (sz != 1 && sz != 9) goto errorEnd; // colortype 1 demands image type 1 or 9 + stbi__skip(s,4); // skip index of first colormap entry and number of entries + sz = stbi__get8(s); // check bits per palette color entry + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + stbi__skip(s,4); // skip image x and y origin + } else { // "normal" image w/o colormap + if ( (sz != 2) && (sz != 3) && (sz != 10) && (sz != 11) ) goto errorEnd; // only RGB or grey allowed, +/- RLE + stbi__skip(s,9); // skip colormap specification and image x/y origin + } + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test width + if ( stbi__get16le(s) < 1 ) goto errorEnd; // test height + sz = stbi__get8(s); // bits per pixel + if ( (tga_color_type == 1) && (sz != 8) && (sz != 16) ) goto errorEnd; // for colormapped images, bpp is size of an index + if ( (sz != 8) && (sz != 15) && (sz != 16) && (sz != 24) && (sz != 32) ) goto errorEnd; + + res = 1; // if we got this far, everything's good and we can return 1 instead of 0 + +errorEnd: + stbi__rewind(s); + return res; +} + +// read 16bit value and convert to 24bit RGB +static void stbi__tga_read_rgb16(stbi__context *s, stbi_uc* out) +{ + stbi__uint16 px = (stbi__uint16)stbi__get16le(s); + stbi__uint16 fiveBitMask = 31; + // we have 3 channels with 5bits each + int r = (px >> 10) & fiveBitMask; + int g = (px >> 5) & fiveBitMask; + int b = px & fiveBitMask; + // Note that this saves the data in RGB(A) order, so it doesn't need to be swapped later + out[0] = (stbi_uc)((r * 255)/31); + out[1] = (stbi_uc)((g * 255)/31); + out[2] = (stbi_uc)((b * 255)/31); + + // some people claim that the most significant bit might be used for alpha + // (possibly if an alpha-bit is set in the "image descriptor byte") + // but that only made 16bit test images completely translucent.. + // so let's treat all 15 and 16bit TGAs as RGB with no alpha. +} + +static void *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + // read in the TGA header stuff + int tga_offset = stbi__get8(s); + int tga_indexed = stbi__get8(s); + int tga_image_type = stbi__get8(s); + int tga_is_RLE = 0; + int tga_palette_start = stbi__get16le(s); + int tga_palette_len = stbi__get16le(s); + int tga_palette_bits = stbi__get8(s); + int tga_x_origin = stbi__get16le(s); + int tga_y_origin = stbi__get16le(s); + int tga_width = stbi__get16le(s); + int tga_height = stbi__get16le(s); + int tga_bits_per_pixel = stbi__get8(s); + int tga_comp, tga_rgb16=0; + int tga_inverted = stbi__get8(s); + // int tga_alpha_bits = tga_inverted & 15; // the 4 lowest bits - unused (useless?) + // image data + unsigned char *tga_data; + unsigned char *tga_palette = NULL; + int i, j; + unsigned char raw_data[4] = {0}; + int RLE_count = 0; + int RLE_repeating = 0; + int read_next_pixel = 1; + STBI_NOTUSED(ri); + STBI_NOTUSED(tga_x_origin); // @TODO + STBI_NOTUSED(tga_y_origin); // @TODO + + if (tga_height > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (tga_width > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // do a tiny bit of precessing + if ( tga_image_type >= 8 ) + { + tga_image_type -= 8; + tga_is_RLE = 1; + } + tga_inverted = 1 - ((tga_inverted >> 5) & 1); + + // If I'm paletted, then I'll use the number of bits from the palette + if ( tga_indexed ) tga_comp = stbi__tga_get_comp(tga_palette_bits, 0, &tga_rgb16); + else tga_comp = stbi__tga_get_comp(tga_bits_per_pixel, (tga_image_type == 3), &tga_rgb16); + + if(!tga_comp) // shouldn't really happen, stbi__tga_test() should have ensured basic consistency + return stbi__errpuc("bad format", "Can't find out TGA pixelformat"); + + // tga info + *x = tga_width; + *y = tga_height; + if (comp) *comp = tga_comp; + + if (!stbi__mad3sizes_valid(tga_width, tga_height, tga_comp, 0)) + return stbi__errpuc("too large", "Corrupt TGA"); + + tga_data = (unsigned char*)stbi__malloc_mad3(tga_width, tga_height, tga_comp, 0); + if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); + + // skip to the data's starting position (offset usually = 0) + stbi__skip(s, tga_offset ); + + if ( !tga_indexed && !tga_is_RLE && !tga_rgb16 ) { + for (i=0; i < tga_height; ++i) { + int row = tga_inverted ? tga_height -i - 1 : i; + stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; + stbi__getn(s, tga_row, tga_width * tga_comp); + } + } else { + // do I need to load a palette? + if ( tga_indexed) + { + if (tga_palette_len == 0) { /* you have to have at least one entry! */ + STBI_FREE(tga_data); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + + // any data to skip? (offset usually = 0) + stbi__skip(s, tga_palette_start ); + // load the palette + tga_palette = (unsigned char*)stbi__malloc_mad2(tga_palette_len, tga_comp, 0); + if (!tga_palette) { + STBI_FREE(tga_data); + return stbi__errpuc("outofmem", "Out of memory"); + } + if (tga_rgb16) { + stbi_uc *pal_entry = tga_palette; + STBI_ASSERT(tga_comp == STBI_rgb); + for (i=0; i < tga_palette_len; ++i) { + stbi__tga_read_rgb16(s, pal_entry); + pal_entry += tga_comp; + } + } else if (!stbi__getn(s, tga_palette, tga_palette_len * tga_comp)) { + STBI_FREE(tga_data); + STBI_FREE(tga_palette); + return stbi__errpuc("bad palette", "Corrupt TGA"); + } + } + // load the data + for (i=0; i < tga_width * tga_height; ++i) + { + // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? + if ( tga_is_RLE ) + { + if ( RLE_count == 0 ) + { + // yep, get the next byte as a RLE command + int RLE_cmd = stbi__get8(s); + RLE_count = 1 + (RLE_cmd & 127); + RLE_repeating = RLE_cmd >> 7; + read_next_pixel = 1; + } else if ( !RLE_repeating ) + { + read_next_pixel = 1; + } + } else + { + read_next_pixel = 1; + } + // OK, if I need to read a pixel, do it now + if ( read_next_pixel ) + { + // load however much data we did have + if ( tga_indexed ) + { + // read in index, then perform the lookup + int pal_idx = (tga_bits_per_pixel == 8) ? stbi__get8(s) : stbi__get16le(s); + if ( pal_idx >= tga_palette_len ) { + // invalid index + pal_idx = 0; + } + pal_idx *= tga_comp; + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = tga_palette[pal_idx+j]; + } + } else if(tga_rgb16) { + STBI_ASSERT(tga_comp == STBI_rgb); + stbi__tga_read_rgb16(s, raw_data); + } else { + // read in the data raw + for (j = 0; j < tga_comp; ++j) { + raw_data[j] = stbi__get8(s); + } + } + // clear the reading flag for the next pixel + read_next_pixel = 0; + } // end of reading a pixel + + // copy data + for (j = 0; j < tga_comp; ++j) + tga_data[i*tga_comp+j] = raw_data[j]; + + // in case we're in RLE mode, keep counting down + --RLE_count; + } + // do I need to invert the image? + if ( tga_inverted ) + { + for (j = 0; j*2 < tga_height; ++j) + { + int index1 = j * tga_width * tga_comp; + int index2 = (tga_height - 1 - j) * tga_width * tga_comp; + for (i = tga_width * tga_comp; i > 0; --i) + { + unsigned char temp = tga_data[index1]; + tga_data[index1] = tga_data[index2]; + tga_data[index2] = temp; + ++index1; + ++index2; + } + } + } + // clear my palette, if I had one + if ( tga_palette != NULL ) + { + STBI_FREE( tga_palette ); + } + } + + // swap RGB - if the source data was RGB16, it already is in the right order + if (tga_comp >= 3 && !tga_rgb16) + { + unsigned char* tga_pixel = tga_data; + for (i=0; i < tga_width * tga_height; ++i) + { + unsigned char temp = tga_pixel[0]; + tga_pixel[0] = tga_pixel[2]; + tga_pixel[2] = temp; + tga_pixel += tga_comp; + } + } + + // convert to target component count + if (req_comp && req_comp != tga_comp) + tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); + + // the things I do to get rid of an error message, and yet keep + // Microsoft's C compilers happy... [8^( + tga_palette_start = tga_palette_len = tga_palette_bits = + tga_x_origin = tga_y_origin = 0; + STBI_NOTUSED(tga_palette_start); + // OK, done + return tga_data; +} +#endif + +// ************************************************************************************************* +// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB + +#ifndef STBI_NO_PSD +static int stbi__psd_test(stbi__context *s) +{ + int r = (stbi__get32be(s) == 0x38425053); + stbi__rewind(s); + return r; +} + +static int stbi__psd_decode_rle(stbi__context *s, stbi_uc *p, int pixelCount) +{ + int count, nleft, len; + + count = 0; + while ((nleft = pixelCount - count) > 0) { + len = stbi__get8(s); + if (len == 128) { + // No-op. + } else if (len < 128) { + // Copy next len+1 bytes literally. + len++; + if (len > nleft) return 0; // corrupt data + count += len; + while (len) { + *p = stbi__get8(s); + p += 4; + len--; + } + } else if (len > 128) { + stbi_uc val; + // Next -len+1 bytes in the dest are replicated from next source byte. + // (Interpret len as a negative 8-bit int.) + len = 257 - len; + if (len > nleft) return 0; // corrupt data + val = stbi__get8(s); + count += len; + while (len) { + *p = val; + p += 4; + len--; + } + } + } + + return 1; +} + +static void *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri, int bpc) +{ + int pixelCount; + int channelCount, compression; + int channel, i; + int bitdepth; + int w,h; + stbi_uc *out; + STBI_NOTUSED(ri); + + // Check identifier + if (stbi__get32be(s) != 0x38425053) // "8BPS" + return stbi__errpuc("not PSD", "Corrupt PSD image"); + + // Check file type version. + if (stbi__get16be(s) != 1) + return stbi__errpuc("wrong version", "Unsupported version of PSD image"); + + // Skip 6 reserved bytes. + stbi__skip(s, 6 ); + + // Read the number of channels (R, G, B, A, etc). + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) + return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); + + // Read the rows and columns of the image. + h = stbi__get32be(s); + w = stbi__get32be(s); + + if (h > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (w > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + // Make sure the depth is 8 bits. + bitdepth = stbi__get16be(s); + if (bitdepth != 8 && bitdepth != 16) + return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); + + // Make sure the color mode is RGB. + // Valid options are: + // 0: Bitmap + // 1: Grayscale + // 2: Indexed color + // 3: RGB color + // 4: CMYK color + // 7: Multichannel + // 8: Duotone + // 9: Lab color + if (stbi__get16be(s) != 3) + return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); + + // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) + stbi__skip(s,stbi__get32be(s) ); + + // Skip the image resources. (resolution, pen tool paths, etc) + stbi__skip(s, stbi__get32be(s) ); + + // Skip the reserved data. + stbi__skip(s, stbi__get32be(s) ); + + // Find out if the data is compressed. + // Known values: + // 0: no compression + // 1: RLE compressed + compression = stbi__get16be(s); + if (compression > 1) + return stbi__errpuc("bad compression", "PSD has an unknown compression format"); + + // Check size + if (!stbi__mad3sizes_valid(4, w, h, 0)) + return stbi__errpuc("too large", "Corrupt PSD"); + + // Create the destination image. + + if (!compression && bitdepth == 16 && bpc == 16) { + out = (stbi_uc *) stbi__malloc_mad3(8, w, h, 0); + ri->bits_per_channel = 16; + } else + out = (stbi_uc *) stbi__malloc(4 * w*h); + + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + pixelCount = w*h; + + // Initialize the data to zero. + //memset( out, 0, pixelCount * 4 ); + + // Finally, the image data. + if (compression) { + // RLE as used by .PSD and .TIFF + // Loop until you get the number of unpacked bytes you are expecting: + // Read the next source byte into n. + // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. + // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. + // Else if n is 128, noop. + // Endloop + + // The RLE-compressed data is preceded by a 2-byte data count for each row in the data, + // which we're going to just skip. + stbi__skip(s, h * channelCount * 2 ); + + // Read the RLE data by channel. + for (channel = 0; channel < 4; channel++) { + stbi_uc *p; + + p = out+channel; + if (channel >= channelCount) { + // Fill this channel with default data. + for (i = 0; i < pixelCount; i++, p += 4) + *p = (channel == 3 ? 255 : 0); + } else { + // Read the RLE data. + if (!stbi__psd_decode_rle(s, p, pixelCount)) { + STBI_FREE(out); + return stbi__errpuc("corrupt", "bad RLE data"); + } + } + } + + } else { + // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) + // where each channel consists of an 8-bit (or 16-bit) value for each pixel in the image. + + // Read the data by channel. + for (channel = 0; channel < 4; channel++) { + if (channel >= channelCount) { + // Fill this channel with default data. + if (bitdepth == 16 && bpc == 16) { + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + stbi__uint16 val = channel == 3 ? 65535 : 0; + for (i = 0; i < pixelCount; i++, q += 4) + *q = val; + } else { + stbi_uc *p = out+channel; + stbi_uc val = channel == 3 ? 255 : 0; + for (i = 0; i < pixelCount; i++, p += 4) + *p = val; + } + } else { + if (ri->bits_per_channel == 16) { // output bpc + stbi__uint16 *q = ((stbi__uint16 *) out) + channel; + for (i = 0; i < pixelCount; i++, q += 4) + *q = (stbi__uint16) stbi__get16be(s); + } else { + stbi_uc *p = out+channel; + if (bitdepth == 16) { // input bpc + for (i = 0; i < pixelCount; i++, p += 4) + *p = (stbi_uc) (stbi__get16be(s) >> 8); + } else { + for (i = 0; i < pixelCount; i++, p += 4) + *p = stbi__get8(s); + } + } + } + } + } + + // remove weird white matte from PSD + if (channelCount >= 4) { + if (ri->bits_per_channel == 16) { + for (i=0; i < w*h; ++i) { + stbi__uint16 *pixel = (stbi__uint16 *) out + 4*i; + if (pixel[3] != 0 && pixel[3] != 65535) { + float a = pixel[3] / 65535.0f; + float ra = 1.0f / a; + float inv_a = 65535.0f * (1 - ra); + pixel[0] = (stbi__uint16) (pixel[0]*ra + inv_a); + pixel[1] = (stbi__uint16) (pixel[1]*ra + inv_a); + pixel[2] = (stbi__uint16) (pixel[2]*ra + inv_a); + } + } + } else { + for (i=0; i < w*h; ++i) { + unsigned char *pixel = out + 4*i; + if (pixel[3] != 0 && pixel[3] != 255) { + float a = pixel[3] / 255.0f; + float ra = 1.0f / a; + float inv_a = 255.0f * (1 - ra); + pixel[0] = (unsigned char) (pixel[0]*ra + inv_a); + pixel[1] = (unsigned char) (pixel[1]*ra + inv_a); + pixel[2] = (unsigned char) (pixel[2]*ra + inv_a); + } + } + } + } + + // convert to desired output format + if (req_comp && req_comp != 4) { + if (ri->bits_per_channel == 16) + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, 4, req_comp, w, h); + else + out = stbi__convert_format(out, 4, req_comp, w, h); + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + + if (comp) *comp = 4; + *y = h; + *x = w; + + return out; +} +#endif + +// ************************************************************************************************* +// Softimage PIC loader +// by Tom Seddon +// +// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format +// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ + +#ifndef STBI_NO_PIC +static int stbi__pic_is4(stbi__context *s,const char *str) +{ + int i; + for (i=0; i<4; ++i) + if (stbi__get8(s) != (stbi_uc)str[i]) + return 0; + + return 1; +} + +static int stbi__pic_test_core(stbi__context *s) +{ + int i; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) + return 0; + + for(i=0;i<84;++i) + stbi__get8(s); + + if (!stbi__pic_is4(s,"PICT")) + return 0; + + return 1; +} + +typedef struct +{ + stbi_uc size,type,channel; +} stbi__pic_packet; + +static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) +{ + int mask=0x80, i; + + for (i=0; i<4; ++i, mask>>=1) { + if (channel & mask) { + if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); + dest[i]=stbi__get8(s); + } + } + + return dest; +} + +static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) +{ + int mask=0x80,i; + + for (i=0;i<4; ++i, mask>>=1) + if (channel&mask) + dest[i]=src[i]; +} + +static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) +{ + int act_comp=0,num_packets=0,y,chained; + stbi__pic_packet packets[10]; + + // this will (should...) cater for even some bizarre stuff like having data + // for the same channel in multiple packets. + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return stbi__errpuc("bad format","too many packets"); + + packet = &packets[num_packets++]; + + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + + act_comp |= packet->channel; + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); + if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? + + for(y=0; ytype) { + default: + return stbi__errpuc("bad format","packet has bad compression type"); + + case 0: {//uncompressed + int x; + + for(x=0;xchannel,dest)) + return 0; + break; + } + + case 1://Pure RLE + { + int left=width, i; + + while (left>0) { + stbi_uc count,value[4]; + + count=stbi__get8(s); + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); + + if (count > left) + count = (stbi_uc) left; + + if (!stbi__readval(s,packet->channel,value)) return 0; + + for(i=0; ichannel,dest,value); + left -= count; + } + } + break; + + case 2: {//Mixed RLE + int left=width; + while (left>0) { + int count = stbi__get8(s), i; + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); + + if (count >= 128) { // Repeated + stbi_uc value[4]; + + if (count==128) + count = stbi__get16be(s); + else + count -= 127; + if (count > left) + return stbi__errpuc("bad file","scanline overrun"); + + if (!stbi__readval(s,packet->channel,value)) + return 0; + + for(i=0;ichannel,dest,value); + } else { // Raw + ++count; + if (count>left) return stbi__errpuc("bad file","scanline overrun"); + + for(i=0;ichannel,dest)) + return 0; + } + left-=count; + } + break; + } + } + } + } + + return result; +} + +static void *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp, stbi__result_info *ri) +{ + stbi_uc *result; + int i, x,y, internal_comp; + STBI_NOTUSED(ri); + + if (!comp) comp = &internal_comp; + + for (i=0; i<92; ++i) + stbi__get8(s); + + x = stbi__get16be(s); + y = stbi__get16be(s); + + if (y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); + if (!stbi__mad3sizes_valid(x, y, 4, 0)) return stbi__errpuc("too large", "PIC image too large to decode"); + + stbi__get32be(s); //skip `ratio' + stbi__get16be(s); //skip `fields' + stbi__get16be(s); //skip `pad' + + // intermediate buffer is RGBA + result = (stbi_uc *) stbi__malloc_mad3(x, y, 4, 0); + if (!result) return stbi__errpuc("outofmem", "Out of memory"); + memset(result, 0xff, x*y*4); + + if (!stbi__pic_load_core(s,x,y,comp, result)) { + STBI_FREE(result); + result=0; + } + *px = x; + *py = y; + if (req_comp == 0) req_comp = *comp; + result=stbi__convert_format(result,4,req_comp,x,y); + + return result; +} + +static int stbi__pic_test(stbi__context *s) +{ + int r = stbi__pic_test_core(s); + stbi__rewind(s); + return r; +} +#endif + +// ************************************************************************************************* +// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb + +#ifndef STBI_NO_GIF +typedef struct +{ + stbi__int16 prefix; + stbi_uc first; + stbi_uc suffix; +} stbi__gif_lzw; + +typedef struct +{ + int w,h; + stbi_uc *out; // output buffer (always 4 components) + stbi_uc *background; // The current "background" as far as a gif is concerned + stbi_uc *history; + int flags, bgindex, ratio, transparent, eflags; + stbi_uc pal[256][4]; + stbi_uc lpal[256][4]; + stbi__gif_lzw codes[8192]; + stbi_uc *color_table; + int parse, step; + int lflags; + int start_x, start_y; + int max_x, max_y; + int cur_x, cur_y; + int line_size; + int delay; +} stbi__gif; + +static int stbi__gif_test_raw(stbi__context *s) +{ + int sz; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; + sz = stbi__get8(s); + if (sz != '9' && sz != '7') return 0; + if (stbi__get8(s) != 'a') return 0; + return 1; +} + +static int stbi__gif_test(stbi__context *s) +{ + int r = stbi__gif_test_raw(s); + stbi__rewind(s); + return r; +} + +static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) +{ + int i; + for (i=0; i < num_entries; ++i) { + pal[i][2] = stbi__get8(s); + pal[i][1] = stbi__get8(s); + pal[i][0] = stbi__get8(s); + pal[i][3] = transp == i ? 0 : 255; + } +} + +static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) +{ + stbi_uc version; + if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') + return stbi__err("not GIF", "Corrupt GIF"); + + version = stbi__get8(s); + if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); + if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); + + stbi__g_failure_reason = ""; + g->w = stbi__get16le(s); + g->h = stbi__get16le(s); + g->flags = stbi__get8(s); + g->bgindex = stbi__get8(s); + g->ratio = stbi__get8(s); + g->transparent = -1; + + if (g->w > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + if (g->h > STBI_MAX_DIMENSIONS) return stbi__err("too large","Very large image (corrupt?)"); + + if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments + + if (is_info) return 1; + + if (g->flags & 0x80) + stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); + + return 1; +} + +static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) +{ + stbi__gif* g = (stbi__gif*) stbi__malloc(sizeof(stbi__gif)); + if (!g) return stbi__err("outofmem", "Out of memory"); + if (!stbi__gif_header(s, g, comp, 1)) { + STBI_FREE(g); + stbi__rewind( s ); + return 0; + } + if (x) *x = g->w; + if (y) *y = g->h; + STBI_FREE(g); + return 1; +} + +static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) +{ + stbi_uc *p, *c; + int idx; + + // recurse to decode the prefixes, since the linked-list is backwards, + // and working backwards through an interleaved image would be nasty + if (g->codes[code].prefix >= 0) + stbi__out_gif_code(g, g->codes[code].prefix); + + if (g->cur_y >= g->max_y) return; + + idx = g->cur_x + g->cur_y; + p = &g->out[idx]; + g->history[idx / 4] = 1; + + c = &g->color_table[g->codes[code].suffix * 4]; + if (c[3] > 128) { // don't render transparent pixels; + p[0] = c[2]; + p[1] = c[1]; + p[2] = c[0]; + p[3] = c[3]; + } + g->cur_x += 4; + + if (g->cur_x >= g->max_x) { + g->cur_x = g->start_x; + g->cur_y += g->step; + + while (g->cur_y >= g->max_y && g->parse > 0) { + g->step = (1 << g->parse) * g->line_size; + g->cur_y = g->start_y + (g->step >> 1); + --g->parse; + } + } +} + +static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) +{ + stbi_uc lzw_cs; + stbi__int32 len, init_code; + stbi__uint32 first; + stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; + stbi__gif_lzw *p; + + lzw_cs = stbi__get8(s); + if (lzw_cs > 12) return NULL; + clear = 1 << lzw_cs; + first = 1; + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + bits = 0; + valid_bits = 0; + for (init_code = 0; init_code < clear; init_code++) { + g->codes[init_code].prefix = -1; + g->codes[init_code].first = (stbi_uc) init_code; + g->codes[init_code].suffix = (stbi_uc) init_code; + } + + // support no starting clear code + avail = clear+2; + oldcode = -1; + + len = 0; + for(;;) { + if (valid_bits < codesize) { + if (len == 0) { + len = stbi__get8(s); // start new block + if (len == 0) + return g->out; + } + --len; + bits |= (stbi__int32) stbi__get8(s) << valid_bits; + valid_bits += 8; + } else { + stbi__int32 code = bits & codemask; + bits >>= codesize; + valid_bits -= codesize; + // @OPTIMIZE: is there some way we can accelerate the non-clear path? + if (code == clear) { // clear code + codesize = lzw_cs + 1; + codemask = (1 << codesize) - 1; + avail = clear + 2; + oldcode = -1; + first = 0; + } else if (code == clear + 1) { // end of stream code + stbi__skip(s, len); + while ((len = stbi__get8(s)) > 0) + stbi__skip(s,len); + return g->out; + } else if (code <= avail) { + if (first) { + return stbi__errpuc("no clear code", "Corrupt GIF"); + } + + if (oldcode >= 0) { + p = &g->codes[avail++]; + if (avail > 8192) { + return stbi__errpuc("too many codes", "Corrupt GIF"); + } + + p->prefix = (stbi__int16) oldcode; + p->first = g->codes[oldcode].first; + p->suffix = (code == avail) ? p->first : g->codes[code].first; + } else if (code == avail) + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + + stbi__out_gif_code(g, (stbi__uint16) code); + + if ((avail & codemask) == 0 && avail <= 0x0FFF) { + codesize++; + codemask = (1 << codesize) - 1; + } + + oldcode = code; + } else { + return stbi__errpuc("illegal code in raster", "Corrupt GIF"); + } + } + } +} + +// this function is designed to support animated gifs, although stb_image doesn't support it +// two back is the image from two frames ago, used for a very specific disposal format +static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp, stbi_uc *two_back) +{ + int dispose; + int first_frame; + int pi; + int pcount; + STBI_NOTUSED(req_comp); + + // on first frame, any non-written pixels get the background colour (non-transparent) + first_frame = 0; + if (g->out == 0) { + if (!stbi__gif_header(s, g, comp,0)) return 0; // stbi__g_failure_reason set by stbi__gif_header + if (!stbi__mad3sizes_valid(4, g->w, g->h, 0)) + return stbi__errpuc("too large", "GIF image is too large"); + pcount = g->w * g->h; + g->out = (stbi_uc *) stbi__malloc(4 * pcount); + g->background = (stbi_uc *) stbi__malloc(4 * pcount); + g->history = (stbi_uc *) stbi__malloc(pcount); + if (!g->out || !g->background || !g->history) + return stbi__errpuc("outofmem", "Out of memory"); + + // image is treated as "transparent" at the start - ie, nothing overwrites the current background; + // background colour is only used for pixels that are not rendered first frame, after that "background" + // color refers to the color that was there the previous frame. + memset(g->out, 0x00, 4 * pcount); + memset(g->background, 0x00, 4 * pcount); // state of the background (starts transparent) + memset(g->history, 0x00, pcount); // pixels that were affected previous frame + first_frame = 1; + } else { + // second frame - how do we dispose of the previous one? + dispose = (g->eflags & 0x1C) >> 2; + pcount = g->w * g->h; + + if ((dispose == 3) && (two_back == 0)) { + dispose = 2; // if I don't have an image to revert back to, default to the old background + } + + if (dispose == 3) { // use previous graphic + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &two_back[pi * 4], 4 ); + } + } + } else if (dispose == 2) { + // restore what was changed last frame to background before that frame; + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi]) { + memcpy( &g->out[pi * 4], &g->background[pi * 4], 4 ); + } + } + } else { + // This is a non-disposal case eithe way, so just + // leave the pixels as is, and they will become the new background + // 1: do not dispose + // 0: not specified. + } + + // background is what out is after the undoing of the previou frame; + memcpy( g->background, g->out, 4 * g->w * g->h ); + } + + // clear my history; + memset( g->history, 0x00, g->w * g->h ); // pixels that were affected previous frame + + for (;;) { + int tag = stbi__get8(s); + switch (tag) { + case 0x2C: /* Image Descriptor */ + { + stbi__int32 x, y, w, h; + stbi_uc *o; + + x = stbi__get16le(s); + y = stbi__get16le(s); + w = stbi__get16le(s); + h = stbi__get16le(s); + if (((x + w) > (g->w)) || ((y + h) > (g->h))) + return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); + + g->line_size = g->w * 4; + g->start_x = x * 4; + g->start_y = y * g->line_size; + g->max_x = g->start_x + w * 4; + g->max_y = g->start_y + h * g->line_size; + g->cur_x = g->start_x; + g->cur_y = g->start_y; + + // if the width of the specified rectangle is 0, that means + // we may not see *any* pixels or the image is malformed; + // to make sure this is caught, move the current y down to + // max_y (which is what out_gif_code checks). + if (w == 0) + g->cur_y = g->max_y; + + g->lflags = stbi__get8(s); + + if (g->lflags & 0x40) { + g->step = 8 * g->line_size; // first interlaced spacing + g->parse = 3; + } else { + g->step = g->line_size; + g->parse = 0; + } + + if (g->lflags & 0x80) { + stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); + g->color_table = (stbi_uc *) g->lpal; + } else if (g->flags & 0x80) { + g->color_table = (stbi_uc *) g->pal; + } else + return stbi__errpuc("missing color table", "Corrupt GIF"); + + o = stbi__process_gif_raster(s, g); + if (!o) return NULL; + + // if this was the first frame, + pcount = g->w * g->h; + if (first_frame && (g->bgindex > 0)) { + // if first frame, any pixel not drawn to gets the background color + for (pi = 0; pi < pcount; ++pi) { + if (g->history[pi] == 0) { + g->pal[g->bgindex][3] = 255; // just in case it was made transparent, undo that; It will be reset next frame if need be; + memcpy( &g->out[pi * 4], &g->pal[g->bgindex], 4 ); + } + } + } + + return o; + } + + case 0x21: // Comment Extension. + { + int len; + int ext = stbi__get8(s); + if (ext == 0xF9) { // Graphic Control Extension. + len = stbi__get8(s); + if (len == 4) { + g->eflags = stbi__get8(s); + g->delay = 10 * stbi__get16le(s); // delay - 1/100th of a second, saving as 1/1000ths. + + // unset old transparent + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 255; + } + if (g->eflags & 0x01) { + g->transparent = stbi__get8(s); + if (g->transparent >= 0) { + g->pal[g->transparent][3] = 0; + } + } else { + // don't need transparent + stbi__skip(s, 1); + g->transparent = -1; + } + } else { + stbi__skip(s, len); + break; + } + } + while ((len = stbi__get8(s)) != 0) { + stbi__skip(s, len); + } + break; + } + + case 0x3B: // gif stream termination code + return (stbi_uc *) s; // using '1' causes warning on some compilers + + default: + return stbi__errpuc("unknown code", "Corrupt GIF"); + } + } +} + +static void *stbi__load_gif_main_outofmem(stbi__gif *g, stbi_uc *out, int **delays) +{ + STBI_FREE(g->out); + STBI_FREE(g->history); + STBI_FREE(g->background); + + if (out) STBI_FREE(out); + if (delays && *delays) STBI_FREE(*delays); + return stbi__errpuc("outofmem", "Out of memory"); +} + +static void *stbi__load_gif_main(stbi__context *s, int **delays, int *x, int *y, int *z, int *comp, int req_comp) +{ + if (stbi__gif_test(s)) { + int layers = 0; + stbi_uc *u = 0; + stbi_uc *out = 0; + stbi_uc *two_back = 0; + stbi__gif g; + int stride; + int out_size = 0; + int delays_size = 0; + + STBI_NOTUSED(out_size); + STBI_NOTUSED(delays_size); + + memset(&g, 0, sizeof(g)); + if (delays) { + *delays = 0; + } + + do { + u = stbi__gif_load_next(s, &g, comp, req_comp, two_back); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + + if (u) { + *x = g.w; + *y = g.h; + ++layers; + stride = g.w * g.h * 4; + + if (out) { + void *tmp = (stbi_uc*) STBI_REALLOC_SIZED( out, out_size, layers * stride ); + if (!tmp) + return stbi__load_gif_main_outofmem(&g, out, delays); + else { + out = (stbi_uc*) tmp; + out_size = layers * stride; + } + + if (delays) { + int *new_delays = (int*) STBI_REALLOC_SIZED( *delays, delays_size, sizeof(int) * layers ); + if (!new_delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + *delays = new_delays; + delays_size = layers * sizeof(int); + } + } else { + out = (stbi_uc*)stbi__malloc( layers * stride ); + if (!out) + return stbi__load_gif_main_outofmem(&g, out, delays); + out_size = layers * stride; + if (delays) { + *delays = (int*) stbi__malloc( layers * sizeof(int) ); + if (!*delays) + return stbi__load_gif_main_outofmem(&g, out, delays); + delays_size = layers * sizeof(int); + } + } + memcpy( out + ((layers - 1) * stride), u, stride ); + if (layers >= 2) { + two_back = out - 2 * stride; + } + + if (delays) { + (*delays)[layers - 1U] = g.delay; + } + } + } while (u != 0); + + // free temp buffer; + STBI_FREE(g.out); + STBI_FREE(g.history); + STBI_FREE(g.background); + + // do the final conversion after loading everything; + if (req_comp && req_comp != 4) + out = stbi__convert_format(out, 4, req_comp, layers * g.w, g.h); + + *z = layers; + return out; + } else { + return stbi__errpuc("not GIF", "Image was not as a gif type."); + } +} + +static void *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *u = 0; + stbi__gif g; + memset(&g, 0, sizeof(g)); + STBI_NOTUSED(ri); + + u = stbi__gif_load_next(s, &g, comp, req_comp, 0); + if (u == (stbi_uc *) s) u = 0; // end of animated gif marker + if (u) { + *x = g.w; + *y = g.h; + + // moved conversion to after successful load so that the same + // can be done for multiple frames. + if (req_comp && req_comp != 4) + u = stbi__convert_format(u, 4, req_comp, g.w, g.h); + } else if (g.out) { + // if there was an error and we allocated an image buffer, free it! + STBI_FREE(g.out); + } + + // free buffers needed for multiple frame loading; + STBI_FREE(g.history); + STBI_FREE(g.background); + + return u; +} + +static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) +{ + return stbi__gif_info_raw(s,x,y,comp); +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR loader +// originally by Nicolas Schulz +#ifndef STBI_NO_HDR +static int stbi__hdr_test_core(stbi__context *s, const char *signature) +{ + int i; + for (i=0; signature[i]; ++i) + if (stbi__get8(s) != signature[i]) + return 0; + stbi__rewind(s); + return 1; +} + +static int stbi__hdr_test(stbi__context* s) +{ + int r = stbi__hdr_test_core(s, "#?RADIANCE\n"); + stbi__rewind(s); + if(!r) { + r = stbi__hdr_test_core(s, "#?RGBE\n"); + stbi__rewind(s); + } + return r; +} + +#define STBI__HDR_BUFLEN 1024 +static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) +{ + int len=0; + char c = '\0'; + + c = (char) stbi__get8(z); + + while (!stbi__at_eof(z) && c != '\n') { + buffer[len++] = c; + if (len == STBI__HDR_BUFLEN-1) { + // flush to end of line + while (!stbi__at_eof(z) && stbi__get8(z) != '\n') + ; + break; + } + c = (char) stbi__get8(z); + } + + buffer[len] = 0; + return buffer; +} + +static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) +{ + if ( input[3] != 0 ) { + float f1; + // Exponent + f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); + if (req_comp <= 2) + output[0] = (input[0] + input[1] + input[2]) * f1 / 3; + else { + output[0] = input[0] * f1; + output[1] = input[1] * f1; + output[2] = input[2] * f1; + } + if (req_comp == 2) output[1] = 1; + if (req_comp == 4) output[3] = 1; + } else { + switch (req_comp) { + case 4: output[3] = 1; /* fallthrough */ + case 3: output[0] = output[1] = output[2] = 0; + break; + case 2: output[1] = 1; /* fallthrough */ + case 1: output[0] = 0; + break; + } + } +} + +static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int width, height; + stbi_uc *scanline; + float *hdr_data; + int len; + unsigned char count, value; + int i, j, k, c1,c2, z; + const char *headerToken; + STBI_NOTUSED(ri); + + // Check identifier + headerToken = stbi__hdr_gettoken(s,buffer); + if (strcmp(headerToken, "#?RADIANCE") != 0 && strcmp(headerToken, "#?RGBE") != 0) + return stbi__errpf("not HDR", "Corrupt HDR image"); + + // Parse header + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); + + // Parse width and height + // can't use sscanf() if we're not using stdio! + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + height = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); + token += 3; + width = (int) strtol(token, NULL, 10); + + if (height > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + if (width > STBI_MAX_DIMENSIONS) return stbi__errpf("too large","Very large image (corrupt?)"); + + *x = width; + *y = height; + + if (comp) *comp = 3; + if (req_comp == 0) req_comp = 3; + + if (!stbi__mad4sizes_valid(width, height, req_comp, sizeof(float), 0)) + return stbi__errpf("too large", "HDR image is too large"); + + // Read data + hdr_data = (float *) stbi__malloc_mad4(width, height, req_comp, sizeof(float), 0); + if (!hdr_data) + return stbi__errpf("outofmem", "Out of memory"); + + // Load image data + // image data is stored as some number of sca + if ( width < 8 || width >= 32768) { + // Read flat data + for (j=0; j < height; ++j) { + for (i=0; i < width; ++i) { + stbi_uc rgbe[4]; + main_decode_loop: + stbi__getn(s, rgbe, 4); + stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); + } + } + } else { + // Read RLE-encoded data + scanline = NULL; + + for (j = 0; j < height; ++j) { + c1 = stbi__get8(s); + c2 = stbi__get8(s); + len = stbi__get8(s); + if (c1 != 2 || c2 != 2 || (len & 0x80)) { + // not run-length encoded, so we have to actually use THIS data as a decoded + // pixel (note this can't be a valid pixel--one of RGB must be >= 128) + stbi_uc rgbe[4]; + rgbe[0] = (stbi_uc) c1; + rgbe[1] = (stbi_uc) c2; + rgbe[2] = (stbi_uc) len; + rgbe[3] = (stbi_uc) stbi__get8(s); + stbi__hdr_convert(hdr_data, rgbe, req_comp); + i = 1; + j = 0; + STBI_FREE(scanline); + goto main_decode_loop; // yes, this makes no sense + } + len <<= 8; + len |= stbi__get8(s); + if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } + if (scanline == NULL) { + scanline = (stbi_uc *) stbi__malloc_mad2(width, 4, 0); + if (!scanline) { + STBI_FREE(hdr_data); + return stbi__errpf("outofmem", "Out of memory"); + } + } + + for (k = 0; k < 4; ++k) { + int nleft; + i = 0; + while ((nleft = width - i) > 0) { + count = stbi__get8(s); + if (count > 128) { + // Run + value = stbi__get8(s); + count -= 128; + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = value; + } else { + // Dump + if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); } + for (z = 0; z < count; ++z) + scanline[i++ * 4 + k] = stbi__get8(s); + } + } + } + for (i=0; i < width; ++i) + stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); + } + if (scanline) + STBI_FREE(scanline); + } + + return hdr_data; +} + +static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) +{ + char buffer[STBI__HDR_BUFLEN]; + char *token; + int valid = 0; + int dummy; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (stbi__hdr_test(s) == 0) { + stbi__rewind( s ); + return 0; + } + + for(;;) { + token = stbi__hdr_gettoken(s,buffer); + if (token[0] == 0) break; + if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; + } + + if (!valid) { + stbi__rewind( s ); + return 0; + } + token = stbi__hdr_gettoken(s,buffer); + if (strncmp(token, "-Y ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *y = (int) strtol(token, &token, 10); + while (*token == ' ') ++token; + if (strncmp(token, "+X ", 3)) { + stbi__rewind( s ); + return 0; + } + token += 3; + *x = (int) strtol(token, NULL, 10); + *comp = 3; + return 1; +} +#endif // STBI_NO_HDR + +#ifndef STBI_NO_BMP +static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) +{ + void *p; + stbi__bmp_data info; + + info.all_a = 255; + p = stbi__bmp_parse_header(s, &info); + if (p == NULL) { + stbi__rewind( s ); + return 0; + } + if (x) *x = s->img_x; + if (y) *y = s->img_y; + if (comp) { + if (info.bpp == 24 && info.ma == 0xff000000) + *comp = 3; + else + *comp = info.ma ? 4 : 3; + } + return 1; +} +#endif + +#ifndef STBI_NO_PSD +static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) +{ + int channelCount, dummy, depth; + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + *y = stbi__get32be(s); + *x = stbi__get32be(s); + depth = stbi__get16be(s); + if (depth != 8 && depth != 16) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 3) { + stbi__rewind( s ); + return 0; + } + *comp = 4; + return 1; +} + +static int stbi__psd_is16(stbi__context *s) +{ + int channelCount, depth; + if (stbi__get32be(s) != 0x38425053) { + stbi__rewind( s ); + return 0; + } + if (stbi__get16be(s) != 1) { + stbi__rewind( s ); + return 0; + } + stbi__skip(s, 6); + channelCount = stbi__get16be(s); + if (channelCount < 0 || channelCount > 16) { + stbi__rewind( s ); + return 0; + } + STBI_NOTUSED(stbi__get32be(s)); + STBI_NOTUSED(stbi__get32be(s)); + depth = stbi__get16be(s); + if (depth != 16) { + stbi__rewind( s ); + return 0; + } + return 1; +} +#endif + +#ifndef STBI_NO_PIC +static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) +{ + int act_comp=0,num_packets=0,chained,dummy; + stbi__pic_packet packets[10]; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { + stbi__rewind(s); + return 0; + } + + stbi__skip(s, 88); + + *x = stbi__get16be(s); + *y = stbi__get16be(s); + if (stbi__at_eof(s)) { + stbi__rewind( s); + return 0; + } + if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { + stbi__rewind( s ); + return 0; + } + + stbi__skip(s, 8); + + do { + stbi__pic_packet *packet; + + if (num_packets==sizeof(packets)/sizeof(packets[0])) + return 0; + + packet = &packets[num_packets++]; + chained = stbi__get8(s); + packet->size = stbi__get8(s); + packet->type = stbi__get8(s); + packet->channel = stbi__get8(s); + act_comp |= packet->channel; + + if (stbi__at_eof(s)) { + stbi__rewind( s ); + return 0; + } + if (packet->size != 8) { + stbi__rewind( s ); + return 0; + } + } while (chained); + + *comp = (act_comp & 0x10 ? 4 : 3); + + return 1; +} +#endif + +// ************************************************************************************************* +// Portable Gray Map and Portable Pixel Map loader +// by Ken Miller +// +// PGM: http://netpbm.sourceforge.net/doc/pgm.html +// PPM: http://netpbm.sourceforge.net/doc/ppm.html +// +// Known limitations: +// Does not support comments in the header section +// Does not support ASCII image data (formats P2 and P3) + +#ifndef STBI_NO_PNM + +static int stbi__pnm_test(stbi__context *s) +{ + char p, t; + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind( s ); + return 0; + } + return 1; +} + +static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp, stbi__result_info *ri) +{ + stbi_uc *out; + STBI_NOTUSED(ri); + + ri->bits_per_channel = stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n); + if (ri->bits_per_channel == 0) + return 0; + + if (s->img_y > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + if (s->img_x > STBI_MAX_DIMENSIONS) return stbi__errpuc("too large","Very large image (corrupt?)"); + + *x = s->img_x; + *y = s->img_y; + if (comp) *comp = s->img_n; + + if (!stbi__mad4sizes_valid(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0)) + return stbi__errpuc("too large", "PNM too large"); + + out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0); + if (!out) return stbi__errpuc("outofmem", "Out of memory"); + if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) { + STBI_FREE(out); + return stbi__errpuc("bad PNM", "PNM file truncated"); + } + + if (req_comp && req_comp != s->img_n) { + if (ri->bits_per_channel == 16) { + out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y); + } else { + out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); + } + if (out == NULL) return out; // stbi__convert_format frees input on failure + } + return out; +} + +static int stbi__pnm_isspace(char c) +{ + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; +} + +static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) +{ + for (;;) { + while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) + *c = (char) stbi__get8(s); + + if (stbi__at_eof(s) || *c != '#') + break; + + while (!stbi__at_eof(s) && *c != '\n' && *c != '\r' ) + *c = (char) stbi__get8(s); + } +} + +static int stbi__pnm_isdigit(char c) +{ + return c >= '0' && c <= '9'; +} + +static int stbi__pnm_getinteger(stbi__context *s, char *c) +{ + int value = 0; + + while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { + value = value*10 + (*c - '0'); + *c = (char) stbi__get8(s); + if((value > 214748364) || (value == 214748364 && *c > '7')) + return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int"); + } + + return value; +} + +static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) +{ + int maxv, dummy; + char c, p, t; + + if (!x) x = &dummy; + if (!y) y = &dummy; + if (!comp) comp = &dummy; + + stbi__rewind(s); + + // Get identifier + p = (char) stbi__get8(s); + t = (char) stbi__get8(s); + if (p != 'P' || (t != '5' && t != '6')) { + stbi__rewind(s); + return 0; + } + + *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm + + c = (char) stbi__get8(s); + stbi__pnm_skip_whitespace(s, &c); + + *x = stbi__pnm_getinteger(s, &c); // read width + if(*x == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + *y = stbi__pnm_getinteger(s, &c); // read height + if (*y == 0) + return stbi__err("invalid width", "PPM image header had zero or overflowing width"); + stbi__pnm_skip_whitespace(s, &c); + + maxv = stbi__pnm_getinteger(s, &c); // read max value + if (maxv > 65535) + return stbi__err("max value > 65535", "PPM image supports only 8-bit and 16-bit images"); + else if (maxv > 255) + return 16; + else + return 8; +} + +static int stbi__pnm_is16(stbi__context *s) +{ + if (stbi__pnm_info(s, NULL, NULL, NULL) == 16) + return 1; + return 0; +} +#endif + +static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) +{ + #ifndef STBI_NO_JPEG + if (stbi__jpeg_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNG + if (stbi__png_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_GIF + if (stbi__gif_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_BMP + if (stbi__bmp_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PIC + if (stbi__pic_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_info(s, x, y, comp)) return 1; + #endif + + #ifndef STBI_NO_HDR + if (stbi__hdr_info(s, x, y, comp)) return 1; + #endif + + // test tga last because it's a crappy test! + #ifndef STBI_NO_TGA + if (stbi__tga_info(s, x, y, comp)) + return 1; + #endif + return stbi__err("unknown image type", "Image not of any known type, or corrupt"); +} + +static int stbi__is_16_main(stbi__context *s) +{ + #ifndef STBI_NO_PNG + if (stbi__png_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PSD + if (stbi__psd_is16(s)) return 1; + #endif + + #ifndef STBI_NO_PNM + if (stbi__pnm_is16(s)) return 1; + #endif + return 0; +} + +#ifndef STBI_NO_STDIO +STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_info_from_file(f, x, y, comp); + fclose(f); + return result; +} + +STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__info_main(&s,x,y,comp); + fseek(f,pos,SEEK_SET); + return r; +} + +STBIDEF int stbi_is_16_bit(char const *filename) +{ + FILE *f = stbi__fopen(filename, "rb"); + int result; + if (!f) return stbi__err("can't fopen", "Unable to open file"); + result = stbi_is_16_bit_from_file(f); + fclose(f); + return result; +} + +STBIDEF int stbi_is_16_bit_from_file(FILE *f) +{ + int r; + stbi__context s; + long pos = ftell(f); + stbi__start_file(&s, f); + r = stbi__is_16_main(&s); + fseek(f,pos,SEEK_SET); + return r; +} +#endif // !STBI_NO_STDIO + +STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__info_main(&s,x,y,comp); +} + +STBIDEF int stbi_is_16_bit_from_memory(stbi_uc const *buffer, int len) +{ + stbi__context s; + stbi__start_mem(&s,buffer,len); + return stbi__is_16_main(&s); +} + +STBIDEF int stbi_is_16_bit_from_callbacks(stbi_io_callbacks const *c, void *user) +{ + stbi__context s; + stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); + return stbi__is_16_main(&s); +} + +#endif // STB_IMAGE_IMPLEMENTATION + +/* + revision history: + 2.20 (2019-02-07) support utf8 filenames in Windows; fix warnings and platform ifdefs + 2.19 (2018-02-11) fix warning + 2.18 (2018-01-30) fix warnings + 2.17 (2018-01-29) change sbti__shiftsigned to avoid clang -O2 bug + 1-bit BMP + *_is_16_bit api + avoid warnings + 2.16 (2017-07-23) all functions have 16-bit variants; + STBI_NO_STDIO works again; + compilation fixes; + fix rounding in unpremultiply; + optimize vertical flip; + disable raw_len validation; + documentation fixes + 2.15 (2017-03-18) fix png-1,2,4 bug; now all Imagenet JPGs decode; + warning fixes; disable run-time SSE detection on gcc; + uniform handling of optional "return" values; + thread-safe initialization of zlib tables + 2.14 (2017-03-03) remove deprecated STBI_JPEG_OLD; fixes for Imagenet JPGs + 2.13 (2016-11-29) add 16-bit API, only supported for PNG right now + 2.12 (2016-04-02) fix typo in 2.11 PSD fix that caused crashes + 2.11 (2016-04-02) allocate large structures on the stack + remove white matting for transparent PSD + fix reported channel count for PNG & BMP + re-enable SSE2 in non-gcc 64-bit + support RGB-formatted JPEG + read 16-bit PNGs (only as 8-bit) + 2.10 (2016-01-22) avoid warning introduced in 2.09 by STBI_REALLOC_SIZED + 2.09 (2016-01-16) allow comments in PNM files + 16-bit-per-pixel TGA (not bit-per-component) + info() for TGA could break due to .hdr handling + info() for BMP to shares code instead of sloppy parse + can use STBI_REALLOC_SIZED if allocator doesn't support realloc + code cleanup + 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA + 2.07 (2015-09-13) fix compiler warnings + partial animated GIF support + limited 16-bpc PSD support + #ifdef unused functions + bug with < 92 byte PIC,PNM,HDR,TGA + 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value + 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning + 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit + 2.03 (2015-04-12) extra corruption checking (mmozeiko) + stbi_set_flip_vertically_on_load (nguillemot) + fix NEON support; fix mingw support + 2.02 (2015-01-19) fix incorrect assert, fix warning + 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 + 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG + 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) + progressive JPEG (stb) + PGM/PPM support (Ken Miller) + STBI_MALLOC,STBI_REALLOC,STBI_FREE + GIF bugfix -- seemingly never worked + STBI_NO_*, STBI_ONLY_* + 1.48 (2014-12-14) fix incorrectly-named assert() + 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) + optimize PNG (ryg) + fix bug in interlaced PNG with user-specified channel count (stb) + 1.46 (2014-08-26) + fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG + 1.45 (2014-08-16) + fix MSVC-ARM internal compiler error by wrapping malloc + 1.44 (2014-08-07) + various warning fixes from Ronny Chevalier + 1.43 (2014-07-15) + fix MSVC-only compiler problem in code changed in 1.42 + 1.42 (2014-07-09) + don't define _CRT_SECURE_NO_WARNINGS (affects user code) + fixes to stbi__cleanup_jpeg path + added STBI_ASSERT to avoid requiring assert.h + 1.41 (2014-06-25) + fix search&replace from 1.36 that messed up comments/error messages + 1.40 (2014-06-22) + fix gcc struct-initialization warning + 1.39 (2014-06-15) + fix to TGA optimization when req_comp != number of components in TGA; + fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) + add support for BMP version 5 (more ignored fields) + 1.38 (2014-06-06) + suppress MSVC warnings on integer casts truncating values + fix accidental rename of 'skip' field of I/O + 1.37 (2014-06-04) + remove duplicate typedef + 1.36 (2014-06-03) + convert to header file single-file library + if de-iphone isn't set, load iphone images color-swapped instead of returning NULL + 1.35 (2014-05-27) + various warnings + fix broken STBI_SIMD path + fix bug where stbi_load_from_file no longer left file pointer in correct place + fix broken non-easy path for 32-bit BMP (possibly never used) + TGA optimization by Arseny Kapoulkine + 1.34 (unknown) + use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case + 1.33 (2011-07-14) + make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements + 1.32 (2011-07-13) + support for "info" function for all supported filetypes (SpartanJ) + 1.31 (2011-06-20) + a few more leak fixes, bug in PNG handling (SpartanJ) + 1.30 (2011-06-11) + added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) + removed deprecated format-specific test/load functions + removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway + error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) + fix inefficiency in decoding 32-bit BMP (David Woo) + 1.29 (2010-08-16) + various warning fixes from Aurelien Pocheville + 1.28 (2010-08-01) + fix bug in GIF palette transparency (SpartanJ) + 1.27 (2010-08-01) + cast-to-stbi_uc to fix warnings + 1.26 (2010-07-24) + fix bug in file buffering for PNG reported by SpartanJ + 1.25 (2010-07-17) + refix trans_data warning (Won Chun) + 1.24 (2010-07-12) + perf improvements reading from files on platforms with lock-heavy fgetc() + minor perf improvements for jpeg + deprecated type-specific functions so we'll get feedback if they're needed + attempt to fix trans_data warning (Won Chun) + 1.23 fixed bug in iPhone support + 1.22 (2010-07-10) + removed image *writing* support + stbi_info support from Jetro Lauha + GIF support from Jean-Marc Lienher + iPhone PNG-extensions from James Brown + warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) + 1.21 fix use of 'stbi_uc' in header (reported by jon blow) + 1.20 added support for Softimage PIC, by Tom Seddon + 1.19 bug in interlaced PNG corruption check (found by ryg) + 1.18 (2008-08-02) + fix a threading bug (local mutable static) + 1.17 support interlaced PNG + 1.16 major bugfix - stbi__convert_format converted one too many pixels + 1.15 initialize some fields for thread safety + 1.14 fix threadsafe conversion bug + header-file-only version (#define STBI_HEADER_FILE_ONLY before including) + 1.13 threadsafe + 1.12 const qualifiers in the API + 1.11 Support installable IDCT, colorspace conversion routines + 1.10 Fixes for 64-bit (don't use "unsigned long") + optimized upsampling by Fabian "ryg" Giesen + 1.09 Fix format-conversion for PSD code (bad global variables!) + 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz + 1.07 attempt to fix C++ warning/errors again + 1.06 attempt to fix C++ warning/errors again + 1.05 fix TGA loading to return correct *comp and use good luminance calc + 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free + 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR + 1.02 support for (subset of) HDR files, float interface for preferred access to them + 1.01 fix bug: possible bug in handling right-side up bmps... not sure + fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all + 1.00 interface to zlib that skips zlib header + 0.99 correct handling of alpha in palette + 0.98 TGA loader by lonesock; dynamically add loaders (untested) + 0.97 jpeg errors on too large a file; also catch another malloc failure + 0.96 fix detection of invalid v value - particleman@mollyrocket forum + 0.95 during header scan, seek to markers in case of padding + 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same + 0.93 handle jpegtran output; verbose errors + 0.92 read 4,8,16,24,32-bit BMP files of several formats + 0.91 output 24-bit Windows 3.0 BMP files + 0.90 fix a few more warnings; bump version number to approach 1.0 + 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd + 0.60 fix compiling as c++ + 0.59 fix warnings: merge Dave Moore's -Wall fixes + 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian + 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available + 0.56 fix bug: zlib uncompressed mode len vs. nlen + 0.55 fix bug: restart_interval not initialized to 0 + 0.54 allow NULL for 'int *comp' + 0.53 fix bug in png 3->4; speedup png decoding + 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments + 0.51 obey req_comp requests, 1-component jpegs return as 1-component, + on 'test' only check type, not whether we support this variant + 0.50 (2006-11-19) + first released version +*/ + + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/ diff --git a/third-party/stb_image/stb_image_write.h b/third-party/stb_image/stb_image_write.h new file mode 100644 index 000000000..e4b32ed1b --- /dev/null +++ b/third-party/stb_image/stb_image_write.h @@ -0,0 +1,1724 @@ +/* stb_image_write - v1.16 - public domain - http://nothings.org/stb + writes out PNG/BMP/TGA/JPEG/HDR images to C stdio - Sean Barrett 2010-2015 + no warranty implied; use at your own risk + + Before #including, + + #define STB_IMAGE_WRITE_IMPLEMENTATION + + in the file that you want to have the implementation. + + Will probably not work correctly with strict-aliasing optimizations. + +ABOUT: + + This header file is a library for writing images to C stdio or a callback. + + The PNG output is not optimal; it is 20-50% larger than the file + written by a decent optimizing implementation; though providing a custom + zlib compress function (see STBIW_ZLIB_COMPRESS) can mitigate that. + This library is designed for source code compactness and simplicity, + not optimal image file size or run-time performance. + +BUILDING: + + You can #define STBIW_ASSERT(x) before the #include to avoid using assert.h. + You can #define STBIW_MALLOC(), STBIW_REALLOC(), and STBIW_FREE() to replace + malloc,realloc,free. + You can #define STBIW_MEMMOVE() to replace memmove() + You can #define STBIW_ZLIB_COMPRESS to use a custom zlib-style compress function + for PNG compression (instead of the builtin one), it must have the following signature: + unsigned char * my_compress(unsigned char *data, int data_len, int *out_len, int quality); + The returned data will be freed with STBIW_FREE() (free() by default), + so it must be heap allocated with STBIW_MALLOC() (malloc() by default), + +UNICODE: + + If compiling for Windows and you wish to use Unicode filenames, compile + with + #define STBIW_WINDOWS_UTF8 + and pass utf8-encoded filenames. Call stbiw_convert_wchar_to_utf8 to convert + Windows wchar_t filenames to utf8. + +USAGE: + + There are five functions, one for each image file format: + + int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); + int stbi_write_jpg(char const *filename, int w, int h, int comp, const void *data, int quality); + int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); + + void stbi_flip_vertically_on_write(int flag); // flag is non-zero to flip data vertically + + There are also five equivalent functions that use an arbitrary write function. You are + expected to open/close your file-equivalent before and after calling these: + + int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); + int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); + int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); + int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + + where the callback is: + void stbi_write_func(void *context, void *data, int size); + + You can configure it with these global variables: + int stbi_write_tga_with_rle; // defaults to true; set to 0 to disable RLE + int stbi_write_png_compression_level; // defaults to 8; set to higher for more compression + int stbi_write_force_png_filter; // defaults to -1; set to 0..5 to force a filter mode + + + You can define STBI_WRITE_NO_STDIO to disable the file variant of these + functions, so the library will not use stdio.h at all. However, this will + also disable HDR writing, because it requires stdio for formatted output. + + Each function returns 0 on failure and non-0 on success. + + The functions create an image file defined by the parameters. The image + is a rectangle of pixels stored from left-to-right, top-to-bottom. + Each pixel contains 'comp' channels of data stored interleaved with 8-bits + per channel, in the following order: 1=Y, 2=YA, 3=RGB, 4=RGBA. (Y is + monochrome color.) The rectangle is 'w' pixels wide and 'h' pixels tall. + The *data pointer points to the first byte of the top-left-most pixel. + For PNG, "stride_in_bytes" is the distance in bytes from the first byte of + a row of pixels to the first byte of the next row of pixels. + + PNG creates output files with the same number of components as the input. + The BMP format expands Y to RGB in the file format and does not + output alpha. + + PNG supports writing rectangles of data even when the bytes storing rows of + data are not consecutive in memory (e.g. sub-rectangles of a larger image), + by supplying the stride between the beginning of adjacent rows. The other + formats do not. (Thus you cannot write a native-format BMP through the BMP + writer, both because it is in BGR order and because it may have padding + at the end of the line.) + + PNG allows you to set the deflate compression level by setting the global + variable 'stbi_write_png_compression_level' (it defaults to 8). + + HDR expects linear float data. Since the format is always 32-bit rgb(e) + data, alpha (if provided) is discarded, and for monochrome data it is + replicated across all three channels. + + TGA supports RLE or non-RLE compressed data. To use non-RLE-compressed + data, set the global variable 'stbi_write_tga_with_rle' to 0. + + JPEG does ignore alpha channels in input data; quality is between 1 and 100. + Higher quality looks better but results in a bigger image. + JPEG baseline (no JPEG progressive). + +CREDITS: + + + Sean Barrett - PNG/BMP/TGA + Baldur Karlsson - HDR + Jean-Sebastien Guay - TGA monochrome + Tim Kelsey - misc enhancements + Alan Hickman - TGA RLE + Emmanuel Julien - initial file IO callback implementation + Jon Olick - original jo_jpeg.cpp code + Daniel Gibson - integrate JPEG, allow external zlib + Aarni Koskela - allow choosing PNG filter + + bugfixes: + github:Chribba + Guillaume Chereau + github:jry2 + github:romigrou + Sergio Gonzalez + Jonas Karlsson + Filip Wasil + Thatcher Ulrich + github:poppolopoppo + Patrick Boettcher + github:xeekworx + Cap Petschulat + Simon Rodriguez + Ivan Tikhonov + github:ignotion + Adam Schackart + Andrew Kensler + +LICENSE + + See end of file for license information. + +*/ + +#ifndef INCLUDE_STB_IMAGE_WRITE_H +#define INCLUDE_STB_IMAGE_WRITE_H + +#include + +// if STB_IMAGE_WRITE_STATIC causes problems, try defining STBIWDEF to 'inline' or 'static inline' +#ifndef STBIWDEF +#ifdef STB_IMAGE_WRITE_STATIC +#define STBIWDEF static +#else +#ifdef __cplusplus +#define STBIWDEF extern "C" +#else +#define STBIWDEF extern +#endif +#endif +#endif + +#ifndef STB_IMAGE_WRITE_STATIC // C++ forbids static forward declarations +STBIWDEF int stbi_write_tga_with_rle; +STBIWDEF int stbi_write_png_compression_level; +STBIWDEF int stbi_write_force_png_filter; +#endif + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr(char const *filename, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality); + +#ifdef STBIW_WINDOWS_UTF8 +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input); +#endif +#endif + +typedef void stbi_write_func(void *context, void *data, int size); + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data, int stride_in_bytes); +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const void *data); +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int w, int h, int comp, const float *data); +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality); + +STBIWDEF void stbi_flip_vertically_on_write(int flip_boolean); + +#endif//INCLUDE_STB_IMAGE_WRITE_H + +#ifdef STB_IMAGE_WRITE_IMPLEMENTATION + +#ifdef _WIN32 + #ifndef _CRT_SECURE_NO_WARNINGS + #define _CRT_SECURE_NO_WARNINGS + #endif + #ifndef _CRT_NONSTDC_NO_DEPRECATE + #define _CRT_NONSTDC_NO_DEPRECATE + #endif +#endif + +#ifndef STBI_WRITE_NO_STDIO +#include +#endif // STBI_WRITE_NO_STDIO + +#include +#include +#include +#include + +#if defined(STBIW_MALLOC) && defined(STBIW_FREE) && (defined(STBIW_REALLOC) || defined(STBIW_REALLOC_SIZED)) +// ok +#elif !defined(STBIW_MALLOC) && !defined(STBIW_FREE) && !defined(STBIW_REALLOC) && !defined(STBIW_REALLOC_SIZED) +// ok +#else +#error "Must define all or none of STBIW_MALLOC, STBIW_FREE, and STBIW_REALLOC (or STBIW_REALLOC_SIZED)." +#endif + +#ifndef STBIW_MALLOC +#define STBIW_MALLOC(sz) malloc(sz) +#define STBIW_REALLOC(p,newsz) realloc(p,newsz) +#define STBIW_FREE(p) free(p) +#endif + +#ifndef STBIW_REALLOC_SIZED +#define STBIW_REALLOC_SIZED(p,oldsz,newsz) STBIW_REALLOC(p,newsz) +#endif + + +#ifndef STBIW_MEMMOVE +#define STBIW_MEMMOVE(a,b,sz) memmove(a,b,sz) +#endif + + +#ifndef STBIW_ASSERT +#include +#define STBIW_ASSERT(x) assert(x) +#endif + +#define STBIW_UCHAR(x) (unsigned char) ((x) & 0xff) + +#ifdef STB_IMAGE_WRITE_STATIC +static int stbi_write_png_compression_level = 8; +static int stbi_write_tga_with_rle = 1; +static int stbi_write_force_png_filter = -1; +#else +int stbi_write_png_compression_level = 8; +int stbi_write_tga_with_rle = 1; +int stbi_write_force_png_filter = -1; +#endif + +static int stbi__flip_vertically_on_write = 0; + +STBIWDEF void stbi_flip_vertically_on_write(int flag) +{ + stbi__flip_vertically_on_write = flag; +} + +typedef struct +{ + stbi_write_func *func; + void *context; + unsigned char buffer[64]; + int buf_used; +} stbi__write_context; + +// initialize a callback-based context +static void stbi__start_write_callbacks(stbi__write_context *s, stbi_write_func *c, void *context) +{ + s->func = c; + s->context = context; +} + +#ifndef STBI_WRITE_NO_STDIO + +static void stbi__stdio_write(void *context, void *data, int size) +{ + fwrite(data,1,size,(FILE*) context); +} + +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) +#ifdef __cplusplus +#define STBIW_EXTERN extern "C" +#else +#define STBIW_EXTERN extern +#endif +STBIW_EXTERN __declspec(dllimport) int __stdcall MultiByteToWideChar(unsigned int cp, unsigned long flags, const char *str, int cbmb, wchar_t *widestr, int cchwide); +STBIW_EXTERN __declspec(dllimport) int __stdcall WideCharToMultiByte(unsigned int cp, unsigned long flags, const wchar_t *widestr, int cchwide, char *str, int cbmb, const char *defchar, int *used_default); + +STBIWDEF int stbiw_convert_wchar_to_utf8(char *buffer, size_t bufferlen, const wchar_t* input) +{ + return WideCharToMultiByte(65001 /* UTF8 */, 0, input, -1, buffer, (int) bufferlen, NULL, NULL); +} +#endif + +static FILE *stbiw__fopen(char const *filename, char const *mode) +{ + FILE *f; +#if defined(_WIN32) && defined(STBIW_WINDOWS_UTF8) + wchar_t wMode[64]; + wchar_t wFilename[1024]; + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, filename, -1, wFilename, sizeof(wFilename)/sizeof(*wFilename))) + return 0; + + if (0 == MultiByteToWideChar(65001 /* UTF8 */, 0, mode, -1, wMode, sizeof(wMode)/sizeof(*wMode))) + return 0; + +#if defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != _wfopen_s(&f, wFilename, wMode)) + f = 0; +#else + f = _wfopen(wFilename, wMode); +#endif + +#elif defined(_MSC_VER) && _MSC_VER >= 1400 + if (0 != fopen_s(&f, filename, mode)) + f=0; +#else + f = fopen(filename, mode); +#endif + return f; +} + +static int stbi__start_write_file(stbi__write_context *s, const char *filename) +{ + FILE *f = stbiw__fopen(filename, "wb"); + stbi__start_write_callbacks(s, stbi__stdio_write, (void *) f); + return f != NULL; +} + +static void stbi__end_write_file(stbi__write_context *s) +{ + fclose((FILE *)s->context); +} + +#endif // !STBI_WRITE_NO_STDIO + +typedef unsigned int stbiw_uint32; +typedef int stb_image_write_test[sizeof(stbiw_uint32)==4 ? 1 : -1]; + +static void stbiw__writefv(stbi__write_context *s, const char *fmt, va_list v) +{ + while (*fmt) { + switch (*fmt++) { + case ' ': break; + case '1': { unsigned char x = STBIW_UCHAR(va_arg(v, int)); + s->func(s->context,&x,1); + break; } + case '2': { int x = va_arg(v,int); + unsigned char b[2]; + b[0] = STBIW_UCHAR(x); + b[1] = STBIW_UCHAR(x>>8); + s->func(s->context,b,2); + break; } + case '4': { stbiw_uint32 x = va_arg(v,int); + unsigned char b[4]; + b[0]=STBIW_UCHAR(x); + b[1]=STBIW_UCHAR(x>>8); + b[2]=STBIW_UCHAR(x>>16); + b[3]=STBIW_UCHAR(x>>24); + s->func(s->context,b,4); + break; } + default: + STBIW_ASSERT(0); + return; + } + } +} + +static void stbiw__writef(stbi__write_context *s, const char *fmt, ...) +{ + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); +} + +static void stbiw__write_flush(stbi__write_context *s) +{ + if (s->buf_used) { + s->func(s->context, &s->buffer, s->buf_used); + s->buf_used = 0; + } +} + +static void stbiw__putc(stbi__write_context *s, unsigned char c) +{ + s->func(s->context, &c, 1); +} + +static void stbiw__write1(stbi__write_context *s, unsigned char a) +{ + if ((size_t)s->buf_used + 1 > sizeof(s->buffer)) + stbiw__write_flush(s); + s->buffer[s->buf_used++] = a; +} + +static void stbiw__write3(stbi__write_context *s, unsigned char a, unsigned char b, unsigned char c) +{ + int n; + if ((size_t)s->buf_used + 3 > sizeof(s->buffer)) + stbiw__write_flush(s); + n = s->buf_used; + s->buf_used = n+3; + s->buffer[n+0] = a; + s->buffer[n+1] = b; + s->buffer[n+2] = c; +} + +static void stbiw__write_pixel(stbi__write_context *s, int rgb_dir, int comp, int write_alpha, int expand_mono, unsigned char *d) +{ + unsigned char bg[3] = { 255, 0, 255}, px[3]; + int k; + + if (write_alpha < 0) + stbiw__write1(s, d[comp - 1]); + + switch (comp) { + case 2: // 2 pixels = mono + alpha, alpha is written separately, so same as 1-channel case + case 1: + if (expand_mono) + stbiw__write3(s, d[0], d[0], d[0]); // monochrome bmp + else + stbiw__write1(s, d[0]); // monochrome TGA + break; + case 4: + if (!write_alpha) { + // composite against pink background + for (k = 0; k < 3; ++k) + px[k] = bg[k] + ((d[k] - bg[k]) * d[3]) / 255; + stbiw__write3(s, px[1 - rgb_dir], px[1], px[1 + rgb_dir]); + break; + } + /* FALLTHROUGH */ + case 3: + stbiw__write3(s, d[1 - rgb_dir], d[1], d[1 + rgb_dir]); + break; + } + if (write_alpha > 0) + stbiw__write1(s, d[comp - 1]); +} + +static void stbiw__write_pixels(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, void *data, int write_alpha, int scanline_pad, int expand_mono) +{ + stbiw_uint32 zero = 0; + int i,j, j_end; + + if (y <= 0) + return; + + if (stbi__flip_vertically_on_write) + vdir *= -1; + + if (vdir < 0) { + j_end = -1; j = y-1; + } else { + j_end = y; j = 0; + } + + for (; j != j_end; j += vdir) { + for (i=0; i < x; ++i) { + unsigned char *d = (unsigned char *) data + (j*x+i)*comp; + stbiw__write_pixel(s, rgb_dir, comp, write_alpha, expand_mono, d); + } + stbiw__write_flush(s); + s->func(s->context, &zero, scanline_pad); + } +} + +static int stbiw__outfile(stbi__write_context *s, int rgb_dir, int vdir, int x, int y, int comp, int expand_mono, void *data, int alpha, int pad, const char *fmt, ...) +{ + if (y < 0 || x < 0) { + return 0; + } else { + va_list v; + va_start(v, fmt); + stbiw__writefv(s, fmt, v); + va_end(v); + stbiw__write_pixels(s,rgb_dir,vdir,x,y,comp,data,alpha,pad, expand_mono); + return 1; + } +} + +static int stbi_write_bmp_core(stbi__write_context *s, int x, int y, int comp, const void *data) +{ + if (comp != 4) { + // write RGB bitmap + int pad = (-x*3) & 3; + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *) data,0,pad, + "11 4 22 4" "4 44 22 444444", + 'B', 'M', 14+40+(x*3+pad)*y, 0,0, 14+40, // file header + 40, x,y, 1,24, 0,0,0,0,0,0); // bitmap header + } else { + // RGBA bitmaps need a v4 header + // use BI_BITFIELDS mode with 32bpp and alpha mask + // (straight BI_RGB with alpha mask doesn't work in most readers) + return stbiw__outfile(s,-1,-1,x,y,comp,1,(void *)data,1,0, + "11 4 22 4" "4 44 22 444444 4444 4 444 444 444 444", + 'B', 'M', 14+108+x*y*4, 0, 0, 14+108, // file header + 108, x,y, 1,32, 3,0,0,0,0,0, 0xff0000,0xff00,0xff,0xff000000u, 0, 0,0,0, 0,0,0, 0,0,0, 0,0,0); // bitmap V4 header + } +} + +STBIWDEF int stbi_write_bmp_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_bmp_core(&s, x, y, comp, data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_bmp(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_bmp_core(&s, x, y, comp, data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif //!STBI_WRITE_NO_STDIO + +static int stbi_write_tga_core(stbi__write_context *s, int x, int y, int comp, void *data) +{ + int has_alpha = (comp == 2 || comp == 4); + int colorbytes = has_alpha ? comp-1 : comp; + int format = colorbytes < 2 ? 3 : 2; // 3 color channels (RGB/RGBA) = 2, 1 color channel (Y/YA) = 3 + + if (y < 0 || x < 0) + return 0; + + if (!stbi_write_tga_with_rle) { + return stbiw__outfile(s, -1, -1, x, y, comp, 0, (void *) data, has_alpha, 0, + "111 221 2222 11", 0, 0, format, 0, 0, 0, 0, 0, x, y, (colorbytes + has_alpha) * 8, has_alpha * 8); + } else { + int i,j,k; + int jend, jdir; + + stbiw__writef(s, "111 221 2222 11", 0,0,format+8, 0,0,0, 0,0,x,y, (colorbytes + has_alpha) * 8, has_alpha * 8); + + if (stbi__flip_vertically_on_write) { + j = 0; + jend = y; + jdir = 1; + } else { + j = y-1; + jend = -1; + jdir = -1; + } + for (; j != jend; j += jdir) { + unsigned char *row = (unsigned char *) data + j * x * comp; + int len; + + for (i = 0; i < x; i += len) { + unsigned char *begin = row + i * comp; + int diff = 1; + len = 1; + + if (i < x - 1) { + ++len; + diff = memcmp(begin, row + (i + 1) * comp, comp); + if (diff) { + const unsigned char *prev = begin; + for (k = i + 2; k < x && len < 128; ++k) { + if (memcmp(prev, row + k * comp, comp)) { + prev += comp; + ++len; + } else { + --len; + break; + } + } + } else { + for (k = i + 2; k < x && len < 128; ++k) { + if (!memcmp(begin, row + k * comp, comp)) { + ++len; + } else { + break; + } + } + } + } + + if (diff) { + unsigned char header = STBIW_UCHAR(len - 1); + stbiw__write1(s, header); + for (k = 0; k < len; ++k) { + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin + k * comp); + } + } else { + unsigned char header = STBIW_UCHAR(len - 129); + stbiw__write1(s, header); + stbiw__write_pixel(s, -1, comp, has_alpha, 0, begin); + } + } + } + stbiw__write_flush(s); + } + return 1; +} + +STBIWDEF int stbi_write_tga_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_tga_core(&s, x, y, comp, (void *) data); +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_tga(char const *filename, int x, int y, int comp, const void *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_tga_core(&s, x, y, comp, (void *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +// ************************************************************************************************* +// Radiance RGBE HDR writer +// by Baldur Karlsson + +#define stbiw__max(a, b) ((a) > (b) ? (a) : (b)) + +#ifndef STBI_WRITE_NO_STDIO + +static void stbiw__linear_to_rgbe(unsigned char *rgbe, float *linear) +{ + int exponent; + float maxcomp = stbiw__max(linear[0], stbiw__max(linear[1], linear[2])); + + if (maxcomp < 1e-32f) { + rgbe[0] = rgbe[1] = rgbe[2] = rgbe[3] = 0; + } else { + float normalize = (float) frexp(maxcomp, &exponent) * 256.0f/maxcomp; + + rgbe[0] = (unsigned char)(linear[0] * normalize); + rgbe[1] = (unsigned char)(linear[1] * normalize); + rgbe[2] = (unsigned char)(linear[2] * normalize); + rgbe[3] = (unsigned char)(exponent + 128); + } +} + +static void stbiw__write_run_data(stbi__write_context *s, int length, unsigned char databyte) +{ + unsigned char lengthbyte = STBIW_UCHAR(length+128); + STBIW_ASSERT(length+128 <= 255); + s->func(s->context, &lengthbyte, 1); + s->func(s->context, &databyte, 1); +} + +static void stbiw__write_dump_data(stbi__write_context *s, int length, unsigned char *data) +{ + unsigned char lengthbyte = STBIW_UCHAR(length); + STBIW_ASSERT(length <= 128); // inconsistent with spec but consistent with official code + s->func(s->context, &lengthbyte, 1); + s->func(s->context, data, length); +} + +static void stbiw__write_hdr_scanline(stbi__write_context *s, int width, int ncomp, unsigned char *scratch, float *scanline) +{ + unsigned char scanlineheader[4] = { 2, 2, 0, 0 }; + unsigned char rgbe[4]; + float linear[3]; + int x; + + scanlineheader[2] = (width&0xff00)>>8; + scanlineheader[3] = (width&0x00ff); + + /* skip RLE for images too small or large */ + if (width < 8 || width >= 32768) { + for (x=0; x < width; x++) { + switch (ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + s->func(s->context, rgbe, 4); + } + } else { + int c,r; + /* encode into scratch buffer */ + for (x=0; x < width; x++) { + switch(ncomp) { + case 4: /* fallthrough */ + case 3: linear[2] = scanline[x*ncomp + 2]; + linear[1] = scanline[x*ncomp + 1]; + linear[0] = scanline[x*ncomp + 0]; + break; + default: + linear[0] = linear[1] = linear[2] = scanline[x*ncomp + 0]; + break; + } + stbiw__linear_to_rgbe(rgbe, linear); + scratch[x + width*0] = rgbe[0]; + scratch[x + width*1] = rgbe[1]; + scratch[x + width*2] = rgbe[2]; + scratch[x + width*3] = rgbe[3]; + } + + s->func(s->context, scanlineheader, 4); + + /* RLE each component separately */ + for (c=0; c < 4; c++) { + unsigned char *comp = &scratch[width*c]; + + x = 0; + while (x < width) { + // find first run + r = x; + while (r+2 < width) { + if (comp[r] == comp[r+1] && comp[r] == comp[r+2]) + break; + ++r; + } + if (r+2 >= width) + r = width; + // dump up to first run + while (x < r) { + int len = r-x; + if (len > 128) len = 128; + stbiw__write_dump_data(s, len, &comp[x]); + x += len; + } + // if there's a run, output it + if (r+2 < width) { // same test as what we break out of in search loop, so only true if we break'd + // find next byte after run + while (r < width && comp[r] == comp[x]) + ++r; + // output run up to r + while (x < r) { + int len = r-x; + if (len > 127) len = 127; + stbiw__write_run_data(s, len, comp[x]); + x += len; + } + } + } + } + } +} + +static int stbi_write_hdr_core(stbi__write_context *s, int x, int y, int comp, float *data) +{ + if (y <= 0 || x <= 0 || data == NULL) + return 0; + else { + // Each component is stored separately. Allocate scratch space for full output scanline. + unsigned char *scratch = (unsigned char *) STBIW_MALLOC(x*4); + int i, len; + char buffer[128]; + char header[] = "#?RADIANCE\n# Written by stb_image_write.h\nFORMAT=32-bit_rle_rgbe\n"; + s->func(s->context, header, sizeof(header)-1); + +#ifdef __STDC_LIB_EXT1__ + len = sprintf_s(buffer, sizeof(buffer), "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#else + len = sprintf(buffer, "EXPOSURE= 1.0000000000000\n\n-Y %d +X %d\n", y, x); +#endif + s->func(s->context, buffer, len); + + for(i=0; i < y; i++) + stbiw__write_hdr_scanline(s, x, comp, scratch, data + comp*x*(stbi__flip_vertically_on_write ? y-1-i : i)); + STBIW_FREE(scratch); + return 1; + } +} + +STBIWDEF int stbi_write_hdr_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const float *data) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_hdr_core(&s, x, y, comp, (float *) data); +} + +STBIWDEF int stbi_write_hdr(char const *filename, int x, int y, int comp, const float *data) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_hdr_core(&s, x, y, comp, (float *) data); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif // STBI_WRITE_NO_STDIO + + +////////////////////////////////////////////////////////////////////////////// +// +// PNG writer +// + +#ifndef STBIW_ZLIB_COMPRESS +// stretchy buffer; stbiw__sbpush() == vector<>::push_back() -- stbiw__sbcount() == vector<>::size() +#define stbiw__sbraw(a) ((int *) (void *) (a) - 2) +#define stbiw__sbm(a) stbiw__sbraw(a)[0] +#define stbiw__sbn(a) stbiw__sbraw(a)[1] + +#define stbiw__sbneedgrow(a,n) ((a)==0 || stbiw__sbn(a)+n >= stbiw__sbm(a)) +#define stbiw__sbmaybegrow(a,n) (stbiw__sbneedgrow(a,(n)) ? stbiw__sbgrow(a,n) : 0) +#define stbiw__sbgrow(a,n) stbiw__sbgrowf((void **) &(a), (n), sizeof(*(a))) + +#define stbiw__sbpush(a, v) (stbiw__sbmaybegrow(a,1), (a)[stbiw__sbn(a)++] = (v)) +#define stbiw__sbcount(a) ((a) ? stbiw__sbn(a) : 0) +#define stbiw__sbfree(a) ((a) ? STBIW_FREE(stbiw__sbraw(a)),0 : 0) + +static void *stbiw__sbgrowf(void **arr, int increment, int itemsize) +{ + int m = *arr ? 2*stbiw__sbm(*arr)+increment : increment+1; + void *p = STBIW_REALLOC_SIZED(*arr ? stbiw__sbraw(*arr) : 0, *arr ? (stbiw__sbm(*arr)*itemsize + sizeof(int)*2) : 0, itemsize * m + sizeof(int)*2); + STBIW_ASSERT(p); + if (p) { + if (!*arr) ((int *) p)[1] = 0; + *arr = (void *) ((int *) p + 2); + stbiw__sbm(*arr) = m; + } + return *arr; +} + +static unsigned char *stbiw__zlib_flushf(unsigned char *data, unsigned int *bitbuffer, int *bitcount) +{ + while (*bitcount >= 8) { + stbiw__sbpush(data, STBIW_UCHAR(*bitbuffer)); + *bitbuffer >>= 8; + *bitcount -= 8; + } + return data; +} + +static int stbiw__zlib_bitrev(int code, int codebits) +{ + int res=0; + while (codebits--) { + res = (res << 1) | (code & 1); + code >>= 1; + } + return res; +} + +static unsigned int stbiw__zlib_countm(unsigned char *a, unsigned char *b, int limit) +{ + int i; + for (i=0; i < limit && i < 258; ++i) + if (a[i] != b[i]) break; + return i; +} + +static unsigned int stbiw__zhash(unsigned char *data) +{ + stbiw_uint32 hash = data[0] + (data[1] << 8) + (data[2] << 16); + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 4; + hash += hash >> 17; + hash ^= hash << 25; + hash += hash >> 6; + return hash; +} + +#define stbiw__zlib_flush() (out = stbiw__zlib_flushf(out, &bitbuf, &bitcount)) +#define stbiw__zlib_add(code,codebits) \ + (bitbuf |= (code) << bitcount, bitcount += (codebits), stbiw__zlib_flush()) +#define stbiw__zlib_huffa(b,c) stbiw__zlib_add(stbiw__zlib_bitrev(b,c),c) +// default huffman tables +#define stbiw__zlib_huff1(n) stbiw__zlib_huffa(0x30 + (n), 8) +#define stbiw__zlib_huff2(n) stbiw__zlib_huffa(0x190 + (n)-144, 9) +#define stbiw__zlib_huff3(n) stbiw__zlib_huffa(0 + (n)-256,7) +#define stbiw__zlib_huff4(n) stbiw__zlib_huffa(0xc0 + (n)-280,8) +#define stbiw__zlib_huff(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : (n) <= 255 ? stbiw__zlib_huff2(n) : (n) <= 279 ? stbiw__zlib_huff3(n) : stbiw__zlib_huff4(n)) +#define stbiw__zlib_huffb(n) ((n) <= 143 ? stbiw__zlib_huff1(n) : stbiw__zlib_huff2(n)) + +#define stbiw__ZHASH 16384 + +#endif // STBIW_ZLIB_COMPRESS + +STBIWDEF unsigned char * stbi_zlib_compress(unsigned char *data, int data_len, int *out_len, int quality) +{ +#ifdef STBIW_ZLIB_COMPRESS + // user provided a zlib compress implementation, use that + return STBIW_ZLIB_COMPRESS(data, data_len, out_len, quality); +#else // use builtin + static unsigned short lengthc[] = { 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258, 259 }; + static unsigned char lengtheb[]= { 0,0,0,0,0,0,0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 }; + static unsigned short distc[] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577, 32768 }; + static unsigned char disteb[] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13 }; + unsigned int bitbuf=0; + int i,j, bitcount=0; + unsigned char *out = NULL; + unsigned char ***hash_table = (unsigned char***) STBIW_MALLOC(stbiw__ZHASH * sizeof(unsigned char**)); + if (hash_table == NULL) + return NULL; + if (quality < 5) quality = 5; + + stbiw__sbpush(out, 0x78); // DEFLATE 32K window + stbiw__sbpush(out, 0x5e); // FLEVEL = 1 + stbiw__zlib_add(1,1); // BFINAL = 1 + stbiw__zlib_add(1,2); // BTYPE = 1 -- fixed huffman + + for (i=0; i < stbiw__ZHASH; ++i) + hash_table[i] = NULL; + + i=0; + while (i < data_len-3) { + // hash next 3 bytes of data to be compressed + int h = stbiw__zhash(data+i)&(stbiw__ZHASH-1), best=3; + unsigned char *bestloc = 0; + unsigned char **hlist = hash_table[h]; + int n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32768) { // if entry lies within window + int d = stbiw__zlib_countm(hlist[j], data+i, data_len-i); + if (d >= best) { best=d; bestloc=hlist[j]; } + } + } + // when hash table entry is too long, delete half the entries + if (hash_table[h] && stbiw__sbn(hash_table[h]) == 2*quality) { + STBIW_MEMMOVE(hash_table[h], hash_table[h]+quality, sizeof(hash_table[h][0])*quality); + stbiw__sbn(hash_table[h]) = quality; + } + stbiw__sbpush(hash_table[h],data+i); + + if (bestloc) { + // "lazy matching" - check match at *next* byte, and if it's better, do cur byte as literal + h = stbiw__zhash(data+i+1)&(stbiw__ZHASH-1); + hlist = hash_table[h]; + n = stbiw__sbcount(hlist); + for (j=0; j < n; ++j) { + if (hlist[j]-data > i-32767) { + int e = stbiw__zlib_countm(hlist[j], data+i+1, data_len-i-1); + if (e > best) { // if next match is better, bail on current match + bestloc = NULL; + break; + } + } + } + } + + if (bestloc) { + int d = (int) (data+i - bestloc); // distance back + STBIW_ASSERT(d <= 32767 && best <= 258); + for (j=0; best > lengthc[j+1]-1; ++j); + stbiw__zlib_huff(j+257); + if (lengtheb[j]) stbiw__zlib_add(best - lengthc[j], lengtheb[j]); + for (j=0; d > distc[j+1]-1; ++j); + stbiw__zlib_add(stbiw__zlib_bitrev(j,5),5); + if (disteb[j]) stbiw__zlib_add(d - distc[j], disteb[j]); + i += best; + } else { + stbiw__zlib_huffb(data[i]); + ++i; + } + } + // write out final bytes + for (;i < data_len; ++i) + stbiw__zlib_huffb(data[i]); + stbiw__zlib_huff(256); // end of block + // pad with 0 bits to byte boundary + while (bitcount) + stbiw__zlib_add(0,1); + + for (i=0; i < stbiw__ZHASH; ++i) + (void) stbiw__sbfree(hash_table[i]); + STBIW_FREE(hash_table); + + // store uncompressed instead if compression was worse + if (stbiw__sbn(out) > data_len + 2 + ((data_len+32766)/32767)*5) { + stbiw__sbn(out) = 2; // truncate to DEFLATE 32K window and FLEVEL = 1 + for (j = 0; j < data_len;) { + int blocklen = data_len - j; + if (blocklen > 32767) blocklen = 32767; + stbiw__sbpush(out, data_len - j == blocklen); // BFINAL = ?, BTYPE = 0 -- no compression + stbiw__sbpush(out, STBIW_UCHAR(blocklen)); // LEN + stbiw__sbpush(out, STBIW_UCHAR(blocklen >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(~blocklen)); // NLEN + stbiw__sbpush(out, STBIW_UCHAR(~blocklen >> 8)); + memcpy(out+stbiw__sbn(out), data+j, blocklen); + stbiw__sbn(out) += blocklen; + j += blocklen; + } + } + + { + // compute adler32 on input + unsigned int s1=1, s2=0; + int blocklen = (int) (data_len % 5552); + j=0; + while (j < data_len) { + for (i=0; i < blocklen; ++i) { s1 += data[j+i]; s2 += s1; } + s1 %= 65521; s2 %= 65521; + j += blocklen; + blocklen = 5552; + } + stbiw__sbpush(out, STBIW_UCHAR(s2 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s2)); + stbiw__sbpush(out, STBIW_UCHAR(s1 >> 8)); + stbiw__sbpush(out, STBIW_UCHAR(s1)); + } + *out_len = stbiw__sbn(out); + // make returned pointer freeable + STBIW_MEMMOVE(stbiw__sbraw(out), out, *out_len); + return (unsigned char *) stbiw__sbraw(out); +#endif // STBIW_ZLIB_COMPRESS +} + +static unsigned int stbiw__crc32(unsigned char *buffer, int len) +{ +#ifdef STBIW_CRC32 + return STBIW_CRC32(buffer, len); +#else + static unsigned int crc_table[256] = + { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0eDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + unsigned int crc = ~0u; + int i; + for (i=0; i < len; ++i) + crc = (crc >> 8) ^ crc_table[buffer[i] ^ (crc & 0xff)]; + return ~crc; +#endif +} + +#define stbiw__wpng4(o,a,b,c,d) ((o)[0]=STBIW_UCHAR(a),(o)[1]=STBIW_UCHAR(b),(o)[2]=STBIW_UCHAR(c),(o)[3]=STBIW_UCHAR(d),(o)+=4) +#define stbiw__wp32(data,v) stbiw__wpng4(data, (v)>>24,(v)>>16,(v)>>8,(v)); +#define stbiw__wptag(data,s) stbiw__wpng4(data, s[0],s[1],s[2],s[3]) + +static void stbiw__wpcrc(unsigned char **data, int len) +{ + unsigned int crc = stbiw__crc32(*data - len - 4, len+4); + stbiw__wp32(*data, crc); +} + +static unsigned char stbiw__paeth(int a, int b, int c) +{ + int p = a + b - c, pa = abs(p-a), pb = abs(p-b), pc = abs(p-c); + if (pa <= pb && pa <= pc) return STBIW_UCHAR(a); + if (pb <= pc) return STBIW_UCHAR(b); + return STBIW_UCHAR(c); +} + +// @OPTIMIZE: provide an option that always forces left-predict or paeth predict +static void stbiw__encode_png_line(unsigned char *pixels, int stride_bytes, int width, int height, int y, int n, int filter_type, signed char *line_buffer) +{ + static int mapping[] = { 0,1,2,3,4 }; + static int firstmap[] = { 0,1,0,5,6 }; + int *mymap = (y != 0) ? mapping : firstmap; + int i; + int type = mymap[filter_type]; + unsigned char *z = pixels + stride_bytes * (stbi__flip_vertically_on_write ? height-1-y : y); + int signed_stride = stbi__flip_vertically_on_write ? -stride_bytes : stride_bytes; + + if (type==0) { + memcpy(line_buffer, z, width*n); + return; + } + + // first loop isn't optimized since it's just one pixel + for (i = 0; i < n; ++i) { + switch (type) { + case 1: line_buffer[i] = z[i]; break; + case 2: line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: line_buffer[i] = z[i] - (z[i-signed_stride]>>1); break; + case 4: line_buffer[i] = (signed char) (z[i] - stbiw__paeth(0,z[i-signed_stride],0)); break; + case 5: line_buffer[i] = z[i]; break; + case 6: line_buffer[i] = z[i]; break; + } + } + switch (type) { + case 1: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-n]; break; + case 2: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - z[i-signed_stride]; break; + case 3: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - ((z[i-n] + z[i-signed_stride])>>1); break; + case 4: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], z[i-signed_stride], z[i-signed_stride-n]); break; + case 5: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - (z[i-n]>>1); break; + case 6: for (i=n; i < width*n; ++i) line_buffer[i] = z[i] - stbiw__paeth(z[i-n], 0,0); break; + } +} + +STBIWDEF unsigned char *stbi_write_png_to_mem(const unsigned char *pixels, int stride_bytes, int x, int y, int n, int *out_len) +{ + int force_filter = stbi_write_force_png_filter; + int ctype[5] = { -1, 0, 4, 2, 6 }; + unsigned char sig[8] = { 137,80,78,71,13,10,26,10 }; + unsigned char *out,*o, *filt, *zlib; + signed char *line_buffer; + int j,zlen; + + if (stride_bytes == 0) + stride_bytes = x * n; + + if (force_filter >= 5) { + force_filter = -1; + } + + filt = (unsigned char *) STBIW_MALLOC((x*n+1) * y); if (!filt) return 0; + line_buffer = (signed char *) STBIW_MALLOC(x * n); if (!line_buffer) { STBIW_FREE(filt); return 0; } + for (j=0; j < y; ++j) { + int filter_type; + if (force_filter > -1) { + filter_type = force_filter; + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, force_filter, line_buffer); + } else { // Estimate the best filter by running through all of them: + int best_filter = 0, best_filter_val = 0x7fffffff, est, i; + for (filter_type = 0; filter_type < 5; filter_type++) { + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, filter_type, line_buffer); + + // Estimate the entropy of the line using this filter; the less, the better. + est = 0; + for (i = 0; i < x*n; ++i) { + est += abs((signed char) line_buffer[i]); + } + if (est < best_filter_val) { + best_filter_val = est; + best_filter = filter_type; + } + } + if (filter_type != best_filter) { // If the last iteration already got us the best filter, don't redo it + stbiw__encode_png_line((unsigned char*)(pixels), stride_bytes, x, y, j, n, best_filter, line_buffer); + filter_type = best_filter; + } + } + // when we get here, filter_type contains the filter type, and line_buffer contains the data + filt[j*(x*n+1)] = (unsigned char) filter_type; + STBIW_MEMMOVE(filt+j*(x*n+1)+1, line_buffer, x*n); + } + STBIW_FREE(line_buffer); + zlib = stbi_zlib_compress(filt, y*( x*n+1), &zlen, stbi_write_png_compression_level); + STBIW_FREE(filt); + if (!zlib) return 0; + + // each tag requires 12 bytes of overhead + out = (unsigned char *) STBIW_MALLOC(8 + 12+13 + 12+zlen + 12); + if (!out) return 0; + *out_len = 8 + 12+13 + 12+zlen + 12; + + o=out; + STBIW_MEMMOVE(o,sig,8); o+= 8; + stbiw__wp32(o, 13); // header length + stbiw__wptag(o, "IHDR"); + stbiw__wp32(o, x); + stbiw__wp32(o, y); + *o++ = 8; + *o++ = STBIW_UCHAR(ctype[n]); + *o++ = 0; + *o++ = 0; + *o++ = 0; + stbiw__wpcrc(&o,13); + + stbiw__wp32(o, zlen); + stbiw__wptag(o, "IDAT"); + STBIW_MEMMOVE(o, zlib, zlen); + o += zlen; + STBIW_FREE(zlib); + stbiw__wpcrc(&o, zlen); + + stbiw__wp32(o,0); + stbiw__wptag(o, "IEND"); + stbiw__wpcrc(&o,0); + + STBIW_ASSERT(o == out + *out_len); + + return out; +} + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes) +{ + FILE *f; + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + + f = stbiw__fopen(filename, "wb"); + if (!f) { STBIW_FREE(png); return 0; } + fwrite(png, 1, len, f); + fclose(f); + STBIW_FREE(png); + return 1; +} +#endif + +STBIWDEF int stbi_write_png_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int stride_bytes) +{ + int len; + unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len); + if (png == NULL) return 0; + func(context, png, len); + STBIW_FREE(png); + return 1; +} + + +/* *************************************************************************** + * + * JPEG writer + * + * This is based on Jon Olick's jo_jpeg.cpp: + * public domain Simple, Minimalistic JPEG writer - http://www.jonolick.com/code.html + */ + +static const unsigned char stbiw__jpg_ZigZag[] = { 0,1,5,6,14,15,27,28,2,4,7,13,16,26,29,42,3,8,12,17,25,30,41,43,9,11,18, + 24,31,40,44,53,10,19,23,32,39,45,52,54,20,22,33,38,46,51,55,60,21,34,37,47,50,56,59,61,35,36,48,49,57,58,62,63 }; + +static void stbiw__jpg_writeBits(stbi__write_context *s, int *bitBufP, int *bitCntP, const unsigned short *bs) { + int bitBuf = *bitBufP, bitCnt = *bitCntP; + bitCnt += bs[1]; + bitBuf |= bs[0] << (24 - bitCnt); + while(bitCnt >= 8) { + unsigned char c = (bitBuf >> 16) & 255; + stbiw__putc(s, c); + if(c == 255) { + stbiw__putc(s, 0); + } + bitBuf <<= 8; + bitCnt -= 8; + } + *bitBufP = bitBuf; + *bitCntP = bitCnt; +} + +static void stbiw__jpg_DCT(float *d0p, float *d1p, float *d2p, float *d3p, float *d4p, float *d5p, float *d6p, float *d7p) { + float d0 = *d0p, d1 = *d1p, d2 = *d2p, d3 = *d3p, d4 = *d4p, d5 = *d5p, d6 = *d6p, d7 = *d7p; + float z1, z2, z3, z4, z5, z11, z13; + + float tmp0 = d0 + d7; + float tmp7 = d0 - d7; + float tmp1 = d1 + d6; + float tmp6 = d1 - d6; + float tmp2 = d2 + d5; + float tmp5 = d2 - d5; + float tmp3 = d3 + d4; + float tmp4 = d3 - d4; + + // Even part + float tmp10 = tmp0 + tmp3; // phase 2 + float tmp13 = tmp0 - tmp3; + float tmp11 = tmp1 + tmp2; + float tmp12 = tmp1 - tmp2; + + d0 = tmp10 + tmp11; // phase 3 + d4 = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * 0.707106781f; // c4 + d2 = tmp13 + z1; // phase 5 + d6 = tmp13 - z1; + + // Odd part + tmp10 = tmp4 + tmp5; // phase 2 + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + // The rotator is modified from fig 4-8 to avoid extra negations. + z5 = (tmp10 - tmp12) * 0.382683433f; // c6 + z2 = tmp10 * 0.541196100f + z5; // c2-c6 + z4 = tmp12 * 1.306562965f + z5; // c2+c6 + z3 = tmp11 * 0.707106781f; // c4 + + z11 = tmp7 + z3; // phase 5 + z13 = tmp7 - z3; + + *d5p = z13 + z2; // phase 6 + *d3p = z13 - z2; + *d1p = z11 + z4; + *d7p = z11 - z4; + + *d0p = d0; *d2p = d2; *d4p = d4; *d6p = d6; +} + +static void stbiw__jpg_calcBits(int val, unsigned short bits[2]) { + int tmp1 = val < 0 ? -val : val; + val = val < 0 ? val-1 : val; + bits[1] = 1; + while(tmp1 >>= 1) { + ++bits[1]; + } + bits[0] = val & ((1<0)&&(DU[end0pos]==0); --end0pos) { + } + // end0pos = first element in reverse order !=0 + if(end0pos == 0) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + return DU[0]; + } + for(i = 1; i <= end0pos; ++i) { + int startpos = i; + int nrzeroes; + unsigned short bits[2]; + for (; DU[i]==0 && i<=end0pos; ++i) { + } + nrzeroes = i-startpos; + if ( nrzeroes >= 16 ) { + int lng = nrzeroes>>4; + int nrmarker; + for (nrmarker=1; nrmarker <= lng; ++nrmarker) + stbiw__jpg_writeBits(s, bitBuf, bitCnt, M16zeroes); + nrzeroes &= 15; + } + stbiw__jpg_calcBits(DU[i], bits); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, HTAC[(nrzeroes<<4)+bits[1]]); + stbiw__jpg_writeBits(s, bitBuf, bitCnt, bits); + } + if(end0pos != 63) { + stbiw__jpg_writeBits(s, bitBuf, bitCnt, EOB); + } + return DU[0]; +} + +static int stbi_write_jpg_core(stbi__write_context *s, int width, int height, int comp, const void* data, int quality) { + // Constants that don't pollute global namespace + static const unsigned char std_dc_luminance_nrcodes[] = {0,0,1,5,1,1,1,1,1,1,0,0,0,0,0,0,0}; + static const unsigned char std_dc_luminance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_luminance_nrcodes[] = {0,0,2,1,3,3,2,4,3,5,5,4,4,0,0,1,0x7d}; + static const unsigned char std_ac_luminance_values[] = { + 0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08, + 0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28, + 0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59, + 0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89, + 0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6, + 0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2, + 0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + static const unsigned char std_dc_chrominance_nrcodes[] = {0,0,3,1,1,1,1,1,1,1,1,1,0,0,0,0,0}; + static const unsigned char std_dc_chrominance_values[] = {0,1,2,3,4,5,6,7,8,9,10,11}; + static const unsigned char std_ac_chrominance_nrcodes[] = {0,0,2,1,2,4,4,3,4,7,5,4,4,0,1,2,0x77}; + static const unsigned char std_ac_chrominance_values[] = { + 0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91, + 0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26, + 0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58, + 0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87, + 0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4, + 0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda, + 0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa + }; + // Huffman tables + static const unsigned short YDC_HT[256][2] = { {0,2},{2,3},{3,3},{4,3},{5,3},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9}}; + static const unsigned short UVDC_HT[256][2] = { {0,2},{1,2},{2,2},{6,3},{14,4},{30,5},{62,6},{126,7},{254,8},{510,9},{1022,10},{2046,11}}; + static const unsigned short YAC_HT[256][2] = { + {10,4},{0,2},{1,2},{4,3},{11,4},{26,5},{120,7},{248,8},{1014,10},{65410,16},{65411,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {12,4},{27,5},{121,7},{502,9},{2038,11},{65412,16},{65413,16},{65414,16},{65415,16},{65416,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {28,5},{249,8},{1015,10},{4084,12},{65417,16},{65418,16},{65419,16},{65420,16},{65421,16},{65422,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{503,9},{4085,12},{65423,16},{65424,16},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1016,10},{65430,16},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2039,11},{65438,16},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {123,7},{4086,12},{65446,16},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {250,8},{4087,12},{65454,16},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{32704,15},{65462,16},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65470,16},{65471,16},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65479,16},{65480,16},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1017,10},{65488,16},{65489,16},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{65497,16},{65498,16},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2040,11},{65506,16},{65507,16},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {65515,16},{65516,16},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65525,16},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const unsigned short UVAC_HT[256][2] = { + {0,2},{1,2},{4,3},{10,4},{24,5},{25,5},{56,6},{120,7},{500,9},{1014,10},{4084,12},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {11,4},{57,6},{246,8},{501,9},{2038,11},{4085,12},{65416,16},{65417,16},{65418,16},{65419,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {26,5},{247,8},{1015,10},{4086,12},{32706,15},{65420,16},{65421,16},{65422,16},{65423,16},{65424,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {27,5},{248,8},{1016,10},{4087,12},{65425,16},{65426,16},{65427,16},{65428,16},{65429,16},{65430,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {58,6},{502,9},{65431,16},{65432,16},{65433,16},{65434,16},{65435,16},{65436,16},{65437,16},{65438,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {59,6},{1017,10},{65439,16},{65440,16},{65441,16},{65442,16},{65443,16},{65444,16},{65445,16},{65446,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {121,7},{2039,11},{65447,16},{65448,16},{65449,16},{65450,16},{65451,16},{65452,16},{65453,16},{65454,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {122,7},{2040,11},{65455,16},{65456,16},{65457,16},{65458,16},{65459,16},{65460,16},{65461,16},{65462,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {249,8},{65463,16},{65464,16},{65465,16},{65466,16},{65467,16},{65468,16},{65469,16},{65470,16},{65471,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {503,9},{65472,16},{65473,16},{65474,16},{65475,16},{65476,16},{65477,16},{65478,16},{65479,16},{65480,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {504,9},{65481,16},{65482,16},{65483,16},{65484,16},{65485,16},{65486,16},{65487,16},{65488,16},{65489,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {505,9},{65490,16},{65491,16},{65492,16},{65493,16},{65494,16},{65495,16},{65496,16},{65497,16},{65498,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {506,9},{65499,16},{65500,16},{65501,16},{65502,16},{65503,16},{65504,16},{65505,16},{65506,16},{65507,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {2041,11},{65508,16},{65509,16},{65510,16},{65511,16},{65512,16},{65513,16},{65514,16},{65515,16},{65516,16},{0,0},{0,0},{0,0},{0,0},{0,0},{0,0}, + {16352,14},{65517,16},{65518,16},{65519,16},{65520,16},{65521,16},{65522,16},{65523,16},{65524,16},{65525,16},{0,0},{0,0},{0,0},{0,0},{0,0}, + {1018,10},{32707,15},{65526,16},{65527,16},{65528,16},{65529,16},{65530,16},{65531,16},{65532,16},{65533,16},{65534,16},{0,0},{0,0},{0,0},{0,0},{0,0} + }; + static const int YQT[] = {16,11,10,16,24,40,51,61,12,12,14,19,26,58,60,55,14,13,16,24,40,57,69,56,14,17,22,29,51,87,80,62,18,22, + 37,56,68,109,103,77,24,35,55,64,81,104,113,92,49,64,78,87,103,121,120,101,72,92,95,98,112,100,103,99}; + static const int UVQT[] = {17,18,24,47,99,99,99,99,18,21,26,66,99,99,99,99,24,26,56,99,99,99,99,99,47,66,99,99,99,99,99,99, + 99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99,99}; + static const float aasf[] = { 1.0f * 2.828427125f, 1.387039845f * 2.828427125f, 1.306562965f * 2.828427125f, 1.175875602f * 2.828427125f, + 1.0f * 2.828427125f, 0.785694958f * 2.828427125f, 0.541196100f * 2.828427125f, 0.275899379f * 2.828427125f }; + + int row, col, i, k, subsample; + float fdtbl_Y[64], fdtbl_UV[64]; + unsigned char YTable[64], UVTable[64]; + + if(!data || !width || !height || comp > 4 || comp < 1) { + return 0; + } + + quality = quality ? quality : 90; + subsample = quality <= 90 ? 1 : 0; + quality = quality < 1 ? 1 : quality > 100 ? 100 : quality; + quality = quality < 50 ? 5000 / quality : 200 - quality * 2; + + for(i = 0; i < 64; ++i) { + int uvti, yti = (YQT[i]*quality+50)/100; + YTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (yti < 1 ? 1 : yti > 255 ? 255 : yti); + uvti = (UVQT[i]*quality+50)/100; + UVTable[stbiw__jpg_ZigZag[i]] = (unsigned char) (uvti < 1 ? 1 : uvti > 255 ? 255 : uvti); + } + + for(row = 0, k = 0; row < 8; ++row) { + for(col = 0; col < 8; ++col, ++k) { + fdtbl_Y[k] = 1 / (YTable [stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + fdtbl_UV[k] = 1 / (UVTable[stbiw__jpg_ZigZag[k]] * aasf[row] * aasf[col]); + } + } + + // Write Headers + { + static const unsigned char head0[] = { 0xFF,0xD8,0xFF,0xE0,0,0x10,'J','F','I','F',0,1,1,0,0,1,0,1,0,0,0xFF,0xDB,0,0x84,0 }; + static const unsigned char head2[] = { 0xFF,0xDA,0,0xC,3,1,0,2,0x11,3,0x11,0,0x3F,0 }; + const unsigned char head1[] = { 0xFF,0xC0,0,0x11,8,(unsigned char)(height>>8),STBIW_UCHAR(height),(unsigned char)(width>>8),STBIW_UCHAR(width), + 3,1,(unsigned char)(subsample?0x22:0x11),0,2,0x11,1,3,0x11,1,0xFF,0xC4,0x01,0xA2,0 }; + s->func(s->context, (void*)head0, sizeof(head0)); + s->func(s->context, (void*)YTable, sizeof(YTable)); + stbiw__putc(s, 1); + s->func(s->context, UVTable, sizeof(UVTable)); + s->func(s->context, (void*)head1, sizeof(head1)); + s->func(s->context, (void*)(std_dc_luminance_nrcodes+1), sizeof(std_dc_luminance_nrcodes)-1); + s->func(s->context, (void*)std_dc_luminance_values, sizeof(std_dc_luminance_values)); + stbiw__putc(s, 0x10); // HTYACinfo + s->func(s->context, (void*)(std_ac_luminance_nrcodes+1), sizeof(std_ac_luminance_nrcodes)-1); + s->func(s->context, (void*)std_ac_luminance_values, sizeof(std_ac_luminance_values)); + stbiw__putc(s, 1); // HTUDCinfo + s->func(s->context, (void*)(std_dc_chrominance_nrcodes+1), sizeof(std_dc_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_dc_chrominance_values, sizeof(std_dc_chrominance_values)); + stbiw__putc(s, 0x11); // HTUACinfo + s->func(s->context, (void*)(std_ac_chrominance_nrcodes+1), sizeof(std_ac_chrominance_nrcodes)-1); + s->func(s->context, (void*)std_ac_chrominance_values, sizeof(std_ac_chrominance_values)); + s->func(s->context, (void*)head2, sizeof(head2)); + } + + // Encode 8x8 macroblocks + { + static const unsigned short fillBits[] = {0x7F, 7}; + int DCY=0, DCU=0, DCV=0; + int bitBuf=0, bitCnt=0; + // comp == 2 is grey+alpha (alpha is ignored) + int ofsG = comp > 2 ? 1 : 0, ofsB = comp > 2 ? 2 : 0; + const unsigned char *dataR = (const unsigned char *)data; + const unsigned char *dataG = dataR + ofsG; + const unsigned char *dataB = dataR + ofsB; + int x, y, pos; + if(subsample) { + for(y = 0; y < height; y += 16) { + for(x = 0; x < width; x += 16) { + float Y[256], U[256], V[256]; + for(row = y, pos = 0; row < y+16; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+16; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+0, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+8, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+128, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y+136, 16, fdtbl_Y, DCY, YDC_HT, YAC_HT); + + // subsample U,V + { + float subU[64], subV[64]; + int yy, xx; + for(yy = 0, pos = 0; yy < 8; ++yy) { + for(xx = 0; xx < 8; ++xx, ++pos) { + int j = yy*32+xx*2; + subU[pos] = (U[j+0] + U[j+1] + U[j+16] + U[j+17]) * 0.25f; + subV[pos] = (V[j+0] + V[j+1] + V[j+16] + V[j+17]) * 0.25f; + } + } + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subU, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, subV, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + } else { + for(y = 0; y < height; y += 8) { + for(x = 0; x < width; x += 8) { + float Y[64], U[64], V[64]; + for(row = y, pos = 0; row < y+8; ++row) { + // row >= height => use last input row + int clamped_row = (row < height) ? row : height - 1; + int base_p = (stbi__flip_vertically_on_write ? (height-1-clamped_row) : clamped_row)*width*comp; + for(col = x; col < x+8; ++col, ++pos) { + // if col >= width => use pixel from last input column + int p = base_p + ((col < width) ? col : (width-1))*comp; + float r = dataR[p], g = dataG[p], b = dataB[p]; + Y[pos]= +0.29900f*r + 0.58700f*g + 0.11400f*b - 128; + U[pos]= -0.16874f*r - 0.33126f*g + 0.50000f*b; + V[pos]= +0.50000f*r - 0.41869f*g - 0.08131f*b; + } + } + + DCY = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, Y, 8, fdtbl_Y, DCY, YDC_HT, YAC_HT); + DCU = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, U, 8, fdtbl_UV, DCU, UVDC_HT, UVAC_HT); + DCV = stbiw__jpg_processDU(s, &bitBuf, &bitCnt, V, 8, fdtbl_UV, DCV, UVDC_HT, UVAC_HT); + } + } + } + + // Do the bit alignment of the EOI marker + stbiw__jpg_writeBits(s, &bitBuf, &bitCnt, fillBits); + } + + // EOI + stbiw__putc(s, 0xFF); + stbiw__putc(s, 0xD9); + + return 1; +} + +STBIWDEF int stbi_write_jpg_to_func(stbi_write_func *func, void *context, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + stbi__start_write_callbacks(&s, func, context); + return stbi_write_jpg_core(&s, x, y, comp, (void *) data, quality); +} + + +#ifndef STBI_WRITE_NO_STDIO +STBIWDEF int stbi_write_jpg(char const *filename, int x, int y, int comp, const void *data, int quality) +{ + stbi__write_context s = { 0 }; + if (stbi__start_write_file(&s,filename)) { + int r = stbi_write_jpg_core(&s, x, y, comp, data, quality); + stbi__end_write_file(&s); + return r; + } else + return 0; +} +#endif + +#endif // STB_IMAGE_WRITE_IMPLEMENTATION + +/* Revision history + 1.16 (2021-07-11) + make Deflate code emit uncompressed blocks when it would otherwise expand + support writing BMPs with alpha channel + 1.15 (2020-07-13) unknown + 1.14 (2020-02-02) updated JPEG writer to downsample chroma channels + 1.13 + 1.12 + 1.11 (2019-08-11) + + 1.10 (2019-02-07) + support utf8 filenames in Windows; fix warnings and platform ifdefs + 1.09 (2018-02-11) + fix typo in zlib quality API, improve STB_I_W_STATIC in C++ + 1.08 (2018-01-29) + add stbi__flip_vertically_on_write, external zlib, zlib quality, choose PNG filter + 1.07 (2017-07-24) + doc fix + 1.06 (2017-07-23) + writing JPEG (using Jon Olick's code) + 1.05 ??? + 1.04 (2017-03-03) + monochrome BMP expansion + 1.03 ??? + 1.02 (2016-04-02) + avoid allocating large structures on the stack + 1.01 (2016-01-16) + STBIW_REALLOC_SIZED: support allocators with no realloc support + avoid race-condition in crc initialization + minor compile issues + 1.00 (2015-09-14) + installable file IO function + 0.99 (2015-09-13) + warning fixes; TGA rle support + 0.98 (2015-04-08) + added STBIW_MALLOC, STBIW_ASSERT etc + 0.97 (2015-01-18) + fixed HDR asserts, rewrote HDR rle logic + 0.96 (2015-01-17) + add HDR output + fix monochrome BMP + 0.95 (2014-08-17) + add monochrome TGA output + 0.94 (2014-05-31) + rename private functions to avoid conflicts with stb_image.h + 0.93 (2014-05-27) + warning fixes + 0.92 (2010-08-01) + casts to unsigned char to fix warnings + 0.91 (2010-07-17) + first public release + 0.90 first internal release +*/ + +/* +------------------------------------------------------------------------------ +This software is available under 2 licenses -- choose whichever you prefer. +------------------------------------------------------------------------------ +ALTERNATIVE A - MIT License +Copyright (c) 2017 Sean Barrett +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +------------------------------------------------------------------------------ +ALTERNATIVE B - Public Domain (www.unlicense.org) +This is free and unencumbered software released into the public domain. +Anyone is free to copy, modify, publish, use, compile, sell, or distribute this +software, either in source code form or as a compiled binary, for any purpose, +commercial or non-commercial, and by any means. +In jurisdictions that recognize copyright laws, the author or authors of this +software dedicate any and all copyright interest in the software to the public +domain. We make this dedication for the benefit of the public at large and to +the detriment of our heirs and successors. We intend this dedication to be an +overt act of relinquishment in perpetuity of all present and future rights to +this software under copyright law. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +------------------------------------------------------------------------------ +*/