From 43c89c3e2d18339eef8d9e6d80b14859c10cdc8d Mon Sep 17 00:00:00 2001 From: "Yew, Chang Ching" Date: Wed, 9 Jun 2021 17:03:47 +0800 Subject: onevpl: Add sample_multi_transcode application Added patches 0001-Update-headers-to-oneAPI-spec-v2.3-e170992.patch 0001-Remove-duplicate-MFXVideoDECODE_VPP-from-samples.patch 0001-Add-SMT-and-media_sdk_compatibility_headers.patch Signed-off-by: Yew, Chang Ching Signed-off-by: Naveen Saini Signed-off-by: Anuj Mittal --- ...d-SMT-and-media_sdk_compatibility_headers.patch | 12988 +++++++++++++++++++ ...duplicate-MFXVideoDECODE_VPP-from-samples.patch | 62 + ...pdate-headers-to-oneAPI-spec-v2.3-e170992.patch | 741 ++ recipes-multimedia/onevpl/onevpl_2021.2.2.bb | 3 + 4 files changed, 13794 insertions(+) create mode 100644 recipes-multimedia/onevpl/onevpl/0001-Add-SMT-and-media_sdk_compatibility_headers.patch create mode 100644 recipes-multimedia/onevpl/onevpl/0001-Remove-duplicate-MFXVideoDECODE_VPP-from-samples.patch create mode 100644 recipes-multimedia/onevpl/onevpl/0001-Update-headers-to-oneAPI-spec-v2.3-e170992.patch (limited to 'recipes-multimedia') diff --git a/recipes-multimedia/onevpl/onevpl/0001-Add-SMT-and-media_sdk_compatibility_headers.patch b/recipes-multimedia/onevpl/onevpl/0001-Add-SMT-and-media_sdk_compatibility_headers.patch new file mode 100644 index 00000000..fb832380 --- /dev/null +++ b/recipes-multimedia/onevpl/onevpl/0001-Add-SMT-and-media_sdk_compatibility_headers.patch @@ -0,0 +1,12988 @@ +From fffc477d33fb255c83202d68d43b485014f8db4f Mon Sep 17 00:00:00 2001 +From: Jeff McAllister +Date: Wed, 2 Jun 2021 13:20:59 +0800 +Subject: [PATCH] Add SMT and media_sdk_compatibility_headers + +Upstream-Status: Submitted +--- + tools/legacy/CMakeLists.txt | 2 + + .../CMakeLists.txt | 11 + + .../mfx_multi_vpp.h | 103 + + .../mfxastructures.h | 169 + + .../mfxaudio.h | 81 + + .../mfxdeprecated.h | 167 + + .../mfxplugin.h | 601 +++ + .../rotate_plugin_api.h | 29 + + tools/legacy/sample_common/CMakeLists.txt | 4 +- + .../sample_common/include/plugin_utils.h | 1 + + .../sample_common/include/sample_utils.h | 5 +- + .../sample_common/include/sample_utils.h.orig | 1437 +++++ + .../include/vpl_implementation_loader.h | 73 + + .../legacy/sample_common/src/plugin_utils.cpp | 8 - + .../src/vpl_implementation_loader.cpp | 220 + + .../sample_multi_transcode/CMakeLists.txt | 42 + + .../include/pipeline_transcode.h | 973 ++++ + .../include/sample_multi_transcode.h | 109 + + .../include/transcode_utils.h | 111 + + .../src/pipeline_transcode.cpp | 4668 +++++++++++++++++ + .../src/sample_multi_transcode.cpp | 1162 ++++ + .../src/transcode_utils.cpp | 2765 ++++++++++ + 22 files changed, 12730 insertions(+), 11 deletions(-) + create mode 100644 tools/legacy/media_sdk_compatibility_headers/CMakeLists.txt + create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfx_multi_vpp.h + create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxastructures.h + create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxaudio.h + create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxdeprecated.h + create mode 100644 tools/legacy/media_sdk_compatibility_headers/mfxplugin.h + create mode 100644 tools/legacy/media_sdk_compatibility_headers/rotate_plugin_api.h + create mode 100644 tools/legacy/sample_common/include/sample_utils.h.orig + create mode 100644 tools/legacy/sample_common/include/vpl_implementation_loader.h + create mode 100644 tools/legacy/sample_common/src/vpl_implementation_loader.cpp + create mode 100644 tools/legacy/sample_multi_transcode/CMakeLists.txt + create mode 100644 tools/legacy/sample_multi_transcode/include/pipeline_transcode.h + create mode 100644 tools/legacy/sample_multi_transcode/include/sample_multi_transcode.h + create mode 100644 tools/legacy/sample_multi_transcode/include/transcode_utils.h + create mode 100644 tools/legacy/sample_multi_transcode/src/pipeline_transcode.cpp + create mode 100644 tools/legacy/sample_multi_transcode/src/sample_multi_transcode.cpp + create mode 100644 tools/legacy/sample_multi_transcode/src/transcode_utils.cpp + +diff --git a/tools/legacy/CMakeLists.txt b/tools/legacy/CMakeLists.txt +index 1d4af73..34ed0ec 100644 +--- a/tools/legacy/CMakeLists.txt ++++ b/tools/legacy/CMakeLists.txt +@@ -7,8 +7,10 @@ + + cmake_minimum_required(VERSION 3.10.2) + ++add_subdirectory(media_sdk_compatibility_headers) + add_subdirectory(sample_common) + add_subdirectory(sample_decode) + add_subdirectory(sample_vpp) + add_subdirectory(sample_encode) + add_subdirectory(sample_misc/wayland) ++add_subdirectory(sample_multi_transcode) +diff --git a/tools/legacy/media_sdk_compatibility_headers/CMakeLists.txt b/tools/legacy/media_sdk_compatibility_headers/CMakeLists.txt +new file mode 100644 +index 0000000..343255a +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/CMakeLists.txt +@@ -0,0 +1,11 @@ ++# ############################################################################## ++# Copyright (C) Intel Corporation ++# ++# SPDX-License-Identifier: MIT ++# ############################################################################## ++cmake_minimum_required(VERSION 3.10.2) ++ ++set(TARGET media_sdk_compatibility_headers) ++ ++add_library(${TARGET} INTERFACE) ++target_include_directories(${TARGET} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) +diff --git a/tools/legacy/media_sdk_compatibility_headers/mfx_multi_vpp.h b/tools/legacy/media_sdk_compatibility_headers/mfx_multi_vpp.h +new file mode 100644 +index 0000000..d53bbac +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/mfx_multi_vpp.h +@@ -0,0 +1,103 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2018, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#ifndef __MFX_MULTI_VPP_H ++#define __MFX_MULTI_VPP_H ++ ++#include "mfxvideo++.h" ++// An interface for a pipeline consisting of multiple (maximum 3) VPP-like components. Base implementation - for single VPP. ++// The application should use this interface to be able to seamlessly switch from MFXVideoVPP to MFXVideoVPPPlugin in the pipeline. ++ ++class MFXVideoMultiVPP : public MFXVideoVPP { ++public: ++ MFXVideoMultiVPP(mfxSession session) : MFXVideoVPP(session) {} ++ virtual ~MFXVideoMultiVPP(void) { ++ Close(); ++ } ++ ++ // topology methods ++ virtual mfxStatus QueryIOSurf(mfxVideoParam *par, mfxFrameAllocRequest *request) override { ++ return QueryIOSurfMulti(par, request); ++ } ++ virtual mfxStatus QueryIOSurfMulti(mfxVideoParam *par, ++ mfxFrameAllocRequest request[2], ++ mfxVideoParam * /*par1*/ = NULL, ++ mfxVideoParam * /*par2*/ = NULL) { ++ return MFXVideoVPP_QueryIOSurf(m_session, par, request); ++ } ++ ++ virtual mfxStatus Init(mfxVideoParam *par) override { ++ return InitMulti(par); ++ } ++ virtual mfxStatus InitMulti(mfxVideoParam *par, ++ mfxVideoParam * /*par1*/ = NULL, ++ mfxVideoParam * /*par2*/ = NULL) { ++ return MFXVideoVPP_Init(m_session, par); ++ } ++ ++ virtual mfxStatus Reset(mfxVideoParam *par) override { ++ return ResetMulti(par); ++ } ++ virtual mfxStatus ResetMulti(mfxVideoParam *par, ++ mfxVideoParam * /*par1*/ = NULL, ++ mfxVideoParam * /*par2*/ = NULL) { ++ return MFXVideoVPP_Reset(m_session, par); ++ } ++ ++ virtual mfxStatus RunFrameVPPAsync(mfxFrameSurface1 *in, ++ mfxFrameSurface1 *out, ++ mfxExtVppAuxData *aux, ++ mfxSyncPoint *syncp) override { ++ return MFXVideoVPP_RunFrameVPPAsync(m_session, in, out, aux, syncp); ++ } ++ ++ virtual mfxStatus SyncOperation(mfxSyncPoint syncp, mfxU32 wait) { ++ return MFXVideoCORE_SyncOperation(m_session, syncp, wait); ++ } ++ ++ virtual mfxStatus Close(void) override { ++ return MFXVideoVPP_Close(m_session); ++ } ++ ++ // per-component methods ++ virtual mfxStatus Query(mfxVideoParam *in, mfxVideoParam *out) override { ++ return QueryMulti(in, out); ++ } ++ virtual mfxStatus QueryMulti(mfxVideoParam *in, ++ mfxVideoParam *out, ++ mfxU8 /*component_idx*/ = 0) { ++ return MFXVideoVPP_Query(m_session, in, out); ++ } ++ ++ virtual mfxStatus GetVideoParam(mfxVideoParam *par) override { ++ return GetVideoParamMulti(par); ++ } ++ virtual mfxStatus GetVideoParamMulti(mfxVideoParam *par, mfxU8 /*component_idx*/ = 0) { ++ return MFXVideoVPP_GetVideoParam(m_session, par); ++ } ++ ++ virtual mfxStatus GetVPPStat(mfxVPPStat *stat) override { ++ return GetVPPStatMulti(stat); ++ } ++ virtual mfxStatus GetVPPStatMulti(mfxVPPStat *stat, mfxU8 /*component_idx*/ = 0) { ++ return MFXVideoVPP_GetVPPStat(m_session, stat); ++ } ++}; ++ ++#endif //__MFX_MULTI_VPP_H +diff --git a/tools/legacy/media_sdk_compatibility_headers/mfxastructures.h b/tools/legacy/media_sdk_compatibility_headers/mfxastructures.h +new file mode 100644 +index 0000000..a66628c +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/mfxastructures.h +@@ -0,0 +1,169 @@ ++/******************************************************************************* ++ ++Copyright (C) 2013-2019 Intel Corporation. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++- Redistributions of source code must retain the above copyright notice, ++this list of conditions and the following disclaimer. ++- 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. ++- Neither the name of Intel Corporation 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 INTEL CORPORATION "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 INTEL CORPORATION 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. ++ ++File Name: mfxastructures.h ++ ++*******************************************************************************/ ++#ifndef __MFXASTRUCTURES_H__ ++#define __MFXASTRUCTURES_H__ ++#include "vpl/mfxcommon.h" ++ ++#if !defined(__GNUC__) ++ #pragma warning(disable : 4201) ++#endif ++ ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++/* CodecId */ ++enum { ++ MFX_CODEC_AAC = MFX_MAKEFOURCC('A', 'A', 'C', ' '), ++ MFX_CODEC_MP3 = MFX_MAKEFOURCC('M', 'P', '3', ' ') ++}; ++ ++enum { ++ /* AAC Profiles & Levels */ ++ MFX_PROFILE_AAC_LC = 2, ++ MFX_PROFILE_AAC_LTP = 4, ++ MFX_PROFILE_AAC_MAIN = 1, ++ MFX_PROFILE_AAC_SSR = 3, ++ MFX_PROFILE_AAC_HE = 5, ++ MFX_PROFILE_AAC_ALS = 0x20, ++ MFX_PROFILE_AAC_BSAC = 22, ++ MFX_PROFILE_AAC_PS = 29, ++ ++ /*MPEG AUDIO*/ ++ MFX_AUDIO_MPEG1_LAYER1 = 0x00000110, ++ MFX_AUDIO_MPEG1_LAYER2 = 0x00000120, ++ MFX_AUDIO_MPEG1_LAYER3 = 0x00000140, ++ MFX_AUDIO_MPEG2_LAYER1 = 0x00000210, ++ MFX_AUDIO_MPEG2_LAYER2 = 0x00000220, ++ MFX_AUDIO_MPEG2_LAYER3 = 0x00000240 ++}; ++ ++/*AAC HE decoder down sampling*/ ++enum { MFX_AUDIO_AAC_HE_DWNSMPL_OFF = 0, MFX_AUDIO_AAC_HE_DWNSMPL_ON = 1 }; ++ ++/* AAC decoder support of PS */ ++enum { ++ MFX_AUDIO_AAC_PS_DISABLE = 0, ++ MFX_AUDIO_AAC_PS_PARSER = 1, ++ MFX_AUDIO_AAC_PS_ENABLE_BL = 111, ++ MFX_AUDIO_AAC_PS_ENABLE_UR = 411 ++}; ++ ++/*AAC decoder SBR support*/ ++enum { MFX_AUDIO_AAC_SBR_DISABLE = 0, MFX_AUDIO_AAC_SBR_ENABLE = 1, MFX_AUDIO_AAC_SBR_UNDEF = 2 }; ++ ++/*AAC header type*/ ++enum { ++ MFX_AUDIO_AAC_ADTS = 1, ++ MFX_AUDIO_AAC_ADIF = 2, ++ MFX_AUDIO_AAC_RAW = 3, ++}; ++ ++/*AAC encoder stereo mode*/ ++enum { ++ MFX_AUDIO_AAC_MONO = 0, ++ MFX_AUDIO_AAC_LR_STEREO = 1, ++ MFX_AUDIO_AAC_MS_STEREO = 2, ++ MFX_AUDIO_AAC_JOINT_STEREO = 3 ++}; ++ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct { ++ mfxU32 CodecId; ++ mfxU16 CodecProfile; ++ mfxU16 CodecLevel; ++ ++ mfxU32 Bitrate; ++ mfxU32 SampleFrequency; ++ mfxU16 NumChannel; ++ mfxU16 BitPerSample; ++ ++ mfxU16 reserved1[22]; ++ ++ union { ++ struct { /* AAC Decoding Options */ ++ mfxU16 FlagPSSupportLev; ++ mfxU16 Layer; ++ mfxU16 AACHeaderDataSize; ++ mfxU8 AACHeaderData[64]; ++ }; ++ struct { /* AAC Encoding Options */ ++ mfxU16 OutputFormat; ++ mfxU16 StereoMode; ++ mfxU16 reserved2[61]; ++ }; ++ }; ++} mfxAudioInfoMFX; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct { ++ mfxU16 AsyncDepth; ++ mfxU16 Protected; ++ mfxU16 reserved[14]; ++ ++ mfxAudioInfoMFX mfx; ++ mfxExtBuffer** ExtParam; ++ mfxU16 NumExtParam; ++} mfxAudioParam; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct { ++ mfxU32 SuggestedInputSize; ++ mfxU32 SuggestedOutputSize; ++ mfxU32 reserved[6]; ++} mfxAudioAllocRequest; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_L_TYPE() ++typedef struct { ++ mfxU64 TimeStamp; /* 1/90KHz */ ++ mfxU16 Locked; ++ mfxU16 NumChannels; ++ mfxU32 SampleFrequency; ++ mfxU16 BitPerSample; ++ mfxU16 reserved1[7]; ++ ++ mfxU8* Data; ++ mfxU32 reserved2; ++ mfxU32 DataLength; ++ mfxU32 MaxLength; ++ ++ mfxU32 NumExtParam; ++ mfxExtBuffer** ExtParam; ++} mfxAudioFrame; ++MFX_PACK_END() ++ ++#ifdef __cplusplus ++} ++#endif /* __cplusplus */ ++ ++#endif +diff --git a/tools/legacy/media_sdk_compatibility_headers/mfxaudio.h b/tools/legacy/media_sdk_compatibility_headers/mfxaudio.h +new file mode 100644 +index 0000000..b252d98 +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/mfxaudio.h +@@ -0,0 +1,81 @@ ++/******************************************************************************* ++ ++Copyright (C) 2013 Intel Corporation. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++- Redistributions of source code must retain the above copyright notice, ++this list of conditions and the following disclaimer. ++- 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. ++- Neither the name of Intel Corporation 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 INTEL CORPORATION "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 INTEL CORPORATION 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. ++ ++File Name: mfxaudio.h ++ ++*******************************************************************************/ ++ ++#ifndef __MFXAUDIO_H__ ++#define __MFXAUDIO_H__ ++#include "mfxastructures.h" ++#include "vpl/mfxsession.h" ++ ++#define MFX_AUDIO_VERSION_MAJOR 1 ++#define MFX_AUDIO_VERSION_MINOR 15 ++ ++#ifdef __cplusplus ++extern "C" { ++#endif ++ ++/* AudioCORE */ ++mfxStatus MFX_CDECL MFXAudioCORE_SyncOperation(mfxSession session, mfxSyncPoint syncp, mfxU32 wait); ++ ++/* AudioENCODE */ ++mfxStatus MFX_CDECL MFXAudioENCODE_Query(mfxSession session, mfxAudioParam *in, mfxAudioParam *out); ++mfxStatus MFX_CDECL MFXAudioENCODE_QueryIOSize(mfxSession session, ++ mfxAudioParam *par, ++ mfxAudioAllocRequest *request); ++mfxStatus MFX_CDECL MFXAudioENCODE_Init(mfxSession session, mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioENCODE_Reset(mfxSession session, mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioENCODE_Close(mfxSession session); ++mfxStatus MFX_CDECL MFXAudioENCODE_GetAudioParam(mfxSession session, mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioENCODE_EncodeFrameAsync(mfxSession session, ++ mfxAudioFrame *frame, ++ mfxBitstream *bs, ++ mfxSyncPoint *syncp); ++ ++/* AudioDECODE */ ++mfxStatus MFX_CDECL MFXAudioDECODE_Query(mfxSession session, mfxAudioParam *in, mfxAudioParam *out); ++mfxStatus MFX_CDECL MFXAudioDECODE_DecodeHeader(mfxSession session, ++ mfxBitstream *bs, ++ mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioDECODE_Init(mfxSession session, mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioDECODE_Reset(mfxSession session, mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioDECODE_Close(mfxSession session); ++mfxStatus MFX_CDECL MFXAudioDECODE_QueryIOSize(mfxSession session, ++ mfxAudioParam *par, ++ mfxAudioAllocRequest *request); ++mfxStatus MFX_CDECL MFXAudioDECODE_GetAudioParam(mfxSession session, mfxAudioParam *par); ++mfxStatus MFX_CDECL MFXAudioDECODE_DecodeFrameAsync(mfxSession session, ++ mfxBitstream *bs, ++ mfxAudioFrame *frame, ++ mfxSyncPoint *syncp); ++ ++#ifdef __cplusplus ++} // extern "C" ++#endif ++ ++#endif +diff --git a/tools/legacy/media_sdk_compatibility_headers/mfxdeprecated.h b/tools/legacy/media_sdk_compatibility_headers/mfxdeprecated.h +new file mode 100644 +index 0000000..5f0ca24 +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/mfxdeprecated.h +@@ -0,0 +1,167 @@ ++/*############################################################################ ++ # Copyright (C) 2020 Intel Corporation ++ # ++ # SPDX-License-Identifier: MIT ++ ############################################################################*/ ++ ++#ifndef __MFXDEPRECATED_H__ ++#define __MFXDEPRECATED_H__ ++ ++#include "vpl/mfxcommon.h" ++#include "vpl/mfxsession.h" ++#include "vpl/mfxstructures.h" ++ ++#if defined(MFX_ONEVPL) ++ ++ #ifdef __cplusplus ++extern "C" { ++ #endif /* __cplusplus */ ++ ++enum { ++ MFX_ERR_INCOMPATIBLE_AUDIO_PARAM = -19, /* incompatible audio parameters */ ++ MFX_ERR_INVALID_AUDIO_PARAM = -20, /* invalid audio parameters */ ++ ++ MFX_WRN_INCOMPATIBLE_AUDIO_PARAM = 11, /* incompatible audio parameters */ ++}; ++ ++mfxStatus MFX_CDECL MFXVideoVPP_RunFrameVPPAsyncEx(mfxSession session, ++ mfxFrameSurface1 *in, ++ mfxFrameSurface1 *surface_work, ++ mfxFrameSurface1 **surface_out, ++ mfxSyncPoint *syncp); ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct { ++ mfxU32 reserved[4]; ++ mfxHDL pthis; ++ mfxStatus(MFX_CDECL *Alloc)(mfxHDL pthis, mfxU32 nbytes, mfxU16 type, mfxMemId *mid); ++ mfxStatus(MFX_CDECL *Lock)(mfxHDL pthis, mfxMemId mid, mfxU8 **ptr); ++ mfxStatus(MFX_CDECL *Unlock)(mfxHDL pthis, mfxMemId mid); ++ mfxStatus(MFX_CDECL *Free)(mfxHDL pthis, mfxMemId mid); ++} mfxBufferAllocator; ++MFX_PACK_END() ++ ++mfxStatus MFX_CDECL MFXVideoCORE_SetBufferAllocator(mfxSession session, ++ mfxBufferAllocator *allocator); ++ ++ #if defined(MFX_ENABLE_OPAQUE_MEMORY) ++ //Sanity check ++ #error MFX_ENABLE_OPAQUE_MEMORY should not be defined when 'mfxdeprecated.h' is included ++ #endif //MFX_ENABLE_OPAQUE_MEMORY ++ ++/* IOPattern */ ++enum { MFX_IOPATTERN_IN_OPAQUE_MEMORY = 0x04, MFX_IOPATTERN_OUT_OPAQUE_MEMORY = 0x40 }; ++ ++enum { MFX_MEMTYPE_OPAQUE_FRAME = 0x0004 }; ++ ++/* Extended Buffer Ids */ ++enum { MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION = MFX_MAKEFOURCC('O', 'P', 'Q', 'S') }; ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct { ++ mfxExtBuffer Header; ++ mfxU32 reserved1[2]; ++ struct { ++ mfxFrameSurface1 **Surfaces; ++ mfxU32 reserved2[5]; ++ mfxU16 Type; ++ mfxU16 NumSurface; ++ } In, Out; ++} mfxExtOpaqueSurfaceAlloc; ++MFX_PACK_END() ++ ++mfxStatus MFX_CDECL MFXDoWork(mfxSession session); ++ ++mfxStatus MFX_CDECL MFXVideoENC_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); ++mfxStatus MFX_CDECL MFXVideoENC_QueryIOSurf(mfxSession session, ++ mfxVideoParam *par, ++ mfxFrameAllocRequest *request); ++mfxStatus MFX_CDECL MFXVideoENC_Init(mfxSession session, mfxVideoParam *par); ++mfxStatus MFX_CDECL MFXVideoENC_Reset(mfxSession session, mfxVideoParam *par); ++mfxStatus MFX_CDECL MFXVideoENC_Close(mfxSession session); ++ ++typedef struct _mfxENCInput { ++} mfxENCInput; ++typedef struct _mfxENCOutput { ++} mfxENCOutput; ++mfxStatus MFX_CDECL MFXVideoENC_ProcessFrameAsync(mfxSession session, ++ mfxENCInput *in, ++ mfxENCOutput *out, ++ mfxSyncPoint *syncp); ++ ++mfxStatus MFX_CDECL MFXVideoENC_GetVideoParam(mfxSession session, mfxVideoParam *par); ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct { ++} mfxPAKInput; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct { ++} mfxPAKOutput; ++MFX_PACK_END() ++ ++mfxStatus MFX_CDECL MFXVideoPAK_Query(mfxSession session, mfxVideoParam *in, mfxVideoParam *out); ++mfxStatus MFX_CDECL MFXVideoPAK_QueryIOSurf(mfxSession session, ++ mfxVideoParam *par, ++ mfxFrameAllocRequest request[2]); ++mfxStatus MFX_CDECL MFXVideoPAK_Init(mfxSession session, mfxVideoParam *par); ++mfxStatus MFX_CDECL MFXVideoPAK_Reset(mfxSession session, mfxVideoParam *par); ++mfxStatus MFX_CDECL MFXVideoPAK_Close(mfxSession session); ++ ++mfxStatus MFX_CDECL MFXVideoPAK_ProcessFrameAsync(mfxSession session, ++ mfxPAKInput *in, ++ mfxPAKOutput *out, ++ mfxSyncPoint *syncp); ++ ++mfxStatus MFX_CDECL MFXVideoPAK_GetVideoParam(mfxSession session, mfxVideoParam *par); ++ ++enum { ++ /*! ++ This extended buffer allow to specify multi-frame submission parameters. ++ */ ++ MFX_EXTBUFF_MULTI_FRAME_PARAM = MFX_MAKEFOURCC('M', 'F', 'R', 'P'), ++ /*! ++ This extended buffer allow to manage multi-frame submission in runtime. ++ */ ++ MFX_EXTBUFF_MULTI_FRAME_CONTROL = MFX_MAKEFOURCC('M', 'F', 'R', 'C'), ++}; ++ ++/* Multi-Frame Mode */ ++enum { MFX_MF_DEFAULT = 0, MFX_MF_DISABLED = 1, MFX_MF_AUTO = 2, MFX_MF_MANUAL = 3 }; ++ ++/* Multi-Frame Initialization parameters */ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct { ++ mfxExtBuffer Header; ++ ++ mfxU16 MFMode; ++ mfxU16 MaxNumFrames; ++ ++ mfxU16 reserved[58]; ++} mfxExtMultiFrameParam; ++MFX_PACK_END() ++ ++/* Multi-Frame Run-time controls */ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct { ++ mfxExtBuffer Header; ++ ++ mfxU32 Timeout; /* timeout in millisecond */ ++ mfxU16 Flush; /* Flush internal frame buffer, e.g. submit all collected frames. */ ++ ++ mfxU16 reserved[57]; ++} mfxExtMultiFrameControl; ++MFX_PACK_END() ++ ++/* RateControlMethod */ ++enum { ++ MFX_RATECONTROL_LA_EXT = 12, ++ MFX_RATECONTROL_VME = 15, ++}; ++ #ifdef __cplusplus ++} ++ #endif /* __cplusplus */ ++ ++#endif //MFX_ONEVPL ++#endif //__MFXDEPRECATED_H__ +diff --git a/tools/legacy/media_sdk_compatibility_headers/mfxplugin.h b/tools/legacy/media_sdk_compatibility_headers/mfxplugin.h +new file mode 100644 +index 0000000..2c42433 +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/mfxplugin.h +@@ -0,0 +1,601 @@ ++/******************************************************************************* *\ ++ ++Copyright (C) 2007-2019 Intel Corporation. All rights reserved. ++ ++Redistribution and use in source and binary forms, with or without ++modification, are permitted provided that the following conditions are met: ++- Redistributions of source code must retain the above copyright notice, ++this list of conditions and the following disclaimer. ++- 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. ++- Neither the name of Intel Corporation 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 INTEL CORPORATION "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 INTEL CORPORATION 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. ++ ++File Name: mfxplugin.h ++ ++*******************************************************************************/ ++#ifndef __MFXPLUGIN_H__ ++#define __MFXPLUGIN_H__ ++#include "mfxaudio.h" ++#include "mfxdeprecated.h" ++#include "vpl/mfxvideo.h" ++#ifdef __cplusplus ++extern "C" { ++#endif /* __cplusplus */ ++ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct { ++ mfxU8 Data[16]; ++} mfxPluginUID; ++MFX_PACK_END() ++ ++static const mfxPluginUID MFX_PLUGINID_HEVCD_SW = { { 0x15, ++ 0xdd, ++ 0x93, ++ 0x68, ++ 0x25, ++ 0xad, ++ 0x47, ++ 0x5e, ++ 0xa3, ++ 0x4e, ++ 0x35, ++ 0xf3, ++ 0xf5, ++ 0x42, ++ 0x17, ++ 0xa6 } }; ++static const mfxPluginUID MFX_PLUGINID_HEVCD_HW = { { 0x33, ++ 0xa6, ++ 0x1c, ++ 0x0b, ++ 0x4c, ++ 0x27, ++ 0x45, ++ 0x4c, ++ 0xa8, ++ 0xd8, ++ 0x5d, ++ 0xde, ++ 0x75, ++ 0x7c, ++ 0x6f, ++ 0x8e } }; ++static const mfxPluginUID MFX_PLUGINID_HEVCE_SW = { { 0x2f, ++ 0xca, ++ 0x99, ++ 0x74, ++ 0x9f, ++ 0xdb, ++ 0x49, ++ 0xae, ++ 0xb1, ++ 0x21, ++ 0xa5, ++ 0xb6, ++ 0x3e, ++ 0xf5, ++ 0x68, ++ 0xf7 } }; ++static const mfxPluginUID MFX_PLUGINID_HEVCE_GACC = { { 0xe5, ++ 0x40, ++ 0x0a, ++ 0x06, ++ 0xc7, ++ 0x4d, ++ 0x41, ++ 0xf5, ++ 0xb1, ++ 0x2d, ++ 0x43, ++ 0x0b, ++ 0xba, ++ 0xa2, ++ 0x3d, ++ 0x0b } }; ++static const mfxPluginUID MFX_PLUGINID_HEVCE_DP_GACC = { { 0x2b, ++ 0xad, ++ 0x6f, ++ 0x9d, ++ 0x77, ++ 0x54, ++ 0x41, ++ 0x2d, ++ 0xbf, ++ 0x63, ++ 0x03, ++ 0xed, ++ 0x4b, ++ 0xb5, ++ 0x09, ++ 0x68 } }; ++static const mfxPluginUID MFX_PLUGINID_HEVCE_HW = { { 0x6f, ++ 0xad, ++ 0xc7, ++ 0x91, ++ 0xa0, ++ 0xc2, ++ 0xeb, ++ 0x47, ++ 0x9a, ++ 0xb6, ++ 0xdc, ++ 0xd5, ++ 0xea, ++ 0x9d, ++ 0xa3, ++ 0x47 } }; ++static const mfxPluginUID MFX_PLUGINID_VP8D_HW = { { 0xf6, ++ 0x22, ++ 0x39, ++ 0x4d, ++ 0x8d, ++ 0x87, ++ 0x45, ++ 0x2f, ++ 0x87, ++ 0x8c, ++ 0x51, ++ 0xf2, ++ 0xfc, ++ 0x9b, ++ 0x41, ++ 0x31 } }; ++static const mfxPluginUID MFX_PLUGINID_VP8E_HW = { { 0xbf, ++ 0xfc, ++ 0x51, ++ 0x8c, ++ 0xde, ++ 0x13, ++ 0x4d, ++ 0xf9, ++ 0x8a, ++ 0x96, ++ 0xf4, ++ 0xcf, ++ 0x81, ++ 0x6c, ++ 0x0f, ++ 0xac } }; ++static const mfxPluginUID MFX_PLUGINID_VP9E_HW = { { 0xce, ++ 0x44, ++ 0xef, ++ 0x6f, ++ 0x1a, ++ 0x6d, ++ 0x22, ++ 0x46, ++ 0xb4, ++ 0x12, ++ 0xbb, ++ 0x38, ++ 0xd6, ++ 0xe4, ++ 0x51, ++ 0x82 } }; ++static const mfxPluginUID MFX_PLUGINID_VP9D_HW = { { 0xa9, ++ 0x22, ++ 0x39, ++ 0x4d, ++ 0x8d, ++ 0x87, ++ 0x45, ++ 0x2f, ++ 0x87, ++ 0x8c, ++ 0x51, ++ 0xf2, ++ 0xfc, ++ 0x9b, ++ 0x41, ++ 0x31 } }; ++static const mfxPluginUID MFX_PLUGINID_CAMERA_HW = { { 0x54, ++ 0x54, ++ 0x26, ++ 0x16, ++ 0x24, ++ 0x33, ++ 0x41, ++ 0xe6, ++ 0x93, ++ 0xae, ++ 0x89, ++ 0x99, ++ 0x42, ++ 0xce, ++ 0x73, ++ 0x55 } }; ++static const mfxPluginUID MFX_PLUGINID_CAPTURE_HW = { { 0x22, ++ 0xd6, ++ 0x2c, ++ 0x07, ++ 0xe6, ++ 0x72, ++ 0x40, ++ 0x8f, ++ 0xbb, ++ 0x4c, ++ 0xc2, ++ 0x0e, ++ 0xd7, ++ 0xa0, ++ 0x53, ++ 0xe4 } }; ++static const mfxPluginUID MFX_PLUGINID_ITELECINE_HW = { { 0xe7, ++ 0x44, ++ 0x75, ++ 0x3a, ++ 0xcd, ++ 0x74, ++ 0x40, ++ 0x2e, ++ 0x89, ++ 0xa2, ++ 0xee, ++ 0x06, ++ 0x35, ++ 0x49, ++ 0x61, ++ 0x79 } }; ++static const mfxPluginUID MFX_PLUGINID_H264LA_HW = { { 0x58, ++ 0x8f, ++ 0x11, ++ 0x85, ++ 0xd4, ++ 0x7b, ++ 0x42, ++ 0x96, ++ 0x8d, ++ 0xea, ++ 0x37, ++ 0x7b, ++ 0xb5, ++ 0xd0, ++ 0xdc, ++ 0xb4 } }; ++static const mfxPluginUID MFX_PLUGINID_AACD = { { 0xe9, ++ 0x34, ++ 0x67, ++ 0x25, ++ 0xac, ++ 0x2f, ++ 0x4c, ++ 0x93, ++ 0xaa, ++ 0x58, ++ 0x5c, ++ 0x11, ++ 0xc7, ++ 0x08, ++ 0x7c, ++ 0xf4 } }; ++static const mfxPluginUID MFX_PLUGINID_AACE = { { 0xb2, ++ 0xa2, ++ 0xa0, ++ 0x5a, ++ 0x4e, ++ 0xac, ++ 0x46, ++ 0xbf, ++ 0xa9, ++ 0xde, ++ 0x7e, ++ 0x80, ++ 0xc9, ++ 0x8d, ++ 0x2e, ++ 0x18 } }; ++static const mfxPluginUID MFX_PLUGINID_HEVCE_FEI_HW = { { 0x87, ++ 0xe0, ++ 0xe8, ++ 0x02, ++ 0x07, ++ 0x37, ++ 0x52, ++ 0x40, ++ 0x85, ++ 0x25, ++ 0x15, ++ 0xcf, ++ 0x4a, ++ 0x5e, ++ 0xdd, ++ 0xe6 } }; ++#if (MFX_VERSION >= 1027) ++static const mfxPluginUID MFX_PLUGINID_HEVC_FEI_ENCODE = { { 0x54, ++ 0x18, ++ 0xa7, ++ 0x06, ++ 0x66, ++ 0xf9, ++ 0x4d, ++ 0x5c, ++ 0xb4, ++ 0xf7, ++ 0xb1, ++ 0xca, ++ 0xee, ++ 0x86, ++ 0x33, ++ 0x9b } }; ++#endif ++#if !defined(OPEN_SOURCE) ++static const mfxPluginUID MFX_PLUGINID_AV1D_SW = { { 0x93, ++ 0x6c, ++ 0x26, ++ 0xe8, ++ 0xf9, ++ 0xb5, ++ 0x45, ++ 0xdc, ++ 0xad, ++ 0xac, ++ 0xe8, ++ 0xcc, ++ 0xeb, ++ 0x8a, ++ 0x57, ++ 0xa9 } }; ++static const mfxPluginUID MFX_PLUGINID_AV1D_HW = { { 0x07, ++ 0x49, ++ 0xdf, ++ 0x10, ++ 0x72, ++ 0x66, ++ 0x4f, ++ 0x1d, ++ 0x8d, ++ 0x77, ++ 0x29, ++ 0x8e, ++ 0xb2, ++ 0x97, ++ 0x5c, ++ 0x3c } }; ++static const mfxPluginUID MFX_PLUGINID_AV1E_GACC = { { 0x34, ++ 0x3d, ++ 0x68, ++ 0x96, ++ 0x65, ++ 0xba, ++ 0x45, ++ 0x48, ++ 0x82, ++ 0x99, ++ 0x42, ++ 0xa3, ++ 0x2a, ++ 0x38, ++ 0x65, ++ 0x69 } }; ++#endif ++ ++typedef enum { ++ MFX_PLUGINTYPE_VIDEO_GENERAL = 0, ++ MFX_PLUGINTYPE_VIDEO_DECODE = 1, ++ MFX_PLUGINTYPE_VIDEO_ENCODE = 2, ++ MFX_PLUGINTYPE_VIDEO_VPP = 3, ++ MFX_PLUGINTYPE_VIDEO_ENC = 4, ++ MFX_PLUGINTYPE_AUDIO_DECODE = 5, ++ MFX_PLUGINTYPE_AUDIO_ENCODE = 6 ++} mfxPluginType; ++ ++typedef enum { MFX_THREADPOLICY_SERIAL = 0, MFX_THREADPOLICY_PARALLEL = 1 } mfxThreadPolicy; ++ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct mfxPluginParam { ++ mfxU32 reserved[6]; ++ mfxU16 reserved1; ++ mfxU16 PluginVersion; ++ mfxVersion APIVersion; ++ mfxPluginUID PluginUID; ++ mfxU32 Type; ++ mfxU32 CodecId; ++ mfxThreadPolicy ThreadPolicy; ++ mfxU32 MaxThreadNum; ++} mfxPluginParam; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_USUAL_STRUCT() ++typedef struct mfxCoreParam { ++ mfxU32 reserved[13]; ++ mfxIMPL Impl; ++ mfxVersion Version; ++ mfxU32 NumWorkingThread; ++} mfxCoreParam; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct mfxCoreInterface { ++ mfxHDL pthis; ++ ++ mfxHDL reserved1[2]; ++ mfxFrameAllocator FrameAllocator; ++ //mfxBufferAllocator reserved3; ++ ++ mfxStatus(MFX_CDECL *GetCoreParam)(mfxHDL pthis, mfxCoreParam *par); ++ mfxStatus(MFX_CDECL *GetHandle)(mfxHDL pthis, mfxHandleType type, mfxHDL *handle); ++ mfxStatus(MFX_CDECL *IncreaseReference)(mfxHDL pthis, mfxFrameData *fd); ++ mfxStatus(MFX_CDECL *DecreaseReference)(mfxHDL pthis, mfxFrameData *fd); ++ mfxStatus(MFX_CDECL *CopyFrame)(mfxHDL pthis, mfxFrameSurface1 *dst, mfxFrameSurface1 *src); ++ mfxStatus(MFX_CDECL *CopyBuffer)(mfxHDL pthis, mfxU8 *dst, mfxU32 size, mfxFrameSurface1 *src); ++ ++ mfxStatus(MFX_CDECL *MapOpaqueSurface)(mfxHDL pthis, ++ mfxU32 num, ++ mfxU32 type, ++ mfxFrameSurface1 **op_surf); ++ mfxStatus(MFX_CDECL *UnmapOpaqueSurface)(mfxHDL pthis, ++ mfxU32 num, ++ mfxU32 type, ++ mfxFrameSurface1 **op_surf); ++ ++ mfxStatus(MFX_CDECL *GetRealSurface)(mfxHDL pthis, ++ mfxFrameSurface1 *op_surf, ++ mfxFrameSurface1 **surf); ++ mfxStatus(MFX_CDECL *GetOpaqueSurface)(mfxHDL pthis, ++ mfxFrameSurface1 *surf, ++ mfxFrameSurface1 **op_surf); ++ ++ mfxStatus(MFX_CDECL *CreateAccelerationDevice)(mfxHDL pthis, ++ mfxHandleType type, ++ mfxHDL *handle); ++ mfxStatus(MFX_CDECL *GetFrameHandle)(mfxHDL pthis, mfxFrameData *fd, mfxHDL *handle); ++ mfxStatus(MFX_CDECL *QueryPlatform)(mfxHDL pthis, mfxPlatform *platform); ++ ++ mfxHDL reserved4[1]; ++} mfxCoreInterface; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++/* video codec plugin extension */ ++typedef struct _mfxENCInput mfxENCInput; ++typedef struct _mfxENCOutput mfxENCOutput; ++typedef struct mfxVideoCodecPlugin { ++ mfxStatus(MFX_CDECL *Query)(mfxHDL pthis, mfxVideoParam *in, mfxVideoParam *out); ++ mfxStatus(MFX_CDECL *QueryIOSurf)(mfxHDL pthis, ++ mfxVideoParam *par, ++ mfxFrameAllocRequest *in, ++ mfxFrameAllocRequest *out); ++ mfxStatus(MFX_CDECL *Init)(mfxHDL pthis, mfxVideoParam *par); ++ mfxStatus(MFX_CDECL *Reset)(mfxHDL pthis, mfxVideoParam *par); ++ mfxStatus(MFX_CDECL *Close)(mfxHDL pthis); ++ mfxStatus(MFX_CDECL *GetVideoParam)(mfxHDL pthis, mfxVideoParam *par); ++ ++ mfxStatus(MFX_CDECL *EncodeFrameSubmit)(mfxHDL pthis, ++ mfxEncodeCtrl *ctrl, ++ mfxFrameSurface1 *surface, ++ mfxBitstream *bs, ++ mfxThreadTask *task); ++ ++ mfxStatus(MFX_CDECL *DecodeHeader)(mfxHDL pthis, mfxBitstream *bs, mfxVideoParam *par); ++ mfxStatus(MFX_CDECL *GetPayload)(mfxHDL pthis, mfxU64 *ts, mfxPayload *payload); ++ mfxStatus(MFX_CDECL *DecodeFrameSubmit)(mfxHDL pthis, ++ mfxBitstream *bs, ++ mfxFrameSurface1 *surface_work, ++ mfxFrameSurface1 **surface_out, ++ mfxThreadTask *task); ++ ++ mfxStatus(MFX_CDECL *VPPFrameSubmit)(mfxHDL pthis, ++ mfxFrameSurface1 *in, ++ mfxFrameSurface1 *out, ++ mfxExtVppAuxData *aux, ++ mfxThreadTask *task); ++ mfxStatus(MFX_CDECL *VPPFrameSubmitEx)(mfxHDL pthis, ++ mfxFrameSurface1 *in, ++ mfxFrameSurface1 *surface_work, ++ mfxFrameSurface1 **surface_out, ++ mfxThreadTask *task); ++ ++ mfxStatus(MFX_CDECL *ENCFrameSubmit)(mfxHDL pthis, ++ mfxENCInput *in, ++ mfxENCOutput *out, ++ mfxThreadTask *task); ++ ++ mfxHDL reserved1[3]; ++ mfxU32 reserved2[8]; ++} mfxVideoCodecPlugin; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct mfxAudioCodecPlugin { ++ mfxStatus(MFX_CDECL *Query)(mfxHDL pthis, mfxAudioParam *in, mfxAudioParam *out); ++ mfxStatus(MFX_CDECL *QueryIOSize)(mfxHDL pthis, ++ mfxAudioParam *par, ++ mfxAudioAllocRequest *request); ++ mfxStatus(MFX_CDECL *Init)(mfxHDL pthis, mfxAudioParam *par); ++ mfxStatus(MFX_CDECL *Reset)(mfxHDL pthis, mfxAudioParam *par); ++ mfxStatus(MFX_CDECL *Close)(mfxHDL pthis); ++ mfxStatus(MFX_CDECL *GetAudioParam)(mfxHDL pthis, mfxAudioParam *par); ++ ++ mfxStatus(MFX_CDECL *EncodeFrameSubmit)(mfxHDL pthis, ++ mfxAudioFrame *aFrame, ++ mfxBitstream *out, ++ mfxThreadTask *task); ++ ++ mfxStatus(MFX_CDECL *DecodeHeader)(mfxHDL pthis, mfxBitstream *bs, mfxAudioParam *par); ++ // mfxStatus (MFX_CDECL *GetPayload)(mfxHDL pthis, mfxU64 *ts, mfxPayload *payload); ++ mfxStatus(MFX_CDECL *DecodeFrameSubmit)(mfxHDL pthis, ++ mfxBitstream *in, ++ mfxAudioFrame *out, ++ mfxThreadTask *task); ++ ++ mfxHDL reserved1[6]; ++ mfxU32 reserved2[8]; ++} mfxAudioCodecPlugin; ++MFX_PACK_END() ++ ++MFX_PACK_BEGIN_STRUCT_W_PTR() ++typedef struct mfxPlugin { ++ mfxHDL pthis; ++ ++ mfxStatus(MFX_CDECL *PluginInit)(mfxHDL pthis, mfxCoreInterface *core); ++ mfxStatus(MFX_CDECL *PluginClose)(mfxHDL pthis); ++ ++ mfxStatus(MFX_CDECL *GetPluginParam)(mfxHDL pthis, mfxPluginParam *par); ++ ++ mfxStatus(MFX_CDECL *Submit)(mfxHDL pthis, ++ const mfxHDL *in, ++ mfxU32 in_num, ++ const mfxHDL *out, ++ mfxU32 out_num, ++ mfxThreadTask *task); ++ mfxStatus(MFX_CDECL *Execute)(mfxHDL pthis, mfxThreadTask task, mfxU32 uid_p, mfxU32 uid_a); ++ mfxStatus(MFX_CDECL *FreeResources)(mfxHDL pthis, mfxThreadTask task, mfxStatus sts); ++ ++ union { ++ mfxVideoCodecPlugin *Video; ++ mfxAudioCodecPlugin *Audio; ++ }; ++ ++ mfxHDL reserved[8]; ++} mfxPlugin; ++MFX_PACK_END() ++ ++mfxStatus MFX_CDECL MFXVideoUSER_Register(mfxSession session, mfxU32 type, const mfxPlugin *par); ++mfxStatus MFX_CDECL MFXVideoUSER_Unregister(mfxSession session, mfxU32 type); ++mfxStatus MFX_CDECL MFXVideoUSER_GetPlugin(mfxSession session, mfxU32 type, mfxPlugin *par); ++mfxStatus MFX_CDECL MFXVideoUSER_ProcessFrameAsync(mfxSession session, ++ const mfxHDL *in, ++ mfxU32 in_num, ++ const mfxHDL *out, ++ mfxU32 out_num, ++ mfxSyncPoint *syncp); ++ ++mfxStatus MFX_CDECL MFXVideoUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version); ++mfxStatus MFX_CDECL MFXVideoUSER_LoadByPath(mfxSession session, ++ const mfxPluginUID *uid, ++ mfxU32 version, ++ const mfxChar *path, ++ mfxU32 len); ++mfxStatus MFX_CDECL MFXVideoUSER_UnLoad(mfxSession session, const mfxPluginUID *uid); ++ ++mfxStatus MFX_CDECL MFXAudioUSER_Register(mfxSession session, mfxU32 type, const mfxPlugin *par); ++mfxStatus MFX_CDECL MFXAudioUSER_Unregister(mfxSession session, mfxU32 type); ++mfxStatus MFX_CDECL MFXAudioUSER_ProcessFrameAsync(mfxSession session, ++ const mfxHDL *in, ++ mfxU32 in_num, ++ const mfxHDL *out, ++ mfxU32 out_num, ++ mfxSyncPoint *syncp); ++ ++mfxStatus MFX_CDECL MFXAudioUSER_Load(mfxSession session, const mfxPluginUID *uid, mfxU32 version); ++mfxStatus MFX_CDECL MFXAudioUSER_UnLoad(mfxSession session, const mfxPluginUID *uid); ++ ++#ifdef __cplusplus ++} // extern "C" ++#endif /* __cplusplus */ ++ ++#endif /* __MFXPLUGIN_H__ */ +diff --git a/tools/legacy/media_sdk_compatibility_headers/rotate_plugin_api.h b/tools/legacy/media_sdk_compatibility_headers/rotate_plugin_api.h +new file mode 100644 +index 0000000..928f6c3 +--- /dev/null ++++ b/tools/legacy/media_sdk_compatibility_headers/rotate_plugin_api.h +@@ -0,0 +1,29 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2018, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#ifndef __MFX_PLUGIN_ROTATE_API_H__ ++#define __MFX_PLUGIN_ROTATE_API_H__ ++ ++#include "mfxdefs.h" ++ ++struct RotateParam { ++ mfxU16 Angle; // rotation angle ++}; ++ ++#endif // __MFX_PLUGIN_ROTATE_API_H__ +diff --git a/tools/legacy/sample_common/CMakeLists.txt b/tools/legacy/sample_common/CMakeLists.txt +index 4f04226..86b5fd8 100644 +--- a/tools/legacy/sample_common/CMakeLists.txt ++++ b/tools/legacy/sample_common/CMakeLists.txt +@@ -17,8 +17,10 @@ list( + src/sysmem_allocator.cpp + src/general_allocator.cpp + src/sample_utils.cpp ++ src/plugin_utils.cpp + src/preset_manager.cpp + src/parameters_dumper.cpp ++ src/vpl_implementation_loader.cpp + src/vm/atomic.cpp + src/vm/time.cpp) + +@@ -62,7 +64,7 @@ if(POLICY CMP0074) + endif() + + find_package(VPL REQUIRED) +-target_link_libraries(${TARGET} VPL::dispatcher) ++target_link_libraries(${TARGET} VPL::dispatcher media_sdk_compatibility_headers) + + if(UNIX) + find_package(PkgConfig REQUIRED) +diff --git a/tools/legacy/sample_common/include/plugin_utils.h b/tools/legacy/sample_common/include/plugin_utils.h +index 80b7baf..8401c0c 100644 +--- a/tools/legacy/sample_common/include/plugin_utils.h ++++ b/tools/legacy/sample_common/include/plugin_utils.h +@@ -7,6 +7,7 @@ + #ifndef __PLUGIN_UTILS_H__ + #define __PLUGIN_UTILS_H__ + ++#include "mfxplugin.h" + #include "sample_defs.h" + #include "sample_types.h" + +diff --git a/tools/legacy/sample_common/include/sample_utils.h b/tools/legacy/sample_common/include/sample_utils.h +index db9b3fd..b138692 100644 +--- a/tools/legacy/sample_common/include/sample_utils.h ++++ b/tools/legacy/sample_common/include/sample_utils.h +@@ -46,6 +46,7 @@ + #include "avc_headers.h" + #include "avc_nal_spl.h" + #include "avc_spl.h" ++#include "vpl_implementation_loader.h" + + // A macro to disallow the copy constructor and operator= functions + // This should be used in the private: declarations for a class +@@ -653,7 +654,7 @@ public: + TB* GetExtBuffer(uint32_t fieldId = 0) const { + return (TB*)FindExtBuffer(mfx_ext_buffer_id::id, fieldId); + } +- ++#if 0 + template + operator TB*() { + return (TB*)FindExtBuffer(mfx_ext_buffer_id::id, 0); +@@ -663,7 +664,7 @@ public: + operator TB*() const { + return (TB*)FindExtBuffer(mfx_ext_buffer_id::id, 0); + } +- ++#endif + private: + mfxExtBuffer* AddExtBuffer(mfxU32 id, mfxU32 size, bool isPairedExtBuffer) { + if (!size || !id) +diff --git a/tools/legacy/sample_common/include/sample_utils.h.orig b/tools/legacy/sample_common/include/sample_utils.h.orig +new file mode 100644 +index 0000000..db9b3fd +--- /dev/null ++++ b/tools/legacy/sample_common/include/sample_utils.h.orig +@@ -0,0 +1,1437 @@ ++/*############################################################################ ++ # Copyright (C) Intel Corporation ++ # ++ # SPDX-License-Identifier: MIT ++ ############################################################################*/ ++ ++#ifndef __SAMPLE_UTILS_H__ ++#define __SAMPLE_UTILS_H__ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "vpl/mfxbrc.h" ++#if (MFX_VERSION < 2000) ++ #include "mfxfei.h" ++ #include "mfxfeihevc.h" ++#endif ++#include "vpl/mfxjpeg.h" ++#if (MFX_VERSION < 2000) ++ #include "mfxla.h" ++ #include "mfxmvc.h" ++ #include "mfxplugin.h" ++#endif ++#include "vpl/mfxstructures.h" ++#include "vpl/mfxvideo++.h" ++#include "vpl/mfxvideo.h" ++ ++#include "vm/atomic_defs.h" ++#include "vm/file_defs.h" ++#include "vm/strings_defs.h" ++#include "vm/thread_defs.h" ++#include "vm/time_defs.h" ++ ++#include "sample_types.h" ++ ++#include "abstract_splitter.h" ++#include "avc_bitstream.h" ++#include "avc_headers.h" ++#include "avc_nal_spl.h" ++#include "avc_spl.h" ++ ++// A macro to disallow the copy constructor and operator= functions ++// This should be used in the private: declarations for a class ++#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ ++ TypeName(const TypeName&); \ ++ void operator=(const TypeName&) ++ ++//! Base class for types that should not be assigned. ++class no_assign { ++ // Deny assignment ++ void operator=(const no_assign&); ++ ++public: ++#if __GNUC__ ++ //! Explicitly define default construction, because otherwise gcc issues gratuitous warning. ++ no_assign() {} ++#endif /* __GNUC__ */ ++}; ++ ++//! Base class for types that should not be copied or assigned. ++class no_copy : no_assign { ++ //! Deny copy construction ++ no_copy(const no_copy&); ++ ++ // Deny assignment ++ void operator=(const no_copy&); ++ ++public: ++ //! Allow default construction ++ no_copy() {} ++}; ++ ++enum { ++ CODEC_VP8 = MFX_MAKEFOURCC('V', 'P', '8', ' '), ++ CODEC_MVC = MFX_MAKEFOURCC('M', 'V', 'C', ' '), ++}; ++ ++#define MFX_CODEC_DUMP MFX_MAKEFOURCC('D', 'U', 'M', 'P') ++#define MFX_CODEC_RGB4 MFX_FOURCC_RGB4 ++#define MFX_CODEC_NV12 MFX_FOURCC_NV12 ++#define MFX_CODEC_I420 MFX_FOURCC_I420 ++#if (MFX_VERSION < 2000) ++enum { ++ MFX_FOURCC_IMC3 = MFX_MAKEFOURCC('I', 'M', 'C', '3'), ++ MFX_FOURCC_YUV400 = MFX_MAKEFOURCC('4', '0', '0', 'P'), ++ MFX_FOURCC_YUV411 = MFX_MAKEFOURCC('4', '1', '1', 'P'), ++ MFX_FOURCC_YUV422H = MFX_MAKEFOURCC('4', '2', '2', 'H'), ++ MFX_FOURCC_YUV422V = MFX_MAKEFOURCC('4', '2', '2', 'V'), ++ MFX_FOURCC_YUV444 = MFX_MAKEFOURCC('4', '4', '4', 'P'), ++ #if (MFX_VERSION <= 1027) ++ MFX_FOURCC_RGBP = MFX_MAKEFOURCC('R', 'G', 'B', 'P'), ++ #endif ++ MFX_FOURCC_I420 = MFX_MAKEFOURCC('I', '4', '2', '0') ++}; ++#endif ++enum ExtBRCType { EXTBRC_DEFAULT, EXTBRC_OFF, EXTBRC_ON, EXTBRC_IMPLICIT }; ++ ++namespace QPFile { ++ ++enum ReaderStatus { ++ READER_ERR_NONE, ++ READER_ERR_NOT_INITIALIZED, ++ READER_ERR_CODEC_UNSUPPORTED, ++ READER_ERR_FILE_NOT_OPEN, ++ READER_ERR_INCORRECT_FILE ++}; ++ ++struct FrameInfo { ++ mfxU32 displayOrder; ++ mfxU16 QP; ++ mfxU16 frameType; ++}; ++ ++// QPFile::Reader reads QP and frame type per frame in encoding order ++// from external text file (for encoding in qpfile mode) ++class Reader { ++public: ++ mfxStatus Read(const msdk_string& strFileName, mfxU32 codecid); ++ void ResetState(); ++ ++ mfxU32 GetCurrentEncodedOrder() const; ++ mfxU32 GetCurrentDisplayOrder() const; ++ mfxU16 GetCurrentQP() const; ++ mfxU16 GetCurrentFrameType() const; ++ mfxU32 GetFramesNum() const; ++ void NextFrame(); ++ std::string GetErrorMessage() const; ++ ++private: ++ void ResetState(ReaderStatus set_sts); ++ ++ ReaderStatus m_ReaderSts = READER_ERR_NOT_INITIALIZED; ++ mfxU32 m_nFrames = UINT_MAX; ++ mfxU32 m_CurFrameNum = UINT_MAX; ++ std::vector m_FrameVals{}; ++}; ++ ++inline bool get_line(std::ifstream& ifs, std::string& line) { ++ std::getline(ifs, line, '\n'); ++ if (!line.empty() && line.back() == '\r') ++ line.pop_back(); ++ return !ifs.fail(); ++} ++inline size_t find_nth(const std::string& str, size_t pos, const std::string& needle, mfxU32 nth) { ++ size_t found_pos = str.find(needle, pos); ++ for (; nth != 0 && std::string::npos != found_pos; --nth) ++ found_pos = str.find(needle, found_pos + 1); ++ return found_pos; ++} ++inline mfxU16 StringToFrameType(std::string str) { ++ if ("IDR_REF" == str) ++ return MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF; ++ else if ("I_REF" == str) ++ return MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF; ++ else if ("P_REF" == str) ++ return MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF; ++ else if ("P" == str) ++ return MFX_FRAMETYPE_P; ++ else if ("B_REF" == str) ++ return MFX_FRAMETYPE_B | MFX_FRAMETYPE_REF; ++ else if ("B" == str) ++ return MFX_FRAMETYPE_B; ++ else ++ return MFX_FRAMETYPE_UNKNOWN; ++} ++inline std::string ReaderStatusToString(ReaderStatus sts) { ++ switch (sts) { ++ case READER_ERR_NOT_INITIALIZED: ++ return std::string("reader not initialized (qpfile has not yet read the file)\n"); ++ case READER_ERR_FILE_NOT_OPEN: ++ return std::string( ++ "failed to open file contains frame parameters (check provided path in -qpfile )\n"); ++ case READER_ERR_INCORRECT_FILE: ++ return std::string("incorrect file with frame parameters\n"); ++ case READER_ERR_CODEC_UNSUPPORTED: ++ return std::string("codecs, except h264 and h265, are not supported\n"); ++ default: ++ return std::string(); ++ } ++} ++inline mfxU32 ReadDisplayOrder(const std::string& line) { ++ return std::stoi(line.substr(0, find_nth(line, 0, ",", 0))); ++} ++inline mfxU16 ReadQP(const std::string& line) { ++ size_t pos = find_nth(line, 0, ",", 0) + 1; ++ return static_cast(std::stoi(line.substr(pos, find_nth(line, 0, ",", 1) - pos))); ++} ++inline mfxU16 ReadFrameType(const std::string& line) { ++ size_t pos = find_nth(line, 0, ",", 1) + 1; ++ return StringToFrameType(line.substr(pos, line.length() - pos)); ++} ++} // namespace QPFile ++ ++mfxStatus GetFrameLength(mfxU16 width, mfxU16 height, mfxU32 ColorFormat, mfxU32& length); ++ ++bool IsDecodeCodecSupported(mfxU32 codecFormat); ++bool IsEncodeCodecSupported(mfxU32 codecFormat); ++bool IsPluginCodecSupported(mfxU32 codecFormat); ++ ++// class is used as custom exception ++class mfxError : public std::runtime_error { ++public: ++ mfxError(mfxStatus status = MFX_ERR_UNKNOWN, std::string msg = "") ++ : runtime_error(msg), ++ m_Status(status) {} ++ ++ mfxStatus GetStatus() const { ++ return m_Status; ++ } ++ ++private: ++ mfxStatus m_Status; ++}; ++ ++//declare used extension buffers ++template ++struct mfx_ext_buffer_id {}; ++ ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_CODING_OPTION }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_CODING_OPTION2 }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_CODING_OPTION3 }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_AVC_TEMPORAL_LAYERS }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_AVC_REFLIST_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_THREADS_PARAM }; ++}; ++#if (MFX_VERSION < 2000) ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_PARAM }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_PREENC_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_PREENC_MV }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_PREENC_MB }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVCFEI_ENC_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVCFEI_ENC_QP }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVCFEI_ENC_CTU_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVC_REFLISTS }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVCFEI_REPACK_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVCFEI_REPACK_STAT }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_BRC }; ++}; ++#endif ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVC_PARAM }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_DEC_VIDEO_PROCESSING }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_DECODE_ERROR_REPORT }; ++}; ++#if (MFX_VERSION < 2000) ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_MVC_SEQ_DESC }; ++}; ++#endif ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_DONOTUSE }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_DOUSE }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_DEINTERLACING }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_CODING_OPTION_SPSPPS }; ++}; ++#if (MFX_VERSION < 2000) ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION }; ++}; ++#endif ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_MCTF }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_COMPOSITE }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_FIELD_PROCESSING }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_DETAIL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_FRAME_RATE_CONVERSION }; ++}; ++#if (MFX_VERSION < 2000) ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_LOOKAHEAD_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_MULTI_FRAME_CONTROL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_MULTI_FRAME_PARAM }; ++}; ++#endif ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVC_TILES }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VP9_PARAM }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VIDEO_SIGNAL_INFO }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_HEVC_REGION }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_AVC_ROUNDING_OFFSET }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_DENOISE }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_PROCAMP }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_IMAGE_STABILIZATION }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_VIDEO_SIGNAL_INFO }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_MIRRORING }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_COLORFILL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_ROTATION }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_SCALING }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_VPP_COLOR_CONVERSION }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_PRED_WEIGHT_TABLE }; ++}; ++#if (MFX_VERSION < 2000) ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_DEC_STREAM_OUT }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_SLICE }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_ENC_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_ENC_MV_PRED }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_REPACK_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_ENC_MB }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_ENC_QP }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_ENC_MB_STAT }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_ENC_MV }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_PAK_CTRL }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_REPACK_STAT }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_SPS }; ++}; ++template <> ++struct mfx_ext_buffer_id { ++ enum { id = MFX_EXTBUFF_FEI_PPS }; ++}; ++#endif ++constexpr uint16_t max_num_ext_buffers = ++ 63 * 2; // '*2' is for max estimation if all extBuffer were 'paired' ++ ++//helper function to initialize mfx ext buffer structure ++template ++void init_ext_buffer(T& ext_buffer) { ++ memset(&ext_buffer, 0, sizeof(ext_buffer)); ++ reinterpret_cast(&ext_buffer)->BufferId = mfx_ext_buffer_id::id; ++ reinterpret_cast(&ext_buffer)->BufferSz = sizeof(ext_buffer); ++} ++ ++template ++struct IsPairedMfxExtBuffer : std::false_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++#if (MFX_VERSION < 2000) ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++template <> ++struct IsPairedMfxExtBuffer : std::true_type {}; ++#endif ++ ++template ++struct ExtParamAccessor { ++private: ++ using mfxExtBufferDoublePtr = mfxExtBuffer**; ++ ++public: ++ mfxU16& NumExtParam; ++ mfxExtBufferDoublePtr& ExtParam; ++ ExtParamAccessor(const R& r) ++ : NumExtParam(const_cast(r.NumExtParam)), ++ ExtParam(const_cast(r.ExtParam)) {} ++}; ++ ++template <> ++struct ExtParamAccessor { ++private: ++ using mfxExtBufferDoublePtr = mfxExtBuffer**; ++ ++public: ++ mfxU16& NumExtParam; ++ mfxExtBufferDoublePtr& ExtParam; ++ ExtParamAccessor(const mfxFrameSurface1& r) ++ : NumExtParam(const_cast(r.Data.NumExtParam)), ++ ExtParam(const_cast(r.Data.ExtParam)) {} ++}; ++ ++/** ExtBufHolder is an utility class which ++ * provide interface for mfxExtBuffer objects management in any mfx structure (e.g. mfxVideoParam) ++ */ ++template ++class ExtBufHolder : public T { ++public: ++ ExtBufHolder() : T(), m_ext_buf() { ++ m_ext_buf.reserve(max_num_ext_buffers); ++ } ++ ++ ~ExtBufHolder() // only buffers allocated by wrapper can be released ++ { ++ for (auto it = m_ext_buf.begin(); it != m_ext_buf.end(); it++) { ++ delete[](mfxU8*)(*it); ++ } ++ } ++ ++ ExtBufHolder(const ExtBufHolder& ref) { ++ m_ext_buf.reserve(max_num_ext_buffers); ++ *this = ref; // call to operator= ++ } ++ ++ ExtBufHolder& operator=(const ExtBufHolder& ref) { ++ const T* src_base = &ref; ++ return operator =(*src_base); ++ } ++ ++ ExtBufHolder(const T& ref) { ++ *this = ref; // call to operator= ++ } ++ ++ ExtBufHolder& operator=(const T& ref) { ++ // copy content of main structure type T ++ T* dst_base = this; ++ const T* src_base = &ref; ++ *dst_base = *src_base; ++ ++ //remove all existing extension buffers ++ ClearBuffers(); ++ ++ const auto ref_ = ExtParamAccessor(ref); ++ ++ //reproduce list of extension buffers and copy its content ++ for (size_t i = 0; i < ref_.NumExtParam; ++i) { ++ const auto src_buf = ref_.ExtParam[i]; ++ if (!src_buf) ++ throw mfxError(MFX_ERR_NULL_PTR, "Null pointer attached to source ExtParam"); ++ if (!IsCopyAllowed(src_buf->BufferId)) { ++ auto msg = ++ "Deep copy of '" + Fourcc2Str(src_buf->BufferId) + "' extBuffer is not allowed"; ++ throw mfxError(MFX_ERR_UNDEFINED_BEHAVIOR, msg); ++ } ++ ++ // 'false' below is because here we just copy extBuffer's one by one ++ auto dst_buf = AddExtBuffer(src_buf->BufferId, src_buf->BufferSz, false); ++ // copy buffer content w/o restoring its type ++ MSDK_MEMCPY((void*)dst_buf, (void*)src_buf, src_buf->BufferSz); ++ } ++ ++ return *this; ++ } ++ ++ ExtBufHolder(ExtBufHolder&&) = default; ++ ExtBufHolder& operator=(ExtBufHolder&&) = default; ++ ++ // Always returns a valid pointer or throws an exception ++ template ++ TB* AddExtBuffer() { ++ mfxExtBuffer* b = ++ AddExtBuffer(mfx_ext_buffer_id::id, sizeof(TB), IsPairedMfxExtBuffer::value); ++ return (TB*)b; ++ } ++ ++ template ++ void RemoveExtBuffer() { ++ auto it = std::find_if(m_ext_buf.begin(), ++ m_ext_buf.end(), ++ CmpExtBufById(mfx_ext_buffer_id::id)); ++ if (it != m_ext_buf.end()) { ++ delete[](mfxU8*)(*it); ++ it = m_ext_buf.erase(it); ++ ++ if (IsPairedMfxExtBuffer::value) { ++ if (it == m_ext_buf.end() || (*it)->BufferId != mfx_ext_buffer_id::id) ++ throw mfxError(MFX_ERR_NULL_PTR, ++ "RemoveExtBuffer: ExtBuffer's parity has been broken"); ++ ++ delete[](mfxU8*)(*it); ++ m_ext_buf.erase(it); ++ } ++ ++ RefreshBuffers(); ++ } ++ } ++ ++ template ++ TB* GetExtBuffer(uint32_t fieldId = 0) const { ++ return (TB*)FindExtBuffer(mfx_ext_buffer_id::id, fieldId); ++ } ++ ++ template ++ operator TB*() { ++ return (TB*)FindExtBuffer(mfx_ext_buffer_id::id, 0); ++ } ++ ++ template ++ operator TB*() const { ++ return (TB*)FindExtBuffer(mfx_ext_buffer_id::id, 0); ++ } ++ ++private: ++ mfxExtBuffer* AddExtBuffer(mfxU32 id, mfxU32 size, bool isPairedExtBuffer) { ++ if (!size || !id) ++ throw mfxError(MFX_ERR_NULL_PTR, "AddExtBuffer: wrong size or id!"); ++ ++ auto it = std::find_if(m_ext_buf.begin(), m_ext_buf.end(), CmpExtBufById(id)); ++ if (it == m_ext_buf.end()) { ++ auto buf = (mfxExtBuffer*)new mfxU8[size]; ++ memset(buf, 0, size); ++ m_ext_buf.push_back(buf); ++ ++ buf->BufferId = id; ++ buf->BufferSz = size; ++ ++ if (isPairedExtBuffer) { ++ // Allocate the other mfxExtBuffer _right_after_ the first one ... ++ buf = (mfxExtBuffer*)new mfxU8[size]; ++ memset(buf, 0, size); ++ m_ext_buf.push_back(buf); ++ ++ buf->BufferId = id; ++ buf->BufferSz = size; ++ ++ RefreshBuffers(); ++ return m_ext_buf[m_ext_buf.size() - 2]; // ... and return a pointer to the first one ++ } ++ ++ RefreshBuffers(); ++ return m_ext_buf.back(); ++ } ++ ++ return *it; ++ } ++ ++ mfxExtBuffer* FindExtBuffer(mfxU32 id, uint32_t fieldId) const { ++ auto it = std::find_if(m_ext_buf.begin(), m_ext_buf.end(), CmpExtBufById(id)); ++ if (fieldId && it != m_ext_buf.end()) { ++ ++it; ++ return it != m_ext_buf.end() ? *it : nullptr; ++ } ++ return it != m_ext_buf.end() ? *it : nullptr; ++ } ++ ++ void RefreshBuffers() { ++ auto this_ = ExtParamAccessor(*this); ++ this_.NumExtParam = static_cast(m_ext_buf.size()); ++ this_.ExtParam = this_.NumExtParam ? m_ext_buf.data() : nullptr; ++ } ++ ++ void ClearBuffers() { ++ if (m_ext_buf.size()) { ++ for (auto it = m_ext_buf.begin(); it != m_ext_buf.end(); it++) { ++ delete[](mfxU8*)(*it); ++ } ++ m_ext_buf.clear(); ++ } ++ RefreshBuffers(); ++ } ++ ++ bool IsCopyAllowed(mfxU32 id) { ++ static const mfxU32 allowed[] = { ++ MFX_EXTBUFF_CODING_OPTION, ++ MFX_EXTBUFF_CODING_OPTION2, ++ MFX_EXTBUFF_CODING_OPTION3, ++#if (MFX_VERSION < 2000) ++ MFX_EXTBUFF_FEI_PARAM, ++ MFX_EXTBUFF_BRC, ++#endif ++ MFX_EXTBUFF_HEVC_PARAM, ++ MFX_EXTBUFF_VP9_PARAM, ++#if (MFX_VERSION < 2000) ++ MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION, ++ MFX_EXTBUFF_FEI_PPS, ++ MFX_EXTBUFF_FEI_SPS, ++ MFX_EXTBUFF_LOOKAHEAD_CTRL, ++ MFX_EXTBUFF_LOOKAHEAD_STAT ++#endif ++ }; ++ ++ auto it = ++ std::find_if(std::begin(allowed), std::end(allowed), [&id](const mfxU32 allowed_id) { ++ return allowed_id == id; ++ }); ++ return it != std::end(allowed); ++ } ++ ++ struct CmpExtBufById { ++ mfxU32 id; ++ ++ CmpExtBufById(mfxU32 _id) : id(_id){}; ++ ++ bool operator()(mfxExtBuffer* b) { ++ return (b && b->BufferId == id); ++ }; ++ }; ++ ++ static std::string Fourcc2Str(mfxU32 fourcc) { ++ std::string s; ++ for (size_t i = 0; i < 4; i++) { ++ s.push_back(*(i + (char*)&fourcc)); ++ } ++ return s; ++ } ++ ++ std::vector m_ext_buf; ++}; ++ ++using MfxVideoParamsWrapper = ExtBufHolder; ++using mfxEncodeCtrlWrap = ExtBufHolder; ++using mfxInitParamlWrap = ExtBufHolder; ++using mfxFrameSurfaceWrap = ExtBufHolder; ++ ++class mfxBitstreamWrapper : public ExtBufHolder { ++ typedef ExtBufHolder base; ++ ++public: ++ mfxBitstreamWrapper() : base(), m_data() {} ++ ++ mfxBitstreamWrapper(mfxU32 n_bytes) : base() { ++ Extend(n_bytes); ++ } ++ ++ mfxBitstreamWrapper(const mfxBitstreamWrapper& bs_wrapper) ++ : base(bs_wrapper), ++ m_data(bs_wrapper.m_data) { ++ Data = m_data.data(); ++ } ++ ++ mfxBitstreamWrapper& operator=(mfxBitstreamWrapper const& bs_wrapper) { ++ mfxBitstreamWrapper tmp(bs_wrapper); ++ ++ *this = std::move(tmp); ++ ++ return *this; ++ } ++ ++ mfxBitstreamWrapper(mfxBitstreamWrapper&& bs_wrapper) = default; ++ mfxBitstreamWrapper& operator=(mfxBitstreamWrapper&& bs_wrapper) = default; ++ ~mfxBitstreamWrapper() = default; ++ ++ void Extend(mfxU32 n_bytes) { ++ if (MaxLength >= n_bytes) ++ return; ++ ++ m_data.resize(n_bytes); ++ ++ Data = m_data.data(); ++ MaxLength = n_bytes; ++ } ++ ++private: ++ std::vector m_data; ++}; ++ ++class CSmplYUVReader { ++public: ++ typedef std::list::iterator ls_iterator; ++ CSmplYUVReader(); ++ virtual ~CSmplYUVReader(); ++ ++ virtual void Close(); ++ virtual mfxStatus Init(std::list inputs, ++ mfxU32 ColorFormat, ++ bool shouldShiftP010 = false); ++ virtual mfxStatus SkipNframesFromBeginning(mfxU16 w, mfxU16 h, mfxU32 viewId, mfxU32 nframes); ++ virtual mfxStatus LoadNextFrame(mfxFrameSurface1* pSurface); ++ virtual void Reset(); ++ mfxU32 m_ColorFormat; // color format of input YUV data, YUV420 or NV12 ++ ++protected: ++ std::vector m_files; ++ ++ bool shouldShift10BitsHigh; ++ bool m_bInited; ++}; ++ ++class CSmplBitstreamWriter { ++public: ++ CSmplBitstreamWriter(); ++ virtual ~CSmplBitstreamWriter(); ++ ++ virtual mfxStatus Init(const msdk_char* strFileName); ++ virtual mfxStatus WriteNextFrame(mfxBitstream* pMfxBitstream, bool isPrint = true); ++ virtual mfxStatus Reset(); ++ virtual void Close(); ++ mfxU32 m_nProcessedFramesNum; ++ ++protected: ++ FILE* m_fSink; ++ bool m_bInited; ++ msdk_string m_sFile; ++}; ++ ++class CSmplYUVWriter { ++public: ++ CSmplYUVWriter(); ++ virtual ~CSmplYUVWriter(); ++ ++ virtual void Close(); ++ virtual mfxStatus Init(const msdk_char* strFileName, const mfxU32 numViews); ++ virtual mfxStatus Reset(); ++ virtual mfxStatus WriteNextFrame(mfxFrameSurface1* pSurface); ++ virtual mfxStatus WriteNextFrameI420(mfxFrameSurface1* pSurface); ++ ++ void SetMultiView() { ++ m_bIsMultiView = true; ++ } ++ ++protected: ++ FILE *m_fDest, **m_fDestMVC; ++ bool m_bInited, m_bIsMultiView; ++ mfxU32 m_numCreatedFiles; ++ msdk_string m_sFile; ++ mfxU32 m_nViews; ++}; ++ ++class CSmplBitstreamReader { ++public: ++ CSmplBitstreamReader(); ++ virtual ~CSmplBitstreamReader(); ++ ++ //resets position to file begin ++ virtual void Reset(); ++ virtual void Close(); ++ virtual mfxStatus Init(const msdk_char* strFileName); ++ virtual mfxStatus ReadNextFrame(mfxBitstream* pBS); ++ ++protected: ++ FILE* m_fSource; ++ bool m_bInited; ++}; ++ ++class CH264FrameReader : public CSmplBitstreamReader { ++public: ++ CH264FrameReader(); ++ virtual ~CH264FrameReader(); ++ ++ /** Free resources.*/ ++ virtual void Close(); ++ virtual mfxStatus Init(const msdk_char* strFileName); ++ virtual mfxStatus ReadNextFrame(mfxBitstream* pBS); ++ ++private: ++ mfxBitstream* m_processedBS; ++ // input bit stream ++ mfxBitstreamWrapper m_originalBS; ++ ++ mfxStatus PrepareNextFrame(mfxBitstream* in, mfxBitstream** out); ++ ++ // is stream ended ++ bool m_isEndOfStream; ++ ++ std::unique_ptr m_pNALSplitter; ++ FrameSplitterInfo* m_frame; ++ mfxU8* m_plainBuffer; ++ mfxU32 m_plainBufferSize; ++ mfxBitstream m_outBS; ++}; ++ ++//provides output bistream with at least 1 frame, reports about error ++class CJPEGFrameReader : public CSmplBitstreamReader { ++ enum JPEGMarker { SOI = 0xD8FF, EOI = 0xD9FF }; ++ ++public: ++ virtual mfxStatus ReadNextFrame(mfxBitstream* pBS); ++ ++protected: ++ mfxU32 FindMarker(mfxBitstream* pBS, mfxU32 startOffset, JPEGMarker marker); ++}; ++ ++//appends output bistream with exactly 1 frame, reports about error ++class CIVFFrameReader : public CSmplBitstreamReader { ++public: ++ CIVFFrameReader(); ++ virtual void Reset(); ++ virtual mfxStatus Init(const msdk_char* strFileName); ++ virtual mfxStatus ReadNextFrame(mfxBitstream* pBS); ++ ++protected: ++ /*bytes 0-3 signature: 'DKIF' ++ bytes 4-5 version (should be 0) ++ bytes 6-7 length of header in bytes ++ bytes 8-11 codec FourCC (e.g., 'VP80') ++ bytes 12-13 width in pixels ++ bytes 14-15 height in pixels ++ bytes 16-19 frame rate ++ bytes 20-23 time scale ++ bytes 24-27 number of frames in file ++ bytes 28-31 unused*/ ++ ++ struct DKIFHrd { ++ mfxU32 dkif; ++ mfxU16 version; ++ mfxU16 header_len; ++ mfxU32 codec_FourCC; ++ mfxU16 width; ++ mfxU16 height; ++ mfxU32 frame_rate; ++ mfxU32 time_scale; ++ mfxU32 num_frames; ++ mfxU32 unused; ++ } m_hdr; ++ mfxStatus ReadHeader(); ++}; ++ ++// writes bitstream to duplicate-file & supports joining ++// (for ViewOutput encoder mode) ++class CSmplBitstreamDuplicateWriter : public CSmplBitstreamWriter { ++public: ++ CSmplBitstreamDuplicateWriter(); ++ ++ virtual mfxStatus InitDuplicate(const msdk_char* strFileName); ++ virtual mfxStatus JoinDuplicate(CSmplBitstreamDuplicateWriter* pJoinee); ++ virtual mfxStatus WriteNextFrame(mfxBitstream* pMfxBitstream, bool isPrint = true); ++ virtual void Close(); ++ ++protected: ++ FILE* m_fSinkDuplicate; ++ bool m_bJoined; ++}; ++ ++#if (MFX_VERSION >= 2000) ++class CIVFFrameWriter : public CSmplBitstreamWriter { ++public: ++ CIVFFrameWriter(); ++ ++ virtual mfxStatus Reset(); ++ virtual mfxStatus Init(const msdk_char* strFileName, ++ const mfxU16 w, ++ const mfxU16 h, ++ const mfxU32 fr_nom, ++ const mfxU32 fr_denom); ++ virtual mfxStatus WriteNextFrame(mfxBitstream* pMfxBitstream, bool isPrint = true); ++ virtual void Close(); ++ ++protected: ++ /* 32 bytes for stream header ++ bytes 0-3 signature: 'DKIF' ++ bytes 4-5 version (should be 0) ++ bytes 6-7 length of header in bytes ++ bytes 8-11 codec FourCC (e.g., 'VP80') ++ bytes 12-13 width in pixels ++ bytes 14-15 height in pixels ++ bytes 16-19 frame rate ++ bytes 20-23 time scale ++ bytes 24-27 number of frames in file ++ bytes 28-31 unused ++ */ ++ struct streamHeader { ++ mfxU32 dkif; ++ mfxU16 version; ++ mfxU16 header_len; ++ mfxU32 codec_FourCC; ++ mfxU16 width; ++ mfxU16 height; ++ mfxU32 frame_rate; ++ mfxU32 time_scale; ++ mfxU32 num_frames; ++ mfxU32 unused; ++ } m_streamHeader; ++ ++ /* 12 bytes for frame header ++ bytes 0-3 frame size ++ bytes 4-11 pts ++ */ ++ struct frameHeader { ++ mfxU32 frame_size; ++ mfxU32 pts_high; ++ mfxU32 pts_low; ++ } m_frameHeader; ++ ++ mfxU64 m_frameNum; ++ mfxStatus WriteStreamHeader(); ++ mfxStatus WriteFrameHeader(); ++ void UpdateNumberOfFrames(); ++}; ++#endif ++ ++//timeinterval calculation helper ++ ++template ++class CTimeInterval : private no_copy { ++ static double g_Freq; ++ double& m_start; ++ double m_own; //reference to this if external counter not required ++ //since QPC functions are quite slow it makes sense to optionally enable them ++ bool m_bEnable; ++ msdk_tick m_StartTick; ++ ++public: ++ CTimeInterval(double& dRef, bool bEnable = true) ++ : m_start(dRef), ++ m_bEnable(bEnable), ++ m_StartTick(0) { ++ if (!m_bEnable) ++ return; ++ Initialize(); ++ } ++ CTimeInterval(bool bEnable = true) ++ : m_start(m_own), ++ m_own(), ++ m_bEnable(bEnable), ++ m_StartTick(0) { ++ if (!m_bEnable) ++ return; ++ Initialize(); ++ } ++ ++ //updates external value with current time ++ double Commit() { ++ if (!m_bEnable) ++ return 0.0; ++ ++ if (0.0 != g_Freq) { ++ m_start = MSDK_GET_TIME(msdk_time_get_tick(), m_StartTick, g_Freq); ++ } ++ return m_start; ++ } ++ //last comitted value ++ double Last() { ++ return m_start; ++ } ++ ~CTimeInterval() { ++ Commit(); ++ } ++ ++private: ++ void Initialize() { ++ if (0.0 == g_Freq) { ++ g_Freq = (double)msdk_time_get_frequency(); ++ } ++ m_StartTick = msdk_time_get_tick(); ++ } ++}; ++ ++template ++double CTimeInterval::g_Freq = 0.0f; ++ ++/** Helper class to measure execution time of some code. Use this class ++ * if you need manual measurements. ++ * ++ * Usage example: ++ * { ++ * CTimer timer; ++ * msdk_tick summary_tick; ++ * ++ * timer.Start() ++ * function_to_measure(); ++ * summary_tick = timer.GetDelta(); ++ * printf("Elapsed time 1: %f\n", timer.GetTime()); ++ * ... ++ * if (condition) timer.Start(); ++ function_to_measure(); ++ * if (condition) { ++ * summary_tick += timer.GetDelta(); ++ * printf("Elapsed time 2: %f\n", timer.GetTime(); ++ * } ++ * printf("Overall time: %f\n", CTimer::ConvertToSeconds(summary_tick); ++ * } ++ */ ++class CTimer { ++public: ++ CTimer() : start(0) {} ++ static msdk_tick GetFrequency() { ++ if (!frequency) ++ frequency = msdk_time_get_frequency(); ++ return frequency; ++ } ++ static mfxF64 ConvertToSeconds(msdk_tick elapsed) { ++ return MSDK_GET_TIME(elapsed, 0, GetFrequency()); ++ } ++ ++ inline void Start() { ++ start = msdk_time_get_tick(); ++ } ++ inline msdk_tick GetDelta() { ++ return msdk_time_get_tick() - start; ++ } ++ inline mfxF64 GetTime() { ++ return MSDK_GET_TIME(msdk_time_get_tick(), start, GetFrequency()); ++ } ++ ++protected: ++ static msdk_tick frequency; ++ msdk_tick start; ++ ++private: ++ CTimer(const CTimer&); ++ void operator=(const CTimer&); ++}; ++ ++/** Helper class to measure overall execution time of some code. Use this ++ * class if you want to measure execution time of the repeatedly executed ++ * code. ++ * ++ * Usage example 1: ++ * ++ * msdk_tick summary_tick = 0; ++ * ++ * void function() { ++ * ++ * { ++ * CAutoTimer timer(&summary_tick); ++ * ... ++ * } ++ * ... ++ * int main() { ++ * for (;condition;) { ++ * function(); ++ * } ++ * printf("Elapsed time: %f\n", CTimer::ConvertToSeconds(summary_tick); ++ * return 0; ++ * } ++ * ++ * Usage example 2: ++ * { ++ * msdk_tick summary_tick = 0; ++ * ++ * { ++ * CAutoTimer timer(&summary_tick); ++ * ++ * for (;condition;) { ++ * ... ++ * { ++ * function_to_measure(); ++ * timer.Sync(); ++ * printf("Progress: %f\n", CTimer::ConvertToSeconds(summary_tick); ++ * } ++ * ... ++ * } ++ * } ++ * printf("Elapsed time: %f\n", CTimer::ConvertToSeconds(summary_tick); ++ * } ++ * ++ */ ++class CAutoTimer { ++public: ++ CAutoTimer(msdk_tick& _elapsed) : elapsed(_elapsed), start(0) { ++ elapsed = _elapsed; ++ start = msdk_time_get_tick(); ++ } ++ ~CAutoTimer() { ++ elapsed += msdk_time_get_tick() - start; ++ } ++ msdk_tick Sync() { ++ msdk_tick cur = msdk_time_get_tick(); ++ elapsed += cur - start; ++ start = cur; ++ return elapsed; ++ } ++ ++protected: ++ msdk_tick& elapsed; ++ msdk_tick start; ++ ++private: ++ CAutoTimer(const CAutoTimer&); ++ void operator=(const CAutoTimer&); ++}; ++ ++mfxStatus ConvertFrameRate(mfxF64 dFrameRate, mfxU32* pnFrameRateExtN, mfxU32* pnFrameRateExtD); ++mfxF64 CalculateFrameRate(mfxU32 nFrameRateExtN, mfxU32 nFrameRateExtD); ++ ++template ++mfxU16 GetFreeSurfaceIndex(T* pSurfacesPool, mfxU16 nPoolSize) { ++ constexpr mfxU16 MSDK_INVALID_SURF_IDX = 0xffff; ++ ++ if (pSurfacesPool) { ++ for (mfxU16 i = 0; i < nPoolSize; i++) { ++ if (0 == pSurfacesPool[i].Data.Locked) { ++ return i; ++ } ++ } ++ } ++ return MSDK_INVALID_SURF_IDX; ++} ++ ++mfxU16 GetFreeSurface(mfxFrameSurface1* pSurfacesPool, mfxU16 nPoolSize); ++void FreeSurfacePool(mfxFrameSurface1* pSurfacesPool, mfxU16 nPoolSize); ++ ++mfxU16 CalculateDefaultBitrate(mfxU32 nCodecId, ++ mfxU32 nTargetUsage, ++ mfxU32 nWidth, ++ mfxU32 nHeight, ++ mfxF64 dFrameRate); ++ ++//serialization fnc set ++std::basic_string CodecIdToStr(mfxU32 nFourCC); ++mfxU16 StrToTargetUsage(msdk_string strInput); ++const msdk_char* TargetUsageToStr(mfxU16 tu); ++const msdk_char* ColorFormatToStr(mfxU32 format); ++const msdk_char* MfxStatusToStr(mfxStatus sts); ++ ++// sets bitstream->PicStruct parsing first APP0 marker in bitstream ++mfxStatus MJPEG_AVI_ParsePicStruct(mfxBitstream* bitstream); ++ ++// For MVC encoding/decoding purposes ++std::basic_string FormMVCFileName(const msdk_char* strFileName, const mfxU32 numView); ++ ++//piecewise linear function for bitrate approximation ++class PartiallyLinearFNC { ++ mfxF64* m_pX; ++ mfxF64* m_pY; ++ mfxU32 m_nPoints; ++ mfxU32 m_nAllocated; ++ ++public: ++ PartiallyLinearFNC(); ++ ~PartiallyLinearFNC(); ++ ++ void AddPair(mfxF64 x, mfxF64 y); ++ mfxF64 at(mfxF64); ++ ++private: ++ DISALLOW_COPY_AND_ASSIGN(PartiallyLinearFNC); ++}; ++ ++// function for getting a pointer to a specific external buffer from the array ++mfxExtBuffer* GetExtBuffer(mfxExtBuffer** ebuffers, mfxU32 nbuffers, mfxU32 BufferId); ++ ++// returns false if buf length is insufficient, otherwise ++// skips step bytes in buf with specified length and returns true ++template ++bool skip(const Buf_t*& buf, Length_t& length, Length_t step) { ++ if (length < step) ++ return false; ++ ++ buf += step; ++ length -= step; ++ ++ return true; ++} ++ ++//do not link MediaSDK dispatched if class not used ++struct MSDKAdapter { ++ // returns the number of adapter associated with MSDK session, 0 for SW session ++ static mfxU32 GetNumber(mfxSession session, mfxIMPL implVia = 0) { ++ mfxU32 adapterNum = 0; // default ++ mfxIMPL impl = MFX_IMPL_SOFTWARE; // default in case no HW IMPL is found ++ ++ // we don't care for error codes in further code; if something goes wrong we fall back to the default adapter ++ if (session) { ++ MFXQueryIMPL(session, &impl); ++ } ++ else { ++ // an auxiliary session, internal for this function ++ mfxSession auxSession; ++ memset(&auxSession, 0, sizeof(auxSession)); ++ ++ mfxVersion ver = { { 1, 1 } }; // minimum API version which supports multiple devices ++ MFXInit(MFX_IMPL_HARDWARE_ANY | implVia, &ver, &auxSession); ++ MFXQueryIMPL(auxSession, &impl); ++ MFXClose(auxSession); ++ } ++ ++ // extract the base implementation type ++ mfxIMPL baseImpl = MFX_IMPL_BASETYPE(impl); ++ ++ const struct { ++ // actual implementation ++ mfxIMPL impl; ++ // adapter's number ++ mfxU32 adapterID; ++ ++ } implTypes[] = { { MFX_IMPL_HARDWARE, 0 }, ++ { MFX_IMPL_SOFTWARE, 0 }, ++ { MFX_IMPL_HARDWARE2, 1 }, ++ { MFX_IMPL_HARDWARE3, 2 }, ++ { MFX_IMPL_HARDWARE4, 3 } }; ++ ++ // get corresponding adapter number ++ for (mfxU8 i = 0; i < sizeof(implTypes) / sizeof(*implTypes); i++) { ++ if (implTypes[i].impl == baseImpl) { ++ adapterNum = implTypes[i].adapterID; ++ break; ++ } ++ } ++ ++ return adapterNum; ++ } ++}; ++ ++struct APIChangeFeatures { ++ bool JpegDecode; ++ bool JpegEncode; ++ bool MVCDecode; ++ bool MVCEncode; ++ bool IntraRefresh; ++ bool LowLatency; ++ bool ViewOutput; ++ bool LookAheadBRC; ++ bool AudioDecode; ++ bool SupportCodecPluginAPI; ++}; ++ ++mfxVersion getMinimalRequiredVersion(const APIChangeFeatures& features); ++ ++enum msdkAPIFeature { ++ MSDK_FEATURE_NONE, ++ MSDK_FEATURE_MVC, ++ MSDK_FEATURE_JPEG_DECODE, ++ MSDK_FEATURE_LOW_LATENCY, ++ MSDK_FEATURE_MVC_VIEWOUTPUT, ++ MSDK_FEATURE_JPEG_ENCODE, ++ MSDK_FEATURE_LOOK_AHEAD, ++ MSDK_FEATURE_PLUGIN_API ++}; ++ ++/* Returns true if feature is supported in the given API version */ ++bool CheckVersion(mfxVersion* version, msdkAPIFeature feature); ++ ++void ConfigureAspectRatioConversion(mfxInfoVPP* pVppInfo); ++ ++void SEICalcSizeType(std::vector& data, mfxU16 type, mfxU32 size); ++ ++mfxU8 Char2Hex(msdk_char ch); ++ ++enum MsdkTraceLevel { ++ MSDK_TRACE_LEVEL_SILENT = -1, ++ MSDK_TRACE_LEVEL_CRITICAL = 0, ++ MSDK_TRACE_LEVEL_ERROR = 1, ++ MSDK_TRACE_LEVEL_WARNING = 2, ++ MSDK_TRACE_LEVEL_INFO = 3, ++ MSDK_TRACE_LEVEL_DEBUG = 4, ++}; ++ ++msdk_string NoFullPath(const msdk_string&); ++int msdk_trace_get_level(); ++void msdk_trace_set_level(int); ++bool msdk_trace_is_printable(int); ++ ++msdk_ostream& operator<<(msdk_ostream& os, MsdkTraceLevel tt); ++ ++template ++mfxStatus msdk_opt_read(const msdk_char* string, T& value); ++ ++template ++mfxStatus msdk_opt_read(const msdk_char* string, msdk_char (&value)[S]) { ++ if (!S) { ++ return MFX_ERR_UNKNOWN; ++ } ++ value[0] = 0; ++#if defined(_WIN32) || defined(_WIN64) ++ value[S - 1] = 0; ++ return (0 == _tcsncpy_s(value, string, S - 1)) ? MFX_ERR_NONE : MFX_ERR_UNKNOWN; ++#else ++ if (strlen(string) < S) { ++ strncpy(value, string, S - 1); ++ value[S - 1] = 0; ++ return MFX_ERR_NONE; ++ } ++ return MFX_ERR_UNKNOWN; ++#endif ++} ++ ++template ++inline mfxStatus msdk_opt_read(const msdk_string& string, T& value) { ++ return msdk_opt_read(string.c_str(), value); ++} ++ ++mfxStatus StrFormatToCodecFormatFourCC(msdk_char* strInput, mfxU32& codecFormat); ++msdk_string StatusToString(mfxStatus sts); ++mfxI32 getMonitorType(msdk_char* str); ++ ++void WaitForDeviceToBecomeFree(MFXVideoSession& session, ++ mfxSyncPoint& syncPoint, ++ mfxStatus& currentStatus); ++ ++mfxU16 FourCCToChroma(mfxU32 fourCC); ++ ++#endif //__SAMPLE_UTILS_H__ +diff --git a/tools/legacy/sample_common/include/vpl_implementation_loader.h b/tools/legacy/sample_common/include/vpl_implementation_loader.h +new file mode 100644 +index 0000000..d5f8fe5 +--- /dev/null ++++ b/tools/legacy/sample_common/include/vpl_implementation_loader.h +@@ -0,0 +1,73 @@ ++/******************************************************************************\ ++Copyright (c) 2021, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from ++https://software.intel.com/en-us/intel-media-server-studio or ++https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#ifndef __VPL_IMPLEMENTATION_LOADER_H__ ++#define __VPL_IMPLEMENTATION_LOADER_H__ ++ ++#include ++#include "vpl/mfxdispatcher.h" ++#include "vpl/mfxvideo++.h" ++ ++class VPLImplementationLoader { ++ mfxLoader m_Loader; ++ std::vector m_Configs; ++ mfxImplDescription *m_idesc; ++ mfxU32 m_ImplIndex; ++ ++public: ++ VPLImplementationLoader(); ++ ~VPLImplementationLoader(); ++ ++ mfxStatus CreateConfig(mfxU16 data, const char *propertyName); ++ mfxStatus CreateConfig(mfxU32 data, const char *propertyName); ++ mfxStatus ConfigureImplementation(mfxIMPL impl); ++ mfxStatus ConfigureAccelerationMode(mfxAccelerationMode accelerationMode, mfxIMPL impl); ++ mfxStatus ConfigureVersion(mfxVersion const &version); ++ mfxStatus EnumImplementations(); ++ mfxStatus EnumImplementations(mfxU16 deviceID, mfxU32 adapterNum); ++ mfxStatus ConfigureAndEnumImplementations(mfxIMPL impl, ++ mfxAccelerationMode accelerationMode, ++ mfxVersion const &version); ++ mfxLoader GetLoader(); ++ mfxU32 GetImplIndex() const; ++ mfxStatus GetVersion(mfxVersion *version); ++}; ++ ++class MainVideoSession : public MFXVideoSession { ++public: ++ mfxStatus CreateSession(VPLImplementationLoader *Loader); ++}; ++ ++#endif //__VPL_IMPLEMENTATION_LOADER_H__ +diff --git a/tools/legacy/sample_common/src/plugin_utils.cpp b/tools/legacy/sample_common/src/plugin_utils.cpp +index 1db329e..03e3e73 100644 +--- a/tools/legacy/sample_common/src/plugin_utils.cpp ++++ b/tools/legacy/sample_common/src/plugin_utils.cpp +@@ -8,7 +8,6 @@ + + #include + #include +-#include "mfxvp8.h" + #include "plugin_utils.h" + + bool AreGuidsEqual(const mfxPluginUID& guid1, const mfxPluginUID& guid2) { +@@ -31,9 +30,6 @@ mfxStatus ConvertStringToGuid(const msdk_string& strGuid, mfxPluginUID& mfxGuid) + uid[MSDK_STRING("hevce_gacc")] = MFX_PLUGINID_HEVCE_GACC; + uid[MSDK_STRING("hevce_hw")] = MFX_PLUGINID_HEVCE_HW; + +- uid[MSDK_STRING("vp8d_hw")] = MFX_PLUGINID_VP8D_HW; +- uid[MSDK_STRING("vp8e_hw")] = MFX_PLUGINID_VP8E_HW; +- + uid[MSDK_STRING("vp9d_hw")] = MFX_PLUGINID_VP9D_HW; + uid[MSDK_STRING("vp9e_hw")] = MFX_PLUGINID_VP9E_HW; + +@@ -96,10 +92,6 @@ const mfxPluginUID& msdkGetPluginUID(mfxIMPL impl, msdkComponentType type, mfxU3 + else { + switch (type) { + case MSDK_VENCODE: +- switch (uCodecid) { +- case MFX_CODEC_VP8: +- return MFX_PLUGINID_VP8E_HW; +- } + break; + #if MFX_VERSION >= 1027 + case (MSDK_VENCODE | MSDK_FEI): +diff --git a/tools/legacy/sample_common/src/vpl_implementation_loader.cpp b/tools/legacy/sample_common/src/vpl_implementation_loader.cpp +new file mode 100644 +index 0000000..2edb0d7 +--- /dev/null ++++ b/tools/legacy/sample_common/src/vpl_implementation_loader.cpp +@@ -0,0 +1,220 @@ ++/******************************************************************************\ ++Copyright (c) 2021, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from ++https://software.intel.com/en-us/intel-media-server-studio or ++https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#include "vpl_implementation_loader.h" ++#include "sample_defs.h" ++#include "vpl/mfxdispatcher.h" ++ ++VPLImplementationLoader::VPLImplementationLoader() { ++ m_Loader = MFXLoad(); ++ m_idesc = nullptr; ++ m_ImplIndex = 0; ++} ++ ++VPLImplementationLoader::~VPLImplementationLoader() { ++ if (m_idesc) { ++ MFXDispReleaseImplDescription(m_Loader, m_idesc); ++ } ++ MFXUnload(m_Loader); ++} ++ ++mfxStatus VPLImplementationLoader::CreateConfig(mfxU16 data, const char *propertyName) { ++ mfxConfig cfg = MFXCreateConfig(m_Loader); ++ mfxVariant variant; ++ variant.Type = MFX_VARIANT_TYPE_U16; ++ variant.Data.U32 = data; ++ mfxStatus sts = MFXSetConfigFilterProperty(cfg, (mfxU8 *)propertyName, variant); ++ MSDK_CHECK_STATUS(sts, "MFXSetConfigFilterProperty failed"); ++ m_Configs.push_back(cfg); ++ ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::CreateConfig(mfxU32 data, const char *propertyName) { ++ mfxConfig cfg = MFXCreateConfig(m_Loader); ++ mfxVariant variant; ++ variant.Type = MFX_VARIANT_TYPE_U32; ++ variant.Data.U32 = data; ++ mfxStatus sts = MFXSetConfigFilterProperty(cfg, (mfxU8 *)propertyName, variant); ++ MSDK_CHECK_STATUS(sts, "MFXSetConfigFilterProperty failed"); ++ m_Configs.push_back(cfg); ++ ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::ConfigureImplementation(mfxIMPL impl) { ++ mfxConfig cfgImpl = MFXCreateConfig(m_Loader); ++ ++ mfxVariant ImplVariant; ++ ImplVariant.Type = MFX_VARIANT_TYPE_U32; ++ ++ std::vector hwImpls = { MFX_IMPL_HARDWARE, MFX_IMPL_HARDWARE_ANY, MFX_IMPL_HARDWARE2, ++ MFX_IMPL_HARDWARE3, MFX_IMPL_HARDWARE4, MFX_IMPL_VIA_D3D9, ++ MFX_IMPL_VIA_D3D11 }; ++ ++ std::vector::iterator hwImplsIt = ++ std::find_if(hwImpls.begin(), hwImpls.end(), [impl](const mfxU32 &val) { ++ return (val == MFX_IMPL_VIA_MASK(impl) || val == MFX_IMPL_BASETYPE(impl)); ++ }); ++ ++ if (MFX_IMPL_BASETYPE(impl) == MFX_IMPL_SOFTWARE) { ++ ImplVariant.Data.U32 = MFX_IMPL_TYPE_SOFTWARE; ++ } ++ else if (hwImplsIt != hwImpls.end()) { ++ ImplVariant.Data.U32 = MFX_IMPL_TYPE_HARDWARE; ++ } ++ else { ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ mfxStatus sts = ++ MFXSetConfigFilterProperty(cfgImpl, (mfxU8 *)"mfxImplDescription.Impl", ImplVariant); ++ MSDK_CHECK_STATUS(sts, "MFXSetConfigFilterProperty failed"); ++ m_Configs.push_back(cfgImpl); ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::ConfigureAccelerationMode(mfxAccelerationMode accelerationMode, ++ mfxIMPL impl) { ++ mfxStatus sts = MFX_ERR_NONE; ++ bool isHW = impl == MFX_IMPL_SOFTWARE ? false : true; ++ ++ // configure accelerationMode, except when required implementation is ++ // MFX_IMPL_TYPE_HARDWARE, but m_accelerationMode not set ++ if (accelerationMode != MFX_ACCEL_MODE_NA || !isHW) { ++ sts = CreateConfig((mfxU32)accelerationMode, "mfxImplDescription.AccelerationMode"); ++ } ++ ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::ConfigureVersion(mfxVersion const &version) { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ sts = CreateConfig(version.Version, "mfxImplDescription.ApiVersion.Version"); ++ sts = CreateConfig(version.Major, "mfxImplDescription.ApiVersion.Major"); ++ sts = CreateConfig(version.Minor, "mfxImplDescription.ApiVersion.Minor"); ++ ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::EnumImplementations() { ++ // pick the first available implementation, m_desc is checked only for being ++ // non-equal to NULL potentially may be needed loop by implementations, set ++ // implIndex corresponding better implementation and add meaningful validation ++ // for the m_idesc ++ mfxImplDescription *idesc; ++ mfxStatus sts = ++ MFXEnumImplementations(m_Loader, 0, MFX_IMPLCAPS_IMPLDESCSTRUCTURE, (mfxHDL *)&idesc); ++ MSDK_CHECK_STATUS(sts, "MFXEnumImplementations failed"); ++ MSDK_CHECK_POINTER(idesc, MFX_ERR_NULL_PTR); ++ m_idesc = idesc; ++ ++ m_ImplIndex = 0; ++ ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::EnumImplementations(mfxU16 deviceID, mfxU32 adapterNum) { ++ mfxImplDescription *idesc; ++ mfxStatus sts = MFX_ERR_NONE; ++ mfxChar devIDAndAdapter[MFX_STRFIELD_LEN] = {}; ++ snprintf(devIDAndAdapter, sizeof(devIDAndAdapter), "%x/%d", deviceID, adapterNum); ++ ++ int impl = 0; ++ while (sts == MFX_ERR_NONE) { ++ sts = MFXEnumImplementations(m_Loader, ++ impl, ++ MFX_IMPLCAPS_IMPLDESCSTRUCTURE, ++ (mfxHDL *)&idesc); ++ if (!idesc) { ++ sts = MFX_ERR_NULL_PTR; ++ break; ++ } ++ else if (strncmp(idesc->Dev.DeviceID, devIDAndAdapter, sizeof(devIDAndAdapter)) == 0) { ++ m_idesc = idesc; ++ m_ImplIndex = impl; ++ break; ++ } ++ impl++; ++ } ++ ++ return sts; ++} ++ ++mfxStatus VPLImplementationLoader::ConfigureAndEnumImplementations( ++ mfxIMPL impl, ++ mfxAccelerationMode accelerationMode, ++ mfxVersion const &version) { ++ mfxStatus sts; ++ ++ sts = ConfigureImplementation(impl); ++ MSDK_CHECK_STATUS(sts, "ConfigureImplementation failed"); ++ ++ sts = ConfigureAccelerationMode(accelerationMode, impl); ++ MSDK_CHECK_STATUS(sts, "ConfigureAccelerationMode failed"); ++ ++ sts = EnumImplementations(); ++ MSDK_CHECK_STATUS(sts, "EnumImplementations failed"); ++ ++ return sts; ++} ++ ++mfxLoader VPLImplementationLoader::GetLoader() { ++ return m_Loader; ++} ++ ++mfxU32 VPLImplementationLoader::GetImplIndex() const { ++ return m_ImplIndex; ++}; ++ ++mfxStatus VPLImplementationLoader::GetVersion(mfxVersion *version) { ++ if (!m_idesc) { ++ EnumImplementations(); ++ } ++ ++ if (m_idesc) { ++ version->Major = m_idesc->ApiVersion.Major; ++ version->Minor = m_idesc->ApiVersion.Minor; ++ version->Version = m_idesc->ApiVersion.Version; ++ return MFX_ERR_NONE; ++ } ++ ++ return MFX_ERR_UNKNOWN; ++} ++ ++mfxStatus MainVideoSession::CreateSession(VPLImplementationLoader *Loader) { ++ return MFXCreateSession(Loader->GetLoader(), Loader->GetImplIndex(), &m_session); ++} +diff --git a/tools/legacy/sample_multi_transcode/CMakeLists.txt b/tools/legacy/sample_multi_transcode/CMakeLists.txt +new file mode 100644 +index 0000000..2121c57 +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/CMakeLists.txt +@@ -0,0 +1,42 @@ ++# ############################################################################## ++# Copyright (C) 2021 Intel Corporation ++# ++# SPDX-License-Identifier: MIT ++# ############################################################################## ++cmake_minimum_required(VERSION 3.10.2) ++ ++set(TARGET sample_multi_transcode) ++ ++set(SOURCES "") ++list(APPEND SOURCES src/pipeline_transcode.cpp src/sample_multi_transcode.cpp ++ src/transcode_utils.cpp) ++ ++add_executable(${TARGET} ${SOURCES}) ++ ++if(MSVC) ++ add_definitions(-D_CRT_SECURE_NO_WARNINGS) ++endif() ++ ++if(POLICY CMP0074) ++ # ignore warning of VPL_ROOT in find_package search path ++ cmake_policy(SET CMP0074 OLD) ++endif() ++ ++target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ++ ${CMAKE_SOURCE_DIR}/api/vpl) ++find_package(VPL REQUIRED) ++target_link_libraries(${TARGET} sample_common media_sdk_compatibility_headers) ++add_definitions(-DMFX_ONEVPL) ++if(UNIX) ++ target_link_libraries(${TARGET} ${PKG_LIBVA_LIBRARIES} ${CMAKE_DL_LIBS} ++ pthread) ++ add_definitions(-DLIBVA_SUPPORT -DLIBVA_DRM_SUPPORT -DLINUX64) ++ target_include_directories(${TARGET} PRIVATE ${PKG_LIBVA_INCLUDE_DIRS} ++ ${PKG_LIBDRM_INCLUDE_DIRS}) ++else() ++ target_link_libraries(${TARGET} DXGI D3D11 D3D9 DXVA2) ++ add_definitions(-DMFX_D3D11_SUPPORT) ++endif() ++ ++install(TARGETS ${TARGET} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} ++ COMPONENT runtime) +diff --git a/tools/legacy/sample_multi_transcode/include/pipeline_transcode.h b/tools/legacy/sample_multi_transcode/include/pipeline_transcode.h +new file mode 100644 +index 0000000..457d72c +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/include/pipeline_transcode.h +@@ -0,0 +1,973 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2019, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#ifndef __SAMPLE_PIPELINE_TRANSCODE_H__ ++#define __SAMPLE_PIPELINE_TRANSCODE_H__ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "base_allocator.h" ++#include "mfx_multi_vpp.h" ++#include "rotate_plugin_api.h" ++#include "sample_defs.h" ++#include "sample_utils.h" ++#include "sysmem_allocator.h" ++ ++#include "mfxdispatcher.h" ++#include "mfxjpeg.h" ++#include "mfxmvc.h" ++#include "mfxvideo++.h" ++#include "mfxvideo.h" ++#if !defined(MFX_ONEVPL) ++ #include "mfxla.h" ++#endif ++#include "mfxvp8.h" ++ ++#if defined(MFX_ONEVPL) ++ #include "mfxdeprecated.h" ++#endif ++ ++#include "mfxplugin.h" ++ ++#if !defined(MFX_ONEVPL) ++ #include "mfxplugin++.h" ++ #include "plugin_loader.h" ++#endif ++ ++#include "hw_device.h" ++#include "plugin_utils.h" ++#include "preset_manager.h" ++#include "sample_defs.h" ++ ++#if (MFX_VERSION >= 1024) ++ #include "brc_routines.h" ++#endif ++ ++#define TIME_STATS 1 // Enable statistics processing ++#include "time_statistics.h" ++ ++#if defined(_WIN32) || defined(_WIN64) ++ #include "decode_render.h" ++#endif ++ ++#if defined(_WIN32) || defined(_WIN64) ++ #define MSDK_CPU_ROTATE_PLUGIN MSDK_STRING("sample_rotate_plugin.dll") ++ #define MSDK_OCL_ROTATE_PLUGIN MSDK_STRING("sample_plugin_opencl.dll") ++#else ++ #define MSDK_CPU_ROTATE_PLUGIN MSDK_STRING("libsample_rotate_plugin.so") ++ #define MSDK_OCL_ROTATE_PLUGIN MSDK_STRING("libsample_plugin_opencl.so") ++#endif ++ ++#define MAX_PREF_LEN 256 ++ ++#ifndef MFX_VERSION ++ #error MFX_VERSION not defined ++#endif ++ ++#ifdef ENABLE_MCTF ++const mfxU16 MCTF_MID_FILTER_STRENGTH = 10; ++const mfxF64 MCTF_LOSSLESS_BPP = 0.0; ++#endif ++ ++namespace TranscodingSample { ++enum PipelineMode { ++ Native = ++ 0, // means that pipeline is based depends on the cmd parameters (decode/encode/transcode) ++ Sink, // means that pipeline makes decode only and put data to shared buffer ++ Source, // means that pipeline makes vpp + encode and get data from shared buffer ++ VppComp, // means that pipeline makes vpp composition + encode and get data from shared buffer ++ VppCompOnly, // means that pipeline makes vpp composition and get data from shared buffer ++ VppCompOnlyEncode // means that pipeline makes vpp composition + encode and get data from shared buffer ++}; ++ ++enum VppCompDumpMode { NULL_RENDER_VPP_COMP = 1, DUMP_FILE_VPP_COMP = 2 }; ++ ++enum EFieldCopyMode { FC_NONE = 0, FC_T2T = 1, FC_T2B = 2, FC_B2T = 4, FC_B2B = 8, FC_FR2FR = 16 }; ++ ++struct sVppCompDstRect { ++ mfxU32 DstX; ++ mfxU32 DstY; ++ mfxU32 DstW; ++ mfxU32 DstH; ++ mfxU16 TileId; ++}; ++ ++#ifdef ENABLE_MCTF ++typedef enum { ++ VPP_FILTER_DISABLED = 0, ++ VPP_FILTER_ENABLED_DEFAULT = 1, ++ VPP_FILTER_ENABLED_CONFIGURED = 7 ++ ++} VPPFilterMode; ++ ++// this is a structure with mctf-parameteres ++// that can be changed in run-time; ++struct sMctfRunTimeParam { ++ #ifdef ENABLE_MCTF_EXT ++ #if 0 ++ mfxU32 BitsPerPixelx100k; ++ mfxU16 Deblock; ++ #endif ++ #endif ++ mfxU16 FilterStrength; ++}; ++ ++struct sMctfRunTimeParams { ++ sMctfRunTimeParams() : CurIdx(0) {} ++ ++ mfxU32 CurIdx; ++ std::vector RunTimeParams; ++ // returns rt-param corresponding to CurIdx or NULL if ++ // CurIdx is behind available info ++ const sMctfRunTimeParam *GetCurParam(); ++ // move CurIdx forward ++ void MoveForward(); ++ // set CurIdx to the begining; restart indexing; ++ void Restart(); ++ // reset vector & index ++ void Reset(); ++ // test for emptiness ++ bool Empty() { ++ return RunTimeParams.empty(); ++ }; ++}; ++ ++struct sMCTFParam { ++ sMctfRunTimeParams rtParams; ++ mfxExtVppMctf params; ++ VPPFilterMode mode; ++}; ++#endif ++ ++enum ExtBRCType { EXTBRC_DEFAULT, EXTBRC_OFF, EXTBRC_ON, EXTBRC_IMPLICIT }; ++ ++enum MemoryModel { ++ UNKNOWN_ALLOC = 0, // GENERAL_ALLOC will be used by default ++ GENERAL_ALLOC = 1, ++ VISIBLE_INT_ALLOC = 2, ++ HIDDEN_INT_ALLOC = 3 ++}; ++ ++struct __sInputParams { ++ // session parameters ++ bool bIsJoin; ++ mfxPriority priority; ++ // common parameters ++ mfxIMPL libType; // Type of used mediaSDK library ++#if defined(LINUX32) || defined(LINUX64) ++ std::string strDevicePath; ++#endif ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ //Adapter type ++ bool bPrefferiGfx; ++ bool bPrefferdGfx; ++#endif ++ bool bIsPerf; // special performance mode. Use pre-allocated bitstreams, output ++ mfxU16 nThreadsNum; // number of internal session threads number ++ bool bRobustFlag; // Robust transcoding mode. Allows auto-recovery after hardware errors ++ bool bSoftRobustFlag; ++ ++ mfxU32 EncodeId; // type of output coded video ++ mfxU32 DecodeId; // type of input coded video ++ ++ msdk_char strSrcFile[MSDK_MAX_FILENAME_LEN]; // source bitstream file ++ msdk_char strDstFile[MSDK_MAX_FILENAME_LEN]; // destination bitstream file ++ msdk_char strDumpVppCompFile[MSDK_MAX_FILENAME_LEN]; // VPP composition output dump file ++ msdk_char strMfxParamsDumpFile[MSDK_MAX_FILENAME_LEN]; ++ ++ // specific encode parameters ++ mfxU16 nTargetUsage; ++ mfxF64 dDecoderFrameRateOverride; ++ mfxF64 dEncoderFrameRateOverride; ++ mfxU16 EncoderPicstructOverride; ++ mfxF64 dVPPOutFramerate; ++ mfxU16 nBitRate; ++ mfxU16 nBitRateMultiplier; ++ mfxU16 nQuality; // quality parameter for JPEG encoder ++ mfxU16 nDstWidth; // destination picture width, specified if resizing required ++ mfxU16 nDstHeight; // destination picture height, specified if resizing required ++ ++ mfxU16 nEncTileRows; // number of rows for encoding tiling ++ mfxU16 nEncTileCols; // number of columns for encoding tiling ++ ++ bool bEnableDeinterlacing; ++ mfxU16 DeinterlacingMode; ++ int DenoiseLevel; ++ int DetailLevel; ++ mfxU16 FRCAlgorithm; ++ EFieldCopyMode fieldProcessingMode; ++ mfxU16 ScalingMode; ++ ++ mfxU16 nAsyncDepth; // asyncronous queue ++ ++ PipelineMode eMode; ++ PipelineMode eModeExt; ++ ++ mfxU32 FrameNumberPreference; // how many surfaces user wants ++ mfxU32 MaxFrameNumber; // maximum frames for transcoding ++ mfxU32 numSurf4Comp; ++ mfxU16 numTiles4Comp; ++ ++ mfxU16 nSlices; // number of slices for encoder initialization ++ mfxU16 nMaxSliceSize; //maximum size of slice ++ ++ mfxU16 WinBRCMaxAvgKbps; ++ mfxU16 WinBRCSize; ++ mfxU16 BufferSizeInKB; ++ mfxU16 GopPicSize; ++ mfxU16 GopRefDist; ++ mfxU16 NumRefFrame; ++ mfxU16 nBRefType; ++ mfxU16 RepartitionCheckMode; ++ mfxU16 GPB; ++ mfxU16 nTransformSkip; ++ ++ mfxU16 CodecLevel; ++ mfxU16 CodecProfile; ++ mfxU16 MaxKbps; ++ mfxU16 InitialDelayInKB; ++ mfxU16 GopOptFlag; ++ mfxU16 AdaptiveI; ++ mfxU16 AdaptiveB; ++ ++ mfxU16 WeightedPred; ++ mfxU16 WeightedBiPred; ++ mfxU16 ExtBrcAdaptiveLTR; ++ ++ bool bExtMBQP; ++ ++ // MVC Specific Options ++ bool bIsMVC; // true if Multi-View-Codec is in use ++ mfxU32 numViews; // number of views for Multi-View-Codec ++ ++ mfxU16 nRotationAngle; // if specified, enables rotation plugin in mfx pipeline ++ msdk_char strVPPPluginDLLPath[MSDK_MAX_FILENAME_LEN]; // plugin dll path and name ++ ++ sPluginParams decoderPluginParams; ++ sPluginParams encoderPluginParams; ++ ++ mfxU32 nTimeout; // how long transcoding works in seconds ++ mfxU32 nFPS; // limit transcoding to the number of frames per second ++ ++ mfxU32 statisticsWindowSize; ++ FILE *statisticsLogFile; ++ ++ bool bLABRC; // use look ahead bitrate control algorithm ++ mfxU16 nLADepth; // depth of the look ahead bitrate control algorithm ++ bool bEnableExtLA; ++ bool bEnableBPyramid; ++ mfxU16 nRateControlMethod; ++ mfxU16 nQPI; ++ mfxU16 nQPP; ++ mfxU16 nQPB; ++ bool bDisableQPOffset; ++ ++ mfxU16 nAvcTemp; ++ mfxU16 nBaseLayerPID; ++ mfxU16 nAvcTemporalLayers[8]; ++ mfxU16 nSPSId; ++ mfxU16 nPPSId; ++ mfxU16 nPicTimingSEI; ++ mfxU16 nNalHrdConformance; ++ mfxU16 nVuiNalHrdParameters; ++ ++ bool bOpenCL; ++ mfxU16 reserved[4]; ++ ++ mfxU16 nVppCompDstX; ++ mfxU16 nVppCompDstY; ++ mfxU16 nVppCompDstW; ++ mfxU16 nVppCompDstH; ++ mfxU16 nVppCompSrcW; ++ mfxU16 nVppCompSrcH; ++ mfxU16 nVppCompTileId; ++ ++ mfxU32 DecoderFourCC; ++ mfxU32 EncoderFourCC; ++ ++ sVppCompDstRect *pVppCompDstRects; ++ ++ bool bForceSysMem; ++ mfxU16 DecOutPattern; ++ mfxU16 VppOutPattern; ++ mfxU16 nGpuCopyMode; ++ ++ mfxU16 nRenderColorForamt; /*0 NV12 - default, 1 is ARGB*/ ++ ++ mfxI32 monitorType; ++ bool shouldUseGreedyFormula; ++ bool enableQSVFF; ++ bool bSingleTexture; ++ ++ ExtBRCType nExtBRC; ++ ++ mfxU16 nAdaptiveMaxFrameSize; ++ mfxU16 LowDelayBRC; ++ ++ mfxU16 IntRefType; ++ mfxU16 IntRefCycleSize; ++ mfxU16 IntRefQPDelta; ++ mfxU16 IntRefCycleDist; ++ ++ mfxU32 nMaxFrameSize; ++ ++ mfxU16 BitrateLimit; ++ ++#if (MFX_VERSION >= 1025) ++ mfxU16 numMFEFrames; ++ mfxU16 MFMode; ++ mfxU32 mfeTimeout; ++#endif ++ ++#if (MFX_VERSION >= 1027) ++ mfxU16 TargetBitDepthLuma; ++ mfxU16 TargetBitDepthChroma; ++#endif ++ ++#if defined(LIBVA_WAYLAND_SUPPORT) ++ mfxU16 nRenderWinX; ++ mfxU16 nRenderWinY; ++ bool bPerfMode; ++#endif ++ ++#if defined(LIBVA_SUPPORT) ++ mfxI32 libvaBackend; ++#endif // defined(MFX_LIBVA_SUPPORT) ++ ++ CHWDevice *m_hwdev; ++ ++ EPresetModes PresetMode; ++ bool shouldPrintPresets; ++ ++ bool rawInput; ++ ++ mfxU16 nMemoryModel; ++}; ++ ++struct sInputParams : public __sInputParams { ++ sInputParams(); ++ msdk_string DumpLogFileName; ++#if MFX_VERSION >= 1022 ++ std::vector m_ROIData; ++ ++ bool bDecoderPostProcessing; ++ bool bROIasQPMAP; ++#endif //MFX_VERSION >= 1022 ++#ifdef ENABLE_MCTF ++ sMCTFParam mctfParam; ++#endif ++}; ++ ++struct PreEncAuxBuffer { ++ mfxEncodeCtrl encCtrl; ++ mfxU16 Locked; ++ mfxENCInput encInput; ++ mfxENCOutput encOutput; ++}; ++ ++struct ExtendedSurface { ++ mfxFrameSurface1 *pSurface; ++ PreEncAuxBuffer *pAuxCtrl; ++ mfxEncodeCtrl *pEncCtrl; ++ mfxSyncPoint Syncp; ++}; ++ ++struct ExtendedBS { ++ bool IsFree = true; ++ mfxBitstreamWrapper Bitstream; ++ mfxSyncPoint Syncp = nullptr; ++ PreEncAuxBuffer *pCtrl = nullptr; ++}; ++ ++class CIOStat : public CTimeStatistics { ++public: ++ CIOStat() : CTimeStatistics(), ofile(stdout) { ++ MSDK_ZERO_MEMORY(bufDir); ++ DumpLogFileName.clear(); ++ } ++ ++ CIOStat(const msdk_char *dir) : CTimeStatistics(), ofile(stdout) { ++ msdk_strncopy_s(bufDir, MAX_PREF_LEN, dir, MAX_PREF_LEN - 1); ++ bufDir[MAX_PREF_LEN - 1] = 0; ++ } ++ ++ ~CIOStat() {} ++ ++ inline void SetOutputFile(FILE *file) { ++ ofile = file; ++ } ++ ++ inline void SetDumpName(const msdk_char *name) { ++ DumpLogFileName = name; ++ if (!DumpLogFileName.empty()) { ++ TurnOnDumping(); ++ } ++ else { ++ TurnOffDumping(); ++ } ++ } ++ ++ inline void SetDirection(const msdk_char *dir) { ++ if (dir) { ++ msdk_strncopy_s(bufDir, MAX_PREF_LEN, dir, MAX_PREF_LEN - 1); ++ bufDir[MAX_PREF_LEN - 1] = 0; ++ } ++ } ++ ++ inline void PrintStatistics(mfxU32 numPipelineid, ++ mfxF64 target_framerate = -1 /*default stands for infinite*/) { ++ // print timings in ms ++ msdk_fprintf( ++ ofile, ++ MSDK_STRING( ++ "stat[%u.%llu]: %s=%d;Framerate=%.3f;Total=%.3lf;Samples=%lld;StdDev=%.3lf;Min=%.3lf;Max=%.3lf;Avg=%.3lf\n"), ++ msdk_get_current_pid(), ++ rdtsc(), ++ bufDir, ++ numPipelineid, ++ target_framerate, ++ GetTotalTime(false), ++ GetNumMeasurements(), ++ GetTimeStdDev(false), ++ GetMinTime(false), ++ GetMaxTime(false), ++ GetAvgTime(false)); ++ fflush(ofile); ++ ++ if (!DumpLogFileName.empty()) { ++ msdk_char buf[MSDK_MAX_FILENAME_LEN]; ++ msdk_sprintf(buf, MSDK_STRING("%s_ID_%d.log"), DumpLogFileName.c_str(), numPipelineid); ++ DumpDeltas(buf); ++ } ++ } ++ ++ inline void DumpDeltas(msdk_char *file_name) { ++ if (m_time_deltas.empty()) ++ return; ++ ++ FILE *dump_file = NULL; ++ if (!MSDK_FOPEN(dump_file, file_name, MSDK_STRING("a"))) { ++ for (std::vector::const_iterator it = m_time_deltas.begin(); ++ it != m_time_deltas.end(); ++ ++it) { ++ fprintf(dump_file, "%.3f, ", (*it)); ++ } ++ fclose(dump_file); ++ } ++ else { ++ perror("DumpDeltas: file cannot be open"); ++ } ++ } ++ ++protected: ++ msdk_tstring DumpLogFileName; ++ FILE *ofile; ++ msdk_char bufDir[MAX_PREF_LEN]; ++}; ++ ++class ExtendedBSStore { ++public: ++ explicit ExtendedBSStore(mfxU32 size) { ++ m_pExtBS.resize(size); ++ } ++ virtual ~ExtendedBSStore() { ++ m_pExtBS.clear(); ++ } ++ ExtendedBS *GetNext() { ++ for (mfxU32 i = 0; i < m_pExtBS.size(); i++) { ++ if (m_pExtBS[i].IsFree) { ++ m_pExtBS[i].IsFree = false; ++ return &m_pExtBS[i]; ++ } ++ } ++ return NULL; ++ } ++ void Release(ExtendedBS *pBS) { ++ for (mfxU32 i = 0; i < m_pExtBS.size(); i++) { ++ if (&m_pExtBS[i] == pBS) { ++ m_pExtBS[i].IsFree = true; ++ return; ++ } ++ } ++ return; ++ } ++ void ReleaseAll() { ++ for (mfxU32 i = 0; i < m_pExtBS.size(); i++) { ++ m_pExtBS[i].IsFree = true; ++ } ++ return; ++ } ++ void FlushAll() { ++ for (mfxU32 i = 0; i < m_pExtBS.size(); i++) { ++ m_pExtBS[i].Bitstream.DataLength = 0; ++ m_pExtBS[i].Bitstream.DataOffset = 0; ++ } ++ return; ++ } ++ ++protected: ++ std::vector m_pExtBS; ++ ++private: ++ DISALLOW_COPY_AND_ASSIGN(ExtendedBSStore); ++}; ++ ++class CTranscodingPipeline; ++// thread safety buffer heterogeneous pipeline ++// only for join sessions ++class SafetySurfaceBuffer { ++public: ++ struct SurfaceDescriptor { ++ ExtendedSurface ExtSurface; ++ mfxU32 Locked; ++ }; ++ ++ SafetySurfaceBuffer(SafetySurfaceBuffer *pNext); ++ virtual ~SafetySurfaceBuffer(); ++ ++ mfxU32 GetLength(); ++ mfxStatus WaitForSurfaceRelease(mfxU32 msec); ++ mfxStatus WaitForSurfaceInsertion(mfxU32 msec); ++ void AddSurface(ExtendedSurface Surf); ++ mfxStatus GetSurface(ExtendedSurface &Surf); ++ mfxStatus ReleaseSurface(mfxFrameSurface1 *pSurf); ++ mfxStatus ReleaseSurfaceAll(); ++ void CancelBuffering(); ++ ++ SafetySurfaceBuffer *m_pNext; ++ ++protected: ++ std::mutex m_mutex; ++ std::list m_SList; ++ bool m_IsBufferingAllowed; ++ MSDKEvent *pRelEvent; ++ MSDKEvent *pInsEvent; ++ ++private: ++ DISALLOW_COPY_AND_ASSIGN(SafetySurfaceBuffer); ++}; ++ ++class FileBitstreamProcessor { ++public: ++ FileBitstreamProcessor(); ++ virtual ~FileBitstreamProcessor(); ++ virtual mfxStatus SetReader(std::unique_ptr &reader); ++ virtual mfxStatus SetReader(std::unique_ptr &reader); ++ virtual mfxStatus SetWriter(std::unique_ptr &writer); ++ virtual mfxStatus GetInputBitstream(mfxBitstreamWrapper **pBitstream); ++ virtual mfxStatus GetInputFrame(mfxFrameSurface1 *pSurface); ++ virtual mfxStatus ProcessOutputBitstream(mfxBitstreamWrapper *pBitstream); ++ virtual mfxStatus ResetInput(); ++ virtual mfxStatus ResetOutput(); ++ ++protected: ++ std::unique_ptr m_pFileReader; ++ std::unique_ptr m_pYUVFileReader; ++ // for performance options can be zero ++ std::unique_ptr m_pFileWriter; ++ mfxBitstreamWrapper m_Bitstream; ++ ++private: ++ DISALLOW_COPY_AND_ASSIGN(FileBitstreamProcessor); ++}; ++ ++// Bitstream is external via BitstreamProcessor ++class CTranscodingPipeline { ++public: ++ CTranscodingPipeline(); ++ virtual ~CTranscodingPipeline(); ++ ++ virtual mfxStatus Init(sInputParams *pParams, ++ MFXFrameAllocator *pMFXAllocator, ++ void *hdl, ++ CTranscodingPipeline *pParentPipeline, ++ SafetySurfaceBuffer *pBuffer, ++ FileBitstreamProcessor *pBSProc, ++ VPLImplementationLoader *mfxLoader); ++ ++ // frames allocation is suspended for heterogeneous pipeline ++ virtual mfxStatus CompleteInit(); ++ virtual void Close(); ++ virtual mfxStatus Reset(VPLImplementationLoader *mfxLoader); ++ virtual mfxStatus Join(MFXVideoSession *pChildSession); ++ virtual mfxStatus Run(); ++ virtual mfxStatus FlushLastFrames() { ++ return MFX_ERR_NONE; ++ } ++ ++ mfxU32 GetProcessFrames() { ++ return m_nProcessedFramesNum; ++ } ++ ++ bool GetJoiningFlag() { ++ return m_bIsJoinSession; ++ } ++ ++ mfxStatus QueryMFXVersion(mfxVersion *version) { ++ MSDK_CHECK_POINTER(m_pmfxSession.get(), MFX_ERR_NULL_PTR); ++ return m_pmfxSession->QueryVersion(version); ++ }; ++ inline mfxU32 GetPipelineID() { ++ return m_nID; ++ } ++ inline void SetPipelineID(mfxU32 id) { ++ m_nID = id; ++ } ++ void StopSession(); ++ bool IsOverlayUsed(); ++ size_t GetRobustFlag(); ++ ++ msdk_string GetSessionText() { ++ msdk_stringstream ss; ++ ss << m_pmfxSession->operator mfxSession(); ++ ++ return ss.str(); ++ } ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ //Adapter type ++ void SetPrefferiGfx(bool prefferiGfx) { ++ bPrefferiGfx = prefferiGfx; ++ }; ++ void SetPrefferdGfx(bool prefferdGfx) { ++ bPrefferdGfx = prefferdGfx; ++ }; ++ bool IsPrefferiGfx() { ++ return bPrefferiGfx; ++ }; ++ bool IsPrefferdGfx() { ++ return bPrefferdGfx; ++ }; ++#endif ++protected: ++ virtual mfxStatus CheckRequiredAPIVersion(mfxVersion &version, sInputParams *pParams); ++ ++ virtual mfxStatus Decode(); ++ virtual mfxStatus Encode(); ++ virtual mfxStatus Transcode(); ++ virtual mfxStatus DecodeOneFrame(ExtendedSurface *pExtSurface); ++ virtual mfxStatus DecodeLastFrame(ExtendedSurface *pExtSurface); ++ virtual mfxStatus VPPOneFrame(ExtendedSurface *pSurfaceIn, ExtendedSurface *pExtSurface); ++ virtual mfxStatus EncodeOneFrame(ExtendedSurface *pExtSurface, mfxBitstreamWrapper *pBS); ++#if !defined(MFX_ONEVPL) ++ virtual mfxStatus PreEncOneFrame(ExtendedSurface *pInSurface, ExtendedSurface *pOutSurface); ++#endif ++ virtual mfxStatus DecodePreInit(sInputParams *pParams); ++ virtual mfxStatus VPPPreInit(sInputParams *pParams); ++ virtual mfxStatus EncodePreInit(sInputParams *pParams); ++#if !defined(MFX_ONEVPL) ++ virtual mfxStatus PreEncPreInit(sInputParams *pParams); ++#endif ++ mfxVideoParam GetDecodeParam(); ++ ++#if !defined(MFX_ONEVPL) ++ mfxExtMVCSeqDesc GetDecMVCSeqDesc() { ++ mfxExtMVCSeqDesc *mvc = m_mfxDecParams; ++ return mvc ? *mvc : mfxExtMVCSeqDesc(); ++ } ++#endif ++ static void ModifyParamsUsingPresets(sInputParams ¶ms, ++ mfxF64 fps, ++ mfxU32 width, ++ mfxU32 height); ++ ++ // alloc frames for all component ++ mfxStatus AllocFrames(mfxFrameAllocRequest *pRequest, bool isDecAlloc); ++ mfxStatus AllocFrames(); ++ ++#if !defined(MFX_ONEVPL) ++ mfxStatus CorrectPreEncAuxPool(mfxU32 num_frames_in_pool); ++ mfxStatus AllocPreEncAuxPool(); ++ void FreePreEncAuxPool(); ++#endif //!MFX_ONEVPL ++ ++ // need for heterogeneous pipeline ++ mfxStatus CalculateNumberOfReqFrames(mfxFrameAllocRequest &pRequestDecOut, ++ mfxFrameAllocRequest &pRequestVPPOut); ++ void CorrectNumberOfAllocatedFrames(mfxFrameAllocRequest *pNewReq); ++ void FreeFrames(); ++ ++ mfxStatus LoadStaticSurface(); ++ ++ mfxFrameSurface1 *GetFreeSurface(bool isDec, mfxU64 timeout); ++ mfxU32 GetFreeSurfacesCount(bool isDec); ++ PreEncAuxBuffer *GetFreePreEncAuxBuffer(); ++ void SetEncCtrlRT(ExtendedSurface &extSurface, bool bInsertIDR); ++ ++ // parameters configuration functions ++ mfxStatus InitDecMfxParams(sInputParams *pInParams); ++ mfxStatus InitVppMfxParams(sInputParams *pInParams); ++ virtual mfxStatus InitEncMfxParams(sInputParams *pInParams); ++ mfxStatus InitPluginMfxParams(sInputParams *pInParams); ++#if !defined(MFX_ONEVPL) ++ mfxStatus InitPreEncMfxParams(sInputParams *pInParams); ++#endif ++ virtual mfxU32 FileFourCC2EncFourCC(mfxU32 fcc); ++ void FillFrameInfoForEncoding(mfxFrameInfo &info, sInputParams *pInParams); ++ ++ mfxStatus AllocAndInitVppDoNotUse(sInputParams *pInParams); ++ mfxStatus AllocMVCSeqDesc(); ++ ++ void FreeVppDoNotUse(); ++ void FreeMVCSeqDesc(); ++ ++ mfxStatus AllocateSufficientBuffer(mfxBitstreamWrapper *pBS); ++ mfxStatus PutBS(); ++ ++ mfxStatus DumpSurface2File(mfxFrameSurface1 *pSurface); ++ mfxStatus Surface2BS(ExtendedSurface *pSurf, mfxBitstreamWrapper *pBS, mfxU32 fourCC); ++ mfxStatus NV12toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS); ++ mfxStatus NV12asI420toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS); ++ mfxStatus RGB4toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS); ++ mfxStatus YUY2toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS); ++ ++ void NoMoreFramesSignal(); ++ mfxStatus AddLaStreams(mfxU16 width, mfxU16 height); ++ ++ void LockPreEncAuxBuffer(PreEncAuxBuffer *pBuff); ++ void UnPreEncAuxBuffer(PreEncAuxBuffer *pBuff); ++ ++ mfxU32 GetNumFramesForReset(); ++ void SetNumFramesForReset(mfxU32 nFrames); ++ ++ void HandlePossibleGpuHang(mfxStatus &sts); ++ ++ mfxStatus SetAllocatorAndHandleIfRequired(); ++ mfxStatus LoadGenericPlugin(); ++ ++ mfxBitstreamWrapper *m_pmfxBS; // contains encoded input data ++ ++ mfxVersion m_Version; // real API version with which library is initialized ++ ++ mfxLoader m_mfxLoader; ++ ++ std::unique_ptr m_pmfxSession; ++ std::unique_ptr m_pmfxDEC; ++ std::unique_ptr m_pmfxENC; ++ std::unique_ptr ++ m_pmfxVPP; // either VPP or VPPPlugin which wraps [VPP]-Plugin-[VPP] pipeline ++#if !defined(MFX_ONEVPL) ++ std::unique_ptr m_pmfxPreENC; ++ std::unique_ptr m_pUserDecoderModule; ++ std::unique_ptr m_pUserEncoderModule; ++ std::unique_ptr m_pUserEncModule; ++ std::unique_ptr m_pUserDecoderPlugin; ++ std::unique_ptr m_pUserEncoderPlugin; ++ std::unique_ptr m_pUserEncPlugin; ++#endif //!MFX_ONEVPL ++ mfxFrameAllocResponse m_mfxDecResponse; // memory allocation response for decoder ++ mfxFrameAllocResponse m_mfxEncResponse; // memory allocation response for encoder ++ ++ MFXFrameAllocator *m_pMFXAllocator; ++ void *m_hdl; // Diret3D device manager ++ bool m_bIsInterOrJoined; ++ ++ mfxU32 m_numEncoders; ++ mfxU32 m_encoderFourCC; ++ ++ CSmplYUVWriter m_dumpVppCompFileWriter; ++ mfxU32 m_vppCompDumpRenderMode; ++ ++#if defined(_WIN32) || defined(_WIN64) ++ CDecodeD3DRender *m_hwdev4Rendering; ++#else ++ CHWDevice *m_hwdev4Rendering; ++#endif ++ ++ typedef std::vector SurfPointersArray; ++ SurfPointersArray m_pSurfaceDecPool; ++ SurfPointersArray m_pSurfaceEncPool; ++ mfxU16 m_EncSurfaceType; // actual type of encoder surface pool ++ mfxU16 m_DecSurfaceType; // actual type of decoder surface pool ++ ++ typedef std::vector PreEncAuxArray; ++ PreEncAuxArray m_pPreEncAuxPool; ++ ++ // transcoding pipeline specific ++ typedef std::list BSList; ++ BSList m_BSPool; ++ ++ mfxInitParamlWrap m_initPar; ++ ++ volatile bool m_bForceStop; ++ ++ sPluginParams m_decoderPluginParams; ++ sPluginParams m_encoderPluginParams; ++ ++ MfxVideoParamsWrapper m_mfxDecParams; ++ MfxVideoParamsWrapper m_mfxEncParams; ++ MfxVideoParamsWrapper m_mfxVppParams; ++ MfxVideoParamsWrapper m_mfxPluginParams; ++ bool m_bIsVpp; // true if there's VPP in the pipeline ++ bool m_bIsFieldWeaving; ++ bool m_bIsFieldSplitting; ++ bool m_bIsPlugin; //true if there's Plugin in the pipeline ++ RotateParam m_RotateParam; ++ MfxVideoParamsWrapper m_mfxPreEncParams; ++ mfxU32 m_nTimeout; ++ bool m_bUseOverlay; ++ ++ bool m_bROIasQPMAP; ++ bool m_bExtMBQP; ++ // various external buffers ++ bool ++ m_bOwnMVCSeqDescMemory; // true if the pipeline owns memory allocated for MVCSeqDesc structure fields ++ ++ // to enable to-do list ++ // number of video enhancement filters (denoise, procamp, detail, video_analysis, multi_view, ste, istab, tcc, ace, svc) ++ constexpr static uint32_t ENH_FILTERS_COUNT = 20; ++ mfxU32 m_tabDoUseAlg[ENH_FILTERS_COUNT]; ++ ++ mfxU32 m_nID; ++ mfxU16 m_AsyncDepth; ++ mfxU32 m_nProcessedFramesNum; ++ ++ bool m_bIsJoinSession; ++ ++ bool m_bDecodeEnable; ++ bool m_bEncodeEnable; ++ mfxU32 m_nVPPCompEnable; ++ mfxI32 m_libvaBackend; ++ ++ mfxU16 m_MemoryModel; ++ ++ mfxSyncPoint m_LastDecSyncPoint; ++ ++ SafetySurfaceBuffer *m_pBuffer; ++ CTranscodingPipeline *m_pParentPipeline; ++ ++ mfxFrameAllocRequest m_Request; ++ bool m_bIsInit; ++ ++ mfxU32 m_NumFramesForReset; ++ std::mutex m_mReset; ++ std::mutex m_mStopSession; ++ bool m_bRobustFlag; ++ bool m_bSoftGpuHangRecovery; ++ ++ bool isHEVCSW; ++ ++ bool m_bInsertIDR; ++ ++ bool m_rawInput; ++ ++ std::unique_ptr m_pBSStore; ++ ++ mfxU32 m_FrameNumberPreference; ++ mfxU32 m_MaxFramesForTranscode; ++ ++ // pointer to already extended bs processor ++ FileBitstreamProcessor *m_pBSProcessor; ++ ++ msdk_tick m_nReqFrameTime; // time required to transcode one frame ++ ++ mfxU32 statisticsWindowSize; // Sliding window size for Statistics ++ mfxU32 m_nOutputFramesNum; ++ ++ CIOStat inputStatistics; ++ CIOStat outputStatistics; ++ ++ bool shouldUseGreedyFormula; ++ ++#if MFX_VERSION >= 1022 ++ // ROI data ++ std::vector m_ROIData; ++ mfxU32 m_nSubmittedFramesNum; ++ ++ // ROI with MBQP map data ++ bool m_bUseQPMap; ++ ++ std::map m_bufExtMBQP; ++ std::map> m_qpMapStorage; ++ std::map> m_extBuffPtrStorage; ++ std::map encControlStorage; ++ ++ mfxU32 m_QPmapWidth; ++ mfxU32 m_QPmapHeight; ++ mfxU32 m_GOPSize; ++ mfxU32 m_QPforI; ++ mfxU32 m_QPforP; ++ ++ msdk_string m_sGenericPluginPath; ++ mfxU16 m_nRotationAngle; ++ ++ msdk_string m_strMfxParamsDumpFile; ++ ++ void FillMBQPBuffer(mfxExtMBQP &qpMap, mfxU16 pictStruct); ++#endif //MFX_VERSION >= 1022 ++ ++#ifdef ENABLE_MCTF ++ sMctfRunTimeParams m_MctfRTParams; ++#endif ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ //Adapter type ++ bool bPrefferiGfx; ++ bool bPrefferdGfx; ++#endif ++private: ++ DISALLOW_COPY_AND_ASSIGN(CTranscodingPipeline); ++}; ++ ++struct ThreadTranscodeContext { ++ // Pointer to the session's pipeline ++ std::unique_ptr pPipeline; ++ // Pointer to bitstream handling object ++ FileBitstreamProcessor *pBSProcessor = nullptr; ++ // Session implementation type ++ mfxIMPL implType = MFX_IMPL_AUTO; ++ ++ // Session's starting status ++ mfxStatus startStatus = MFX_ERR_NONE; ++ // Session's working time ++ mfxF64 working_time = 0; ++ ++ // Number of processed frames ++ mfxU32 numTransFrames = 0; ++ // Status of the finished session ++ mfxStatus transcodingSts = MFX_ERR_NONE; ++ ++ // Thread handle ++ std::future handle; ++ ++ void TranscodeRoutine() { ++ using namespace std::chrono; ++ MSDK_CHECK_POINTER_NO_RET(pPipeline); ++ transcodingSts = MFX_ERR_NONE; ++ ++ auto start_time = system_clock::now(); ++ while (MFX_ERR_NONE == transcodingSts) { ++ transcodingSts = pPipeline->Run(); ++ } ++ working_time = duration_cast>(system_clock::now() - start_time).count(); ++ ++ MSDK_IGNORE_MFX_STS(transcodingSts, MFX_WRN_VALUE_NOT_CHANGED); ++ numTransFrames = pPipeline->GetProcessFrames(); ++ } ++}; ++} // namespace TranscodingSample ++ ++#endif +diff --git a/tools/legacy/sample_multi_transcode/include/sample_multi_transcode.h b/tools/legacy/sample_multi_transcode/include/sample_multi_transcode.h +new file mode 100644 +index 0000000..7bba85a +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/include/sample_multi_transcode.h +@@ -0,0 +1,109 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2019, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#ifndef __SAMPLE_MULTI_TRANSCODE_H__ ++#define __SAMPLE_MULTI_TRANSCODE_H__ ++ ++#include "mfxdefs.h" ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ #include "mfxadapter.h" ++#endif ++ ++#include "pipeline_transcode.h" ++#include "sample_utils.h" ++#include "transcode_utils.h" ++#include "vpl_implementation_loader.h" ++ ++#include "d3d11_allocator.h" ++#include "d3d11_device.h" ++#include "d3d_allocator.h" ++#include "d3d_device.h" ++#include "general_allocator.h" ++#include "hw_device.h" ++ ++#ifdef LIBVA_SUPPORT ++ #include "vaapi_allocator.h" ++ #include "vaapi_device.h" ++ #include "vaapi_utils.h" ++#endif ++ ++#ifndef MFX_VERSION ++ #error MFX_VERSION not defined ++#endif ++ ++namespace TranscodingSample { ++class Launcher { ++public: ++ Launcher(); ++ virtual ~Launcher(); ++ ++ virtual mfxStatus Init(int argc, msdk_char *argv[]); ++ virtual void Run(); ++ virtual mfxStatus ProcessResult(); ++ ++protected: ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ mfxStatus QueryAdapters(); ++ void ForceImplForSession(mfxU32 idxSession); ++ mfxStatus CheckAndFixAdapterDependency(mfxU32 idxSession, ++ CTranscodingPipeline *pParentPipeline); ++#endif ++ virtual mfxStatus VerifyCrossSessionsOptions(); ++ virtual mfxStatus CreateSafetyBuffers(); ++ virtual void DoTranscoding(); ++ virtual void DoRobustTranscoding(); ++ ++ virtual void Close(); ++ ++ // command line parser ++ CmdProcessor m_parser; ++ // threads contexts to process playlist ++ std::vector> m_pThreadContextArray; ++ // allocator for each session ++ std::vector> m_pAllocArray; ++ // input parameters for each session ++ std::vector m_InputParamsArray; ++ // safety buffers ++ // needed for heterogeneous pipeline ++ std::vector> m_pBufferArray; ++ ++ std::vector> m_pExtBSProcArray; ++ std::vector> m_pAllocParams; ++ std::vector> m_hwdevs; ++ msdk_tick m_StartTime; ++ // need to work with HW pipeline ++ mfxHandleType m_eDevType; ++ mfxAccelerationMode m_accelerationMode; ++ mfxU32 m_adapterNum; ++ mfxU16 m_deviceID; ++ std::unique_ptr m_pLoader; ++ ++ std::vector m_VppDstRects; ++ ++private: ++ DISALLOW_COPY_AND_ASSIGN(Launcher); ++ ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ std::vector m_DisplaysData; ++ mfxAdaptersInfo m_Adapters; ++#endif ++}; ++} // namespace TranscodingSample ++ ++#endif +diff --git a/tools/legacy/sample_multi_transcode/include/transcode_utils.h b/tools/legacy/sample_multi_transcode/include/transcode_utils.h +new file mode 100644 +index 0000000..f69aebe +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/include/transcode_utils.h +@@ -0,0 +1,111 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2019, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#ifndef __TRANSCODE_UTILS_H__ ++#define __TRANSCODE_UTILS_H__ ++ ++#if defined(_WIN32) || defined(_WIN64) ++ #include ++ #pragma warning(disable : 4201) ++ #include ++ #include ++#endif ++ ++#include ++#include ++#include "pipeline_transcode.h" ++ ++struct D3DAllocatorParams; ++ ++#ifdef _MSC_VER ++ #pragma warning(disable : 4127) // constant expression ++#endif ++ ++// Extensions for internal use, normally these macros are blank ++#ifdef MOD_SMT ++ #include "extension_macros.h" ++#else ++ #define MOD_SMT_CREATE_PIPELINE ++ #define MOD_SMT_PRINT_HELP ++ #define MOD_SMT_PARSE_INPUT ++#endif ++ ++#ifndef MFX_VERSION ++ #error MFX_VERSION not defined ++#endif ++ ++namespace TranscodingSample { ++struct sInputParams; ++ ++msdk_tick GetTick(); ++mfxF64 GetTime(msdk_tick start); ++ ++void PrintHelp(); ++void PrintError(const msdk_char *strErrorMessage, ...); ++void PrintInfo(mfxU32 session_number, sInputParams *pParams, mfxVersion *pVer); ++ ++bool PrintDllInfo(msdk_char *buf, mfxU32 buf_size, sInputParams *pParams); ++ ++class CmdProcessor { ++public: ++ CmdProcessor(); ++ virtual ~CmdProcessor(); ++ mfxStatus ParseCmdLine(int argc, msdk_char *argv[]); ++ bool GetNextSessionParams(TranscodingSample::sInputParams &InputParams); ++ FILE *GetPerformanceFile() { ++ return m_PerfFILE; ++ }; ++ void PrintParFileName(); ++ msdk_string GetLine(mfxU32 n); ++ ++protected: ++ mfxStatus ParseParFile(FILE *file); ++ mfxStatus TokenizeLine(msdk_char *pLine, mfxU32 length); ++ mfxU32 GetStringLength(msdk_char *pTempLine, mfxU32 length); ++ ++#if MFX_VERSION >= 1022 ++ static bool isspace(char a); ++ static bool is_not_allowed_char(char a); ++ bool ParseROIFile(msdk_char const *roi_file_name, std::vector &m_ROIData); ++#endif //MFX_VERSION >= 1022 ++ ++ mfxStatus ParseParamsForOneSession(mfxU32 argc, msdk_char *argv[]); ++ mfxStatus ParseOption__set(msdk_char *strCodecType, msdk_char *strPluginPath); ++ mfxStatus VerifyAndCorrectInputParams(TranscodingSample::sInputParams &InputParams); ++ mfxU32 m_SessionParamId; ++ std::vector m_SessionArray; ++ std::map m_decoderPlugins; ++ std::map m_encoderPlugins; ++ FILE *m_PerfFILE; ++ msdk_char *m_parName; ++ mfxU32 statisticsWindowSize; ++ FILE *statisticsLogFile; ++ //store a name of a Logfile ++ msdk_tstring DumpLogFileName; ++ mfxU32 m_nTimeout; ++ bool bRobustFlag; ++ bool bSoftRobustFlag; ++ bool shouldUseGreedyFormula; ++ std::vector m_lines; ++ ++private: ++ DISALLOW_COPY_AND_ASSIGN(CmdProcessor); ++}; ++} // namespace TranscodingSample ++#endif //__TRANSCODE_UTILS_H__ +diff --git a/tools/legacy/sample_multi_transcode/src/pipeline_transcode.cpp b/tools/legacy/sample_multi_transcode/src/pipeline_transcode.cpp +new file mode 100644 +index 0000000..5815df1 +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/src/pipeline_transcode.cpp +@@ -0,0 +1,4668 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2020, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#include "mfx_samples_config.h" ++ ++#if defined(_WIN32) || defined(_WIN64) ++ #include ++#endif ++ ++#include "mfxdispatcher.h" ++#include "pipeline_transcode.h" ++#include "sample_utils.h" ++#include "transcode_utils.h" ++#if !defined(MFX_ONEVPL) ++ #include "mfx_vpp_plugin.h" ++#endif ++#include ++#include ++#include ++#include "mfx_itt_trace.h" ++ ++#include "parameters_dumper.h" ++ ++#include "sample_utils.h" ++ ++// let's use std::max and std::min instead ++#undef max ++#undef min ++ ++#ifndef MFX_VERSION ++ #error MFX_VERSION not defined ++#endif ++ ++using namespace TranscodingSample; ++ ++#ifdef ENABLE_MCTF ++namespace TranscodingSample { ++const sMctfRunTimeParam *sMctfRunTimeParams::GetCurParam() { ++ if (CurIdx >= RunTimeParams.size()) ++ return NULL; ++ else ++ return &(RunTimeParams[CurIdx]); ++} ++ ++void sMctfRunTimeParams::MoveForward() { ++ if (CurIdx < RunTimeParams.size()) ++ ++CurIdx; ++} ++ ++void sMctfRunTimeParams::Restart() { ++ CurIdx = 0; ++} ++ ++void sMctfRunTimeParams::Reset() { ++ CurIdx = 0; ++ RunTimeParams.clear(); ++} ++} // namespace TranscodingSample ++#endif ++ ++mfxFrameInfo GetFrameInfo(const MfxVideoParamsWrapper ¶m) { ++ mfxFrameInfo frameInfo = param.mfx.FrameInfo; ++ auto decPostProc = param.GetExtBuffer(); ++ if (decPostProc) { ++ frameInfo.Width = decPostProc->Out.Width; ++ frameInfo.Height = decPostProc->Out.Height; ++ frameInfo.CropW = decPostProc->Out.CropW; ++ frameInfo.CropH = decPostProc->Out.CropH; ++ } ++ ++ return frameInfo; ++} ++ ++// set structure to define values ++sInputParams::sInputParams() : __sInputParams() { ++#ifdef ENABLE_MCTF ++ mctfParam.mode = VPP_FILTER_DISABLED; ++ mctfParam.params.FilterStrength = 0; ++ mctfParam.rtParams.Reset(); ++ #ifdef ENABLE_MCTF_EXT ++ mctfParam.params.BitsPerPixelx100k = 0; ++ mctfParam.params.Deblocking = MFX_CODINGOPTION_OFF; ++ mctfParam.params.Overlap = MFX_CODINGOPTION_OFF; ++ mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_2REF; ++ mctfParam.params.MVPrecision = MFX_MVPRECISION_INTEGER; ++ #endif ++#endif ++ priority = MFX_PRIORITY_NORMAL; ++ libType = MFX_IMPL_SOFTWARE; ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ //Adapter type ++ bPrefferiGfx = false; ++ bPrefferdGfx = false; ++#endif ++ MaxFrameNumber = MFX_INFINITE; ++ pVppCompDstRects = NULL; ++ m_hwdev = NULL; ++ DenoiseLevel = -1; ++ DetailLevel = -1; ++ ++#if (MFX_VERSION >= 1025) ++ MFMode = MFX_MF_DEFAULT; ++ numMFEFrames = 0; ++ mfeTimeout = 0; ++#endif ++ ++#if MFX_VERSION >= 1022 ++ bDecoderPostProcessing = false; ++ bROIasQPMAP = false; ++#endif ++} ++ ++CTranscodingPipeline::CTranscodingPipeline() ++ : m_pmfxBS(NULL), ++ m_pMFXAllocator(NULL), ++ m_hdl(NULL), ++ m_encoderFourCC(0), ++ m_vppCompDumpRenderMode(0), ++ m_hwdev4Rendering(NULL), ++ m_EncSurfaceType(0), ++ m_DecSurfaceType(0), ++ m_bIsVpp(false), ++ m_bIsPlugin(false), ++ m_nTimeout(0), ++ m_bOwnMVCSeqDescMemory(true), ++ m_nID(0), ++ m_AsyncDepth(0), ++ m_nProcessedFramesNum(0), ++ m_bIsJoinSession(false), ++ m_bDecodeEnable(true), ++ m_bEncodeEnable(true), ++ m_nVPPCompEnable(0), ++ m_MemoryModel(UNKNOWN_ALLOC), ++ m_LastDecSyncPoint(0), ++ m_pBuffer(NULL), ++ m_pParentPipeline(NULL), ++ m_bIsInit(false), ++ m_NumFramesForReset(0), ++ isHEVCSW(false), ++ m_bInsertIDR(false), ++ m_rawInput(false), ++ m_FrameNumberPreference(0xFFFFFFFF), ++ m_MaxFramesForTranscode(0xFFFFFFFF), ++ m_pBSProcessor(NULL), ++ m_nReqFrameTime(0), ++ m_nOutputFramesNum(0), ++ shouldUseGreedyFormula(false), ++ m_nRotationAngle(0) { ++ MSDK_ZERO_MEMORY(m_RotateParam); ++ MSDK_ZERO_MEMORY(m_mfxDecResponse); ++ MSDK_ZERO_MEMORY(m_mfxEncResponse); ++ MSDK_ZERO_MEMORY(m_Request); ++ ++#if MFX_VERSION >= 1022 ++ m_bUseQPMap = 0; ++ m_QPmapWidth = 0; ++ m_QPmapHeight = 0; ++ m_GOPSize = 0; ++ m_QPforI = 0; ++ m_QPforP = 0; ++ m_nSubmittedFramesNum = 0; ++#endif //MFX_VERSION >= 1022 ++ ++ inputStatistics.SetDirection(MSDK_STRING("Input")); ++ outputStatistics.SetDirection(MSDK_STRING("Output")); ++ ++ m_numEncoders = 0; ++ m_encoderFourCC = 0; ++ m_libvaBackend = 0; ++ statisticsWindowSize = 0; ++ m_bIsFieldWeaving = false; ++ m_bIsFieldSplitting = false; ++ m_bUseOverlay = false; ++ m_bForceStop = false; ++ m_bIsInterOrJoined = false; ++ m_bRobustFlag = false; ++ m_bSoftGpuHangRecovery = false; ++ m_nRotationAngle = 0; ++ m_bROIasQPMAP = false; ++ m_bExtMBQP = false; ++} //CTranscodingPipeline::CTranscodingPipeline() ++ ++CTranscodingPipeline::~CTranscodingPipeline() { ++ Close(); ++} //CTranscodingPipeline::CTranscodingPipeline() ++ ++mfxStatus CTranscodingPipeline::CheckRequiredAPIVersion(mfxVersion &version, ++ sInputParams *pParams) { ++ MSDK_CHECK_POINTER(pParams, MFX_ERR_NULL_PTR); ++ ++ if (pParams->bIsMVC && !CheckVersion(&version, MSDK_FEATURE_MVC)) { ++ msdk_printf(MSDK_STRING("error: MVC is not supported in the %d.%d API version\n"), ++ version.Major, ++ version.Minor); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if ((pParams->DecodeId == MFX_CODEC_JPEG) && ++ !CheckVersion(&version, MSDK_FEATURE_JPEG_DECODE)) { ++ msdk_printf(MSDK_STRING("error: Jpeg decoder is not supported in the %d.%d API version\n"), ++ version.Major, ++ version.Minor); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if ((pParams->EncodeId == MFX_CODEC_JPEG) && ++ !CheckVersion(&version, MSDK_FEATURE_JPEG_ENCODE)) { ++ msdk_printf(MSDK_STRING("error: Jpeg encoder is not supported in the %d.%d API version\n"), ++ version.Major, ++ version.Minor); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((pParams->bLABRC || pParams->nLADepth) && ++ !CheckVersion(&version, MSDK_FEATURE_LOOK_AHEAD)) { ++ msdk_printf(MSDK_STRING("error: Look Ahead is not supported in the %d.%d API version\n"), ++ version.Major, ++ version.Minor); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++// initialize decode part ++mfxStatus CTranscodingPipeline::DecodePreInit(sInputParams *pParams) { ++ // initialize decode pert ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ if (m_bDecodeEnable) { ++#if !defined(MFX_ONEVPL) ++ if (CheckVersion(&m_Version, MSDK_FEATURE_PLUGIN_API)) { ++ /* Here we actually define the following codec initialization scheme: ++ * 1. If plugin path or guid is specified: we load user-defined plugin (example: VP9 sample decoder plugin) ++ * 2. If plugin path not specified: ++ * 2.a) we check if codec is distributed as a mediasdk plugin and load it if yes ++ * 2.b) if codec is not in the list of mediasdk plugins, we assume, that it is supported inside mediasdk library ++ */ ++ if (pParams->decoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && ++ msdk_strnlen(pParams->decoderPluginParams.strPluginPath, ++ sizeof(pParams->decoderPluginParams.strPluginPath))) { ++ m_pUserDecoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get())); ++ m_pUserDecoderPlugin.reset(LoadPlugin( ++ MFX_PLUGINTYPE_VIDEO_DECODE, ++ *m_pmfxSession.get(), ++ pParams->decoderPluginParams.pluginGuid, ++ 1, ++ pParams->decoderPluginParams.strPluginPath, ++ (mfxU32)msdk_strnlen(pParams->decoderPluginParams.strPluginPath, ++ sizeof(pParams->decoderPluginParams.strPluginPath)))); ++ if (m_pUserDecoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ else { ++ bool isDefaultPlugin = false; ++ if (AreGuidsEqual(pParams->decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ pParams->decoderPluginParams.pluginGuid = ++ msdkGetPluginUID(pParams->libType, MSDK_VDECODE, pParams->DecodeId); ++ isDefaultPlugin = true; ++ } ++ if (!AreGuidsEqual(pParams->decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ m_pUserDecoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, ++ *m_pmfxSession.get(), ++ pParams->decoderPluginParams.pluginGuid, ++ 1)); ++ if (m_pUserDecoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ if (sts == MFX_ERR_UNSUPPORTED) { ++ msdk_printf( ++ isDefaultPlugin ++ ? MSDK_STRING( ++ "Default plugin cannot be loaded (possibly you have to define plugin explicitly)\n") ++ : MSDK_STRING("Explicitly specified plugin cannot be loaded.\n")); ++ } ++ } ++ MSDK_CHECK_STATUS(sts, "LoadPlugin failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ // create decoder ++ if (!m_bUseOverlay) { ++ m_pmfxDEC.reset(new MFXVideoDECODE(*m_pmfxSession.get())); ++ } ++ ++ // set video type in parameters ++ m_mfxDecParams.mfx.CodecId = pParams->DecodeId; ++ ++ // configure specific decoder parameters ++ sts = InitDecMfxParams(pParams); ++ if (MFX_ERR_MORE_DATA == sts) { ++ m_pmfxDEC.reset(NULL); ++ return sts; ++ } ++ else { ++ MSDK_CHECK_STATUS(sts, "InitDecMfxParams failed"); ++ } ++ } ++#if !defined(MFX_ONEVPL) ++ else { ++ m_mfxDecParams = m_pParentPipeline->GetDecodeParam(); ++ auto mvc = m_mfxDecParams.AddExtBuffer(); ++ *mvc = m_pParentPipeline->GetDecMVCSeqDesc(); ++ m_bOwnMVCSeqDescMemory = false; ++ } ++#endif ++ ++ if (pParams->nFPS) { ++ this->m_nReqFrameTime = 1000000 / pParams->nFPS; ++ } ++ ++ return sts; ++ ++} //mfxStatus CTranscodingPipeline::Init(sInputParams *pParams) ++ ++mfxStatus CTranscodingPipeline::VPPPreInit(sInputParams *pParams) { ++ mfxStatus sts = MFX_ERR_NONE; ++ bool bVppCompInitRequire = false; ++ m_bIsFieldWeaving = false; ++ m_bIsFieldSplitting = false; ++ ++ if (((pParams->eModeExt == VppComp) || (pParams->eModeExt == VppCompOnly)) && ++ (pParams->eMode == Source)) ++ bVppCompInitRequire = true; ++ ++ // Obtaining decoder output FourCC - in case of inter-session, just take it from params, in intra-session case, take it from parent session ++ // In inter-session case, we'll enable chroma-changing VPP only in encoding session, and only if decoderFourCC!=encoderFourCC ++ mfxU32 decoderFourCC = m_bDecodeEnable ++ ? m_mfxDecParams.mfx.FrameInfo.FourCC ++ : m_pParentPipeline->GetDecodeParam().mfx.FrameInfo.FourCC; ++ ++ if (m_bEncodeEnable || m_bDecodeEnable) { ++ if (m_mfxDecParams.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_FIELD_SINGLE && ++ pParams->EncodeId != MFX_CODEC_HEVC && !pParams->bEnableDeinterlacing) { ++ m_bIsFieldWeaving = true; ++ m_bIsVpp = true; ++ } ++ ++ if ((m_mfxDecParams.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_TFF || ++ m_mfxDecParams.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_BFF || ++ m_mfxDecParams.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_UNKNOWN) && ++ pParams->EncodeId == MFX_CODEC_HEVC && pParams->DecodeId != MFX_CODEC_HEVC && ++ !pParams->bEnableDeinterlacing) { ++ m_bIsFieldSplitting = true; ++ m_bIsVpp = true; ++ m_mfxVppParams.vpp.In.PicStruct = MFX_PICSTRUCT_UNKNOWN; ++ } ++ ++ if ((GetFrameInfo(m_mfxDecParams).CropW != pParams->nDstWidth && pParams->nDstWidth) || ++ (GetFrameInfo(m_mfxDecParams).CropH != pParams->nDstHeight && pParams->nDstHeight) || ++ (pParams->bEnableDeinterlacing) || (pParams->DenoiseLevel != -1) || ++ (pParams->DetailLevel != -1) || (pParams->FRCAlgorithm) || (bVppCompInitRequire) || ++ (pParams->fieldProcessingMode) || ++#ifdef ENABLE_MCTF ++ (VPP_FILTER_DISABLED != pParams->mctfParam.mode) || ++#endif ++ (pParams->EncoderFourCC && decoderFourCC && pParams->EncoderFourCC != decoderFourCC && ++ m_bEncodeEnable)) { ++ if (m_bIsFieldWeaving || m_bIsFieldSplitting) { ++ msdk_printf(MSDK_STRING( ++ "ERROR: Field weaving or Field Splitting is enabled according to streams parameters. Other VPP filters cannot be used in this mode, please remove corresponding options.\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ m_bIsVpp = true; ++ } ++ ++ if (m_bIsVpp) { ++ sts = InitVppMfxParams(pParams); ++ MSDK_CHECK_STATUS(sts, "InitVppMfxParams failed"); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (pParams->nRotationAngle) // plugin was requested ++ { ++ m_bIsPlugin = true; ++ sts = InitPluginMfxParams(pParams); ++ MSDK_CHECK_STATUS(sts, "InitPluginMfxParams failed"); ++ sts = LoadGenericPlugin(); ++ MSDK_CHECK_STATUS(sts, "LoadGenericPlugin failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ if (!m_bIsPlugin && m_bIsVpp) // only VPP was requested ++ { ++ m_pmfxVPP.reset(new MFXVideoMultiVPP(*m_pmfxSession.get())); ++ } ++ } ++ ++ return sts; ++ ++} //mfxStatus CTranscodingPipeline::VPPInit(sInputParams *pParams) ++ ++mfxStatus CTranscodingPipeline::EncodePreInit(sInputParams *pParams) { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ if (m_bEncodeEnable) { ++ if (pParams->EncodeId != MFX_CODEC_DUMP) { ++#if !defined(MFX_ONEVPL) ++ if (CheckVersion(&m_Version, MSDK_FEATURE_PLUGIN_API) && ++ (m_pUserEncPlugin.get() == NULL)) { ++ /* Here we actually define the following codec initialization scheme: ++ * 1. If plugin path or guid is specified: we load user-defined plugin (example: HEVC encoder plugin) ++ * 2. If plugin path not specified: ++ * 2.a) we check if codec is distributed as a mediasdk plugin and load it if yes ++ * 2.b) if codec is not in the list of mediasdk plugins, we assume, that it is supported inside mediasdk library ++ */ ++ if (pParams->encoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && ++ msdk_strnlen(pParams->encoderPluginParams.strPluginPath, ++ sizeof(pParams->encoderPluginParams.strPluginPath))) { ++ m_pUserEncoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get())); ++ m_pUserEncoderPlugin.reset(LoadPlugin( ++ MFX_PLUGINTYPE_VIDEO_ENCODE, ++ *m_pmfxSession.get(), ++ pParams->encoderPluginParams.pluginGuid, ++ 1, ++ pParams->encoderPluginParams.strPluginPath, ++ (mfxU32)msdk_strnlen(pParams->encoderPluginParams.strPluginPath, ++ sizeof(pParams->encoderPluginParams.strPluginPath)))); ++ if (m_pUserEncoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ else { ++ bool isDefaultPlugin = false; ++ if (AreGuidsEqual(pParams->encoderPluginParams.pluginGuid, ++ MSDK_PLUGINGUID_NULL)) { ++ pParams->encoderPluginParams.pluginGuid = ++ msdkGetPluginUID(pParams->libType, MSDK_VENCODE, pParams->EncodeId); ++ isDefaultPlugin = true; ++ } ++ if (!AreGuidsEqual(pParams->encoderPluginParams.pluginGuid, ++ MSDK_PLUGINGUID_NULL)) { ++ m_pUserEncoderPlugin.reset( ++ LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, ++ *m_pmfxSession.get(), ++ pParams->encoderPluginParams.pluginGuid, ++ 1)); ++ if (m_pUserEncoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ if (sts == MFX_ERR_UNSUPPORTED) { ++ msdk_printf( ++ MSDK_STRING("%s"), ++ isDefaultPlugin ++ ? MSDK_STRING( ++ "Default plugin cannot be loaded (possibly you have to define plugin explicitly)\n") ++ : MSDK_STRING("Explicitly specified plugin cannot be loaded.\n")); ++ } ++ } ++ MSDK_CHECK_STATUS(sts, "LoadPlugin failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ // create encoder ++ m_pmfxENC.reset(new MFXVideoENCODE(*m_pmfxSession.get())); ++ ++ if (m_nVPPCompEnable == VppCompOnlyEncode) { ++ pParams->EncoderFourCC = MFX_FOURCC_NV12; ++ } ++ ++ sts = InitEncMfxParams(pParams); ++ MSDK_CHECK_STATUS(sts, "InitEncMfxParams failed"); ++ ++ // Querying parameters ++ mfxU16 ioPattern = m_mfxEncParams.IOPattern; ++ mfxU16 initialTargetKbps = m_mfxEncParams.mfx.TargetKbps; ++ auto co2 = m_mfxEncParams.GetExtBuffer(); ++ ++ msdk_stringstream str1, str2; ++ CParametersDumper().SerializeVideoParamStruct(str1, MSDK_STRING(""), m_mfxEncParams); ++ ++ sts = m_pmfxENC->Query(&m_mfxEncParams, &m_mfxEncParams); ++ ++ CParametersDumper().SerializeVideoParamStruct(str2, MSDK_STRING(""), m_mfxEncParams); ++ ++ m_mfxEncParams.IOPattern = ++ ioPattern; // Workaround for a problem: Query changes IOPattern incorrectly ++ ++ if (sts == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM) { ++ if (co2 && co2->BitrateLimit != MFX_CODINGOPTION_OFF && ++ initialTargetKbps != m_mfxEncParams.mfx.TargetKbps) { ++ msdk_printf( ++ MSDK_STRING("[WARNING] -BitrateLimit:on, target bitrate was changed\n")); ++ } ++ ++ msdk_printf(MSDK_STRING("[WARNING] Configuration changed on the Query() call\n")); ++ ++ CParametersDumper().ShowConfigurationDiff(str1, str2); ++ MSDK_IGNORE_MFX_STS(sts, MFX_WRN_INCOMPATIBLE_VIDEO_PARAM); ++ } ++ ++ MSDK_CHECK_STATUS(sts, "m_pmfxENC->Query failed"); ++ } ++ else { ++ //--- This one is required for YUV output ++ m_mfxEncParams.mfx.CodecId = pParams->EncodeId; ++ } ++ } ++ return sts; ++ ++} // mfxStatus CTranscodingPipeline::EncodeInit(sInputParams *pParams) ++ ++#if !defined(MFX_ONEVPL) ++mfxStatus CTranscodingPipeline::PreEncPreInit(sInputParams *pParams) { ++ mfxStatus sts = MFX_ERR_NONE; ++ // PreInit is allowed in decoder session only ++ if (pParams->bEnableExtLA && m_bDecodeEnable) { ++ /* Here we actually define the following codec initialization scheme: ++ * a) we check if codec is distributed as a user plugin and load it if yes ++ * b) we check if codec is distributed as a mediasdk plugin and load it if yes ++ * c) if codec is not in the list of user plugins or mediasdk plugins, we assume, that it is supported inside mediasdk library ++ */ ++ ++ m_pUserEncPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, ++ *m_pmfxSession.get(), ++ MFX_PLUGINID_H264LA_HW, ++ 1)); ++ if (m_pUserEncPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ ++ // create encoder ++ m_pmfxPreENC.reset(new MFXVideoENC(*m_pmfxSession.get())); ++ ++ sts = InitPreEncMfxParams(pParams); ++ MSDK_CHECK_STATUS(sts, "InitPreEncMfxParams failed"); ++ } ++ ++ return sts; ++} ++#endif //!MFX_ONEVPL ++ ++mfxVideoParam CTranscodingPipeline::GetDecodeParam() { ++ if (m_bIsVpp) { ++ mfxVideoParam tmp = m_mfxDecParams; ++ tmp.mfx.FrameInfo = m_mfxVppParams.vpp.Out; ++ return tmp; ++ } ++ else if (m_bIsPlugin) { ++ mfxVideoParam tmp = m_mfxDecParams; ++ tmp.mfx.FrameInfo = m_mfxPluginParams.mfx.FrameInfo; ++ return tmp; ++ } ++ ++ return m_mfxDecParams; ++}; ++// 1 ms provides better result in range [0..5] ms ++enum { TIME_TO_SLEEP = 1 }; ++ ++mfxStatus CTranscodingPipeline::DecodeOneFrame(ExtendedSurface *pExtSurface) { ++ MFX_ITT_TASK("DecodeOneFrame"); ++ MSDK_CHECK_POINTER(pExtSurface, MFX_ERR_NULL_PTR); ++ ++ mfxStatus sts = MFX_ERR_MORE_SURFACE; ++ mfxFrameSurface1 *pmfxSurface = NULL; ++ pExtSurface->pSurface = NULL; ++ ++ //--- Time measurements ++ if (statisticsWindowSize) { ++ inputStatistics.StopTimeMeasurementWithCheck(); ++ inputStatistics.StartTimeMeasurement(); ++ } ++ ++ CTimer DevBusyTimer; ++ DevBusyTimer.Start(); ++ while (MFX_ERR_MORE_DATA == sts || MFX_ERR_MORE_SURFACE == sts || MFX_ERR_NONE < sts) { ++ if (m_rawInput) { ++ pExtSurface->pSurface = GetFreeSurface(false, MSDK_SURFACE_WAIT_INTERVAL); ++ sts = m_pBSProcessor->GetInputFrame(pExtSurface->pSurface); ++ if (sts != MFX_ERR_NONE) ++ return sts; ++ } ++ else if (MFX_WRN_DEVICE_BUSY == sts) { ++ WaitForDeviceToBecomeFree(*m_pmfxSession, m_LastDecSyncPoint, sts); ++ } ++ else if (MFX_ERR_MORE_DATA == sts) { ++ sts = ++ m_pBSProcessor->GetInputBitstream(&m_pmfxBS); // read more data to input bit stream ++ MSDK_BREAK_ON_ERROR(sts); ++ } ++ ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ // Find new working surface ++ pmfxSurface = GetFreeSurface(true, MSDK_SURFACE_WAIT_INTERVAL); ++ { ++ std::unique_lock lock(m_mStopSession); ++ if (m_bForceStop) { ++ lock.unlock(); ++ m_nTimeout = 0; ++ // add surfaces in queue for all sinks ++ NoMoreFramesSignal(); ++ return MFX_WRN_VALUE_NOT_CHANGED; ++ } ++ } ++ MSDK_CHECK_POINTER_SAFE( ++ pmfxSurface, ++ MFX_ERR_MEMORY_ALLOC, ++ msdk_printf(MSDK_STRING( ++ "ERROR: No free surfaces in decoder pool (during long period)\n"))); // return an error if a free surface wasn't found ++ } ++#if defined(MFX_ONEVPL) ++ else if (m_MemoryModel == VISIBLE_INT_ALLOC) { ++ sts = m_pmfxDEC->GetSurface(&pmfxSurface); ++ MSDK_BREAK_ON_ERROR(sts); ++ } ++#endif //MFX_ONEVPL ++ ++ if (!m_rawInput) { ++ sts = m_pmfxDEC->DecodeFrameAsync(m_pmfxBS, ++ pmfxSurface, ++ &pExtSurface->pSurface, ++ &pExtSurface->Syncp); ++#if defined(MFX_ONEVPL) ++ if (m_MemoryModel == VISIBLE_INT_ALLOC) { ++ mfxStatus sts_release = pmfxSurface->FrameInterface->Release(pmfxSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ } ++ ++ if ((MFX_WRN_DEVICE_BUSY == sts) && (DevBusyTimer.GetTime() > MSDK_WAIT_INTERVAL / 1000)) { ++ msdk_printf(MSDK_STRING("ERROR: Decoder device busy (during long period)\n")); ++ return MFX_ERR_DEVICE_FAILED; ++ } ++ ++ if (sts == MFX_ERR_NONE) { ++ m_LastDecSyncPoint = pExtSurface->Syncp; ++ } ++ // ignore warnings if output is available, ++ if (MFX_ERR_NONE < sts && pExtSurface->Syncp) { ++ sts = MFX_ERR_NONE; ++ } ++ ++ } //while processing ++ ++ // HEVC SW requires additional synchronization ++ if (MFX_ERR_NONE == sts && isHEVCSW) { ++ sts = m_pmfxSession->SyncOperation(pExtSurface->Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Decode: SyncOperation failed"); ++ } ++ return sts; ++ ++} // mfxStatus CTranscodingPipeline::DecodeOneFrame(ExtendedSurface *pExtSurface) ++mfxStatus CTranscodingPipeline::DecodeLastFrame(ExtendedSurface *pExtSurface) { ++ MFX_ITT_TASK("DecodeLastFrame"); ++ mfxFrameSurface1 *pmfxSurface = NULL; ++ mfxStatus sts = MFX_ERR_MORE_SURFACE; ++ ++ //--- Time measurements ++ if (statisticsWindowSize) { ++ inputStatistics.StopTimeMeasurementWithCheck(); ++ inputStatistics.StartTimeMeasurement(); ++ } ++ ++ CTimer DevBusyTimer; ++ DevBusyTimer.Start(); ++ // retrieve the buffered decoded frames ++ while (MFX_ERR_MORE_SURFACE == sts || MFX_WRN_DEVICE_BUSY == sts) { ++ if (m_rawInput) { ++ pExtSurface->pSurface = GetFreeSurface(false, MSDK_SURFACE_WAIT_INTERVAL); ++ sts = m_pBSProcessor->GetInputFrame(pExtSurface->pSurface); ++ } ++ else if (MFX_WRN_DEVICE_BUSY == sts) { ++ WaitForDeviceToBecomeFree(*m_pmfxSession, m_LastDecSyncPoint, sts); ++ } ++ ++ if (!m_rawInput) { ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ // find new working surface ++ pmfxSurface = GetFreeSurface(true, MSDK_SURFACE_WAIT_INTERVAL); ++ MSDK_CHECK_POINTER_SAFE( ++ pmfxSurface, ++ MFX_ERR_MEMORY_ALLOC, ++ msdk_printf(MSDK_STRING( ++ "ERROR: No free surfaces in decoder pool (during long period)\n"))); // return an error if a free surface wasn't found ++ ++ sts = m_pmfxDEC->DecodeFrameAsync(nullptr, ++ pmfxSurface, ++ &pExtSurface->pSurface, ++ &pExtSurface->Syncp); ++ } ++#if defined(MFX_ONEVPL) ++ else if (m_MemoryModel == VISIBLE_INT_ALLOC) { ++ sts = m_pmfxDEC->GetSurface(&pmfxSurface); ++ MSDK_BREAK_ON_ERROR(sts); ++ ++ sts = m_pmfxDEC->DecodeFrameAsync(nullptr, ++ pmfxSurface, ++ &pExtSurface->pSurface, ++ &pExtSurface->Syncp); ++ ++ mfxStatus sts_release = pmfxSurface->FrameInterface->Release(pmfxSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ else { ++ sts = m_pmfxDEC->DecodeFrameAsync(nullptr, ++ pmfxSurface, ++ &pExtSurface->pSurface, ++ &pExtSurface->Syncp); ++ } ++ } ++ ++ if ((MFX_WRN_DEVICE_BUSY == sts) && (DevBusyTimer.GetTime() > MSDK_WAIT_INTERVAL / 1000)) { ++ msdk_printf(MSDK_STRING("ERROR: Decoder device busy (during long period)\n")); ++ return MFX_ERR_DEVICE_FAILED; ++ } ++ } ++ ++ // HEVC SW requires additional synchronization ++ if (MFX_ERR_NONE == sts && isHEVCSW) { ++ sts = m_pmfxSession->SyncOperation(pExtSurface->Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Decode: SyncOperation failed"); ++ } ++ ++ return sts; ++} ++ ++mfxStatus CTranscodingPipeline::VPPOneFrame(ExtendedSurface *pSurfaceIn, ++ ExtendedSurface *pExtSurface) { ++ MFX_ITT_TASK("VPPOneFrame"); ++ MSDK_CHECK_POINTER(pExtSurface, MFX_ERR_NULL_PTR); ++ mfxFrameSurface1 *out_surface = NULL; ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ if (m_MemoryModel == GENERAL_ALLOC || m_MemoryModel == VISIBLE_INT_ALLOC) { ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ // find/wait for a free working surface ++ out_surface = GetFreeSurface(false, MSDK_SURFACE_WAIT_INTERVAL); ++ MSDK_CHECK_POINTER_SAFE( ++ out_surface, ++ MFX_ERR_MEMORY_ALLOC, ++ msdk_printf(MSDK_STRING( ++ "ERROR: No free surfaces for VPP in encoder pool (during long period)\n"))); // return an error if a free surface wasn't found ++ } ++#if defined(MFX_ONEVPL) ++ else if (m_MemoryModel == VISIBLE_INT_ALLOC) { ++ sts = m_pmfxVPP->GetSurfaceOut(&out_surface); ++ MFX_CHECK_STS(sts); ++ } ++#endif //MFX_ONEVPL ++ ++ // make sure picture structure has the initial value ++ // surfaces are reused and VPP may change this parameter in certain configurations ++ out_surface->Info.PicStruct = ++ m_mfxVppParams.vpp.Out.PicStruct ++ ? m_mfxVppParams.vpp.Out.PicStruct ++ : (m_bEncodeEnable ? m_mfxEncParams : m_mfxDecParams).mfx.FrameInfo.PicStruct; ++ pExtSurface->pSurface = out_surface; ++ } ++ ++#ifdef ENABLE_MCTF ++ const auto MCTFCurParam = m_MctfRTParams.GetCurParam(); ++ bool applyMCTF = !!MCTFCurParam; ++ ++ if (applyMCTF && pSurfaceIn->pSurface) { ++ auto surface = static_cast(pSurfaceIn->pSurface); ++ ++ auto mctf = surface->AddExtBuffer(); ++ mctf->FilterStrength = MCTFCurParam->FilterStrength; ++ #if defined ENABLE_MCTF_EXT ++ mctf->BitsPerPixelx100k = mfxU32(MCTF_LOSSLESS_BPP * MCTF_BITRATE_MULTIPLIER); ++ mctf->Deblocking = MFX_CODINGOPTION_OFF; ++ #endif ++ m_MctfRTParams.MoveForward(); ++ } ++#endif ++ ++ for (;;) { ++ if (m_MemoryModel == GENERAL_ALLOC || m_MemoryModel == VISIBLE_INT_ALLOC) { ++ sts = m_pmfxVPP->RunFrameVPPAsync(pSurfaceIn->pSurface, ++ out_surface, ++ NULL, ++ &pExtSurface->Syncp); ++ } ++#if defined(MFX_ONEVPL) ++ else { ++ sts = m_pmfxVPP->ProcessFrameAsync(pSurfaceIn->pSurface, &pExtSurface->pSurface); ++ } ++#endif ++ ++ if (MFX_ERR_NONE < sts) { ++ if ((m_MemoryModel != HIDDEN_INT_ALLOC && !pExtSurface->Syncp) || ++ (m_MemoryModel == HIDDEN_INT_ALLOC && ++ !out_surface)) // repeat the call if warning and no output ++ { ++ if (MFX_WRN_DEVICE_BUSY == sts) ++ MSDK_SLEEP(1); // wait if device is busy ++ } ++ else { ++ sts = MFX_ERR_NONE; // ignore warnings if output is available ++ break; ++ } ++ } ++ else { ++ break; ++ } ++ } ++ ++ return sts; ++ ++} // mfxStatus CTranscodingPipeline::DecodeOneFrame(ExtendedSurface *pExtSurface) ++ ++mfxStatus CTranscodingPipeline::EncodeOneFrame(ExtendedSurface *pExtSurface, ++ mfxBitstreamWrapper *pBS) { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ if (!pBS->Data) { ++ sts = AllocateSufficientBuffer(pBS); ++ MSDK_CHECK_STATUS(sts, "AllocateSufficientBuffer failed"); ++ } ++ ++ for (;;) { ++ // at this point surface for encoder contains either a frame from file or a frame processed by vpp ++ sts = m_pmfxENC->EncodeFrameAsync(pExtSurface->pEncCtrl, ++ pExtSurface->pSurface, ++ pBS, ++ &pExtSurface->Syncp); ++ ++ if (MFX_ERR_NONE < sts && !pExtSurface->Syncp) // repeat the call if warning and no output ++ { ++ if (MFX_WRN_DEVICE_BUSY == sts) ++ MSDK_SLEEP(TIME_TO_SLEEP); // wait if device is busy ++ } ++ else if (MFX_ERR_NONE < sts && pExtSurface->Syncp) { ++ sts = MFX_ERR_NONE; // ignore warnings if output is available ++ break; ++ } ++ else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts) { ++ sts = AllocateSufficientBuffer(pBS); ++ MSDK_CHECK_STATUS(sts, "AllocateSufficientBuffer failed"); ++ } ++ else { ++ break; ++ } ++ } ++ ++ return sts; ++ ++} //CTranscodingPipeline::EncodeOneFrame(ExtendedSurface *pExtSurface) ++ ++#if !defined(MFX_ONEVPL) ++mfxStatus CTranscodingPipeline::PreEncOneFrame(ExtendedSurface *pInSurface, ++ ExtendedSurface *pOutSurface) { ++ mfxStatus sts = MFX_ERR_NONE; ++ PreEncAuxBuffer *pAux = NULL; ++ ++ for (mfxU32 i = 0; i < MSDK_WAIT_INTERVAL; i += TIME_TO_SLEEP) { ++ pAux = GetFreePreEncAuxBuffer(); ++ if (pAux) { ++ break; ++ } ++ else { ++ MSDK_SLEEP(TIME_TO_SLEEP); ++ } ++ } ++ MSDK_CHECK_POINTER(pAux, MFX_ERR_MEMORY_ALLOC); ++ for (;;) { ++ pAux->encInput.InSurface = pInSurface->pSurface; ++ // at this point surface for encoder contains either a frame from file or a frame processed by vpp ++ sts = ++ m_pmfxPreENC->ProcessFrameAsync(&pAux->encInput, &pAux->encOutput, &pOutSurface->Syncp); ++ ++ if (MFX_ERR_NONE < sts && !pOutSurface->Syncp) // repeat the call if warning and no output ++ { ++ if (MFX_WRN_DEVICE_BUSY == sts) ++ MSDK_SLEEP(TIME_TO_SLEEP); // wait if device is busy ++ } ++ else if (MFX_ERR_NONE <= sts && pOutSurface->Syncp) { ++ LockPreEncAuxBuffer(pAux); ++ pOutSurface->pAuxCtrl = pAux; ++ MSDK_CHECK_POINTER(pAux->encOutput.ExtParam, MFX_ERR_NULL_PTR); ++ MSDK_CHECK_NOT_EQUAL(pAux->encOutput.NumExtParam, 1, MFX_ERR_UNSUPPORTED); ++ pOutSurface->pSurface = ++ ((mfxExtLAFrameStatistics *)pAux->encOutput.ExtParam[0])->OutSurface; ++ sts = MFX_ERR_NONE; // ignore warnings if output is available ++ break; ++ } ++ else { ++ break; ++ } ++ } ++ return sts; ++} ++#endif //!MFX_ONEVPL ++ ++// signal that there are no more frames ++void CTranscodingPipeline::NoMoreFramesSignal() { ++ SafetySurfaceBuffer *pNextBuffer = m_pBuffer; ++ ++ // For transcoding pipelines (PipelineMode::Native) this pointer is null ++ if (!pNextBuffer) ++ return; ++ ++ ExtendedSurface surf = {}; ++ pNextBuffer->AddSurface(surf); ++ ++ /*if 1_to_N mode */ ++ if (0 == m_nVPPCompEnable) { ++ while (pNextBuffer->m_pNext) { ++ pNextBuffer = pNextBuffer->m_pNext; ++ pNextBuffer->AddSurface(surf); ++ } ++ } ++} ++ ++void CTranscodingPipeline::StopSession() { ++ std::lock_guard guard(m_mStopSession); ++ m_bForceStop = true; ++ ++ msdk_stringstream ss; ++ ss << MSDK_STRING("session [") << GetSessionText() << MSDK_STRING("] m_bForceStop is set") ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++} ++ ++bool CTranscodingPipeline::IsOverlayUsed() { ++ return m_bUseOverlay; ++} ++ ++mfxStatus CTranscodingPipeline::Decode() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ ExtendedSurface DecExtSurface = { 0 }; ++ ExtendedSurface VppExtSurface = { 0 }; ++ ExtendedSurface PreEncExtSurface = { 0 }; ++ bool shouldReadNextFrame = true; ++ ++ SafetySurfaceBuffer *pNextBuffer = m_pBuffer; ++ bool bEndOfFile = false; ++ bool bLastCycle = false; ++ time_t start = time(0); ++ ++ { ++ std::unique_lock lock(m_mStopSession); ++ if (m_bForceStop) { ++ lock.unlock(); ++ // add surfaces in queue for all sinks ++ NoMoreFramesSignal(); ++ return MFX_WRN_VALUE_NOT_CHANGED; ++ } ++ } ++ ++ if (m_bUseOverlay) { ++ PreEncExtSurface.pSurface = m_pSurfaceDecPool[0]; ++ ++ if (pNextBuffer->GetLength() == 0) { ++ // add surfaces in queue for all sinks ++ pNextBuffer->AddSurface(PreEncExtSurface); ++ m_nProcessedFramesNum++; ++ } ++ return MFX_ERR_NONE; ++ } ++ ++ while (MFX_ERR_NONE == sts) { ++ pNextBuffer = m_pBuffer; ++ ++ if (time(0) - start >= m_nTimeout) ++ bLastCycle = true; ++ ++ if (bLastCycle) ++ SetNumFramesForReset(0); ++ ++ msdk_tick nBeginTime = msdk_time_get_tick(); // microseconds. ++ ++ if (shouldReadNextFrame) { ++ if (!bEndOfFile) { ++ if (!m_bUseOverlay) { ++ sts = DecodeOneFrame(&DecExtSurface); ++ if (MFX_ERR_MORE_DATA == sts) { ++ sts = bLastCycle ? DecodeLastFrame(&DecExtSurface) : MFX_ERR_MORE_DATA; ++ bEndOfFile = bLastCycle ? true : false; ++ } ++ } ++ else { ++ // Use preloaded overlay frame ++ DecExtSurface.pSurface = m_pSurfaceDecPool[0]; ++ sts = MFX_ERR_NONE; ++ } ++ } ++ else { ++ sts = DecodeLastFrame(&DecExtSurface); ++ } ++ ++ if (sts == MFX_ERR_NONE) { ++ // print statistics if m_nProcessedFramesNum is multiple of ++ // statisticsWindowSize OR we at the end of file AND ++ // statisticsWindowSize is not zero ++ if (statisticsWindowSize && m_nProcessedFramesNum && ++ ((0 == m_nProcessedFramesNum % statisticsWindowSize) || bEndOfFile)) { ++ inputStatistics.PrintStatistics(GetPipelineID()); ++ inputStatistics.ResetStatistics(); ++ } ++ } ++ if (sts == MFX_ERR_MORE_DATA && (m_pmfxVPP.get() ++#if !defined(MFX_ONEVPL) ++ || m_pmfxPreENC.get() ++#endif ++ )) { ++ DecExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames ++ sts = MFX_ERR_NONE; ++ } ++ if (!bLastCycle && (DecExtSurface.pSurface == NULL)) { ++ m_pBSProcessor->ResetInput(); ++ ++ if (!GetNumFramesForReset()) ++ SetNumFramesForReset(m_nProcessedFramesNum); ++ sts = MFX_ERR_NONE; ++ continue; ++ } ++ MSDK_BREAK_ON_ERROR(sts); ++ } ++ ++ if (m_pmfxVPP.get() && !m_rawInput) { ++ if (m_bIsFieldWeaving) { ++ // We might have 2 cases: decoder gives us pairs (TF BF)... or (BF)(TF). In first case we should set TFF for output, in second - BFF. ++ // So, if even input surface is BF, we set TFF for output and vise versa. For odd input surface - no matter what we set. ++ if (!(m_nProcessedFramesNum % 2)) { ++ if (DecExtSurface.pSurface) { ++ if ((DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF)) { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_BFF; ++ } ++ if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF) { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_TFF; ++ } ++ } ++ } ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ else { ++ if (m_bIsFieldSplitting) { ++ if (DecExtSurface.pSurface) { ++ if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF || ++ DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF) { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_SINGLE; ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ else { ++ VppExtSurface.pSurface = DecExtSurface.pSurface; ++ VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl; ++ VppExtSurface.Syncp = DecExtSurface.Syncp; ++ } ++ } ++ else { ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ } ++ else { ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ } ++ // check for interlaced stream ++ ++#if defined(MFX_ONEVPL) ++ if (m_MemoryModel != GENERAL_ALLOC && DecExtSurface.pSurface) { ++ mfxStatus sts_release = ++ DecExtSurface.pSurface->FrameInterface->Release(DecExtSurface.pSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ } ++ else // no VPP - just copy pointers ++ { ++ VppExtSurface.pSurface = DecExtSurface.pSurface; ++ VppExtSurface.Syncp = DecExtSurface.Syncp; ++ } ++ ++ //--- Sometimes VPP may return 2 surfaces on output, for the first one it'll return status MFX_ERR_MORE_SURFACE - we have to call VPPOneFrame again in this case ++ if (MFX_ERR_MORE_SURFACE == sts) { ++ shouldReadNextFrame = false; ++ sts = MFX_ERR_NONE; ++ } ++ else { ++ shouldReadNextFrame = true; ++ } ++ ++ if (sts == MFX_ERR_MORE_DATA || !VppExtSurface.pSurface) { ++ if (!bEndOfFile) { ++ sts = MFX_ERR_NONE; ++ continue; // go get next frame from Decode ++ } ++ } ++#if !defined(MFX_ONEVPL) ++ if (sts == MFX_ERR_MORE_DATA && m_pmfxPreENC.get()) { ++ VppExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames ++ sts = MFX_ERR_NONE; ++ } ++#endif //!MFX_ONEVPL ++ ++ MSDK_BREAK_ON_ERROR(sts); ++ ++#if !defined(MFX_ONEVPL) ++ if (m_pmfxPreENC.get()) { ++ sts = PreEncOneFrame(&VppExtSurface, &PreEncExtSurface); ++ } ++ else // no VPP - just copy pointers ++#endif //!MFX_ONEVPL ++ { ++ PreEncExtSurface.pSurface = VppExtSurface.pSurface; ++ PreEncExtSurface.Syncp = VppExtSurface.Syncp; ++ } ++ ++ if (sts == MFX_ERR_MORE_DATA || !PreEncExtSurface.pSurface) { ++ if (!bEndOfFile) { ++ sts = MFX_ERR_NONE; ++ continue; // go get next frame from Decode ++ } ++ } ++ if (!bLastCycle) { ++ sts = MFX_ERR_NONE; ++ } ++ MSDK_BREAK_ON_ERROR(sts); ++ ++ // If session is not joined and it is not parent - synchronize. ++ // If there was PreENC plugin in the pipeline - synchronize, because ++ // plugin will output data to the extended buffers and mediasdk can't ++ // track such dependency on its own. ++ if ((!m_bIsJoinSession && m_pParentPipeline) ++#if !defined(MFX_ONEVPL) ++ || m_pmfxPreENC.get() ++#endif ++ ) { ++ MFX_ITT_TASK("SyncOperation"); ++ sts = m_pmfxSession->SyncOperation(PreEncExtSurface.Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ PreEncExtSurface.Syncp = NULL; ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "PreEnc: SyncOperation failed"); ++ } ++ ++ // add surfaces in queue for all sinks ++ pNextBuffer->AddSurface(PreEncExtSurface); ++ /* one of key parts for N_to_1 mode: ++ * decoded frame should be in one buffer only as we have only 1 (one!) sink ++ * */ ++ if (0 == m_nVPPCompEnable) { ++ while (pNextBuffer->m_pNext) { ++ pNextBuffer = pNextBuffer->m_pNext; ++ pNextBuffer->AddSurface(PreEncExtSurface); ++ } ++ } ++ ++#if defined(MFX_ONEVPL) ++ if (m_MemoryModel != GENERAL_ALLOC && PreEncExtSurface.pSurface) { ++ mfxStatus sts_release = ++ PreEncExtSurface.pSurface->FrameInterface->Release(PreEncExtSurface.pSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ ++ // We need to synchronize oldest stored surface if we've already stored enough surfaces in buffer (buffer length >= AsyncDepth) ++ // Because we have to wait for decoder to finish processing and free some internally used surfaces ++ //mfxU32 len = pNextBuffer->GetLength(); ++ if (pNextBuffer->GetLength() >= m_AsyncDepth) { ++ ExtendedSurface frontSurface; ++ pNextBuffer->GetSurface(frontSurface); ++ ++ if (frontSurface.Syncp) { ++ sts = m_pmfxSession->SyncOperation(frontSurface.Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "SyncOperation failed"); ++ frontSurface.Syncp = NULL; ++ } ++ } ++ ++ if (!statisticsWindowSize && 0 == (m_nProcessedFramesNum - 1) % 100) { ++ msdk_printf(MSDK_STRING(".")); ++ } ++ ++ if (bEndOfFile && m_nTimeout) { ++ break; ++ } ++ ++ msdk_tick nFrameTime = msdk_time_get_tick() - nBeginTime; ++ if (nFrameTime < m_nReqFrameTime) { ++ MSDK_USLEEP((mfxU32)(m_nReqFrameTime - nFrameTime)); ++ } ++ if (++m_nProcessedFramesNum >= m_MaxFramesForTranscode) { ++ break; ++ } ++ } ++ ++ MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA); ++ ++ NoMoreFramesSignal(); ++ ++ if (MFX_ERR_NONE == sts) ++ sts = MFX_WRN_VALUE_NOT_CHANGED; ++ ++ return sts; ++} // mfxStatus CTranscodingPipeline::Decode() ++ ++mfxStatus CTranscodingPipeline::Encode() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ExtendedSurface DecExtSurface = {}; ++ ExtendedSurface VppExtSurface = {}; ++ ExtendedBS *pBS = NULL; ++ bool isQuit = false; ++ bool bPollFlag = false; ++ int nFramesAlreadyPut = 0; ++ SafetySurfaceBuffer *curBuffer = m_pBuffer; ++ ++ bool shouldReadNextFrame = true; ++ while (MFX_ERR_NONE == sts || MFX_ERR_MORE_DATA == sts) { ++ msdk_tick nBeginTime = msdk_time_get_tick(); // microseconds ++ if (shouldReadNextFrame) { ++ if (isQuit) { ++ // We're here because one of decoders has reported that there're no any more frames ready. ++ //So, let's pass null surface to extract data from the VPP and encoder caches. ++ ++ MSDK_ZERO_MEMORY(DecExtSurface); ++ } ++ else { ++ // Getting next frame ++ while (MFX_ERR_MORE_SURFACE == curBuffer->GetSurface(DecExtSurface)) { ++ if (MFX_ERR_NONE != ++ curBuffer->WaitForSurfaceInsertion(MSDK_SURFACE_WAIT_INTERVAL)) { ++ msdk_printf(MSDK_STRING( ++ "ERROR: timed out waiting surface from upstream component\n")); ++ return MFX_ERR_NOT_FOUND; ++ } ++ } ++ } ++ ++ // if session is not joined and it is not parent - synchronize ++ if (!m_bIsJoinSession && m_pParentPipeline) { ++ // if it is not already synchronized ++ if (DecExtSurface.Syncp) { ++ MFX_ITT_TASK("SyncOperation"); ++ sts = m_pParentPipeline->m_pmfxSession->SyncOperation(DecExtSurface.Syncp, ++ MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, ++ MFX_ERR_ABORTED, ++ "Encode: SyncOperation failed"); ++ } ++ } ++ ++ mfxU32 NumFramesForReset = ++ m_pParentPipeline ? m_pParentPipeline->GetNumFramesForReset() : 0; ++ if (NumFramesForReset && !(nFramesAlreadyPut % NumFramesForReset)) { ++ m_bInsertIDR = true; ++ } ++ ++ if (NULL == DecExtSurface.pSurface) { ++ isQuit = true; ++ } ++ } ++ ++ if (m_pmfxVPP.get()) { ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl; ++ } ++ else // no VPP - just copy pointers ++ { ++ VppExtSurface.pSurface = DecExtSurface.pSurface; ++ VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl; ++ VppExtSurface.Syncp = DecExtSurface.Syncp; ++ } ++ ++ if (MFX_ERR_MORE_SURFACE == sts) { ++ shouldReadNextFrame = false; ++ sts = MFX_ERR_NONE; ++ } ++ else { ++ shouldReadNextFrame = true; ++ } ++ ++ if (MFX_ERR_MORE_DATA == sts) { ++ if (isQuit) { ++ // to get buffered VPP or ENC frames ++ VppExtSurface.pSurface = NULL; ++ sts = MFX_ERR_NONE; ++ } ++ else { ++ curBuffer->ReleaseSurface(DecExtSurface.pSurface); ++ ++ //--- We should switch to another buffer ONLY in case of Composition ++ if (curBuffer->m_pNext != NULL && m_nVPPCompEnable > 0) { ++ curBuffer = curBuffer->m_pNext; ++ continue; ++ } ++ else { ++ curBuffer = m_pBuffer; ++ continue; /* No more buffer from decoders */ ++ } ++ } ++ } ++ ++ MSDK_CHECK_STATUS(sts, "Unexpected error!!"); ++ ++ if (m_nVPPCompEnable > 0) ++ curBuffer->ReleaseSurface(DecExtSurface.pSurface); ++ ++ // Do RenderFrame before Encode to improves on-screen performance ++ // Presentation packet would now precedes "ENC" packet within the EU ++ if ((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ if (VppExtSurface.pSurface) { ++ // Sync to ensure VPP is completed to avoid flicker ++ sts = m_pmfxSession->SyncOperation(VppExtSurface.Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "VPP: SyncOperation failed"); ++ ++ /* in case if enabled dumping into file for after VPP composition */ ++ if (DUMP_FILE_VPP_COMP == m_vppCompDumpRenderMode) { ++ sts = DumpSurface2File(VppExtSurface.pSurface); ++ MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); ++ } ++ /* Rendering may be explicitly disabled for performance measurements */ ++ if (NULL_RENDER_VPP_COMP != m_vppCompDumpRenderMode) { ++#if defined(_WIN32) || defined(_WIN64) ++ sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, m_pMFXAllocator); ++#else ++ sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, NULL); ++#endif ++ MSDK_CHECK_RESULT(sts, MFX_ERR_NONE, sts); ++ } // if (NULL_RENDER_VPP_COMP != m_vppCompDumpRenderMode) ++ } ++ } ++ ++ curBuffer = m_pBuffer; ++ ++ pBS = m_pBSStore->GetNext(); ++ if (!pBS) ++ return MFX_ERR_NOT_FOUND; ++ ++ m_BSPool.push_back(pBS); ++ ++ mfxU32 NumFramesForReset = ++ m_pParentPipeline ? m_pParentPipeline->GetNumFramesForReset() : 0; ++ if (NumFramesForReset && !(m_nProcessedFramesNum % NumFramesForReset)) { ++ m_pBSProcessor->ResetOutput(); ++ } ++ ++ SetEncCtrlRT(VppExtSurface, m_bInsertIDR); ++ m_bInsertIDR = false; ++ ++ if ((m_nVPPCompEnable != VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ if (m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP) { ++ if (bPollFlag) { ++ VppExtSurface.pSurface = 0; ++ } ++ sts = EncodeOneFrame(&VppExtSurface, &m_BSPool.back()->Bitstream); ++ ++ // Count only real surfaces ++ if (VppExtSurface.pSurface) { ++ m_nProcessedFramesNum++; ++ } ++ ++ if (m_nProcessedFramesNum >= m_MaxFramesForTranscode) { ++ bPollFlag = true; ++ } ++ ++ if (!sts) ++ nFramesAlreadyPut++; ++ } ++ else { ++ sts = Surface2BS(&VppExtSurface, &m_BSPool.back()->Bitstream, m_encoderFourCC); ++ } ++ ++#if defined(MFX_ONEVPL) ++ if (m_MemoryModel != GENERAL_ALLOC && VppExtSurface.pSurface && m_pmfxVPP) { ++ mfxStatus sts_release = ++ VppExtSurface.pSurface->FrameInterface->Release(VppExtSurface.pSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ } ++ ++ if (shouldReadNextFrame) // Release current decoded surface only if we're going to read next one during next iteration ++ { ++ m_pBuffer->ReleaseSurface(DecExtSurface.pSurface); ++ } ++ ++ // check if we need one more frame from decode ++ if (MFX_ERR_MORE_DATA == sts) { ++ // the task in not in Encode queue ++ m_BSPool.pop_back(); ++ m_pBSStore->Release(pBS); ++ ++ if (NULL == VppExtSurface.pSurface) // there are no more buffered frames in encoder ++ { ++ break; ++ } ++ else { ++ // get next frame from Decode ++ sts = MFX_ERR_NONE; ++ continue; ++ } ++ } ++ ++ // check encoding result ++ MSDK_CHECK_STATUS(sts, " failed"); ++ ++ // output statistics if several conditions are true OR we've approached ++ // the end, and statisticsWindowSize is not 0, but number of frames is ++ // not multiple of statisticsWindowSize; should use m_nProcessedFramesNum ++ // as it simplifies conditions ++ if ((statisticsWindowSize && m_nOutputFramesNum && ++ 0 == m_nProcessedFramesNum % statisticsWindowSize) || ++ (statisticsWindowSize && (m_nProcessedFramesNum >= m_MaxFramesForTranscode))) { ++ outputStatistics.PrintStatistics(GetPipelineID()); ++ outputStatistics.ResetStatistics(); ++ } ++ ++ m_BSPool.back()->Syncp = VppExtSurface.Syncp; ++ m_BSPool.back()->pCtrl = VppExtSurface.pAuxCtrl; ++ ++ /* Actually rendering... if enabled ++ * SYNC have not done by driver !!! */ ++ if ((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ if (m_BSPool.size()) { ++ ExtendedBS *pBitstreamEx_temp = m_BSPool.front(); ++ ++ // get result coded stream ++ ////Note! Better to do rendering before encode ++ // if(VppExtSurface.pSurface) ++ // { ++ // if(m_nVPPCompEnable != VppCompOnlyEncode) ++ // { ++ // sts = m_pmfxSession->SyncOperation(VppExtSurface.Syncp, MSDK_WAIT_INTERVAL); ++ // MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "VPP: SyncOperation failed"); ++ // } ++ //#if defined(_WIN32) || defined(_WIN64) ++ // sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, m_pMFXAllocator); ++ //#else ++ // sts = m_hwdev4Rendering->RenderFrame(VppExtSurface.pSurface, NULL); ++ //#endif ++ // MSDK_CHECK_STATUS(sts, "m_hwdev4Rendering->RenderFrame failed"); ++ // } ++ ++ UnPreEncAuxBuffer(pBitstreamEx_temp->pCtrl); ++ ++ if (m_nVPPCompEnable != VppCompOnlyEncode) { ++ pBitstreamEx_temp->Bitstream.DataLength = 0; ++ pBitstreamEx_temp->Bitstream.DataOffset = 0; ++ ++ m_BSPool.pop_front(); ++ m_pBSStore->Release(pBitstreamEx_temp); ++ } ++ } ++ ++ //--- If there's no data coming out from VPP and there's no data coming from decoders (isQuit==true), ++ // then we should quit, otherwise we may stuck here forever (cause there's no new data coming) ++ if (!VppExtSurface.pSurface && isQuit) { ++ break; ++ } ++ } ++ ++ if ((m_nVPPCompEnable != VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ if (m_BSPool.size() == m_AsyncDepth) { ++ sts = PutBS(); ++ MSDK_CHECK_STATUS(sts, "PutBS failed"); ++ } ++ else { ++ continue; ++ } ++ } // if (m_nVPPCompEnable != VppCompOnly) ++ ++ msdk_tick nFrameTime = msdk_time_get_tick() - nBeginTime; ++ if (nFrameTime < m_nReqFrameTime) { ++ MSDK_USLEEP((mfxU32)(m_nReqFrameTime - nFrameTime)); ++ } ++ } ++ MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA); ++ ++ if (m_nVPPCompEnable != VppCompOnly || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ // need to get buffered bitstream ++ if (MFX_ERR_NONE == sts) { ++ while (m_BSPool.size()) { ++ sts = PutBS(); ++ MSDK_CHECK_STATUS(sts, "PutBS failed"); ++ } ++ } ++ } ++ ++ // Clean up decoder buffers to avoid locking them (if some decoder still have some data to decode, but does not have enough surfaces) ++ if (m_nVPPCompEnable != 0) { ++ // Composition case - we have to clean up all buffers (all of them have data from decoders) ++ for (SafetySurfaceBuffer *buf = m_pBuffer; buf != NULL; buf = buf->m_pNext) { ++ while (buf->GetSurface(DecExtSurface) != MFX_ERR_MORE_SURFACE) { ++ buf->ReleaseSurface(DecExtSurface.pSurface); ++ buf->CancelBuffering(); ++ } ++ } ++ } ++ else { ++ // Clean up only current buffer ++ m_pBuffer->CancelBuffering(); ++ while (m_pBuffer->GetSurface(DecExtSurface) != MFX_ERR_MORE_SURFACE) { ++ m_pBuffer->ReleaseSurface(DecExtSurface.pSurface); ++ } ++ } ++ ++ // Close encoder and decoder and clean up buffers ++ if (m_pmfxENC.get()) ++ m_pmfxENC->Close(); ++ ++ if (m_pmfxVPP.get()) ++ m_pmfxVPP->Close(); ++ ++ if (MFX_ERR_NONE == sts) ++ sts = MFX_WRN_VALUE_NOT_CHANGED; ++ return sts; ++ ++} // mfxStatus CTranscodingPipeline::Encode() ++ ++#if MFX_VERSION >= 1022 ++void CTranscodingPipeline::FillMBQPBuffer(mfxExtMBQP &qpMap, mfxU16 pictStruct) { ++ // External MBQP case ++ if (m_bExtMBQP) { ++ // Use simplistic approach to fill in QP buffer ++ for (size_t i = 0; i < qpMap.NumQPAlloc; i++) { ++ qpMap.QP[i] = i % 52; ++ } ++ return; ++ } ++ ++ // External MBQP with ROI case ++ if (pictStruct == MFX_PICSTRUCT_PROGRESSIVE) { ++ mfxI8 fQP = (m_nSubmittedFramesNum % m_GOPSize) ? (mfxI8)m_QPforP : (mfxI8)m_QPforI; ++ std::memset(qpMap.QP, fQP, qpMap.NumQPAlloc); ++ ++ // printf("QP expectation: %d, map PTR %lld\n",fQP,(long long int)qpMap.QP); ++ ++ if (m_ROIData.size() > m_nSubmittedFramesNum) { ++ mfxExtEncoderROI &roi = m_ROIData[m_nSubmittedFramesNum]; ++ for (mfxI32 i = roi.NumROI - 1; i >= 0; i--) { ++ mfxU32 l = (roi.ROI[i].Left) >> 4, t = (roi.ROI[i].Top) >> 4, ++ r = (roi.ROI[i].Right + 15) >> 4, b = (roi.ROI[i].Bottom + 15) >> 4; ++ ++ //Additional 32x32 block alignment for HEVC VDEnc, using caps could be better ++ if (m_mfxEncParams.mfx.CodecId == MFX_CODEC_HEVC && ++ m_mfxEncParams.mfx.LowPower == MFX_CODINGOPTION_ON) { ++ l = ((roi.ROI[i].Left) >> 5) << 1; ++ t = ((roi.ROI[i].Top) >> 5) << 1; ++ r = ((roi.ROI[i].Right + 31) >> 5) << 1; ++ b = ((roi.ROI[i].Bottom + 31) >> 5) << 1; ++ } ++ ++ if (l > m_QPmapWidth) ++ l = m_QPmapWidth; ++ if (r > m_QPmapWidth) ++ r = m_QPmapWidth; ++ if (t > m_QPmapHeight) ++ t = m_QPmapHeight; ++ if (b > m_QPmapHeight) ++ b = m_QPmapHeight; ++ ++ mfxI8 qp_value = (mfxI8)std::min(std::max(fQP + (mfxI8)roi.ROI[i].DeltaQP, 0), 51); ++ ++ for (mfxU32 k = t; k < b; k++) ++ std::memset(qpMap.QP + k * m_QPmapWidth + l, qp_value, r - l); ++ } ++ } ++ } ++ else if (pictStruct == MFX_PICSTRUCT_FIELD_TFF || pictStruct == MFX_PICSTRUCT_FIELD_BFF) { ++ mfxU32 fQP[2] = { (m_nSubmittedFramesNum % m_GOPSize) ? m_QPforP : m_QPforI, ++ (m_GOPSize > 1) ? m_QPforP : m_QPforI }; ++ mfxU32 fIdx[2] = { 2 * m_nSubmittedFramesNum, 2 * m_nSubmittedFramesNum + 1 }; ++ mfxU32 fOff[2] = { 0, 0 }; ++ ++ fOff[(pictStruct == MFX_PICSTRUCT_FIELD_BFF) ? 0 : 1] = qpMap.NumQPAlloc / 2; ++ ++ for (int fld = 0; fld <= 1; fld++) { ++ std::memset(qpMap.QP + fOff[fld], fQP[fld], qpMap.NumQPAlloc / 2); ++ if (m_ROIData.size() > fIdx[fld]) { ++ mfxExtEncoderROI &roi = m_ROIData[fIdx[fld]]; ++ for (mfxI32 i = roi.NumROI - 1; i >= 0; i--) { ++ mfxU32 l = (roi.ROI[i].Left) >> 4, t = (roi.ROI[i].Top) >> 5, ++ r = (roi.ROI[i].Right + 15) >> 4, b = (roi.ROI[i].Bottom + 31) >> 5; ++ mfxI8 qp_delta = (mfxI8)roi.ROI[i].DeltaQP; ++ mfxU8 roi_qp = (mfxU8)std::min(std::max(mfxI8(fQP[fld]) + qp_delta, 0), 51); ++ ++ if (l > m_QPmapWidth) ++ l = m_QPmapWidth; ++ if (r > m_QPmapWidth) ++ r = m_QPmapWidth; ++ if (t > m_QPmapHeight / 2) ++ t = m_QPmapHeight / 2; ++ if (b > m_QPmapHeight / 2) ++ b = m_QPmapHeight / 2; ++ ++ for (mfxU32 k = t; k < b; k++) ++ std::memset(qpMap.QP + fOff[fld] + k * m_QPmapWidth + l, roi_qp, r - l); ++ } ++ } ++ } ++ } ++ else { ++ mfxI8 fQP = (m_nSubmittedFramesNum % m_GOPSize) ? (mfxI8)m_QPforP : (mfxI8)m_QPforI; ++ std::memset(qpMap.QP, fQP, qpMap.NumQPAlloc); ++ } ++} ++#endif //MFX_VERSION >= 1022 ++ ++void CTranscodingPipeline::SetEncCtrlRT(ExtendedSurface &extSurface, bool bInsertIDR) { ++ extSurface.pEncCtrl = NULL; ++ if (extSurface.pAuxCtrl) { ++ extSurface.pEncCtrl = &extSurface.pAuxCtrl->encCtrl; ++ } ++ ++#if MFX_VERSION >= 1022 ++ ++ if (extSurface.pSurface) { ++ void *keyId = (void *)extSurface.pSurface; ++ ++ // Use encoded surface pointer to find placeholders for run-time structures in maps ++ if (m_bUseQPMap && m_bufExtMBQP.find(keyId) == m_bufExtMBQP.end()) { ++ m_extBuffPtrStorage[keyId] = std::vector(); ++ ++ m_qpMapStorage[keyId] = std::vector(); ++ m_qpMapStorage[keyId].resize(m_QPmapWidth * m_QPmapHeight); ++ ++ m_bufExtMBQP[keyId] = mfxExtMBQP(); ++ m_bufExtMBQP[keyId].Header.BufferId = MFX_EXTBUFF_MBQP; ++ m_bufExtMBQP[keyId].Header.BufferSz = sizeof(mfxExtMBQP); ++ m_bufExtMBQP[keyId].NumQPAlloc = m_QPmapWidth * m_QPmapHeight; ++ m_bufExtMBQP[keyId].QP = ++ m_QPmapWidth && m_QPmapHeight ? &(m_qpMapStorage[keyId][0]) : NULL; ++ } ++ ++ // Initialize *pCtrl optionally copying content of the pExtSurface.pAuxCtrl.encCtrl ++ mfxEncodeCtrl &ctrl = encControlStorage[keyId]; ++ MSDK_ZERO_MEMORY(ctrl); ++ ++ if (extSurface.pEncCtrl) { ++ ctrl = *extSurface.pEncCtrl; ++ } ++ ++ // Copy all extended buffer pointers from pExtSurface.pAuxCtrl.encCtrl ++ m_extBuffPtrStorage[keyId].clear(); ++ if (extSurface.pAuxCtrl) { ++ for (unsigned int i = 0; i < ctrl.NumExtParam; i++) { ++ m_extBuffPtrStorage[keyId].push_back(extSurface.pAuxCtrl->encCtrl.ExtParam[i]); ++ } ++ } ++ ++ // Attach additional buffer with either MBQP or ROI information ++ if (m_bUseQPMap) { ++ #if (MFX_VERSION >= 1022) ++ FillMBQPBuffer(m_bufExtMBQP[keyId], extSurface.pSurface->Info.PicStruct); ++ m_extBuffPtrStorage[keyId].push_back((mfxExtBuffer *)&m_bufExtMBQP[keyId]); ++ #endif ++ } ++ else { ++ if (m_ROIData.size() > m_nSubmittedFramesNum) ++ m_extBuffPtrStorage[keyId].push_back( ++ (mfxExtBuffer *)&m_ROIData[m_nSubmittedFramesNum]); ++ } ++ ++ // Replace the buffers pointer to pre-allocated storage ++ ctrl.NumExtParam = (mfxU16)m_extBuffPtrStorage[keyId].size(); ++ if (ctrl.NumExtParam) { ++ ctrl.ExtParam = &(m_extBuffPtrStorage[keyId][0]); ++ } ++ ++ extSurface.pEncCtrl = &ctrl; ++ m_nSubmittedFramesNum++; ++ } ++#endif //MFX_VERSION >= 1022 ++ ++ if (bInsertIDR && extSurface.pSurface) { ++ if (extSurface.pEncCtrl == NULL) { ++ mfxEncodeCtrl &ctrl = encControlStorage[(void *)extSurface.pSurface]; ++ MSDK_ZERO_MEMORY(ctrl); ++ extSurface.pEncCtrl = &ctrl; ++ } ++ extSurface.pEncCtrl->FrameType = MFX_FRAMETYPE_I | MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF; ++ } ++ else { ++ if (extSurface.pEncCtrl) { ++ extSurface.pEncCtrl->FrameType = 0; ++ } ++ } ++} ++ ++mfxStatus CTranscodingPipeline::Transcode() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ExtendedSurface DecExtSurface = { 0 }; ++ ExtendedSurface VppExtSurface = { 0 }; ++ ExtendedBS *pBS = NULL; ++ bool bNeedDecodedFrames = true; // indicates if we need to decode frames ++ bool bEndOfFile = false; ++ bool bLastCycle = false; ++ bool shouldReadNextFrame = true; ++ ++ time_t start = time(0); ++ while (MFX_ERR_NONE == sts) { ++ msdk_tick nBeginTime = msdk_time_get_tick(); // microseconds. ++ ++ if (time(0) - start >= m_nTimeout) ++ bLastCycle = true; ++ if (m_MaxFramesForTranscode == m_nProcessedFramesNum) { ++ DecExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames ++ bNeedDecodedFrames = false; // no more decoded frames needed ++ } ++ ++ // if need more decoded frames ++ // decode a frame ++ if (bNeedDecodedFrames && shouldReadNextFrame) { ++ if (!bEndOfFile) { ++ sts = DecodeOneFrame(&DecExtSurface); ++ if (MFX_ERR_MORE_DATA == sts) { ++ if (!bLastCycle) { ++ m_bInsertIDR = true; ++ ++ m_pBSProcessor->ResetInput(); ++ m_pBSProcessor->ResetOutput(); ++ bNeedDecodedFrames = true; ++ ++ bEndOfFile = false; ++ sts = MFX_ERR_NONE; ++ continue; ++ } ++ else { ++ bEndOfFile = true; ++ } ++ } ++ } ++ ++ if (bEndOfFile) { ++ sts = DecodeLastFrame(&DecExtSurface); ++ } ++ ++ if (sts == MFX_ERR_MORE_DATA) { ++ DecExtSurface.pSurface = NULL; // to get buffered VPP or ENC frames ++ sts = MFX_ERR_NONE; ++ } ++ MSDK_CHECK_STATUS(sts, "DecodeFrame failed"); ++ } ++ if (m_bIsFieldWeaving && DecExtSurface.pSurface != NULL) { ++ m_mfxDecParams.mfx.FrameInfo.PicStruct = DecExtSurface.pSurface->Info.PicStruct; ++ } ++ if (m_bIsFieldSplitting && DecExtSurface.pSurface != NULL) { ++ m_mfxDecParams.mfx.FrameInfo.PicStruct = DecExtSurface.pSurface->Info.PicStruct; ++ } ++ // pre-process a frame ++ if (m_pmfxVPP.get() && bNeedDecodedFrames && !m_rawInput) { ++ if (m_bIsFieldWeaving) { ++ // In case of field weaving output surface's parameters for ODD calls to VPPOneFrame will be ignored (because VPP will return ERR_MORE_DATA). ++ // So, we need to set output surface picstruct properly for EVEN calls (no matter what will be set for ODD calls). ++ // We might have 2 cases: decoder gives us pairs (TF BF)... or (BF)(TF). In first case we should set TFF for output, in second - BFF. ++ // So, if even input surface is BF, we set TFF for output and vise versa. For odd input surface - no matter what we set. ++ if (DecExtSurface.pSurface) { ++ if ((DecExtSurface.pSurface->Info.PicStruct & ++ MFX_PICSTRUCT_FIELD_TFF)) // Incoming Top Field in a single surface ++ { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_BFF; ++ } ++ if (DecExtSurface.pSurface->Info.PicStruct & ++ MFX_PICSTRUCT_FIELD_BFF) // Incoming Bottom Field in a single surface ++ { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_TFF; ++ } ++ } ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ else { ++ if (m_bIsFieldSplitting) { ++ if (DecExtSurface.pSurface) { ++ if (DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_TFF || ++ DecExtSurface.pSurface->Info.PicStruct & MFX_PICSTRUCT_FIELD_BFF) { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_SINGLE; ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ else { ++ VppExtSurface.pSurface = DecExtSurface.pSurface; ++ VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl; ++ VppExtSurface.Syncp = DecExtSurface.Syncp; ++ } ++ } ++ else { ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ } ++ else { ++ sts = VPPOneFrame(&DecExtSurface, &VppExtSurface); ++ } ++ } ++ // check for interlaced stream ++ ++#if defined(MFX_ONEVPL) ++ if (m_MemoryModel != GENERAL_ALLOC && DecExtSurface.pSurface) { ++ mfxStatus sts_release = ++ DecExtSurface.pSurface->FrameInterface->Release(DecExtSurface.pSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ } ++ else // no VPP - just copy pointers ++ { ++ VppExtSurface.pSurface = DecExtSurface.pSurface; ++ VppExtSurface.pAuxCtrl = DecExtSurface.pAuxCtrl; ++ VppExtSurface.Syncp = DecExtSurface.Syncp; ++ } ++ ++ if (MFX_ERR_MORE_SURFACE == sts) { ++ shouldReadNextFrame = false; ++ sts = MFX_ERR_NONE; ++ } ++ else { ++ shouldReadNextFrame = true; ++ } ++ ++ if (sts == MFX_ERR_MORE_DATA) { ++ sts = MFX_ERR_NONE; ++ if (NULL == DecExtSurface.pSurface) // there are no more buffered frames in VPP ++ { ++ VppExtSurface.pSurface = NULL; // to get buffered ENC frames ++ } ++ else { ++ continue; // go get next frame from Decode ++ } ++ } ++ ++ MSDK_CHECK_STATUS(sts, "Unexpected error!!"); ++ ++ // encode frame ++ pBS = m_pBSStore->GetNext(); ++ if (!pBS) ++ return MFX_ERR_NOT_FOUND; ++ ++ m_BSPool.push_back(pBS); ++ ++ // Set Encoding control if it is required. ++ ++ SetEncCtrlRT(VppExtSurface, m_bInsertIDR); ++ m_bInsertIDR = false; ++ ++ if (DecExtSurface.pSurface) ++ m_nProcessedFramesNum++; ++ ++ if (m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP) { ++ sts = EncodeOneFrame(&VppExtSurface, &m_BSPool.back()->Bitstream); ++ } ++ else { ++ sts = Surface2BS(&VppExtSurface, &m_BSPool.back()->Bitstream, m_encoderFourCC); ++ } ++ ++#if defined(MFX_ONEVPL) ++ if (m_MemoryModel != GENERAL_ALLOC && VppExtSurface.pSurface) { ++ mfxStatus sts_release = ++ VppExtSurface.pSurface->FrameInterface->Release(VppExtSurface.pSurface); ++ MSDK_CHECK_STATUS(sts_release, "FrameInterface->Release failed"); ++ } ++#endif //MFX_ONEVPL ++ ++ // check if we need one more frame from decode ++ if (MFX_ERR_MORE_DATA == sts) { ++ // the task in not in Encode queue ++ m_BSPool.pop_back(); ++ m_pBSStore->Release(pBS); ++ ++ if (NULL == VppExtSurface.pSurface) // there are no more buffered frames in encoder ++ { ++ break; ++ } ++ sts = MFX_ERR_NONE; ++ continue; ++ } ++ ++ // check encoding result ++ MSDK_CHECK_STATUS(sts, " failed"); ++ ++ if (statisticsWindowSize) { ++ if ((statisticsWindowSize && m_nOutputFramesNum && ++ 0 == m_nProcessedFramesNum % statisticsWindowSize) || ++ (statisticsWindowSize && (m_nProcessedFramesNum >= m_MaxFramesForTranscode))) { ++ inputStatistics.PrintStatistics(GetPipelineID()); ++ outputStatistics.PrintStatistics( ++ GetPipelineID(), ++ (m_mfxEncParams.mfx.FrameInfo.FrameRateExtD) ++ ? (mfxF64)m_mfxEncParams.mfx.FrameInfo.FrameRateExtN / ++ (mfxF64)m_mfxEncParams.mfx.FrameInfo.FrameRateExtD ++ : -1); ++ inputStatistics.ResetStatistics(); ++ outputStatistics.ResetStatistics(); ++ } ++ } ++ else if (0 == (m_nProcessedFramesNum - 1) % 100) { ++ msdk_printf(MSDK_STRING(".")); ++ } ++ ++ m_BSPool.back()->Syncp = VppExtSurface.Syncp; ++ ++ if (m_BSPool.size() == m_AsyncDepth) { ++ sts = PutBS(); ++ MSDK_CHECK_STATUS(sts, "PutBS failed"); ++ } ++ ++ msdk_tick nFrameTime = msdk_time_get_tick() - nBeginTime; ++ if (nFrameTime < m_nReqFrameTime) { ++ MSDK_USLEEP((mfxU32)(m_nReqFrameTime - nFrameTime)); ++ } ++ } ++ MSDK_IGNORE_MFX_STS(sts, MFX_ERR_MORE_DATA); ++ ++ // need to get buffered bitstream ++ if (MFX_ERR_NONE == sts) { ++ while (m_BSPool.size()) { ++ sts = PutBS(); ++ MSDK_CHECK_STATUS(sts, "PutBS failed"); ++ } ++ } ++ ++ if (MFX_ERR_NONE == sts) ++ sts = MFX_WRN_VALUE_NOT_CHANGED; ++ ++ return sts; ++} // mfxStatus CTranscodingPipeline::Transcode() ++ ++mfxStatus CTranscodingPipeline::PutBS() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ExtendedBS *pBitstreamEx = m_BSPool.front(); ++ MSDK_CHECK_POINTER(pBitstreamEx, MFX_ERR_NULL_PTR); ++ ++ // get result coded stream, synchronize only if we still have sync point ++ if (pBitstreamEx->Syncp) { ++ sts = m_pmfxSession->SyncOperation(pBitstreamEx->Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "Encode: SyncOperation failed"); ++ } ++ ++ m_nOutputFramesNum++; ++ ++ //--- Time measurements ++ if (statisticsWindowSize) { ++ outputStatistics.StopTimeMeasurementWithCheck(); ++ outputStatistics.StartTimeMeasurement(); ++ } ++ ++ sts = m_pBSProcessor->ProcessOutputBitstream(&pBitstreamEx->Bitstream); ++ MSDK_CHECK_STATUS(sts, "m_pBSProcessor->ProcessOutputBitstream failed"); ++ ++ UnPreEncAuxBuffer(pBitstreamEx->pCtrl); ++ ++ pBitstreamEx->Bitstream.DataLength = 0; ++ pBitstreamEx->Bitstream.DataOffset = 0; ++ ++ if (m_BSPool.size()) ++ m_BSPool.pop_front(); ++ m_pBSStore->Release(pBitstreamEx); ++ ++ return sts; ++} //mfxStatus CTranscodingPipeline::PutBS() ++ ++mfxStatus CTranscodingPipeline::DumpSurface2File(mfxFrameSurface1 *pSurf) { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ sts = m_pMFXAllocator->Lock(m_pMFXAllocator->pthis, pSurf->Data.MemId, &pSurf->Data); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Lock failed"); ++ } ++#if defined(MFX_ONEVPL) ++ else { ++ sts = pSurf->FrameInterface->Map(pSurf, MFX_MAP_READ); ++ MSDK_CHECK_STATUS(sts, "FrameInterface->Map failed"); ++ } ++#endif //MFX_ONEVPL ++ ++ sts = m_dumpVppCompFileWriter.WriteNextFrame(pSurf); ++ MSDK_CHECK_STATUS(sts, "m_dumpVppCompFileWriter.WriteNextFrame failed"); ++ ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ sts = m_pMFXAllocator->Unlock(m_pMFXAllocator->pthis, pSurf->Data.MemId, &pSurf->Data); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Unlock failed"); ++ } ++#if defined(MFX_ONEVPL) ++ else { ++ sts = pSurf->FrameInterface->Unmap(pSurf); ++ MSDK_CHECK_STATUS(sts, "FrameInterface->Unmap failed"); ++ } ++#endif //MFX_ONEVPL ++ ++ return sts; ++} // mfxStatus CTranscodingPipeline::DumpSurface2File(ExtendedSurface* pSurf) ++ ++mfxStatus CTranscodingPipeline::Surface2BS(ExtendedSurface *pSurf, ++ mfxBitstreamWrapper *pBS, ++ mfxU32 fourCC) { ++ mfxStatus sts = MFX_ERR_MORE_DATA; ++ // get result coded stream ++ if (!pSurf->pSurface) { ++ return MFX_ERR_MORE_DATA; ++ } ++ ++ if (pSurf->Syncp) { ++ sts = m_pmfxSession->SyncOperation(pSurf->Syncp, MSDK_WAIT_INTERVAL); ++ HandlePossibleGpuHang(sts); ++ MSDK_CHECK_ERR_NONE_STATUS(sts, MFX_ERR_ABORTED, "SyncOperation failed"); ++ pSurf->Syncp = 0; ++ ++ //--- Copying data from surface to bitstream ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ sts = m_pMFXAllocator->Lock(m_pMFXAllocator->pthis, ++ pSurf->pSurface->Data.MemId, ++ &pSurf->pSurface->Data); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Lock failed"); ++ } ++#if defined(MFX_ONEVPL) ++ else { ++ sts = pSurf->pSurface->FrameInterface->Map(pSurf->pSurface, MFX_MAP_READ); ++ MSDK_CHECK_STATUS(sts, "FrameInterface->Map failed"); ++ } ++#endif //MFX_ONEVPL ++ ++ switch (fourCC) { ++ case 0: // Default value is MFX_FOURCC_I420 ++ case MFX_FOURCC_I420: ++ sts = NV12asI420toBS(pSurf->pSurface, pBS); ++ break; ++ case MFX_FOURCC_NV12: ++ sts = NV12toBS(pSurf->pSurface, pBS); ++ break; ++ case MFX_FOURCC_RGB4: ++ sts = RGB4toBS(pSurf->pSurface, pBS); ++ break; ++ case MFX_FOURCC_YUY2: ++ sts = YUY2toBS(pSurf->pSurface, pBS); ++ break; ++ } ++ MSDK_CHECK_STATUS(sts, "toBS failed"); ++ ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ sts = m_pMFXAllocator->Unlock(m_pMFXAllocator->pthis, ++ pSurf->pSurface->Data.MemId, ++ &pSurf->pSurface->Data); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Unlock failed"); ++ } ++#if defined(MFX_ONEVPL) ++ else { ++ sts = pSurf->pSurface->FrameInterface->Unmap(pSurf->pSurface); ++ MSDK_CHECK_STATUS(sts, "FrameInterface->Unmap failed"); ++ } ++#endif //MFX_ONEVPL ++ } ++ ++ return sts; ++} ++ ++mfxStatus CTranscodingPipeline::NV12asI420toBS(mfxFrameSurface1 *pSurface, ++ mfxBitstreamWrapper *pBS) { ++ mfxFrameInfo &info = pSurface->Info; ++ mfxFrameData &data = pSurface->Data; ++ if ((int)pBS->MaxLength - (int)pBS->DataLength < (int)(info.CropH * info.CropW * 3 / 2)) { ++ pBS->Extend(pBS->DataLength + (int)(info.CropH * info.CropW * 3 / 2)); ++ } ++ ++ for (mfxU16 i = 0; i < info.CropH; i++) { ++ MSDK_MEMCPY(pBS->Data + pBS->DataLength, ++ data.Y + (info.CropY * data.Pitch + info.CropX) + i * data.Pitch, ++ info.CropW); ++ pBS->DataLength += info.CropW; ++ } ++ ++ mfxU16 h = info.CropH / 2; ++ mfxU16 w = info.CropW; ++ ++ for (mfxU16 offset = 0; offset < 2; offset++) { ++ for (mfxU16 i = 0; i < h; i++) { ++ for (mfxU16 j = offset; j < w; j += 2) { ++ pBS->Data[pBS->DataLength] = ++ *(data.UV + (info.CropY * data.Pitch / 2 + info.CropX) + i * data.Pitch + j); ++ pBS->DataLength++; ++ } ++ } ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus CTranscodingPipeline::NV12toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS) { ++ mfxFrameInfo &info = pSurface->Info; ++ mfxFrameData &data = pSurface->Data; ++ if ((int)pBS->MaxLength - (int)pBS->DataLength < (int)(info.CropH * info.CropW * 3 / 2)) { ++ pBS->Extend(pBS->DataLength + (int)(info.CropH * info.CropW * 3 / 2)); ++ } ++ ++ for (mfxU16 i = 0; i < info.CropH; i++) { ++ MSDK_MEMCPY(pBS->Data + pBS->DataLength, ++ data.Y + (info.CropY * data.Pitch + info.CropX) + i * data.Pitch, ++ info.CropW); ++ pBS->DataLength += info.CropW; ++ } ++ ++ for (mfxU16 i = 0; i < info.CropH / 2; i++) { ++ MSDK_MEMCPY(pBS->Data + pBS->DataLength, ++ data.UV + (info.CropY * data.Pitch + info.CropX) + i * data.Pitch, ++ info.CropW); ++ pBS->DataLength += info.CropW; ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus CTranscodingPipeline::RGB4toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS) { ++ mfxFrameInfo &info = pSurface->Info; ++ mfxFrameData &data = pSurface->Data; ++ if ((int)pBS->MaxLength - (int)pBS->DataLength < (int)(info.CropH * info.CropW * 4)) { ++ pBS->Extend(pBS->DataLength + (int)(info.CropH * info.CropW * 4)); ++ } ++ ++ for (mfxU16 i = 0; i < info.CropH; i++) { ++ MSDK_MEMCPY(pBS->Data + pBS->DataLength, ++ data.B + (info.CropY * data.Pitch + info.CropX * 4) + i * data.Pitch, ++ info.CropW * 4); ++ pBS->DataLength += info.CropW * 4; ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus CTranscodingPipeline::YUY2toBS(mfxFrameSurface1 *pSurface, mfxBitstreamWrapper *pBS) { ++ mfxFrameInfo &info = pSurface->Info; ++ mfxFrameData &data = pSurface->Data; ++ if ((int)pBS->MaxLength - (int)pBS->DataLength < (int)(info.CropH * info.CropW * 4)) { ++ pBS->Extend(pBS->DataLength + (int)(info.CropH * info.CropW * 4)); ++ } ++ ++ for (mfxU16 i = 0; i < info.CropH; i++) { ++ MSDK_MEMCPY(pBS->Data + pBS->DataLength, ++ data.Y + (info.CropY * data.Pitch + info.CropX / 2 * 4) + i * data.Pitch, ++ info.CropW * 2); ++ pBS->DataLength += info.CropW * 2; ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++#if !defined(MFX_ONEVPL) ++mfxStatus CTranscodingPipeline::AllocMVCSeqDesc() { ++ auto mvc = m_mfxDecParams.AddExtBuffer(); ++ mvc->View = new mfxMVCViewDependency[mvc->NumView]; ++ mvc->NumViewAlloc = mvc->NumView; ++ ++ mvc->ViewId = new mfxU16[mvc->NumViewId]; ++ mvc->NumViewIdAlloc = mvc->NumViewId; ++ ++ mvc->OP = new mfxMVCOperationPoint[mvc->NumOP]; ++ mvc->NumOPAlloc = mvc->NumOP; ++ ++ return MFX_ERR_NONE; ++} ++ ++void CTranscodingPipeline::FreeMVCSeqDesc() { ++ mfxExtMVCSeqDesc *mvc = m_mfxDecParams; ++ if (m_bOwnMVCSeqDescMemory && mvc) { ++ MSDK_SAFE_DELETE_ARRAY(mvc->View); ++ MSDK_SAFE_DELETE_ARRAY(mvc->ViewId); ++ MSDK_SAFE_DELETE_ARRAY(mvc->OP); ++ } ++} ++#endif ++mfxStatus CTranscodingPipeline::InitDecMfxParams(sInputParams *pInParams) { ++ mfxStatus sts = MFX_ERR_NONE; ++ MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR); ++ ++ m_mfxDecParams.AsyncDepth = m_AsyncDepth; ++ ++#if !defined(MFX_ONEVPL) ++ if (pInParams->bIsMVC) ++ m_mfxDecParams.AddExtBuffer(); ++#endif ++ if (!m_bUseOverlay) { ++ // read a portion of data for DecodeHeader function ++ sts = m_pBSProcessor->GetInputBitstream(&m_pmfxBS); ++ if (MFX_ERR_MORE_DATA == sts) ++ return sts; ++ else ++ MSDK_CHECK_STATUS(sts, "m_pBSProcessor->GetInputBitstream failed"); ++ ++ // try to find a sequence header in the stream ++ // if header is not found this function exits with error (e.g. if device was lost and there's no header in the remaining stream) ++ for (;;) { ++ // trying to find PicStruct information in AVI headers ++ if (pInParams->DecodeId == MFX_CODEC_JPEG) ++ MJPEG_AVI_ParsePicStruct(m_pmfxBS); ++ ++ // parse bit stream and fill mfx params ++ sts = m_pmfxDEC->DecodeHeader(m_pmfxBS, &m_mfxDecParams); ++ ++ if (MFX_ERR_MORE_DATA == sts) { ++ if (m_pmfxBS->MaxLength == m_pmfxBS->DataLength) { ++ m_pmfxBS->Extend(m_pmfxBS->MaxLength * 2); ++ } ++ ++ // read a portion of data for DecodeHeader function ++ sts = m_pBSProcessor->GetInputBitstream(&m_pmfxBS); ++ if (MFX_ERR_MORE_DATA == sts) ++ return sts; ++ else ++ MSDK_CHECK_STATUS(sts, "m_pBSProcessor->GetInputBitstream failed"); ++ ++ continue; ++ } ++#if !defined(MFX_ONEVPL) ++ else if (MFX_ERR_NOT_ENOUGH_BUFFER == sts && pInParams->bIsMVC) { ++ sts = AllocMVCSeqDesc(); ++ MSDK_CHECK_STATUS(sts, "m_pmfxDEC->DecodeHeader failed"); ++ ++ continue; ++ } ++#endif ++ else ++ break; ++ } ++ ++ // to enable decorative flags, has effect with 1.3 API libraries only ++ // (in case of JPEG decoder - it is not valid to use this field) ++ if (m_mfxDecParams.mfx.CodecId != MFX_CODEC_JPEG) ++ m_mfxDecParams.mfx.ExtendedPicStruct = 1; ++ ++ // check DecodeHeader status ++ if (MFX_WRN_PARTIAL_ACCELERATION == sts) { ++ msdk_printf(MSDK_STRING("WARNING: partial acceleration\n")); ++ MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION); ++ } ++ MSDK_CHECK_STATUS(sts, "m_pmfxDEC->DecodeHeader failed"); ++ ++ // if input is interlaced JPEG stream ++ if (((pInParams->DecodeId == MFX_CODEC_JPEG) && ++ (m_pmfxBS->PicStruct == MFX_PICSTRUCT_FIELD_TFF)) || ++ (m_pmfxBS->PicStruct == MFX_PICSTRUCT_FIELD_BFF)) { ++ m_mfxDecParams.mfx.FrameInfo.CropH *= 2; ++ m_mfxDecParams.mfx.FrameInfo.Height = MSDK_ALIGN16(m_mfxDecParams.mfx.FrameInfo.CropH); ++ m_mfxDecParams.mfx.FrameInfo.PicStruct = m_pmfxBS->PicStruct; ++ } ++ } ++ else { ++ m_mfxDecParams.mfx.FrameInfo.Width = MSDK_ALIGN32(pInParams->nVppCompSrcW); ++ m_mfxDecParams.mfx.FrameInfo.Height = MSDK_ALIGN32(pInParams->nVppCompSrcH); ++ m_mfxDecParams.mfx.FrameInfo.CropW = pInParams->nVppCompSrcW; ++ m_mfxDecParams.mfx.FrameInfo.CropH = pInParams->nVppCompSrcH; ++ ++ m_mfxDecParams.mfx.FrameInfo.AspectRatioW = m_mfxDecParams.mfx.FrameInfo.AspectRatioH = 1; ++ m_mfxDecParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; ++ m_mfxDecParams.mfx.FrameInfo.FourCC = MFX_FOURCC_RGB4; ++ } ++ ++ // set memory pattern ++ if (pInParams->bForceSysMem || (MFX_IMPL_SOFTWARE == pInParams->libType) || ++ (pInParams->DecOutPattern == MFX_IOPATTERN_OUT_SYSTEM_MEMORY)) ++ m_mfxDecParams.IOPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; ++ else ++ m_mfxDecParams.IOPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; ++ ++ // if frame rate specified by user set it for decoder output ++ if (pInParams->dDecoderFrameRateOverride) { ++ ConvertFrameRate(pInParams->dDecoderFrameRateOverride, ++ &m_mfxDecParams.mfx.FrameInfo.FrameRateExtN, ++ &m_mfxDecParams.mfx.FrameInfo.FrameRateExtD); ++ } ++ // if frame rate not specified and input stream header doesn't contain valid values use default (30.0) ++ else if (0 == (m_mfxDecParams.mfx.FrameInfo.FrameRateExtN * ++ m_mfxDecParams.mfx.FrameInfo.FrameRateExtD)) { ++ m_mfxDecParams.mfx.FrameInfo.FrameRateExtN = 30; ++ m_mfxDecParams.mfx.FrameInfo.FrameRateExtD = 1; ++ } ++ else { ++ // use the value from input stream header ++ } ++ ++ //--- Force setting fourcc type if required ++ if (pInParams->DecoderFourCC) { ++ m_mfxDecParams.mfx.FrameInfo.FourCC = pInParams->DecoderFourCC; ++ m_mfxDecParams.mfx.FrameInfo.ChromaFormat = FourCCToChroma(pInParams->DecoderFourCC); ++ } ++ ++#if MFX_VERSION >= 1022 ++ /* SFC usage if enabled */ ++ if (pInParams->bDecoderPostProcessing) { ++ auto decPostProc = m_mfxDecParams.AddExtBuffer(); ++ decPostProc->In.CropX = 0; ++ decPostProc->In.CropY = 0; ++ decPostProc->In.CropW = m_mfxDecParams.mfx.FrameInfo.CropW; ++ decPostProc->In.CropH = m_mfxDecParams.mfx.FrameInfo.CropH; ++ ++ decPostProc->Out.FourCC = m_mfxDecParams.mfx.FrameInfo.FourCC; ++ decPostProc->Out.ChromaFormat = m_mfxDecParams.mfx.FrameInfo.ChromaFormat; ++ decPostProc->Out.CropX = 0; ++ decPostProc->Out.CropY = 0; ++ decPostProc->Out.CropW = ++ pInParams->eModeExt == VppComp ? pInParams->nVppCompDstW : pInParams->nDstWidth; ++ decPostProc->Out.CropH = ++ pInParams->eModeExt == VppComp ? pInParams->nVppCompDstH : pInParams->nDstHeight; ++ decPostProc->Out.Width = MSDK_ALIGN16(decPostProc->Out.CropW); ++ decPostProc->Out.Height = MSDK_ALIGN16(decPostProc->Out.CropH); ++ } ++#endif ++ ++ return MFX_ERR_NONE; ++} // mfxStatus CTranscodingPipeline::InitDecMfxParams() ++ ++void CTranscodingPipeline::FillFrameInfoForEncoding(mfxFrameInfo &info, sInputParams *pInParams) { ++ // Getting parameters from previous blocks ++ if (m_bIsVpp) { ++ MSDK_MEMCPY_VAR(info, &m_mfxVppParams.vpp.Out, sizeof(mfxFrameInfo)); ++ } ++ else if (m_bIsPlugin) { ++ info = m_mfxPluginParams.vpp.Out; ++ } ++ else { ++ info = GetFrameInfo(m_mfxDecParams); ++ } ++ ++ if (pInParams->dEncoderFrameRateOverride) { ++ ConvertFrameRate(pInParams->dEncoderFrameRateOverride, ++ &info.FrameRateExtN, ++ &info.FrameRateExtD); ++ } ++ else if (pInParams->dVPPOutFramerate) { ++ ConvertFrameRate(pInParams->dVPPOutFramerate, &info.FrameRateExtN, &info.FrameRateExtD); ++ } ++} ++ ++mfxStatus CTranscodingPipeline::InitEncMfxParams(sInputParams *pInParams) { ++ MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR); ++ ++ FillFrameInfoForEncoding(m_mfxEncParams.mfx.FrameInfo, pInParams); ++ ++ MSDK_CHECK_ERROR( ++ m_mfxEncParams.mfx.FrameInfo.FrameRateExtN * m_mfxEncParams.mfx.FrameInfo.FrameRateExtD, ++ 0, ++ MFX_ERR_INVALID_VIDEO_PARAM); ++ ++ m_mfxEncParams.mfx.CodecId = pInParams->EncodeId; ++ m_mfxEncParams.mfx.TargetUsage = pInParams->nTargetUsage; // trade-off between quality and speed ++ m_mfxEncParams.AsyncDepth = m_AsyncDepth; ++ ++#if !defined(MFX_ONEVPL) ++ #if (MFX_VERSION >= 1025) ++ if (pInParams->numMFEFrames || pInParams->MFMode) { ++ auto mfePar = m_mfxEncParams.AddExtBuffer(); ++ mfePar->MaxNumFrames = pInParams->numMFEFrames; ++ mfePar->MFMode = pInParams->MFMode; ++ } ++ ++ if (pInParams->mfeTimeout) { ++ auto mfeCtrl = m_mfxEncParams.AddExtBuffer(); ++ mfeCtrl->Timeout = pInParams->mfeTimeout; ++ } ++ #endif ++#endif //!MFX_ONEVPL ++ ++#if !defined(MFX_ONEVPL) ++ if (m_pParentPipeline && m_pParentPipeline->m_pmfxPreENC.get()) { ++ m_mfxEncParams.mfx.RateControlMethod = MFX_RATECONTROL_LA_EXT; ++ m_mfxEncParams.mfx.EncodedOrder = ++ 1; // binary flag, 0 signals encoder to take frames in display order ++ m_mfxEncParams.AsyncDepth = m_mfxEncParams.AsyncDepth == 0 ? 2 : m_mfxEncParams.AsyncDepth; ++ } ++ else ++#endif //!MFX_ONEVPL ++ { ++ m_mfxEncParams.mfx.RateControlMethod = pInParams->nRateControlMethod; ++ } ++ m_mfxEncParams.mfx.NumSlice = pInParams->nSlices; ++ ++ if (pInParams->nRateControlMethod == MFX_RATECONTROL_CQP) { ++ m_mfxEncParams.mfx.QPI = pInParams->nQPI; ++ m_mfxEncParams.mfx.QPP = pInParams->nQPP; ++ m_mfxEncParams.mfx.QPB = pInParams->nQPB; ++ } ++ ++ if (pInParams->enableQSVFF) { ++ m_mfxEncParams.mfx.LowPower = MFX_CODINGOPTION_ON; ++ } ++ ++ // leave PAR unset to avoid MPEG2 encoder rejecting streams with unsupported DAR ++ m_mfxEncParams.mfx.FrameInfo.AspectRatioW = m_mfxEncParams.mfx.FrameInfo.AspectRatioH = 0; ++ ++ // calculate default bitrate based on resolution and framerate ++ if (pInParams->EncoderPicstructOverride) { ++ m_mfxEncParams.mfx.FrameInfo.PicStruct = pInParams->EncoderPicstructOverride; ++ } ++ ++ MSDK_CHECK_ERROR( ++ m_mfxEncParams.mfx.FrameInfo.FrameRateExtN * m_mfxEncParams.mfx.FrameInfo.FrameRateExtD, ++ 0, ++ MFX_ERR_INVALID_VIDEO_PARAM); ++ ++ if (pInParams->nRateControlMethod != MFX_RATECONTROL_CQP) { ++ if (pInParams->nBitRate == 0) { ++ pInParams->nBitRate = ++ CalculateDefaultBitrate(pInParams->EncodeId, ++ pInParams->nTargetUsage, ++ m_mfxEncParams.mfx.FrameInfo.Width, ++ m_mfxEncParams.mfx.FrameInfo.Height, ++ 1.0 * m_mfxEncParams.mfx.FrameInfo.FrameRateExtN / ++ m_mfxEncParams.mfx.FrameInfo.FrameRateExtD); ++ } ++ m_mfxEncParams.mfx.TargetKbps = pInParams->nBitRate; // in Kbps ++ m_mfxEncParams.mfx.BRCParamMultiplier = pInParams->nBitRateMultiplier; ++ } ++ ++ // In case of HEVC when height and/or width divided with 8 but not divided with 16 ++ // add extended parameter to increase performance ++ if ((!((m_mfxEncParams.mfx.FrameInfo.CropW & 15) ^ 8) || ++ !((m_mfxEncParams.mfx.FrameInfo.CropH & 15) ^ 8)) && ++ (m_mfxEncParams.mfx.CodecId == MFX_CODEC_HEVC)) { ++ auto hevcPar = m_mfxEncParams.AddExtBuffer(); ++ hevcPar->PicWidthInLumaSamples = m_mfxEncParams.mfx.FrameInfo.CropW; ++ hevcPar->PicHeightInLumaSamples = m_mfxEncParams.mfx.FrameInfo.CropH; ++ } ++ ++#if !defined(MFX_ONEVPL) ++ #if (MFX_VERSION >= 1024) ++ // This is for explicit extbrc only. In case of implicit (built-into-library) version - we don't need this extended buffer ++ if (pInParams->nExtBRC == EXTBRC_ON && ++ (pInParams->EncodeId == MFX_CODEC_HEVC || pInParams->EncodeId == MFX_CODEC_AVC)) { ++ auto extbrc = m_mfxEncParams.AddExtBuffer(); ++ HEVCExtBRC::Create(*extbrc); ++ } ++ #endif ++#endif ++ ++ m_mfxEncParams.mfx.FrameInfo.CropX = 0; ++ m_mfxEncParams.mfx.FrameInfo.CropY = 0; ++ ++ mfxU16 InPatternFromParent = ++ (mfxU16)((MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxDecParams.IOPattern) ++ ? MFX_IOPATTERN_IN_VIDEO_MEMORY ++ : MFX_IOPATTERN_IN_SYSTEM_MEMORY); ++ ++ // set memory pattern ++ m_mfxEncParams.IOPattern = InPatternFromParent; ++ ++ if (pInParams->nEncTileRows && pInParams->nEncTileCols) { ++ if (m_mfxEncParams.mfx.CodecId == MFX_CODEC_HEVC) { ++ auto tiles = m_mfxEncParams.AddExtBuffer(); ++ tiles->NumTileRows = pInParams->nEncTileRows; ++ tiles->NumTileColumns = pInParams->nEncTileCols; ++ } ++#if MFX_VERSION >= 1029 ++ else if (m_mfxEncParams.mfx.CodecId == MFX_CODEC_VP9) { ++ auto vp9par = m_mfxEncParams.AddExtBuffer(); ++ vp9par->NumTileRows = pInParams->nEncTileRows; ++ vp9par->NumTileColumns = pInParams->nEncTileCols; ++ } ++#endif ++ } ++ ++ if (pInParams->nAvcTemp) { ++ if (pInParams->EncodeId == MFX_CODEC_HEVC) { ++ auto tl = m_mfxEncParams.AddExtBuffer(); ++ tl->BaseLayerPID = pInParams->nBaseLayerPID; ++ for (int i = 0; i < 8; i++) { ++ tl->Layer[i].Scale = pInParams->nAvcTemporalLayers[i]; ++ } ++ } ++ } ++ ++ if (pInParams->nSPSId || pInParams->nPPSId) { ++ if (pInParams->EncodeId == MFX_CODEC_HEVC) { ++ auto spspps = m_mfxEncParams.AddExtBuffer(); ++ spspps->SPSId = pInParams->nSPSId; ++ spspps->PPSId = pInParams->nPPSId; ++ } ++ } ++ ++ if (pInParams->nPicTimingSEI || pInParams->nNalHrdConformance || ++ pInParams->nVuiNalHrdParameters) { ++ auto co = m_mfxEncParams.AddExtBuffer(); ++ co->PicTimingSEI = pInParams->nPicTimingSEI; ++ co->NalHrdConformance = pInParams->nNalHrdConformance; ++ co->VuiNalHrdParameters = pInParams->nVuiNalHrdParameters; ++ } ++ ++#if !defined(MFX_ONEVPL) ++ // we don't specify profile and level and let the encoder choose those basing on parameters ++ // we must specify profile only for MVC codec ++ if (pInParams->bIsMVC) { ++ m_mfxEncParams.mfx.CodecProfile = m_mfxDecParams.mfx.CodecProfile; ++ } ++#endif ++ ++ // JPEG encoder settings overlap nasc other encoders settings in mfxInfoMFX structure ++ if (MFX_CODEC_JPEG == pInParams->EncodeId) { ++ m_mfxEncParams.mfx.Interleaved = 1; ++ m_mfxEncParams.mfx.Quality = pInParams->nQuality; ++ m_mfxEncParams.mfx.RestartInterval = 0; ++ MSDK_ZERO_MEMORY(m_mfxEncParams.mfx.reserved5); ++ } ++ ++ // configure and attach external parameters ++ if (pInParams->bLABRC || pInParams->nMaxSliceSize || pInParams->nBRefType || ++ (pInParams->BitrateLimit && pInParams->EncodeId == MFX_CODEC_AVC) || ++ (pInParams->nExtBRC && ++ (pInParams->EncodeId == MFX_CODEC_HEVC || pInParams->EncodeId == MFX_CODEC_AVC)) || ++ pInParams->IntRefType || pInParams->IntRefCycleSize || pInParams->IntRefQPDelta || ++ pInParams->nMaxFrameSize || pInParams->AdaptiveI || pInParams->AdaptiveB) { ++ auto co2 = m_mfxEncParams.AddExtBuffer(); ++ co2->LookAheadDepth = pInParams->nLADepth; ++ co2->MaxSliceSize = pInParams->nMaxSliceSize; ++ co2->MaxFrameSize = pInParams->nMaxFrameSize; ++ co2->BRefType = pInParams->nBRefType; ++ co2->BitrateLimit = pInParams->BitrateLimit; ++ ++ co2->IntRefType = pInParams->IntRefType; ++ co2->IntRefCycleSize = pInParams->IntRefCycleSize; ++ co2->IntRefQPDelta = pInParams->IntRefQPDelta; ++ co2->AdaptiveI = pInParams->AdaptiveI; ++ co2->AdaptiveB = pInParams->AdaptiveB; ++ ++ if (pInParams->nExtBRC != EXTBRC_DEFAULT && ++ (pInParams->EncodeId == MFX_CODEC_HEVC || pInParams->EncodeId == MFX_CODEC_AVC)) { ++ co2->ExtBRC = (mfxU16)(pInParams->nExtBRC == EXTBRC_OFF ? MFX_CODINGOPTION_OFF ++ : MFX_CODINGOPTION_ON); ++ } ++ else { ++ co2->ExtBRC = MFX_CODINGOPTION_UNKNOWN; ++ } ++ } ++ ++ if (pInParams->WinBRCMaxAvgKbps || pInParams->WinBRCSize) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->WinBRCMaxAvgKbps = pInParams->WinBRCMaxAvgKbps; ++ co3->WinBRCSize = pInParams->WinBRCSize; ++ } ++#if MFX_VERSION >= 1022 ++ if (pInParams->bROIasQPMAP || pInParams->bExtMBQP) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ // QP map defines QP value for every 16x16 sub-block of a frame ++ m_QPmapWidth = (m_mfxEncParams.mfx.FrameInfo.Width + 15) >> 4; ++ m_QPmapHeight = (m_mfxEncParams.mfx.FrameInfo.Height + 15) >> 4; ++ co3->EnableMBQP = MFX_CODINGOPTION_ON; ++ } ++#endif ++ ++ if (pInParams->WeightedPred || pInParams->WeightedBiPred || pInParams->IntRefCycleDist || ++ pInParams->nAdaptiveMaxFrameSize || pInParams->LowDelayBRC) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->WeightedPred = pInParams->WeightedPred; ++ co3->WeightedBiPred = pInParams->WeightedBiPred; ++ co3->LowDelayBRC = pInParams->LowDelayBRC; ++ co3->IntRefCycleDist = pInParams->IntRefCycleDist; ++ co3->AdaptiveMaxFrameSize = pInParams->nAdaptiveMaxFrameSize; ++ } ++#if (MFX_VERSION >= 1026) ++ if (pInParams->ExtBrcAdaptiveLTR) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->ExtBrcAdaptiveLTR = pInParams->ExtBrcAdaptiveLTR; ++ } ++#endif ++#if MFX_VERSION >= 1023 ++ if (pInParams->RepartitionCheckMode) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->RepartitionCheckEnable = pInParams->RepartitionCheckMode; ++ } ++#endif ++ ++ if (pInParams->GPB) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->GPB = pInParams->GPB; ++ } ++#if (MFX_VERSION >= 1026) ++ if (pInParams->nTransformSkip) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->TransformSkip = pInParams->nTransformSkip; ++ } ++#endif ++ if (pInParams->bDisableQPOffset) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->EnableQPOffset = MFX_CODINGOPTION_OFF; ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (pInParams->bIsMVC) ++ m_mfxEncParams.AddExtBuffer(); ++#endif ++ ++#if (MFX_VERSION >= 1027) ++ if (pInParams->TargetBitDepthLuma) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->TargetBitDepthLuma = pInParams->TargetBitDepthLuma; ++ } ++ if (pInParams->TargetBitDepthChroma) { ++ auto co3 = m_mfxEncParams.AddExtBuffer(); ++ co3->TargetBitDepthChroma = pInParams->TargetBitDepthChroma; ++ } ++#endif ++ ++#if !defined(MFX_ONEVPL) ++ if (m_pParentPipeline) { ++ m_pParentPipeline->AddLaStreams(m_mfxEncParams.mfx.FrameInfo.Width, ++ m_mfxEncParams.mfx.FrameInfo.Height); ++ } ++#endif //!MFX_ONEVPL ++ ++ //--- Settings HRD buffer size ++ if (pInParams->BufferSizeInKB) { ++ m_mfxEncParams.mfx.BufferSizeInKB = pInParams->BufferSizeInKB; ++ } ++ ++ //--- Force setting fourcc type if required ++ if (pInParams->EncoderFourCC) { ++ m_mfxEncParams.mfx.FrameInfo.FourCC = pInParams->EncoderFourCC; ++ m_mfxEncParams.mfx.FrameInfo.ChromaFormat = FourCCToChroma(pInParams->EncoderFourCC); ++ } ++ ++ // GopPicSize and GopRefDist values are always set using presets manager, but do not set them for JPEG ++ if (MFX_CODEC_JPEG != pInParams->EncodeId) { ++ m_mfxEncParams.mfx.GopPicSize = pInParams->GopPicSize; ++ m_mfxEncParams.mfx.GopRefDist = pInParams->GopRefDist; ++ } ++ ++ if (pInParams->NumRefFrame) { ++ m_mfxEncParams.mfx.NumRefFrame = pInParams->NumRefFrame; ++ } ++ ++ if (pInParams->CodecLevel) { ++ m_mfxEncParams.mfx.CodecLevel = pInParams->CodecLevel; ++ } ++ ++ if (pInParams->CodecProfile) { ++ m_mfxEncParams.mfx.CodecProfile = pInParams->CodecProfile; ++ } ++ ++ if (pInParams->GopOptFlag) { ++ m_mfxEncParams.mfx.GopOptFlag = pInParams->GopOptFlag; ++ } ++ ++ if (pInParams->MaxKbps) { ++ m_mfxEncParams.mfx.MaxKbps = pInParams->MaxKbps; ++ } ++ ++ if (pInParams->InitialDelayInKB) { ++ m_mfxEncParams.mfx.InitialDelayInKB = pInParams->InitialDelayInKB; ++ } ++ ++ return MFX_ERR_NONE; ++} // mfxStatus CTranscodingPipeline::InitEncMfxParams(sInputParams *pInParams) ++ ++#if !defined(MFX_ONEVPL) ++mfxStatus CTranscodingPipeline::CorrectPreEncAuxPool(mfxU32 num_frames_in_pool) { ++ if (!m_pmfxPreENC) ++ return MFX_ERR_NONE; ++ ++ if (m_pPreEncAuxPool.size() < num_frames_in_pool) { ++ m_pPreEncAuxPool.resize(num_frames_in_pool); ++ } ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus CTranscodingPipeline::AllocPreEncAuxPool() { ++ if (!m_pmfxPreENC) ++ return MFX_ERR_NONE; ++ ++ auto laCtrl = m_mfxPreEncParams.AddExtBuffer(); ++ mfxU16 num_resolutions = laCtrl->NumOutStream; ++ int buff_size = sizeof(mfxExtLAFrameStatistics) + ++ sizeof(mfxLAFrameInfo) * num_resolutions * laCtrl->LookAheadDepth; ++ ++ for (size_t i = 0; i < m_pPreEncAuxPool.size(); i++) { ++ memset(&m_pPreEncAuxPool[i], 0, sizeof(m_pPreEncAuxPool[i])); ++ ++ m_pPreEncAuxPool[i].encCtrl.NumExtParam = 1; ++ m_pPreEncAuxPool[i].encCtrl.ExtParam = new mfxExtBuffer *[1]; ++ ++ char *pBuff = new char[buff_size]; ++ memset(pBuff, 0, buff_size); ++ ++ m_pPreEncAuxPool[i].encCtrl.ExtParam[0] = (mfxExtBuffer *)pBuff; ++ mfxExtLAFrameStatistics *pExtBuffer = (mfxExtLAFrameStatistics *)pBuff; ++ ++ pExtBuffer = (mfxExtLAFrameStatistics *)pBuff; ++ pExtBuffer->Header.BufferId = MFX_EXTBUFF_LOOKAHEAD_STAT; ++ pExtBuffer->Header.BufferSz = buff_size; ++ pExtBuffer->NumAlloc = num_resolutions * laCtrl->LookAheadDepth; ++ pExtBuffer->FrameStat = (mfxLAFrameInfo *)(pBuff + sizeof(mfxExtLAFrameStatistics)); ++ ++ m_pPreEncAuxPool[i].encOutput.NumExtParam = 1; ++ m_pPreEncAuxPool[i].encOutput.ExtParam = m_pPreEncAuxPool[i].encCtrl.ExtParam; ++ } ++ return MFX_ERR_NONE; ++} ++ ++void CTranscodingPipeline::FreePreEncAuxPool() { ++ for (size_t i = 0; i < m_pPreEncAuxPool.size(); i++) { ++ if (m_pPreEncAuxPool[i].encCtrl.ExtParam) { ++ delete[] m_pPreEncAuxPool[i].encCtrl.ExtParam[0]; ++ delete[] m_pPreEncAuxPool[i].encCtrl.ExtParam; ++ } ++ } ++ m_pPreEncAuxPool.resize(0); ++} ++#endif //!MFX_ONEVPL ++ ++mfxStatus TranscodingSample::CTranscodingPipeline::LoadStaticSurface() { ++ if (m_bUseOverlay) { ++ mfxFrameSurface1 *pSurf = m_pSurfaceDecPool[0]; ++ mfxStatus sts = m_pMFXAllocator->LockFrame(pSurf->Data.MemId, &pSurf->Data); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->LockFrame failed"); ++ sts = m_pBSProcessor->GetInputFrame(pSurf); ++ MSDK_CHECK_STATUS(sts, "m_YUVReader->LoadNextFrame failed"); ++ sts = m_pMFXAllocator->UnlockFrame(pSurf->Data.MemId, &pSurf->Data); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->UnlockFrame failed"); ++ } ++ return MFX_ERR_NONE; ++} ++ ++#if !defined(MFX_ONEVPL) ++mfxStatus CTranscodingPipeline::InitPreEncMfxParams(sInputParams *pInParams) { ++ MSDK_CHECK_ERROR(pInParams->bEnableExtLA, false, MFX_ERR_INVALID_VIDEO_PARAM); ++ MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR); ++ ++ mfxVideoParam ¶m = m_mfxPreEncParams; ++ ++ param.AsyncDepth = m_AsyncDepth; ++ ++ MSDK_ZERO_MEMORY(param.mfx); ++ param.mfx.CodecId = MFX_CODEC_AVC; ++ param.mfx.TargetUsage = pInParams->nTargetUsage; ++ ++ if (m_bIsVpp) { ++ MSDK_MEMCPY_VAR(param.mfx.FrameInfo, &m_mfxVppParams.vpp.Out, sizeof(mfxFrameInfo)); ++ } ++ else if (m_bIsPlugin) { ++ MSDK_MEMCPY_VAR(param.mfx.FrameInfo, &m_mfxPluginParams.vpp.Out, sizeof(mfxFrameInfo)); ++ } ++ else { ++ param.mfx.FrameInfo = GetFrameInfo(m_mfxDecParams); ++ } ++ ++ mfxU16 InPatternFromParent = ++ (mfxU16)((MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxDecParams.IOPattern) ++ ? MFX_IOPATTERN_IN_VIDEO_MEMORY ++ : MFX_IOPATTERN_IN_SYSTEM_MEMORY); ++ ++ // set memory pattern ++ param.IOPattern = InPatternFromParent; ++ ++ auto laCtrl = m_mfxPreEncParams.AddExtBuffer(); ++ laCtrl->LookAheadDepth = pInParams->nLADepth ? pInParams->nLADepth : 40; ++ laCtrl->NumOutStream = 0; ++ laCtrl->BPyramid = ++ (mfxU16)(pInParams->bEnableBPyramid ? MFX_CODINGOPTION_ON : MFX_CODINGOPTION_OFF); ++ ++ m_mfxPreEncParams.mfx.GopPicSize = pInParams->GopPicSize ? pInParams->GopPicSize : 1500; ++ ++ if (pInParams->GopRefDist) { ++ m_mfxPreEncParams.mfx.GopRefDist = pInParams->GopRefDist; ++ } ++ ++ if (pInParams->nTargetUsage) { ++ m_mfxPreEncParams.mfx.TargetUsage = pInParams->nTargetUsage; ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus CTranscodingPipeline::AddLaStreams(mfxU16 width, mfxU16 height) { ++ if (m_pmfxPreENC.get() != NULL) { ++ auto laCtrl = m_mfxPreEncParams.AddExtBuffer(); ++ mfxU32 num = laCtrl->NumOutStream; ++ m_numEncoders++; ++ for (mfxU32 i = 0; i < num; i++) { ++ if (laCtrl->OutStream[i].Width == width && laCtrl->OutStream[i].Height == height) ++ return MFX_ERR_NONE; ++ } ++ if ((sizeof(laCtrl->OutStream) / sizeof(laCtrl->OutStream[0])) < (num + 1)) ++ return MFX_ERR_UNSUPPORTED; ++ ++ laCtrl->OutStream[num].Width = width; ++ laCtrl->OutStream[num].Height = height; ++ laCtrl->NumOutStream = (mfxU16)num + 1; ++ } ++ return MFX_ERR_NONE; ++} ++#endif //!MFX_ONEVPL ++ ++mfxU32 CTranscodingPipeline::FileFourCC2EncFourCC(mfxU32 fcc) { ++ if (fcc == MFX_FOURCC_I420) ++ return MFX_FOURCC_NV12; ++ else ++ return fcc; ++} ++ ++mfxStatus CTranscodingPipeline::InitVppMfxParams(sInputParams *pInParams) { ++ MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR); ++ m_mfxVppParams.AsyncDepth = m_AsyncDepth; ++ ++ mfxU16 InPatternFromParent = ++ (mfxU16)((MFX_IOPATTERN_OUT_VIDEO_MEMORY == m_mfxDecParams.IOPattern) ++ ? MFX_IOPATTERN_IN_VIDEO_MEMORY ++ : MFX_IOPATTERN_IN_SYSTEM_MEMORY); ++ ++ // set memory pattern ++ if (pInParams->VppOutPattern) { ++ m_mfxVppParams.IOPattern = (mfxU16)(InPatternFromParent | pInParams->VppOutPattern); ++ } ++ else if (pInParams->bForceSysMem || (MFX_IMPL_SOFTWARE == pInParams->libType)) { ++ m_mfxVppParams.IOPattern = (mfxU16)(InPatternFromParent | MFX_IOPATTERN_OUT_SYSTEM_MEMORY); ++ } ++ else { ++ m_mfxVppParams.IOPattern = (mfxU16)(InPatternFromParent | MFX_IOPATTERN_OUT_VIDEO_MEMORY); ++ } ++ ++ // input frame info ++ m_mfxVppParams.vpp.In = GetFrameInfo(m_mfxDecParams); ++ ++ if (m_mfxVppParams.vpp.In.Width * m_mfxVppParams.vpp.In.Height == 0) { ++ m_mfxVppParams.vpp.In.Width = MSDK_ALIGN32(pInParams->nDstWidth); ++ m_mfxVppParams.vpp.In.Height = MSDK_ALIGN32(pInParams->nDstHeight); ++ } ++ ++ if (m_mfxVppParams.vpp.In.CropW * m_mfxVppParams.vpp.In.CropH == 0) { ++ m_mfxVppParams.vpp.In.CropW = pInParams->nDstWidth; ++ m_mfxVppParams.vpp.In.CropH = pInParams->nDstHeight; ++ } ++ ++ if (m_mfxVppParams.vpp.In.FrameRateExtN * m_mfxVppParams.vpp.In.FrameRateExtD == 0) { ++ m_mfxVppParams.vpp.In.FrameRateExtN = 30; ++ m_mfxVppParams.vpp.In.FrameRateExtD = 1; ++ } ++ ++ if (m_mfxVppParams.vpp.In.FourCC == 0) { ++ m_mfxVppParams.vpp.In.FourCC = FileFourCC2EncFourCC(pInParams->DecodeId); ++ m_mfxVppParams.mfx.FrameInfo.ChromaFormat = FourCCToChroma(pInParams->DecoderFourCC); ++ } ++ ++ if (m_rawInput) { ++ m_mfxVppParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; ++ } ++ ++ // fill output frame info ++ MSDK_MEMCPY_VAR(m_mfxVppParams.vpp.Out, &m_mfxVppParams.vpp.In, sizeof(mfxFrameInfo)); ++ ++ if (m_bIsFieldWeaving) { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_UNKNOWN; ++ m_mfxVppParams.vpp.Out.Height = m_mfxVppParams.vpp.In.Height << 1; ++ m_mfxVppParams.vpp.Out.CropH = m_mfxVppParams.vpp.In.CropH << 1; ++ } ++ ++ if (m_bIsFieldSplitting) { ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_FIELD_SINGLE; ++ m_mfxVppParams.vpp.Out.Height = m_mfxVppParams.vpp.In.Height >> 1; ++ m_mfxVppParams.vpp.Out.CropH = m_mfxVppParams.vpp.In.CropH >> 1; ++ } ++ if (pInParams->bEnableDeinterlacing) ++ m_mfxVppParams.vpp.Out.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; ++ ++ // Resizing ++ if (pInParams->nDstWidth) { ++ m_mfxVppParams.vpp.Out.CropW = pInParams->nDstWidth; ++ m_mfxVppParams.vpp.Out.Width = MSDK_ALIGN16(pInParams->nDstWidth); ++ } ++ ++ // Framerate conversion ++ if (pInParams->dVPPOutFramerate) { ++ ConvertFrameRate(pInParams->dVPPOutFramerate, ++ &m_mfxVppParams.vpp.Out.FrameRateExtN, ++ &m_mfxVppParams.vpp.Out.FrameRateExtD); ++ } ++ ++ if (pInParams->nDstHeight) { ++ m_mfxVppParams.vpp.Out.CropH = pInParams->nDstHeight; ++ m_mfxVppParams.vpp.Out.Height = ++ (MFX_PICSTRUCT_PROGRESSIVE == m_mfxVppParams.vpp.Out.PicStruct) ++ ? MSDK_ALIGN16(pInParams->nDstHeight) ++ : MSDK_ALIGN32(pInParams->nDstHeight); ++ } ++ ++ if (pInParams->bEnableDeinterlacing) { ++ // If stream were interlaced before then 32 bit alignment were applied. ++ // Discard 32 bit alignment as progressive doesn't require it. ++ m_mfxVppParams.vpp.Out.Height = MSDK_ALIGN16(m_mfxVppParams.vpp.Out.CropH); ++ m_mfxVppParams.vpp.Out.Width = MSDK_ALIGN16(m_mfxVppParams.vpp.Out.CropW); ++ } ++ ++ // configure and attach external parameters ++ mfxStatus sts = AllocAndInitVppDoNotUse(pInParams); ++ MSDK_CHECK_STATUS(sts, "AllocAndInitVppDoNotUse failed"); ++ ++ //--- Setting output FourCC type (input type is taken from m_mfxDecParams) ++ if (pInParams->EncoderFourCC) { ++ m_mfxVppParams.vpp.Out.FourCC = pInParams->EncoderFourCC; ++ m_mfxVppParams.vpp.Out.ChromaFormat = FourCCToChroma(pInParams->EncoderFourCC); ++ ++ // set bit depth according to FourCC, it must be not inherited from m_mfxVppParams.vpp.In ++ switch (m_mfxVppParams.vpp.Out.FourCC) { ++ case MFX_FOURCC_RGB4: ++ case MFX_FOURCC_YUY2: ++ case MFX_FOURCC_NV12: ++ case MFX_FOURCC_NV16: ++ m_mfxVppParams.vpp.Out.BitDepthLuma = m_mfxVppParams.vpp.Out.BitDepthChroma = 8; ++ break; ++ case MFX_FOURCC_P010: ++ case MFX_FOURCC_P210: ++#if (MFX_VERSION >= 1027) ++ case MFX_FOURCC_Y210: ++ case MFX_FOURCC_Y410: ++#endif ++ m_mfxVppParams.vpp.Out.BitDepthLuma = m_mfxVppParams.vpp.Out.BitDepthChroma = 10; ++ break; ++ default: ++ assert(0); ++ MSDK_CHECK_STATUS(MFX_ERR_UNSUPPORTED, "Unexpected encoder FourCC"); ++ } ++ } ++ ++ /* VPP Comp Init */ ++ if (((pInParams->eModeExt == VppComp) || (pInParams->eModeExt == VppCompOnly)) && ++ (pInParams->numSurf4Comp != 0)) { ++ if (m_nVPPCompEnable != VppCompOnlyEncode) ++ m_nVPPCompEnable = pInParams->eModeExt; ++ ++ auto vppCompPar = m_mfxVppParams.AddExtBuffer(); ++ vppCompPar->NumInputStream = (mfxU16)pInParams->numSurf4Comp; ++ vppCompPar->InputStream = (mfxVPPCompInputStream *)malloc(sizeof(mfxVPPCompInputStream) * ++ vppCompPar->NumInputStream); ++ MSDK_CHECK_POINTER(vppCompPar->InputStream, MFX_ERR_NULL_PTR); ++ ++ // stream params ++ /* if input streams in NV12 format background color should be in YUV format too ++ * The same for RGB4 input, background color should be in ARGB format ++ * */ ++ ++ switch (pInParams->EncoderFourCC) { ++ case MFX_FOURCC_RGB4: ++ /* back color in RGB */ ++ vppCompPar->R = 0x00; ++ vppCompPar->G = 0x00; ++ vppCompPar->B = 0x00; ++ break; ++ case MFX_FOURCC_NV12: ++ case MFX_FOURCC_P010: ++ case MFX_FOURCC_NV16: ++ case MFX_FOURCC_P210: ++ case MFX_FOURCC_YUY2: ++ default: ++ /* back color in YUV */ ++ vppCompPar->Y = 0x10; ++ vppCompPar->U = 0x80; ++ vppCompPar->V = 0x80; ++ break; ++ } ++ ++#if MFX_VERSION >= 1024 ++ vppCompPar->NumTiles = pInParams->numTiles4Comp; ++#endif ++ ++ MSDK_CHECK_POINTER(pInParams->pVppCompDstRects, MFX_ERR_NULL_PTR); ++ for (mfxU32 i = 0; i < pInParams->numSurf4Comp; i++) { ++ vppCompPar->InputStream[i].DstX = pInParams->pVppCompDstRects[i].DstX; ++ vppCompPar->InputStream[i].DstY = pInParams->pVppCompDstRects[i].DstY; ++ vppCompPar->InputStream[i].DstW = pInParams->pVppCompDstRects[i].DstW; ++ vppCompPar->InputStream[i].DstH = pInParams->pVppCompDstRects[i].DstH; ++#if MFX_VERSION >= 1024 ++ vppCompPar->InputStream[i].TileId = pInParams->pVppCompDstRects[i].TileId; ++#endif ++ vppCompPar->InputStream[i].GlobalAlpha = 0; ++ vppCompPar->InputStream[i].GlobalAlphaEnable = 0; ++ vppCompPar->InputStream[i].PixelAlphaEnable = 0; ++ ++ vppCompPar->InputStream[i].LumaKeyEnable = 0; ++ vppCompPar->InputStream[i].LumaKeyMin = 0; ++ vppCompPar->InputStream[i].LumaKeyMax = 0; ++ } ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (pInParams->bIsMVC) ++ m_mfxVppParams.AddExtBuffer(); ++#endif ++ ++ mfxU32 enhFilterCount = 0; ++ ++#ifdef ENABLE_MCTF ++ if (VPP_FILTER_ENABLED_CONFIGURED == pInParams->mctfParam.mode) { ++ auto mctf = m_mfxVppParams.AddExtBuffer(); ++ mctf->FilterStrength = pInParams->mctfParam.params.FilterStrength; ++ // If an external file is given & at least 1 value is given, use it ++ if (!pInParams->mctfParam.rtParams.Empty() && pInParams->mctfParam.rtParams.GetCurParam()) { ++ mctf->FilterStrength = pInParams->mctfParam.rtParams.GetCurParam()->FilterStrength; ++ } ++ #if defined ENABLE_MCTF_EXT ++ mctf->Overlap = pInParams->mctfParam.pInParams.Overlap; ++ mctf->TemporalMode = pInParams->mctfParam.params.TemporalMode; ++ mctf->MVPrecision = pInParams->mctfParam.params.MVPrecision; ++ mctf->BitsPerPixelx100k = pInParams->mctfParam.params.BitsPerPixelx100k; ++ mctf->Deblocking = pInParams->mctfParam.params.Deblocking; ++ #endif ++ } ++ else if (VPP_FILTER_ENABLED_DEFAULT == pInParams->mctfParam.mode) { ++ // MCTF enabling through do-use list: ++ m_tabDoUseAlg[enhFilterCount++] = MFX_EXTBUFF_VPP_MCTF; ++ } ++#endif //ENABLE_MCTF ++ ++ if (pInParams->DenoiseLevel != -1) { ++ auto denoise = m_mfxVppParams.AddExtBuffer(); ++ denoise->DenoiseFactor = (mfxU16)pInParams->DenoiseLevel; ++ } ++ ++ if (pInParams->DetailLevel != -1) { ++ auto detail = m_mfxVppParams.AddExtBuffer(); ++ detail->DetailFactor = (mfxU16)pInParams->DetailLevel; ++ } ++ ++ if (pInParams->FRCAlgorithm) { ++ auto frc = m_mfxVppParams.AddExtBuffer(); ++ frc->Algorithm = pInParams->FRCAlgorithm; ++ } ++ ++ if (pInParams->bEnableDeinterlacing && pInParams->DeinterlacingMode) { ++ auto di = m_mfxVppParams.AddExtBuffer(); ++ di->Mode = pInParams->DeinterlacingMode; ++ } ++ ++ //--- Field Copy Mode ++ if (pInParams->fieldProcessingMode) { ++ auto fieldProc = m_mfxVppParams.AddExtBuffer(); ++ ++ //--- To check first is we do copy frame of field ++ fieldProc->Mode = (mfxU16)(pInParams->fieldProcessingMode == FC_FR2FR ? MFX_VPP_COPY_FRAME ++ : MFX_VPP_COPY_FIELD); ++ ++ fieldProc->InField = (mfxU16)( ++ (pInParams->fieldProcessingMode == FC_T2T || pInParams->fieldProcessingMode == FC_T2B) ++ ? MFX_PICSTRUCT_FIELD_TFF ++ : MFX_PICSTRUCT_FIELD_BFF); ++ ++ fieldProc->OutField = (mfxU16)( ++ (pInParams->fieldProcessingMode == FC_T2T || pInParams->fieldProcessingMode == FC_B2T) ++ ? MFX_PICSTRUCT_FIELD_TFF ++ : MFX_PICSTRUCT_FIELD_BFF); ++ } ++ ++ if (pInParams->ScalingMode) { ++ auto par = m_mfxVppParams.AddExtBuffer(); ++ par->ScalingMode = pInParams->ScalingMode; ++ } ++ ++ if (enhFilterCount) { ++ auto doUse = m_mfxVppParams.AddExtBuffer(); ++ doUse->NumAlg = enhFilterCount; ++ doUse->AlgList = m_tabDoUseAlg; ++ } ++ ++#ifdef ENABLE_MCTF ++ // would it be more efficienct to get a pointer? ++ m_MctfRTParams = pInParams->mctfParam.rtParams; ++ m_MctfRTParams.Restart(); ++#endif ++ ++ return MFX_ERR_NONE; ++ ++} //mfxStatus CTranscodingPipeline::InitMfxVppParams(sInputParams *pInParams) ++ ++mfxStatus CTranscodingPipeline::InitPluginMfxParams(sInputParams *pInParams) { ++ MSDK_CHECK_POINTER(pInParams, MFX_ERR_NULL_PTR); ++ ++ mfxU16 parentPattern = m_bIsVpp ? m_mfxVppParams.IOPattern : m_mfxDecParams.IOPattern; ++ mfxU16 InPatternFromParent = ++ (mfxU16)((MFX_IOPATTERN_OUT_VIDEO_MEMORY & parentPattern) ? MFX_IOPATTERN_IN_VIDEO_MEMORY ++ : MFX_IOPATTERN_IN_SYSTEM_MEMORY); ++ ++ // set memory pattern ++ if (pInParams->bForceSysMem || (MFX_IMPL_SOFTWARE == pInParams->libType)) ++ m_mfxPluginParams.IOPattern = ++ (mfxU16)(InPatternFromParent | MFX_IOPATTERN_OUT_SYSTEM_MEMORY); ++ else ++ m_mfxPluginParams.IOPattern = ++ (mfxU16)(InPatternFromParent | MFX_IOPATTERN_OUT_VIDEO_MEMORY); ++ ++ m_mfxPluginParams.AsyncDepth = m_AsyncDepth; ++ ++ // input frame info ++ if (m_bIsVpp) { ++ MSDK_MEMCPY_VAR(m_mfxPluginParams.vpp.In, &m_mfxVppParams.vpp.Out, sizeof(mfxFrameInfo)); ++ } ++ else { ++ m_mfxPluginParams.vpp.In = GetFrameInfo(m_mfxDecParams); ++ } ++ ++ // fill output frame info ++ // in case of rotation plugin sample output frameinfo is same as input ++ MSDK_MEMCPY_VAR(m_mfxPluginParams.vpp.Out, &m_mfxPluginParams.vpp.In, sizeof(mfxFrameInfo)); ++ ++ return MFX_ERR_NONE; ++ ++} //mfxStatus CTranscodingPipeline::InitMfxVppParams(sInputParams *pInParams) ++ ++mfxStatus CTranscodingPipeline::AllocFrames(mfxFrameAllocRequest *pRequest, bool isDecAlloc) { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ mfxU16 nSurfNum = 0; // number of surfaces ++ mfxU16 i; ++ ++ nSurfNum = pRequest->NumFrameMin = pRequest->NumFrameSuggested; ++ msdk_printf(MSDK_STRING("Pipeline surfaces number (%s): %d\n"), ++ isDecAlloc ? MSDK_STRING("DecPool") : MSDK_STRING("EncPool"), ++ nSurfNum); ++ ++ mfxFrameAllocResponse *pResponse = isDecAlloc ? &m_mfxDecResponse : &m_mfxEncResponse; ++ ++ sts = m_pMFXAllocator->Alloc(m_pMFXAllocator->pthis, pRequest, pResponse); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Alloc failed"); ++ ++ for (i = 0; i < nSurfNum; i++) { ++ auto surface = std::unique_ptr(new mfxFrameSurfaceWrap()); ++ surface->Info = pRequest->Info; ++ ++ if (m_rawInput) { ++ sts = ++ m_pMFXAllocator->Lock(m_pMFXAllocator->pthis, pResponse->mids[i], &(surface->Data)); ++ MSDK_CHECK_STATUS(sts, "m_pMFXAllocator->Lock failed"); ++ } ++ else { ++ surface->Data.MemId = pResponse->mids[i]; ++ } ++ ++ (isDecAlloc) ? m_pSurfaceDecPool.push_back(surface.get()) ++ : m_pSurfaceEncPool.push_back(surface.get()); ++ ++ std::ignore = surface.release(); ++ } ++ ++ (isDecAlloc) ? m_DecSurfaceType = pRequest->Type : m_EncSurfaceType = pRequest->Type; ++ ++ return MFX_ERR_NONE; ++ ++} // mfxStatus CTranscodingPipeline::AllocFrames(Component* pComp, mfxFrameAllocResponse* pMfxResponse, mfxVideoParam* pMfxVideoParam) ++ ++//return true if correct ++static bool CheckAsyncDepth(mfxFrameAllocRequest &curReq, mfxU16 asyncDepth) { ++ return (curReq.NumFrameSuggested >= asyncDepth); ++} ++ ++static mfxStatus CorrectAsyncDepth(mfxFrameAllocRequest &curReq, mfxU16 asyncDepth) { ++ mfxStatus sts = MFX_ERR_NONE; ++ if (!CheckAsyncDepth(curReq, asyncDepth)) { ++ sts = MFX_ERR_MEMORY_ALLOC; ++ } ++ else { ++ // The request holds summary of required surfaces numbers from 2 components and ++ // asyncDepth is included twice. Here we patch surfaces number removing ++ // one asyncDepth. ++ curReq.NumFrameSuggested = curReq.NumFrameSuggested - asyncDepth; ++ curReq.NumFrameMin = curReq.NumFrameSuggested; ++ } ++ ++ return sts; ++} ++ ++static void SumAllocRequest(mfxFrameAllocRequest &curReq, mfxFrameAllocRequest &newReq) { ++ curReq.NumFrameSuggested = curReq.NumFrameSuggested + newReq.NumFrameSuggested; ++ curReq.NumFrameMin = curReq.NumFrameSuggested; ++ curReq.Type = curReq.Type | newReq.Type; ++ ++ if ((curReq.Type & MFX_MEMTYPE_SYSTEM_MEMORY) && ++ ((curReq.Type & 0xf0) != MFX_MEMTYPE_SYSTEM_MEMORY)) ++ curReq.Type = (mfxU16)(curReq.Type & (~MFX_MEMTYPE_SYSTEM_MEMORY)); ++ if ((curReq.Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) && ++ ((curReq.Type & 0xf0) != MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)) ++ curReq.Type = (mfxU16)(curReq.Type & (~MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)); ++ ++ if (curReq.Info.Width == 0) { ++ curReq.Info = newReq.Info; ++ } ++ else { ++ curReq.Info.Width = ++ curReq.Info.Width < newReq.Info.Width ? newReq.Info.Width : curReq.Info.Width; ++ curReq.Info.Height = ++ curReq.Info.Height < newReq.Info.Height ? newReq.Info.Height : curReq.Info.Height; ++ } ++} ++ ++mfxStatus CTranscodingPipeline::AllocFrames() { ++ mfxStatus sts = MFX_ERR_NONE; ++ bool bAddFrames = true; // correct shared pool between session ++ ++ mfxFrameAllocRequest DecOut; ++ mfxFrameAllocRequest VPPOut; ++ ++ MSDK_ZERO_MEMORY(DecOut); ++ MSDK_ZERO_MEMORY(VPPOut); ++ ++ sts = CalculateNumberOfReqFrames(DecOut, VPPOut); ++ MSDK_CHECK_STATUS(sts, "CalculateNumberOfReqFrames failed"); ++ ++ if (VPPOut.NumFrameSuggested) { ++ if (bAddFrames) { ++ SumAllocRequest(VPPOut, m_Request); ++ bAddFrames = false; ++ } ++ ++ // Do not correct anything if we're using raw output - we'll need those surfaces for storing data for writer ++ if (m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP) { ++ // In case of rendering enabled we need to add 1 additional surface for renderer ++ if ((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ VPPOut.NumFrameSuggested++; ++ VPPOut.NumFrameMin++; ++ } ++ sts = CorrectAsyncDepth(VPPOut, m_AsyncDepth); ++ MSDK_CHECK_STATUS(sts, "CorrectAsyncDepth failed"); ++ /* WA for rendering: VPP should have at least 2 frames on output (for front & back buffer accordinally) */ ++ if ((VPPOut.NumFrameSuggested <= 1) || (VPPOut.NumFrameMin <= 1)) { ++ VPPOut.NumFrameSuggested = 2; ++ VPPOut.NumFrameMin = 2; ++ } ++ } ++ ++#ifdef LIBVA_SUPPORT ++ if (((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) && ++ ((m_libvaBackend == MFX_LIBVA_DRM_MODESET) || ++ #if defined(X11_DRI3_SUPPORT) ++ (m_libvaBackend == MFX_LIBVA_X11) || ++ #endif // X11_DRI3_SUPPORT ++ (m_libvaBackend == MFX_LIBVA_WAYLAND))) { ++ VPPOut.Type |= MFX_MEMTYPE_EXPORT_FRAME; ++ } ++#endif ++ sts = AllocFrames(&VPPOut, false); ++ MSDK_CHECK_STATUS(sts, "AllocFrames failed"); ++ } ++ ++ if (DecOut.NumFrameSuggested) { ++ if (bAddFrames) { ++ SumAllocRequest(DecOut, m_Request); ++ bAddFrames = false; ++ } ++ ++ if (m_bDecodeEnable) { ++ if (0 == m_nVPPCompEnable && m_mfxEncParams.mfx.CodecId != MFX_CODEC_DUMP) { ++ //--- Make correction to number of surfaces only if composition is not enabled. In case of composition we need all the surfaces QueryIOSurf has requested to pass them to another session's VPP ++ // In other inter-session cases, other sessions request additional surfaces using additional calls to AllocFrames ++ sts = CorrectAsyncDepth(DecOut, m_AsyncDepth); ++ MSDK_CHECK_STATUS(sts, "CorrectAsyncDepth failed"); ++ } ++ ++ // AllocId just opaque handle which allow separate decoder requests in case of VPP Composition with external allocator ++ static mfxU32 mark_alloc = 0; ++ m_mfxDecParams.AllocId = mark_alloc; ++ DecOut.AllocId = mark_alloc; ++ if (m_nVPPCompEnable) // WORKAROUND: Remove this if clause after problem with AllocID is fixed in library (mark_alloc++ should be left here) ++ { ++ mark_alloc++; ++ } ++ ++ if ((DecOut.NumFrameSuggested <= 1) || (DecOut.NumFrameMin <= 1)) { ++ DecOut.NumFrameSuggested = 2; ++ DecOut.NumFrameMin = 2; ++ } ++ ++ sts = AllocFrames(&DecOut, true); ++ MSDK_CHECK_STATUS(sts, "AllocFrames failed"); ++#if !defined(MFX_ONEVPL) ++ sts = CorrectPreEncAuxPool( ++ (VPPOut.NumFrameSuggested ? VPPOut.NumFrameSuggested : DecOut.NumFrameSuggested) + ++ m_AsyncDepth); ++ MSDK_CHECK_STATUS(sts, "CorrectPreEncAuxPool failed"); ++ sts = AllocPreEncAuxPool(); ++ MSDK_CHECK_STATUS(sts, "AllocPreEncAuxPool failed"); ++#endif //!MFX_ONEVPL ++ } ++ else { ++ if ((m_pParentPipeline) && (0 == m_nVPPCompEnable) /* case if 1_to_N */) { ++ m_pParentPipeline->CorrectNumberOfAllocatedFrames(&DecOut); ++#if !defined(MFX_ONEVPL) ++ sts = m_pParentPipeline->CorrectPreEncAuxPool( ++ VPPOut.NumFrameSuggested + DecOut.NumFrameSuggested + m_AsyncDepth); ++ MSDK_CHECK_STATUS(sts, "m_pParentPipeline->CorrectPreEncAuxPool failed"); ++#endif //!MFX_ONEVPL ++ } ++ } ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus CTranscodingPipeline::CalculateNumberOfReqFrames(mfxFrameAllocRequest &pDecOut, ++ mfxFrameAllocRequest &pVPPOut) { ++ mfxStatus sts = MFX_ERR_NONE; ++ mfxFrameAllocRequest *pSumRequest = &pDecOut; ++ ++ memset(&pDecOut, 0, sizeof(pDecOut)); ++ memset(&pVPPOut, 0, sizeof(pVPPOut)); ++ ++ mfxFrameAllocRequest DecRequest; ++ MSDK_ZERO_MEMORY(DecRequest); ++ ++ if (m_pmfxDEC.get()) { ++ sts = m_pmfxDEC.get()->QueryIOSurf(&m_mfxDecParams, &DecRequest); ++ MSDK_CHECK_STATUS(sts, "m_pmfxDEC.get failed"); ++ ++ if (!CheckAsyncDepth(DecRequest, m_mfxDecParams.AsyncDepth)) ++ return MFX_ERR_MEMORY_ALLOC; ++ SumAllocRequest(*pSumRequest, DecRequest); ++ } ++ else if (m_bUseOverlay) { ++ // It takes 1 surface for overlay ++ DecRequest.NumFrameMin = DecRequest.NumFrameSuggested = 1; ++ DecRequest.Type = MFX_MEMTYPE_FROM_DECODE | MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET | ++ MFX_MEMTYPE_EXTERNAL_FRAME; ++ DecRequest.Info = GetFrameInfo(m_mfxDecParams); ++ SumAllocRequest(*pSumRequest, DecRequest); ++ } ++ ++ if (m_pmfxVPP.get()) { ++ mfxFrameAllocRequest VppRequest[2]; ++ ++ MSDK_ZERO_MEMORY(VppRequest); ++ if (m_bIsPlugin && m_bIsVpp) { ++ sts = m_pmfxVPP.get()->QueryIOSurfMulti(&m_mfxPluginParams, ++ &(VppRequest[0]), ++ &m_mfxVppParams); ++ if (!CheckAsyncDepth(VppRequest[0], m_mfxPluginParams.AsyncDepth) || ++ !CheckAsyncDepth(VppRequest[1], m_mfxPluginParams.AsyncDepth) || ++ !CheckAsyncDepth(VppRequest[0], m_mfxVppParams.AsyncDepth) || ++ !CheckAsyncDepth(VppRequest[1], m_mfxVppParams.AsyncDepth)) ++ return MFX_ERR_MEMORY_ALLOC; ++ } ++ else if (m_bIsPlugin) { ++ sts = m_pmfxVPP.get()->QueryIOSurf(&m_mfxPluginParams, &(VppRequest[0])); ++ if (!CheckAsyncDepth(VppRequest[0], m_mfxPluginParams.AsyncDepth) || ++ !CheckAsyncDepth(VppRequest[1], m_mfxPluginParams.AsyncDepth)) ++ return MFX_ERR_MEMORY_ALLOC; ++ } ++ else { ++ sts = m_pmfxVPP.get()->QueryIOSurf(&m_mfxVppParams, &(VppRequest[0])); ++ if (!CheckAsyncDepth(VppRequest[0], m_mfxVppParams.AsyncDepth) || ++ !CheckAsyncDepth(VppRequest[1], m_mfxVppParams.AsyncDepth)) ++ return MFX_ERR_MEMORY_ALLOC; ++ } ++ ++ MSDK_CHECK_STATUS(sts, "m_pmfxVPP.get()->QueryIOSurf failed"); ++ ++ SumAllocRequest(*pSumRequest, VppRequest[0]); ++ pSumRequest = &pVPPOut; ++ SumAllocRequest(*pSumRequest, VppRequest[1]); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (m_pmfxPreENC.get()) { ++ mfxFrameAllocRequest PreEncRequest; ++ ++ MSDK_ZERO_MEMORY(PreEncRequest); ++ sts = m_pmfxPreENC.get()->QueryIOSurf(&m_mfxPreEncParams, &PreEncRequest); ++ MSDK_CHECK_STATUS(sts, "m_pmfxPreENC.get()->QueryIOSurf failed"); ++ ++ if (!CheckAsyncDepth(PreEncRequest, m_mfxPreEncParams.AsyncDepth)) ++ return MFX_ERR_MEMORY_ALLOC; ++ SumAllocRequest(*pSumRequest, PreEncRequest); ++ } ++#endif //!MFX_ONEVPL ++ ++ if (m_pmfxENC.get()) { ++ mfxFrameAllocRequest EncRequest; ++ ++ MSDK_ZERO_MEMORY(EncRequest); ++ ++ sts = m_pmfxENC.get()->QueryIOSurf(&m_mfxEncParams, &EncRequest); ++ MSDK_CHECK_STATUS(sts, "m_pmfxENC.get()->QueryIOSurf failed"); ++ ++ if (!CheckAsyncDepth(EncRequest, m_mfxEncParams.AsyncDepth)) ++ return MFX_ERR_MEMORY_ALLOC; ++ SumAllocRequest(*pSumRequest, EncRequest); ++ } ++ ++ if (!pSumRequest->Type && m_pmfxDEC.get()) { ++ //--- If noone has set type to VPP request type yet, set it now basing on decoder request type ++ pSumRequest->Type = MFX_MEMTYPE_BASE(DecRequest.Type) | MFX_MEMTYPE_FROM_VPPOUT; ++ } ++ ++ return MFX_ERR_NONE; ++} ++void CTranscodingPipeline::CorrectNumberOfAllocatedFrames(mfxFrameAllocRequest *pNewReq) { ++ if (shouldUseGreedyFormula) { ++ m_Request.NumFrameSuggested += pNewReq->NumFrameSuggested; ++ } ++ else { ++ m_Request.NumFrameSuggested = ++ std::max(m_Request.NumFrameSuggested, pNewReq->NumFrameSuggested); ++ } ++ ++ m_Request.NumFrameMin = m_Request.NumFrameSuggested; ++ m_Request.Type = m_Request.Type | pNewReq->Type; ++ ++ if ((m_Request.Type & MFX_MEMTYPE_SYSTEM_MEMORY) && ++ ((m_Request.Type & 0xf0) != MFX_MEMTYPE_SYSTEM_MEMORY)) ++ m_Request.Type = (mfxU16)(m_Request.Type & (~MFX_MEMTYPE_SYSTEM_MEMORY)); ++ if ((m_Request.Type & MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET) && ++ ((m_Request.Type & 0xf0) != MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET)) ++ m_Request.Type = (mfxU16)(m_Request.Type & (~MFX_MEMTYPE_DXVA2_PROCESSOR_TARGET)); ++ ++ if (m_Request.Info.Width == 0) { ++ m_Request.Info = pNewReq->Info; ++ } ++ else { ++ m_Request.Info.Width = ++ m_Request.Info.Width < pNewReq->Info.Width ? pNewReq->Info.Width : m_Request.Info.Width; ++ m_Request.Info.Height = m_Request.Info.Height < pNewReq->Info.Height ++ ? pNewReq->Info.Height ++ : m_Request.Info.Height; ++ } ++} ++ ++void CTranscodingPipeline::FreeFrames() { ++ std::for_each(m_pSurfaceDecPool.begin(), m_pSurfaceDecPool.end(), [](mfxFrameSurface1 *s) { ++ auto surface = static_cast(s); ++ delete surface; ++ }); ++ m_pSurfaceDecPool.clear(); ++ ++ std::for_each(m_pSurfaceEncPool.begin(), m_pSurfaceEncPool.end(), [](mfxFrameSurface1 *s) { ++ auto surface = static_cast(s); ++ delete surface; ++ }); ++ m_pSurfaceEncPool.clear(); ++ ++ if (m_pMFXAllocator) { ++ m_pMFXAllocator->Free(m_pMFXAllocator->pthis, &m_mfxEncResponse); ++ m_pMFXAllocator->Free(m_pMFXAllocator->pthis, &m_mfxDecResponse); ++ } ++} // CTranscodingPipeline::FreeFrames() ++ ++mfxStatus CTranscodingPipeline::Init(sInputParams *pParams, ++ MFXFrameAllocator *pMFXAllocator, ++ void *hdl, ++ CTranscodingPipeline *pParentPipeline, ++ SafetySurfaceBuffer *pBuffer, ++ FileBitstreamProcessor *pBSProc, ++ VPLImplementationLoader *mfxLoader) { ++ MSDK_CHECK_POINTER(pParams, MFX_ERR_NULL_PTR); ++ MSDK_CHECK_POINTER(pMFXAllocator, MFX_ERR_NULL_PTR); ++ MSDK_CHECK_POINTER(pBSProc, MFX_ERR_NULL_PTR); ++ mfxStatus sts = MFX_ERR_NONE; ++ m_MaxFramesForTranscode = pParams->MaxFrameNumber; ++ // if no number of frames for a particular session is undefined, default ++ // value is 0xFFFFFFFF. Thus, use it as a marker to assign parent ++ // MaxFramesForTranscode to m_MaxFramesForTranscode ++ if (pParentPipeline && (0xFFFFFFFF == m_MaxFramesForTranscode) && ++ pParentPipeline->m_MaxFramesForTranscode) ++ m_MaxFramesForTranscode = pParentPipeline->m_MaxFramesForTranscode; ++ ++ // use external allocator ++ m_pMFXAllocator = pMFXAllocator; ++ m_pBSProcessor = pBSProc; ++ m_hdl = hdl; ++ ++ m_pParentPipeline = pParentPipeline; ++ shouldUseGreedyFormula = pParams->shouldUseGreedyFormula; ++ ++ m_nTimeout = pParams->nTimeout; ++ ++ m_AsyncDepth = (0 == pParams->nAsyncDepth) ? 1 : pParams->nAsyncDepth; ++ m_FrameNumberPreference = pParams->FrameNumberPreference; ++ m_numEncoders = 0; ++ m_bUseOverlay = pParams->DecodeId == MFX_CODEC_RGB4 ? true : false; ++ m_bRobustFlag = pParams->bRobustFlag; ++ m_bSoftGpuHangRecovery = pParams->bSoftRobustFlag; ++ m_nRotationAngle = pParams->nRotationAngle; ++ m_sGenericPluginPath = pParams->strVPPPluginDLLPath; ++ m_decoderPluginParams = pParams->decoderPluginParams; ++ m_encoderPluginParams = pParams->encoderPluginParams; ++ ++ m_encoderFourCC = pParams->EncoderFourCC; ++ ++ m_rawInput = pParams->rawInput; ++ ++ m_bExtMBQP = pParams->bExtMBQP; ++ m_bROIasQPMAP = pParams->bROIasQPMAP; ++ ++ m_MemoryModel = ++ (UNKNOWN_ALLOC == pParams->nMemoryModel) ? GENERAL_ALLOC : pParams->nMemoryModel; ++ ++#if MFX_VERSION >= 1022 ++ m_ROIData = pParams->m_ROIData; ++#endif //MFX_VERSION >= 1022 ++ ++ statisticsWindowSize = pParams->statisticsWindowSize; ++ if (statisticsWindowSize > m_MaxFramesForTranscode) ++ statisticsWindowSize = m_MaxFramesForTranscode; ++ ++ m_strMfxParamsDumpFile.assign(pParams->strMfxParamsDumpFile); ++ ++ if (pParams->statisticsLogFile) { ++ //same log file for intput/output ++ inputStatistics.SetOutputFile(pParams->statisticsLogFile); ++ outputStatistics.SetOutputFile(pParams->statisticsLogFile); ++ } ++ ++ if (!pParams->DumpLogFileName.empty()) { ++ inputStatistics.SetDumpName((pParams->DumpLogFileName + MSDK_STRING("_input")).c_str()); ++ outputStatistics.SetDumpName((pParams->DumpLogFileName + MSDK_STRING("_output")).c_str()); ++ } ++ ++ // if no statistic-window is passed but overall stat-log exist: ++ // is requested, set statisticsWindowSize to m_MaxFramesForTranscode ++ if ((pParams->statisticsLogFile || !pParams->DumpLogFileName.empty()) && ++ 0 == statisticsWindowSize) ++ statisticsWindowSize = m_MaxFramesForTranscode; ++ ++ if (m_bEncodeEnable) { ++ m_pBSStore.reset(new ExtendedBSStore(m_AsyncDepth)); ++ } ++ ++ // Determine processing mode ++ switch (pParams->eMode) { ++ case Native: ++ break; ++ case Sink: ++ if ((VppComp == pParams->eModeExt) || (VppCompOnly == pParams->eModeExt)) { ++ if ((NULL != pParentPipeline) && (NULL != pParentPipeline->m_pMFXAllocator)) ++ m_pMFXAllocator = pParentPipeline->m_pMFXAllocator; ++ } ++ ++ m_bEncodeEnable = false; // decode only ++ break; ++ case Source: ++ // for heterogeneous pipeline use parent allocator ++ MSDK_CHECK_POINTER(pParentPipeline, MFX_ERR_NULL_PTR); ++ m_pMFXAllocator = pParentPipeline->m_pMFXAllocator; ++ m_bDecodeEnable = false; // encode only ++ /**/ ++ if ((pParams->m_hwdev != NULL) && (VppCompOnly == pParams->eModeExt)) { ++#if defined(_WIN32) || defined(_WIN64) ++ m_hwdev4Rendering = new CDecodeD3DRender; ++ m_hwdev4Rendering->SetHWDevice(pParams->m_hwdev); ++ ++ sWindowParams RenderParam; ++ ++ memset(&RenderParam, 0, sizeof(sWindowParams)); ++ ++ RenderParam.lpWindowName = MSDK_STRING("sample_multi_transcode"); ++ RenderParam.nx = 0; ++ RenderParam.ny = 0; ++ RenderParam.nWidth = pParams->nDstWidth; ++ RenderParam.nHeight = pParams->nDstHeight; ++ RenderParam.ncell = 0; ++ RenderParam.nAdapter = 0; ++ ++ RenderParam.lpClassName = MSDK_STRING("Render Window Class"); ++ RenderParam.dwStyle = WS_OVERLAPPEDWINDOW; ++ RenderParam.hWndParent = NULL; ++ RenderParam.hMenu = NULL; ++ RenderParam.hInstance = GetModuleHandle(NULL); ++ RenderParam.lpParam = NULL; ++ RenderParam.bFullScreen = TRUE; ++ ++ m_hwdev4Rendering->Init(RenderParam); ++#else ++ if (pParams->EncodeId) { ++ m_nVPPCompEnable = VppCompOnlyEncode; ++ } ++ m_hwdev4Rendering = pParams->m_hwdev; ++#endif ++ } ++ break; ++ default: ++ // unknown mode ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((VppComp == pParams->eModeExt) || (VppCompOnly == pParams->eModeExt)) { ++ if (m_nVPPCompEnable != VppCompOnlyEncode) ++ m_nVPPCompEnable = pParams->eModeExt; ++ } ++ ++#ifdef LIBVA_SUPPORT ++ m_libvaBackend = pParams->libvaBackend; ++#endif ++ ++ m_pBuffer = pBuffer; ++ ++#if defined(MFX_ONEVPL) ++ m_initPar.Version.Major = 2; ++ m_initPar.Version.Minor = 2; ++#else ++ // we set version to 1.0 and later we will query actual version of the library which will got leaded ++ m_initPar.Version.Major = 1; ++ m_initPar.Version.Minor = 0; ++#endif ++ m_initPar.Implementation = pParams->libType; ++ ++ if (pParams->nThreadsNum) { ++ auto threadsPar = m_initPar.AddExtBuffer(); ++ threadsPar->NumThread = pParams->nThreadsNum; ++ } ++ ++ //--- GPU Copy settings ++ m_initPar.GPUCopy = pParams->nGpuCopyMode; ++ ++ // init session ++ m_pmfxSession.reset(new MainVideoSession); ++ ++ sts = m_pmfxSession->CreateSession(mfxLoader); ++ MSDK_CHECK_STATUS(sts, "m_pmfxSession->CreateSession failed"); ++ ++ // check the API version of actually loaded library ++ sts = m_pmfxSession->QueryVersion(&m_Version); ++ MSDK_CHECK_STATUS(sts, "m_pmfxSession->QueryVersion failed"); ++ // check the implementation version of actually loaded library ++ sts = m_pmfxSession->QueryIMPL(&pParams->libType); ++ MSDK_CHECK_STATUS(sts, "m_pmfxSession->QueryIMPL failed"); ++ ++#if defined(_WIN32) || defined(_WIN64) ++ if (MFX_CODEC_AV1 == pParams->DecodeId && ++ MFX_IMPL_VIA_MASK(pParams->libType) == MFX_IMPL_VIA_D3D9) { ++ sts = MFX_ERR_UNSUPPORTED; ++ MSDK_CHECK_STATUS(sts, "AV1d have no DX9 support \n"); ++ } ++#endif ++ ++ sts = CheckRequiredAPIVersion(m_Version, pParams); ++ MSDK_CHECK_STATUS(sts, "CheckRequiredAPIVersion failed"); ++ ++ // common session settings ++ if (MFX_VERSION >= 1001) ++ sts = m_pmfxSession->SetPriority(pParams->priority); ++ ++ m_bIsInterOrJoined = pParams->eMode == Sink || pParams->eMode == Source || pParams->bIsJoin; ++ ++ sts = SetAllocatorAndHandleIfRequired(); ++ MSDK_CHECK_STATUS(sts, "SetAllocatorAndHandleIfRequired failed"); ++ ++ // Joining sessions if required ++ if (pParams->bIsJoin && pParentPipeline) { ++ sts = pParentPipeline->Join(m_pmfxSession.get()); ++ MSDK_CHECK_STATUS(sts, "pParentPipeline->Join failed"); ++ m_bIsJoinSession = true; ++ } ++ ++ // Initialize pipeline components following downstream direction ++ // Pre-init methods fill parameters and create components ++ ++ if (!m_rawInput) { ++ // Decode component initialization ++ sts = DecodePreInit(pParams); ++ if (MFX_ERR_MORE_DATA == sts) ++ return sts; ++ else ++ MSDK_CHECK_STATUS(sts, "DecodePreInit failed"); ++ } ++ else { ++ m_mfxDecParams.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE; ++ } ++ ++ // VPP component initialization ++ sts = VPPPreInit(pParams); ++ MSDK_CHECK_STATUS(sts, "VPPPreInit failed"); ++ ++ // Adjusting encoding settings according to selected preset ++ if (Sink != pParams->eMode) { ++ mfxFrameInfo eInfo; ++ FillFrameInfoForEncoding(eInfo, pParams); ++ ModifyParamsUsingPresets(*pParams, ++ ((double)eInfo.FrameRateExtN) / eInfo.FrameRateExtD, ++ eInfo.Width, ++ eInfo.Height); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ // LA component initialization ++ sts = PreEncPreInit(pParams); ++ MSDK_CHECK_STATUS(sts, "PreEncPreInit failed"); ++#endif //MFX_ONEVPL ++ ++ // Encode component initialization ++ if ((m_nVPPCompEnable != VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode)) { ++ sts = EncodePreInit(pParams); ++ MSDK_CHECK_STATUS(sts, "EncodePreInit failed"); ++ } ++ ++ if ((pParams->eMode == Source) && ++ ((m_nVPPCompEnable == VppCompOnly) || (m_nVPPCompEnable == VppCompOnlyEncode) || ++ (m_nVPPCompEnable == VppComp))) { ++ if ((0 == msdk_strncmp(MSDK_STRING("null_render"), ++ pParams->strDumpVppCompFile, ++ msdk_strlen(MSDK_STRING("null_render"))))) ++ m_vppCompDumpRenderMode = NULL_RENDER_VPP_COMP; // null_render case ++ else if (0 != msdk_strlen(pParams->strDumpVppCompFile)) { ++ sts = m_dumpVppCompFileWriter.Init(pParams->strDumpVppCompFile, 0); ++ MSDK_CHECK_STATUS(sts, "VPP COMP DUMP File Init failed"); ++ m_vppCompDumpRenderMode = DUMP_FILE_VPP_COMP; ++ } ++ } ++ ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ // Frames allocation for all component ++ if (Native == pParams->eMode) { ++ sts = AllocFrames(); ++ MSDK_CHECK_STATUS(sts, "AllocFrames failed"); ++ } ++ else if (Source == ++ pParams->eMode) // need allocate frames only for VPP and Encode if VPP exist ++ { ++ if (!m_bDecodeEnable) { ++ sts = AllocFrames(); ++ MSDK_CHECK_STATUS(sts, "AllocFrames failed"); ++ } ++ } ++ } ++ ++ isHEVCSW = AreGuidsEqual(pParams->decoderPluginParams.pluginGuid, MFX_PLUGINID_HEVCD_SW); ++ ++ // if sink - suspended allocation ++ ++ // common session settings ++ if (m_Version.Major >= 1 && m_Version.Minor >= 1) ++ sts = m_pmfxSession->SetPriority(pParams->priority); ++ ++ // if sink - suspended allocation ++ if (Native != pParams->eMode) ++ return sts; ++ ++ // Init decode ++ if (m_pmfxDEC.get()) { ++ sts = m_pmfxDEC->Init(&m_mfxDecParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed"); ++ } ++ ++ // Init VPP ++ if (m_pmfxVPP.get()) { ++ if (m_bIsPlugin && m_bIsVpp) ++ sts = m_pmfxVPP->InitMulti(&m_mfxPluginParams, &m_mfxVppParams); ++ else if (m_bIsPlugin) ++ sts = m_pmfxVPP->Init(&m_mfxPluginParams); ++ else ++ sts = m_pmfxVPP->Init(&m_mfxVppParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed"); ++ ++ if (MFX_WRN_PARTIAL_ACCELERATION == sts) { ++ msdk_printf(MSDK_STRING("WARNING: partial acceleration\n")); ++ MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION); ++ } ++ MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed"); ++ } ++#if !defined(MFX_ONEVPL) ++ // LA initialization ++ if (m_pmfxPreENC.get()) { ++ sts = m_pmfxPreENC->Init(&m_mfxPreEncParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxPreENC->Init failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ // Init encode ++ if (m_pmfxENC.get()) { ++ sts = m_pmfxENC->Init(&m_mfxEncParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxENC->Init failed"); ++ ++#if MFX_VERSION >= 1022 ++ if (pParams->bExtMBQP) { ++ m_bUseQPMap = true; ++ } ++ ++ if (pParams->bROIasQPMAP) { ++ mfxVideoParam enc_par; ++ MSDK_ZERO_MEMORY(enc_par); ++ mfxStatus sts1 = m_pmfxENC->GetVideoParam(&enc_par); ++ MSDK_CHECK_STATUS(sts1, "m_pmfxENC->GetVideoParam failed"); ++ ++ if (enc_par.mfx.GopRefDist != 1) { ++ printf( ++ "INFO: Sample implementation of ROI through MBQP map require B-frames to be disabled.\n"); ++ m_bUseQPMap = false; ++ } ++ else if (enc_par.mfx.RateControlMethod != MFX_RATECONTROL_CQP) { ++ printf("INFO: MBQP map require ConstQP mode to operate.\n"); ++ m_bUseQPMap = false; ++ } ++ else { ++ m_GOPSize = (enc_par.mfx.GopPicSize) ? enc_par.mfx.GopPicSize : 1; ++ m_QPforI = enc_par.mfx.QPI; ++ m_QPforP = enc_par.mfx.QPP; ++ m_bUseQPMap = true; ++ } ++ } ++#endif //MFX_VERSION >= 1022 ++ } ++ ++ // Dumping components configuration if required ++ if (m_strMfxParamsDumpFile.size()) { ++ CParametersDumper::DumpLibraryConfiguration(m_strMfxParamsDumpFile, ++ m_pmfxDEC.get(), ++ m_pmfxVPP.get(), ++ m_pmfxENC.get(), ++ &m_mfxDecParams, ++ &m_mfxVppParams, ++ &m_mfxEncParams); ++ } ++ ++ m_bIsInit = true; ++ ++ return sts; ++} //mfxStatus CTranscodingPipeline::Init(sInputParams *pParams) ++ ++mfxStatus CTranscodingPipeline::CompleteInit() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ if (m_bIsInit) ++ return MFX_ERR_NONE; ++ ++ if (m_MemoryModel == GENERAL_ALLOC) { ++ // need to allocate remaining frames ++ if (m_bDecodeEnable) { ++ sts = AllocFrames(); ++ MSDK_CHECK_STATUS(sts, "AllocFrames failed"); ++ LoadStaticSurface(); ++ MSDK_CHECK_STATUS(sts, "LoadStaticSurface failed"); ++ } ++ } ++ ++ // Init decode ++ if (m_pmfxDEC.get()) { ++ sts = m_pmfxDEC->Init(&m_mfxDecParams); ++ if (MFX_WRN_PARTIAL_ACCELERATION == sts) { ++ msdk_printf(MSDK_STRING("WARNING: partial acceleration\n")); ++ MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION); ++ } ++ MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed"); ++ } ++ ++ // Init vpp ++ if (m_pmfxVPP.get()) { ++ if (m_bIsPlugin && m_bIsVpp) ++ sts = m_pmfxVPP->InitMulti(&m_mfxPluginParams, &m_mfxVppParams); ++ else if (m_bIsPlugin) ++ sts = m_pmfxVPP->Init(&m_mfxPluginParams); ++ else ++ sts = m_pmfxVPP->Init(&m_mfxVppParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed"); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ // Pre init encode ++ if (m_pmfxPreENC.get()) { ++ sts = m_pmfxPreENC->Init(&m_mfxPreEncParams); ++ if (MFX_WRN_PARTIAL_ACCELERATION == sts) { ++ msdk_printf(MSDK_STRING("WARNING: partial acceleration\n")); ++ MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION); ++ } ++ MSDK_CHECK_STATUS(sts, "m_pmfxPreENC->Init failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ // Init encode ++ if (m_pmfxENC.get()) { ++ sts = m_pmfxENC->Init(&m_mfxEncParams); ++ if (MFX_WRN_PARTIAL_ACCELERATION == sts) { ++ msdk_printf(MSDK_STRING("WARNING: partial acceleration\n")); ++ MSDK_IGNORE_MFX_STS(sts, MFX_WRN_PARTIAL_ACCELERATION); ++ } ++ MSDK_CHECK_STATUS(sts, "m_pmfxENC->Init failed"); ++ } ++ ++ m_bIsInit = true; ++ ++ return sts; ++} // mfxStatus CTranscodingPipeline::CompleteInit() ++mfxFrameSurface1 *CTranscodingPipeline::GetFreeSurface(bool isDec, mfxU64 timeout) { ++ mfxFrameSurface1 *pSurf = NULL; ++ ++ CTimer t; ++ t.Start(); ++ do { ++ { ++ std::lock_guard lock(m_mStopSession); ++ if (m_bForceStop) { ++ msdk_printf(MSDK_STRING( ++ "WARNING: m_bForceStop is set, returning NULL ptr from GetFreeSurface\n")); ++ break; ++ } ++ } ++ ++ SurfPointersArray &workArray = isDec ? m_pSurfaceDecPool : m_pSurfaceEncPool; ++ ++ for (mfxU32 i = 0; i < workArray.size(); i++) { ++ if (!workArray[i]->Data.Locked) { ++ pSurf = workArray[i]; ++ break; ++ } ++ } ++ if (pSurf) { ++ break; ++ } ++ else { ++ MSDK_SLEEP(TIME_TO_SLEEP); ++ } ++ } while (t.GetTime() < timeout / 1000); ++ ++ return pSurf; ++} // mfxFrameSurface1* CTranscodingPipeline::GetFreeSurface(bool isDec) ++ ++mfxU32 CTranscodingPipeline::GetFreeSurfacesCount(bool isDec) { ++ SurfPointersArray &workArray = isDec ? m_pSurfaceDecPool : m_pSurfaceEncPool; ++ mfxU32 count = 0; ++ for (mfxU32 i = 0; i < workArray.size(); i++) { ++ if (!workArray[i]->Data.Locked) { ++ count++; ++ } ++ } ++ return count; ++} ++ ++PreEncAuxBuffer *CTranscodingPipeline::GetFreePreEncAuxBuffer() { ++ for (mfxU32 i = 0; i < m_pPreEncAuxPool.size(); i++) { ++ if (!m_pPreEncAuxPool[i].Locked) ++ return &(m_pPreEncAuxPool[i]); ++ } ++ return NULL; ++} ++ ++void CTranscodingPipeline::LockPreEncAuxBuffer(PreEncAuxBuffer *pBuff) { ++ if (!pBuff) ++ return; ++ for (mfxU32 i = 0; i < m_numEncoders; i++) { ++ msdk_atomic_inc16(&pBuff->Locked); ++ } ++} ++ ++void CTranscodingPipeline::UnPreEncAuxBuffer(PreEncAuxBuffer *pBuff) { ++ if (!pBuff) ++ return; ++ msdk_atomic_dec16(&pBuff->Locked); ++} ++ ++mfxU32 CTranscodingPipeline::GetNumFramesForReset() { ++ std::lock_guard guard(m_mReset); ++ return m_NumFramesForReset; ++} ++ ++void CTranscodingPipeline::SetNumFramesForReset(mfxU32 nFrames) { ++ std::lock_guard guard(m_mReset); ++ m_NumFramesForReset = nFrames; ++} ++ ++void CTranscodingPipeline::HandlePossibleGpuHang(mfxStatus &sts) { ++ if (sts == MFX_ERR_GPU_HANG && m_bSoftGpuHangRecovery) { ++ msdk_printf(MSDK_STRING( ++ "[WARNING] GPU hang happened. Inserting an IDR and continuing transcoding.\n")); ++ m_bInsertIDR = true; ++ for (BSList::iterator it = m_BSPool.begin(); it != m_BSPool.end(); it++) { ++ (*it)->IsFree = true; ++ (*it)->Bitstream.DataOffset = 0; ++ (*it)->Bitstream.DataLength = 0; ++ } ++ m_BSPool.clear(); ++ sts = MFX_ERR_NONE; ++ } ++} ++ ++mfxStatus CTranscodingPipeline::SetAllocatorAndHandleIfRequired() { ++ mfxStatus sts = MFX_ERR_NONE; ++ mfxIMPL impl = 0; ++ m_pmfxSession->QueryIMPL(&impl); ++ ++ bool bIsMustSetExternalHandle = false; ++ mfxHandleType handleType = (mfxHandleType)0; ++ ++ if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(impl)) { ++ handleType = MFX_HANDLE_D3D11_DEVICE; ++ bIsMustSetExternalHandle = false; ++ } ++ else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(impl)) { ++ handleType = MFX_HANDLE_D3D9_DEVICE_MANAGER; ++ bIsMustSetExternalHandle = false; ++ } ++#ifdef LIBVA_SUPPORT ++ else if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(impl)) { ++ handleType = MFX_HANDLE_VA_DISPLAY; ++ bIsMustSetExternalHandle = true; ++ } ++#endif ++ ++ bool ext_allocator_exists = m_MemoryModel == GENERAL_ALLOC; ++ if (m_hdl && (bIsMustSetExternalHandle || (m_bIsInterOrJoined || ext_allocator_exists))) { ++ sts = m_pmfxSession->SetHandle(handleType, m_hdl); ++ MSDK_CHECK_STATUS(sts, "m_pmfxSession->SetHandle failed"); ++ } ++ ++ if (ext_allocator_exists) { ++ sts = m_pmfxSession->SetFrameAllocator(m_pMFXAllocator); ++ MSDK_CHECK_STATUS(sts, "m_pmfxSession->SetFrameAllocator failed"); ++ } ++ ++ return sts; ++} ++ ++#if !defined(MFX_ONEVPL) ++mfxStatus CTranscodingPipeline::LoadGenericPlugin() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ std::unique_ptr pVPPPlugin(new MFXVideoVPPPlugin(*m_pmfxSession.get())); ++ MSDK_CHECK_POINTER(pVPPPlugin.get(), MFX_ERR_NULL_PTR); ++ ++ sts = pVPPPlugin->LoadDLL((msdk_char *)m_sGenericPluginPath.c_str()); ++ MSDK_CHECK_STATUS(sts, "pVPPPlugin->LoadDLL failed"); ++ ++ m_RotateParam.Angle = m_nRotationAngle; ++ sts = pVPPPlugin->SetAuxParam(&m_RotateParam, sizeof(m_RotateParam)); ++ MSDK_CHECK_STATUS(sts, "pVPPPlugin->SetAuxParam failed"); ++ ++ sts = pVPPPlugin->SetFrameAllocator(m_pMFXAllocator); ++ MSDK_CHECK_STATUS(sts, "pVPPPlugin->SetFrameAllocator failed"); ++ ++ m_pmfxVPP.reset(pVPPPlugin.release()); ++ return MFX_ERR_NONE; ++} ++#endif //!MFX_ONEVPL ++ ++size_t CTranscodingPipeline::GetRobustFlag() { ++ return m_bRobustFlag; ++} ++ ++void CTranscodingPipeline::Close() { ++ m_pmfxDEC.reset(); ++ ++ m_pmfxENC.reset(); ++ ++ m_pmfxVPP.reset(); ++ ++ m_pmfxSession.reset(); ++ ++#if !defined(MFX_ONEVPL) ++ if (m_pUserDecoderPlugin.get()) ++ m_pUserDecoderPlugin.reset(); ++ ++ if (m_pUserEncoderPlugin.get()) ++ m_pUserEncoderPlugin.reset(); ++ ++ if (m_pUserEncPlugin.get()) ++ m_pUserEncPlugin.reset(); ++#endif //!MFX_ONEVPL ++ ++ FreeVppDoNotUse(); ++#if !defined(MFX_ONEVPL) ++ FreeMVCSeqDesc(); ++ FreePreEncAuxPool(); ++ ++ mfxExtVPPComposite *vppCompPar = m_mfxVppParams; ++ if (vppCompPar && vppCompPar->InputStream) ++ free(vppCompPar->InputStream); ++#endif ++ ++ if (m_bIsJoinSession) { ++ //m_pmfxSession->DisjoinSession(); ++ m_bIsJoinSession = false; ++ } ++ ++ //Destroy renderer ++#if defined(_WIN32) || defined(_WIN64) ++ if (m_hwdev4Rendering) { ++ delete m_hwdev4Rendering; ++ m_hwdev4Rendering = NULL; ++ } ++#endif ++ ++ // free allocated surfaces AFTER closing components ++ FreeFrames(); ++ ++ m_bIsInit = false; ++ ++} // void CTranscodingPipeline::Close() ++ ++mfxStatus CTranscodingPipeline::Reset(VPLImplementationLoader *mfxLoader) { ++ mfxStatus sts = MFX_ERR_NONE; ++ bool isDec = m_pmfxDEC.get() ? true : false, isEnc = m_pmfxENC.get() ? true : false, ++ isVPP = m_pmfxVPP.get() ? true : false, isGenericPLugin = m_nRotationAngle ? true : false ++#if !defined(MFX_ONEVPL) ++ , ++ isPreEnc = m_pmfxPreENC.get() ? true : false, ++ isDecoderPlugin = m_pUserDecoderPlugin.get() ? true : false, ++ isEncoderPlugin = m_pUserEncoderPlugin.get() ? true : false, ++ isPreEncPlugin = m_pUserEncPlugin.get() ? true : false ++#endif //!MFX_ONEVPL ++ ; ++ ++ // Close components being used ++ if (isDec) { ++ m_pmfxDEC->Close(); ++ m_pmfxDEC.reset(); ++ } ++ ++ if (isVPP) { ++ m_pmfxVPP->Close(); ++ m_pmfxVPP.reset(); ++ } ++ ++ if (isEnc) { ++ m_pmfxENC->Close(); ++ m_pmfxENC.reset(); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (isPreEnc) { ++ m_pmfxPreENC->Close(); ++ m_pmfxPreENC.reset(); ++ } ++ ++ if (isDecoderPlugin) { ++ m_pUserDecoderPlugin.reset(); ++ m_pUserDecoderModule.reset(); ++ } ++ ++ if (isEncoderPlugin) { ++ m_pUserEncoderPlugin.reset(); ++ m_pUserEncoderModule.reset(); ++ } ++#endif //!MFX_ONEVPL ++ ++ m_pmfxSession->Close(); ++ ++ m_pmfxSession.reset(new MainVideoSession()); ++ ++ sts = m_pmfxSession->CreateSession(mfxLoader); ++ MSDK_CHECK_STATUS(sts, "CreateSession failed"); ++ ++ // Release dec and enc surface pools ++ for (size_t i = 0; i < m_pSurfaceDecPool.size(); i++) { ++ m_pSurfaceDecPool[i]->Data.Locked = 0; ++ } ++ for (size_t i = 0; i < m_pSurfaceEncPool.size(); i++) { ++ m_pSurfaceEncPool[i]->Data.Locked = 0; ++ } ++ ++ // Release all safety buffers ++ SafetySurfaceBuffer *sptr = m_pBuffer; ++ while (sptr) { ++ sptr->ReleaseSurfaceAll(); ++ sptr = sptr->m_pNext; ++ } ++ ++ // Release output bitstram pools ++ m_BSPool.clear(); ++ m_pBSStore->ReleaseAll(); ++ m_pBSStore->FlushAll(); ++ ++#if !defined(MFX_ONEVPL) ++ // Load external decoder plugin ++ if (isDecoderPlugin) { ++ if (m_decoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && ++ msdk_strnlen(m_decoderPluginParams.strPluginPath, ++ sizeof(m_decoderPluginParams.strPluginPath))) { ++ m_pUserDecoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get())); ++ m_pUserDecoderPlugin.reset( ++ LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, ++ *m_pmfxSession.get(), ++ m_decoderPluginParams.pluginGuid, ++ 1, ++ m_decoderPluginParams.strPluginPath, ++ (mfxU32)msdk_strnlen(m_decoderPluginParams.strPluginPath, ++ sizeof(m_decoderPluginParams.strPluginPath)))); ++ if (m_pUserDecoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ else { ++ if (AreGuidsEqual(m_decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ m_decoderPluginParams.pluginGuid = msdkGetPluginUID(m_initPar.Implementation, ++ MSDK_VDECODE, ++ m_mfxDecParams.mfx.CodecId); ++ } ++ if (!AreGuidsEqual(m_decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ m_pUserDecoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_DECODE, ++ *m_pmfxSession.get(), ++ m_decoderPluginParams.pluginGuid, ++ 1)); ++ if (m_pUserDecoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ } ++ MSDK_CHECK_STATUS(sts, "LoadPlugin failed"); ++ } ++ ++ // Load external encoder plugin ++ if (isEncoderPlugin) { ++ if (m_encoderPluginParams.type == MFX_PLUGINLOAD_TYPE_FILE && ++ msdk_strnlen(m_encoderPluginParams.strPluginPath, ++ sizeof(m_encoderPluginParams.strPluginPath))) { ++ m_pUserEncoderModule.reset(new MFXVideoUSER(*m_pmfxSession.get())); ++ m_pUserEncoderPlugin.reset( ++ LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, ++ *m_pmfxSession.get(), ++ m_encoderPluginParams.pluginGuid, ++ 1, ++ m_encoderPluginParams.strPluginPath, ++ (mfxU32)msdk_strnlen(m_encoderPluginParams.strPluginPath, ++ sizeof(m_encoderPluginParams.strPluginPath)))); ++ if (m_pUserEncoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ else { ++ if (AreGuidsEqual(m_encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ m_decoderPluginParams.pluginGuid = msdkGetPluginUID(m_initPar.Implementation, ++ MSDK_VENCODE, ++ m_mfxEncParams.mfx.CodecId); ++ } ++ if (!AreGuidsEqual(m_encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ m_pUserEncoderPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, ++ *m_pmfxSession.get(), ++ m_encoderPluginParams.pluginGuid, ++ 1)); ++ if (m_pUserEncoderPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ } ++ } ++ MSDK_CHECK_STATUS(sts, "LoadPlugin failed"); ++ } ++ ++ // Load external pre-enc plugin ++ if (isPreEncPlugin) { ++ m_pUserEncPlugin.reset(LoadPlugin(MFX_PLUGINTYPE_VIDEO_ENCODE, ++ *m_pmfxSession.get(), ++ MFX_PLUGINID_H264LA_HW, ++ 1)); ++ if (m_pUserEncPlugin.get() == NULL) ++ sts = MFX_ERR_UNSUPPORTED; ++ MSDK_CHECK_STATUS(sts, "LoadPlugin failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ sts = SetAllocatorAndHandleIfRequired(); ++ MSDK_CHECK_STATUS(sts, "SetAllocatorAndHandleIfRequired failed"); ++ ++ if (isDec) ++ m_pmfxDEC.reset(new MFXVideoDECODE((mfxSession)*m_pmfxSession)); ++ if (isVPP) ++ m_pmfxVPP.reset(new MFXVideoMultiVPP((mfxSession)*m_pmfxSession)); ++#if !defined(MFX_ONEVPL) ++ if (isPreEnc) ++ m_pmfxPreENC.reset(new MFXVideoENC((mfxSession)*m_pmfxSession)); ++#endif //!MFX_ONEVPL ++ ++ if (isEnc) ++ m_pmfxENC.reset(new MFXVideoENCODE((mfxSession)*m_pmfxSession)); ++ ++ if (isDec) { ++ sts = m_pmfxDEC->Init(&m_mfxDecParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxDEC->Init failed"); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (isGenericPLugin) { ++ sts = LoadGenericPlugin(); ++ MSDK_CHECK_STATUS(sts, "LoadGenericPlugin failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ if (isVPP) { ++ if (m_bIsPlugin && m_bIsVpp) { ++ mfxFrameAllocRequest request[2] = {}; ++ sts = m_pmfxVPP->QueryIOSurfMulti(&m_mfxPluginParams, request, &m_mfxVppParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxVPP->QueryIOSurf failed"); ++ ++ sts = m_pmfxVPP->InitMulti(&m_mfxPluginParams, &m_mfxVppParams); ++ } ++ else if (m_bIsPlugin) ++ sts = m_pmfxVPP->Init(&m_mfxPluginParams); ++ else ++ sts = m_pmfxVPP->Init(&m_mfxVppParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxVPP->Init failed"); ++ } ++ ++#if !defined(MFX_ONEVPL) ++ if (isPreEnc) { ++ sts = m_pmfxPreENC->Init(&m_mfxPreEncParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxPreENC->Init failed"); ++ } ++#endif //!MFX_ONEVPL ++ ++ if (isEnc) { ++ sts = m_pmfxENC->Init(&m_mfxEncParams); ++ MSDK_CHECK_STATUS(sts, "m_pmfxENC->Init failed"); ++ } ++ ++ // Joining sessions if required ++ if (m_bIsJoinSession && m_pParentPipeline) { ++ sts = m_pParentPipeline->Join(m_pmfxSession.get()); ++ MSDK_CHECK_STATUS(sts, "m_pParentPipeline->Join failed"); ++ m_bIsJoinSession = true; ++ } ++ return sts; ++} ++ ++mfxStatus CTranscodingPipeline::AllocAndInitVppDoNotUse(sInputParams *pInParams) { ++ std::vector filtersDisabled; ++ if (pInParams->DenoiseLevel == -1) { ++ filtersDisabled.push_back(MFX_EXTBUFF_VPP_DENOISE); // turn off denoising (on by default) ++ } ++ filtersDisabled.push_back( ++ MFX_EXTBUFF_VPP_SCENE_ANALYSIS); // turn off scene analysis (on by default) ++ ++ if (filtersDisabled.size()) { ++ auto doNotUse = m_mfxVppParams.AddExtBuffer(); ++ delete[] doNotUse->AlgList; ++ ++ doNotUse->NumAlg = (mfxU32)filtersDisabled.size(); ++ doNotUse->AlgList = new mfxU32[doNotUse->NumAlg]; ++ MSDK_MEMCPY(doNotUse->AlgList, ++ filtersDisabled.data(), ++ sizeof(mfxU32) * filtersDisabled.size()); ++ } ++ ++ return MFX_ERR_NONE; ++} // CTranscodingPipeline::AllocAndInitVppDoNotUse() ++ ++void CTranscodingPipeline::FreeVppDoNotUse() { ++#if 0 ++ mfxExtVPPDoNotUse* doNotUse = m_mfxVppParams; ++ if (doNotUse) ++ MSDK_SAFE_DELETE_ARRAY(doNotUse->AlgList); ++#endif ++} ++ ++mfxStatus CTranscodingPipeline::AllocateSufficientBuffer(mfxBitstreamWrapper *pBS) { ++ MSDK_CHECK_POINTER(pBS, MFX_ERR_NULL_PTR); ++ ++ mfxVideoParam par; ++ MSDK_ZERO_MEMORY(par); ++ ++ // find out the required buffer size ++ mfxStatus sts = m_pmfxENC->GetVideoParam(&par); ++ MSDK_CHECK_STATUS(sts, "m_pmfxENC->GetVideoParam failed"); ++ ++ mfxU32 new_size = 0; ++ ++ // if encoder provided us information about buffer size ++ if (0 != par.mfx.BufferSizeInKB) { ++ //--- If value calculated basing on par.mfx.BufferSizeInKB is too low, just double the buffer size ++ new_size = par.mfx.BufferSizeInKB * 1000u > pBS->MaxLength ? par.mfx.BufferSizeInKB * 1000u ++ : pBS->MaxLength * 2; ++ } ++ else { ++ // trying to guess the size (e.g. for JPEG encoder) ++ new_size = (0 == pBS->MaxLength) ++ // some heuristic init value ++ ? 4 + (par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height * 3 + 1023) ++ // double existing size ++ : 2 * pBS->MaxLength; ++ } ++ ++ pBS->Extend(new_size); ++ ++ return MFX_ERR_NONE; ++} // CTranscodingPipeline::AllocateSufficientBuffer(mfxBitstreamWrapper* pBS) ++ ++mfxStatus CTranscodingPipeline::Join(MFXVideoSession *pChildSession) { ++ mfxStatus sts = MFX_ERR_NONE; ++ MSDK_CHECK_POINTER(pChildSession, MFX_ERR_NULL_PTR); ++ sts = m_pmfxSession->JoinSession(*pChildSession); ++ m_bIsJoinSession = (MFX_ERR_NONE == sts); ++ return sts; ++} // CTranscodingPipeline::Join(MFXVideoSession *pChildSession) ++ ++mfxStatus CTranscodingPipeline::Run() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ msdk_stringstream ss; ++ if (m_bDecodeEnable && m_bEncodeEnable) { ++ sts = Transcode(); ++ ss << MSDK_STRING("CTranscodingPipeline::Run::Transcode() [") << GetSessionText() ++ << MSDK_STRING("] failed"); ++ MSDK_CHECK_STATUS(sts, ss.str()); ++ } ++ else if (m_bDecodeEnable) { ++ sts = Decode(); ++ ss << MSDK_STRING("CTranscodingPipeline::Run::Decode() [") << GetSessionText() ++ << MSDK_STRING("] failed"); ++ MSDK_CHECK_STATUS(sts, ss.str()); ++ } ++ else if (m_bEncodeEnable) { ++ sts = Encode(); ++ ss << MSDK_STRING("CTranscodingPipeline::Run::Encode() [") << GetSessionText() ++ << MSDK_STRING("] failed"); ++ MSDK_CHECK_STATUS(sts, ss.str()); ++ } ++ else ++ return MFX_ERR_UNSUPPORTED; ++ ++ return sts; ++} ++ ++void IncreaseReference(mfxFrameSurface1 &surf) { ++ msdk_atomic_inc16((volatile mfxU16 *)(&surf.Data.Locked)); ++#if defined(MFX_ONEVPL) ++ if (surf.FrameInterface) { ++ std::ignore = surf.FrameInterface->AddRef(&surf); ++ } ++#endif ++} ++ ++void DecreaseReference(mfxFrameSurface1 &surf) { ++ msdk_atomic_dec16((volatile mfxU16 *)&surf.Data.Locked); ++#if defined(MFX_ONEVPL) ++ if (surf.FrameInterface) { ++ std::ignore = surf.FrameInterface->Release(&surf); ++ } ++#endif ++} ++ ++SafetySurfaceBuffer::SafetySurfaceBuffer(SafetySurfaceBuffer *pNext) ++ : m_pNext(pNext), ++ m_IsBufferingAllowed(true), ++ pInsEvent(nullptr) { ++ mfxStatus sts = MFX_ERR_NONE; ++ pRelEvent = new MSDKEvent(sts, false, false); ++ MSDK_CHECK_POINTER_NO_RET(pRelEvent); ++ ++ pInsEvent = new MSDKEvent(sts, false, false); ++ MSDK_CHECK_POINTER_NO_RET(pInsEvent); ++ ++} // SafetySurfaceBuffer::SafetySurfaceBuffer ++ ++SafetySurfaceBuffer::~SafetySurfaceBuffer() { ++ delete pRelEvent; ++ delete pInsEvent; ++} //SafetySurfaceBuffer::~SafetySurfaceBuffer() ++ ++mfxU32 SafetySurfaceBuffer::GetLength() { ++ std::lock_guard guard(m_mutex); ++ return (mfxU32)m_SList.size(); ++} ++ ++mfxStatus SafetySurfaceBuffer::WaitForSurfaceRelease(mfxU32 msec) { ++ return pRelEvent->TimedWait(msec); ++} ++ ++mfxStatus SafetySurfaceBuffer::WaitForSurfaceInsertion(mfxU32 msec) { ++ return pInsEvent->TimedWait(msec); ++} ++ ++void SafetySurfaceBuffer::AddSurface(ExtendedSurface Surf) { ++ bool isBufferingAllowed = false; ++ ++ { ++ std::lock_guard guard(m_mutex); ++ ++ isBufferingAllowed = m_IsBufferingAllowed; ++ if (isBufferingAllowed) { ++ SurfaceDescriptor sDescriptor; ++ // Locked is used to signal when we can free surface ++ sDescriptor.Locked = 1; ++ sDescriptor.ExtSurface = Surf; ++ ++ if (Surf.pSurface) { ++ IncreaseReference(*Surf.pSurface); ++ } ++ ++ m_SList.push_back(sDescriptor); ++ } ++ } ++ ++ if (isBufferingAllowed) { ++ pInsEvent->Signal(); ++ } ++ ++} // SafetySurfaceBuffer::AddSurface(mfxFrameSurface1 *pSurf) ++ ++mfxStatus SafetySurfaceBuffer::GetSurface(ExtendedSurface &Surf) { ++ std::lock_guard guard(m_mutex); ++ ++ // no ready surfaces ++ if (0 == m_SList.size()) { ++ MSDK_ZERO_MEMORY(Surf) ++ return MFX_ERR_MORE_SURFACE; ++ } ++ ++ SurfaceDescriptor sDescriptor = m_SList.front(); ++ ++ Surf = sDescriptor.ExtSurface; ++ ++ return MFX_ERR_NONE; ++ ++} // SafetySurfaceBuffer::GetSurface() ++ ++mfxStatus SafetySurfaceBuffer::ReleaseSurface(mfxFrameSurface1 *pSurf) { ++ std::unique_lock lock(m_mutex); ++ ++ std::list::iterator it; ++ for (it = m_SList.begin(); it != m_SList.end(); it++) { ++ if (pSurf == it->ExtSurface.pSurface) { ++ it->Locked--; ++ if (it->ExtSurface.pSurface) ++ DecreaseReference(*it->ExtSurface.pSurface); ++ if (0 == it->Locked) { ++ m_SList.erase(it); ++ lock.unlock(); ++ ++ // event operation should be out of synced context ++ pRelEvent->Signal(); ++ } ++ ++ return MFX_ERR_NONE; ++ } ++ } ++ ++ return MFX_ERR_UNKNOWN; ++} // mfxStatus SafetySurfaceBuffer::ReleaseSurface(mfxFrameSurface1* pSurf) ++ ++mfxStatus SafetySurfaceBuffer::ReleaseSurfaceAll() { ++ std::lock_guard guard(m_mutex); ++ ++ m_SList.clear(); ++ m_IsBufferingAllowed = true; ++ return MFX_ERR_NONE; ++ ++} // mfxStatus SafetySurfaceBuffer::ReleaseSurface(mfxFrameSurface1* pSurf) ++ ++void SafetySurfaceBuffer::CancelBuffering() { ++ std::lock_guard guard(m_mutex); ++ m_IsBufferingAllowed = false; ++} ++ ++FileBitstreamProcessor::FileBitstreamProcessor() { ++ m_Bitstream.TimeStamp = (mfxU64)-1; ++} ++ ++FileBitstreamProcessor::~FileBitstreamProcessor() { ++ if (m_pFileReader.get()) ++ m_pFileReader->Close(); ++ if (m_pFileWriter.get()) ++ m_pFileWriter->Close(); ++} ++ ++mfxStatus FileBitstreamProcessor::SetReader(std::unique_ptr &reader) { ++ m_pYUVFileReader = std::move(reader); ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus FileBitstreamProcessor::SetReader(std::unique_ptr &reader) { ++ m_pFileReader = std::move(reader); ++ m_Bitstream.Extend(1024 * 1024); ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus FileBitstreamProcessor::SetWriter(std::unique_ptr &writer) { ++ m_pFileWriter = std::move(writer); ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus FileBitstreamProcessor::GetInputBitstream(mfxBitstreamWrapper **pBitstream) { ++ if (!m_pFileReader.get()) { ++ return MFX_ERR_UNSUPPORTED; ++ } ++ mfxStatus sts = m_pFileReader->ReadNextFrame(&m_Bitstream); ++ if (MFX_ERR_NONE == sts) { ++ *pBitstream = &m_Bitstream; ++ return sts; ++ } ++ return sts; ++} ++ ++mfxStatus FileBitstreamProcessor::GetInputFrame(mfxFrameSurface1 *pSurface) { ++ //MSDK_CHECK_POINTER(pSurface); ++ if (!m_pYUVFileReader.get()) { ++ return MFX_ERR_UNSUPPORTED; ++ } ++ return m_pYUVFileReader->LoadNextFrame(pSurface); ++} ++ ++mfxStatus FileBitstreamProcessor::ProcessOutputBitstream(mfxBitstreamWrapper *pBitstream) { ++ if (m_pFileWriter.get()) ++ return m_pFileWriter->WriteNextFrame(pBitstream, false); ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus FileBitstreamProcessor::ResetInput() { ++ if (m_pFileReader.get()) { ++ m_pFileReader->Reset(); ++ ++ // Reset input bitstream state ++ m_Bitstream.DataFlag = 0; ++ } ++ if (m_pYUVFileReader.get()) { ++ m_pYUVFileReader->Reset(); ++ } ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus FileBitstreamProcessor::ResetOutput() { ++ if (m_pFileWriter.get()) { ++ m_pFileWriter->Reset(); ++ } ++ return MFX_ERR_NONE; ++} ++ ++void CTranscodingPipeline::ModifyParamsUsingPresets(sInputParams ¶ms, ++ mfxF64 fps, ++ mfxU32 width, ++ mfxU32 height) { ++ COutputPresetParameters presetParams = ++ CPresetManager::Inst.GetPreset(params.PresetMode, ++ params.EncodeId, ++ fps, ++ width, ++ height, ++ params.libType != MFX_IMPL_SOFTWARE); ++ ++ if (params.shouldPrintPresets) { ++ msdk_printf(MSDK_STRING("Preset-controlled parameters (%s):\n"), ++ presetParams.PresetName.c_str()); ++ } ++ ++ if (!params.nRateControlMethod) { ++ MODIFY_AND_PRINT_PARAM_EXT(params.nExtBRC, ++ ExtBRCUsage, ++ (ExtBRCType)presetParams.ExtBRCUsage, ++ params.shouldPrintPresets); ++ } ++ if (presetParams.RateControlMethod == MFX_RATECONTROL_LA_EXT) { ++ // Use external LA ++ params.bEnableExtLA = true; ++ params.nRateControlMethod = 0; ++ if (params.shouldPrintPresets) { ++ msdk_printf(MSDK_STRING("RateControlMethod: ExtLA\n")); ++ } ++ } ++ else { ++ MODIFY_AND_PRINT_PARAM(params.nRateControlMethod, ++ RateControlMethod, ++ params.shouldPrintPresets); ++ } ++ ++ MODIFY_AND_PRINT_PARAM(params.nAdaptiveMaxFrameSize, ++ AdaptiveMaxFrameSize, ++ params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.nAsyncDepth, AsyncDepth, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.nBRefType, BRefType, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.bEnableBPyramid, EnableBPyramid, params.shouldPrintPresets); ++ // MODIFY_AND_PRINT_PARAM(params., EnablePPyramid, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.GopRefDist, GopRefDist, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.IntRefCycleDist, IntRefCycleDist, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.IntRefCycleSize, IntRefCycleSize, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.IntRefQPDelta, IntRefQPDelta, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.IntRefType, IntRefType, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.LowDelayBRC, LowDelayBRC, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.nTargetUsage, TargetUsage, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.WeightedBiPred, WeightedBiPred, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.WeightedPred, WeightedPred, params.shouldPrintPresets); ++ ++ MODIFY_AND_PRINT_PARAM(params.GopPicSize, GopPicSize, params.shouldPrintPresets); ++ ++ if (params.nRateControlMethod != MFX_RATECONTROL_CQP) { ++ MODIFY_AND_PRINT_PARAM(params.MaxKbps, MaxKbps, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.nBitRate, TargetKbps, params.shouldPrintPresets); ++ presetParams.BufferSizeInKB = ++ params ++ .nBitRate; // Update bitrate to reflect manually set bitrate. BufferSize should be enough for 1 second of video ++ MODIFY_AND_PRINT_PARAM(params.BufferSizeInKB, BufferSizeInKB, params.shouldPrintPresets); ++ } ++ ++ MODIFY_AND_PRINT_PARAM(params.nMaxFrameSize, MaxFrameSize, params.shouldPrintPresets); ++ MODIFY_AND_PRINT_PARAM(params.nLADepth, LookAheadDepth, params.shouldPrintPresets); ++ if (params.shouldPrintPresets) { ++ msdk_printf(MSDK_STRING("\n")); ++ } ++} +diff --git a/tools/legacy/sample_multi_transcode/src/sample_multi_transcode.cpp b/tools/legacy/sample_multi_transcode/src/sample_multi_transcode.cpp +new file mode 100644 +index 0000000..81ccb73 +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/src/sample_multi_transcode.cpp +@@ -0,0 +1,1162 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2020, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#include "mfx_samples_config.h" ++#if defined(_WIN32) || defined(_WIN64) ++ #include ++#endif ++ ++#include "sample_multi_transcode.h" ++ ++#if defined(LIBVA_WAYLAND_SUPPORT) ++ #include "class_wayland.h" ++#endif ++ ++#ifndef MFX_VERSION ++ #error MFX_VERSION not defined ++#endif ++ ++#include ++#include ++using namespace std; ++using namespace TranscodingSample; ++ ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++mfxU32 GetPreferredAdapterNum(const mfxAdaptersInfo& adapters, const sInputParams& params) { ++ if (adapters.NumActual == 0 || !adapters.Adapters) ++ return 0; ++ ++ if (params.bPrefferdGfx) { ++ // Find dGfx adapter in list and return it's index ++ ++ auto idx = std::find_if(adapters.Adapters, ++ adapters.Adapters + adapters.NumActual, ++ [](const mfxAdapterInfo info) { ++ return info.Platform.MediaAdapterType == ++ mfxMediaAdapterType::MFX_MEDIA_DISCRETE; ++ }); ++ ++ // No dGfx in list ++ if (idx == adapters.Adapters + adapters.NumActual) { ++ msdk_printf( ++ MSDK_STRING("Warning: No dGfx detected on machine. Will pick another adapter\n")); ++ return 0; ++ } ++ ++ return static_cast(std::distance(adapters.Adapters, idx)); ++ } ++ ++ if (params.bPrefferiGfx) { ++ // Find iGfx adapter in list and return it's index ++ ++ auto idx = std::find_if(adapters.Adapters, ++ adapters.Adapters + adapters.NumActual, ++ [](const mfxAdapterInfo info) { ++ return info.Platform.MediaAdapterType == ++ mfxMediaAdapterType::MFX_MEDIA_INTEGRATED; ++ }); ++ ++ // No iGfx in list ++ if (idx == adapters.Adapters + adapters.NumActual) { ++ msdk_printf( ++ MSDK_STRING("Warning: No iGfx detected on machine. Will pick another adapter\n")); ++ return 0; ++ } ++ ++ return static_cast(std::distance(adapters.Adapters, idx)); ++ } ++ ++ // Other ways return 0, i.e. best suitable detected by dispatcher ++ return 0; ++} ++#endif ++ ++Launcher::Launcher() ++ : m_StartTime(0), ++ m_eDevType(static_cast(0)), ++ m_accelerationMode(MFX_ACCEL_MODE_NA) {} // Launcher::Launcher() ++ ++Launcher::~Launcher() { ++ Close(); ++} // Launcher::~Launcher() ++ ++CTranscodingPipeline* CreatePipeline() { ++ MOD_SMT_CREATE_PIPELINE; ++ ++ return new CTranscodingPipeline; ++} ++ ++mfxStatus Launcher::Init(int argc, msdk_char* argv[]) { ++ mfxStatus sts; ++ mfxU32 i = 0; ++ SafetySurfaceBuffer* pBuffer = NULL; ++ mfxU32 BufCounter = 0; ++ mfxHDL hdl = NULL; ++ std::vector hdls; ++ sInputParams InputParams; ++ bool bNeedToCreateDevice = true; ++ ++ //parent transcode pipeline ++ CTranscodingPipeline* pParentPipeline = NULL; ++ // source transcode pipeline use instead parent in heterogeneous pipeline ++ CTranscodingPipeline* pSinkPipeline = NULL; ++ ++ // parse input par file ++ sts = m_parser.ParseCmdLine(argc, argv); ++ MSDK_CHECK_PARSE_RESULT(sts, MFX_ERR_NONE, sts); ++ if (sts == MFX_WRN_OUT_OF_RANGE) { ++ // There's no error in parameters parsing, but we should not continue further. For instance, in case of -? option ++ return sts; ++ } ++ ++ // get parameters for each session from parser ++ while (m_parser.GetNextSessionParams(InputParams)) { ++ m_InputParamsArray.push_back(InputParams); ++ } ++ ++ // check correctness of input parameters ++ sts = VerifyCrossSessionsOptions(); ++ MSDK_CHECK_STATUS(sts, "VerifyCrossSessionsOptions failed"); ++ ++ mfxVersion ver = { { MFX_VERSION_MINOR, MFX_VERSION_MAJOR } }; ++ ++ m_pLoader.reset(new VPLImplementationLoader); ++ sts = m_pLoader->ConfigureAndEnumImplementations(m_InputParamsArray[0].libType, ++ m_accelerationMode, ++ ver); ++ MSDK_CHECK_STATUS(sts, "pLoader->ConfigureAndEnumImplementations failed"); ++ ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ // check available adapters ++ sts = QueryAdapters(); ++ MSDK_CHECK_STATUS(sts, "QueryAdapters failed"); ++ ++ if (m_eDevType && m_DisplaysData.empty()) { ++ msdk_printf(MSDK_STRING("No adapters found. HW-accelerated transcoding is impossible.\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++#endif ++ ++ for (i = 0; i < m_InputParamsArray.size(); i++) { ++ /* In the case of joined sessions, need to create device only for a zero session ++ * In the case of a shared buffer, need to create device only for decode */ ++ if ((m_InputParamsArray[i].bIsJoin && i != 0) || m_InputParamsArray[i].eMode == Source) ++ bNeedToCreateDevice = false; ++ ++#if defined(_WIN32) || defined(_WIN64) ++ ForceImplForSession(i); ++ sts = m_pLoader->EnumImplementations(m_deviceID, m_adapterNum); ++ MSDK_CHECK_STATUS(sts, "EnumImplementations(m_deviceID, m_adapterNum) failed"); ++ ++ if (m_eDevType == MFX_HANDLE_D3D9_DEVICE_MANAGER) { ++ if (bNeedToCreateDevice) { ++ mfxAllocatorParams* pAllocParam(new D3DAllocatorParams()); ++ D3DAllocatorParams* pD3DParams = dynamic_cast(pAllocParam); ++ std::unique_ptr hwdev(new CD3D9Device()); ++ ++ /* The last param set in vector always describe VPP+ENCODE or Only VPP ++ * So, if we want to do rendering we need to do pass HWDev to CTranscodingPipeline */ ++ if (m_InputParamsArray[m_InputParamsArray.size() - 1].eModeExt == VppCompOnly) { ++ /* Rendering case */ ++ //sts = hwdev->Init(NULL, 1, MSDKAdapter::GetNumber(0, m_pLoader.get())); ++ sts = hwdev->Init(NULL, 1, 0); ++ m_InputParamsArray[m_InputParamsArray.size() - 1].m_hwdev = hwdev.get(); ++ } ++ else /* NO RENDERING */ ++ { ++ //sts = hwdev->Init(NULL, 0, MSDKAdapter::GetNumber(0, m_pLoader.get())); ++ sts = hwdev->Init(NULL, 0, 0); ++ } ++ MSDK_CHECK_STATUS(sts, "hwdev->Init failed"); ++ sts = hwdev->GetHandle(MFX_HANDLE_D3D9_DEVICE_MANAGER, (mfxHDL*)&hdl); ++ MSDK_CHECK_STATUS(sts, "hwdev->GetHandle failed"); ++ // set Device Manager to external dx9 allocator ++ pD3DParams->pManager = (IDirect3DDeviceManager9*)hdl; ++ ++ m_pAllocParams.push_back(std::shared_ptr(pAllocParam)); ++ m_hwdevs.push_back(std::move(hwdev)); ++ hdls.push_back(hdl); ++ } ++ else { ++ if (!m_pAllocParams.empty() && !hdls.empty()) { ++ m_pAllocParams.push_back(m_pAllocParams.back()); ++ hdls.push_back(hdls.back()); ++ } ++ else { ++ msdk_printf(MSDK_STRING("error: failed to initialize alloc parameters\n")); ++ return MFX_ERR_MEMORY_ALLOC; ++ } ++ } ++ } ++ #if MFX_D3D11_SUPPORT ++ else if (m_eDevType == MFX_HANDLE_D3D11_DEVICE) { ++ if (bNeedToCreateDevice) { ++ mfxAllocatorParams* pAllocParam(new D3D11AllocatorParams()); ++ D3D11AllocatorParams* pD3D11Params = ++ dynamic_cast(pAllocParam); ++ std::unique_ptr hwdev(new CD3D11Device()); ++ ++ /* The last param set in vector always describe VPP+ENCODE or Only VPP ++ * So, if we want to do rendering we need to do pass HWDev to CTranscodingPipeline */ ++ if (m_InputParamsArray[m_InputParamsArray.size() - 1].eModeExt == VppCompOnly) { ++ /* Rendering case */ ++ //sts = hwdev->Init(NULL, 1, MSDKAdapter::GetNumber(0, m_pLoader.get())); ++ sts = hwdev->Init(NULL, 1, 0); ++ m_InputParamsArray[m_InputParamsArray.size() - 1].m_hwdev = hwdev.get(); ++ } ++ else /* NO RENDERING */ ++ { ++ //sts = hwdev->Init(NULL, 0, MSDKAdapter::GetNumber(0, m_pLoader.get())); ++ sts = hwdev->Init(NULL, 0, 0); ++ } ++ MSDK_CHECK_STATUS(sts, "hwdev->Init failed"); ++ sts = hwdev->GetHandle(MFX_HANDLE_D3D11_DEVICE, (mfxHDL*)&hdl); ++ MSDK_CHECK_STATUS(sts, "hwdev->GetHandle failed"); ++ ++ pD3D11Params->bUseSingleTexture = m_InputParamsArray[i].bSingleTexture; ++ // set Device to external dx11 allocator ++ pD3D11Params->pDevice = (ID3D11Device*)hdl; ++ ++ m_pAllocParams.push_back(std::shared_ptr(pAllocParam)); ++ m_hwdevs.push_back(std::move(hwdev)); ++ hdls.push_back(hdl); ++ } ++ else { ++ if (!m_pAllocParams.empty() && !hdls.empty()) { ++ m_pAllocParams.push_back(m_pAllocParams.back()); ++ hdls.push_back(hdls.back()); ++ } ++ else { ++ msdk_printf(MSDK_STRING("error: failed to initialize alloc parameters\n")); ++ return MFX_ERR_MEMORY_ALLOC; ++ } ++ } ++ } ++ #endif ++#elif defined(LIBVA_X11_SUPPORT) || defined(LIBVA_DRM_SUPPORT) || defined(ANDROID) ++ if (m_eDevType == MFX_HANDLE_VA_DISPLAY) { ++ if (bNeedToCreateDevice) { ++ mfxI32 libvaBackend = 0; ++ mfxAllocatorParams* pAllocParam(new vaapiAllocatorParams); ++ std::unique_ptr hwdev; ++ ++ vaapiAllocatorParams* pVAAPIParams = ++ dynamic_cast(pAllocParam); ++ /* The last param set in vector always describe VPP+ENCODE or Only VPP ++ * So, if we want to do rendering we need to do pass HWDev to CTranscodingPipeline */ ++ if (m_InputParamsArray[m_InputParamsArray.size() - 1].eModeExt == VppCompOnly) { ++ sInputParams& params = m_InputParamsArray[m_InputParamsArray.size() - 1]; ++ libvaBackend = params.libvaBackend; ++ ++ /* Rendering case */ ++ hwdev.reset(CreateVAAPIDevice(InputParams.strDevicePath, params.libvaBackend)); ++ if (!hwdev.get()) { ++ msdk_printf(MSDK_STRING("error: failed to initialize VAAPI device\n")); ++ return MFX_ERR_DEVICE_FAILED; ++ } ++ //sts = hwdev->Init(¶ms.monitorType, 1, MSDKAdapter::GetNumber(0, m_pLoader.get())); ++ sts = hwdev->Init(¶ms.monitorType, 1, 0); ++ #if defined(LIBVA_X11_SUPPORT) || defined(LIBVA_DRM_SUPPORT) ++ if (params.libvaBackend == MFX_LIBVA_DRM_MODESET) { ++ CVAAPIDeviceDRM* drmdev = dynamic_cast(hwdev.get()); ++ pVAAPIParams->m_export_mode = vaapiAllocatorParams::CUSTOM_FLINK; ++ pVAAPIParams->m_exporter = ++ dynamic_cast(drmdev->getRenderer()); ++ } ++ else if (params.libvaBackend == MFX_LIBVA_X11) { ++ pVAAPIParams->m_export_mode = vaapiAllocatorParams::PRIME; ++ } ++ #endif ++ #if defined(LIBVA_WAYLAND_SUPPORT) ++ else if (params.libvaBackend == MFX_LIBVA_WAYLAND) { ++ VADisplay va_dpy = NULL; ++ sts = hwdev->GetHandle(MFX_HANDLE_VA_DISPLAY, (mfxHDL*)&va_dpy); ++ MSDK_CHECK_STATUS(sts, "hwdev->GetHandle failed"); ++ hdl = pVAAPIParams->m_dpy = (VADisplay)va_dpy; ++ ++ CVAAPIDeviceWayland* w_dev = ++ dynamic_cast(hwdev.get()); ++ if (!w_dev) { ++ MSDK_CHECK_STATUS(MFX_ERR_DEVICE_FAILED, ++ "Failed to reach Wayland VAAPI device"); ++ } ++ Wayland* wld = w_dev->GetWaylandHandle(); ++ if (!wld) { ++ MSDK_CHECK_STATUS(MFX_ERR_DEVICE_FAILED, ++ "Failed to reach Wayland VAAPI device"); ++ } ++ ++ wld->SetRenderWinPos(params.nRenderWinX, params.nRenderWinY); ++ wld->SetPerfMode(params.bPerfMode); ++ ++ pVAAPIParams->m_export_mode = vaapiAllocatorParams::PRIME; ++ } ++ #endif // LIBVA_WAYLAND_SUPPORT ++ params.m_hwdev = hwdev.get(); ++ } ++ else /* NO RENDERING*/ ++ { ++ hwdev.reset(CreateVAAPIDevice(InputParams.strDevicePath)); ++ ++ if (!hwdev.get()) { ++ msdk_printf(MSDK_STRING("error: failed to initialize VAAPI device\n")); ++ return MFX_ERR_DEVICE_FAILED; ++ } ++ //sts = hwdev->Init(NULL, 0, MSDKAdapter::GetNumber(0, m_pLoader.get())); ++ sts = hwdev->Init(NULL, 0, 0); ++ } ++ if (libvaBackend != MFX_LIBVA_WAYLAND) { ++ MSDK_CHECK_STATUS(sts, "hwdev->Init failed"); ++ sts = hwdev->GetHandle(MFX_HANDLE_VA_DISPLAY, (mfxHDL*)&hdl); ++ MSDK_CHECK_STATUS(sts, "hwdev->GetHandle failed"); ++ // set Device to external vaapi allocator ++ pVAAPIParams->m_dpy = (VADisplay)hdl; ++ } ++ ++ m_pAllocParams.push_back(std::shared_ptr(pAllocParam)); ++ m_hwdevs.push_back(std::move(hwdev)); ++ hdls.push_back(hdl); ++ } ++ else { ++ if (!m_pAllocParams.empty() && !hdls.empty()) { ++ m_pAllocParams.push_back(m_pAllocParams.back()); ++ hdls.push_back(hdls.back()); ++ } ++ else { ++ msdk_printf(MSDK_STRING("error: failed to initialize alloc parameters\n")); ++ return MFX_ERR_MEMORY_ALLOC; ++ } ++ } ++ } ++#endif ++ } ++ if (m_pAllocParams.empty()) { ++ m_pAllocParams.push_back(std::shared_ptr(new SysMemAllocatorParams)); ++ hdls.push_back(NULL); ++ ++ for (i = 1; i < m_InputParamsArray.size(); i++) { ++ m_pAllocParams.push_back(m_pAllocParams.back()); ++ hdls.push_back(NULL); ++ } ++ } ++ ++ // each pair of source and sink has own safety buffer ++ sts = CreateSafetyBuffers(); ++ MSDK_CHECK_STATUS(sts, "CreateSafetyBuffers failed"); ++ ++ /* One more hint. Example you have 3 dec + 1 enc sessions ++ * (enc means vpp_comp call invoked. m_InputParamsArray.size() is 4. ++ * You don't need take vpp comp params from last one session as it is enc session. ++ * But you need process {0, 1, 2} sessions - totally 3. ++ * So, you need start from 0 and end at 2. ++ * */ ++ for (mfxI32 jj = 0; jj < (mfxI32)m_InputParamsArray.size() - 1; jj++) { ++ /* Save params for VPP composition */ ++ sVppCompDstRect tempDstRect; ++ tempDstRect.DstX = m_InputParamsArray[jj].nVppCompDstX; ++ tempDstRect.DstY = m_InputParamsArray[jj].nVppCompDstY; ++ tempDstRect.DstW = m_InputParamsArray[jj].nVppCompDstW; ++ tempDstRect.DstH = m_InputParamsArray[jj].nVppCompDstH; ++ tempDstRect.TileId = m_InputParamsArray[jj].nVppCompTileId; ++ m_VppDstRects.push_back(tempDstRect); ++ } ++ ++ // create sessions, allocators ++ for (i = 0; i < m_InputParamsArray.size(); i++) { ++ msdk_printf(MSDK_STRING("Session %d:\n"), i); ++ std::unique_ptr pAllocator(new GeneralAllocator); ++ sts = pAllocator->Init(m_pAllocParams[i].get()); ++ MSDK_CHECK_STATUS(sts, "pAllocator->Init failed"); ++ ++ m_pAllocArray.push_back(std::move(pAllocator)); ++ ++ std::unique_ptr pThreadPipeline(new ThreadTranscodeContext); ++ // extend BS processing init ++ m_pExtBSProcArray.push_back( ++ std::unique_ptr(new FileBitstreamProcessor)); ++ ++ pThreadPipeline->pPipeline.reset(CreatePipeline()); ++ ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ pThreadPipeline->pPipeline->SetPrefferiGfx(m_InputParamsArray[i].bPrefferiGfx); ++ pThreadPipeline->pPipeline->SetPrefferdGfx(m_InputParamsArray[i].bPrefferdGfx); ++#endif ++ ++ pThreadPipeline->pBSProcessor = m_pExtBSProcArray.back().get(); ++ ++ std::unique_ptr reader; ++ std::unique_ptr yuvreader; ++ if (m_InputParamsArray[i].DecodeId == MFX_CODEC_VP9 || ++ m_InputParamsArray[i].DecodeId == MFX_CODEC_VP8 || ++ m_InputParamsArray[i].DecodeId == MFX_CODEC_AV1) { ++ reader.reset(new CIVFFrameReader()); ++ } ++ else if (m_InputParamsArray[i].DecodeId == MFX_CODEC_RGB4 || ++ m_InputParamsArray[i].DecodeId == MFX_CODEC_I420 || ++ m_InputParamsArray[i].DecodeId == MFX_CODEC_NV12) { ++ // YUV reader for RGB4 overlay and raw input ++ yuvreader.reset(new CSmplYUVReader()); ++ } ++ else { ++ reader.reset(new CSmplBitstreamReader()); ++ } ++ ++ if (reader.get()) { ++ sts = reader->Init(m_InputParamsArray[i].strSrcFile); ++ MSDK_CHECK_STATUS(sts, "reader->Init failed"); ++ sts = m_pExtBSProcArray.back()->SetReader(reader); ++ MSDK_CHECK_STATUS(sts, "m_pExtBSProcArray.back()->SetReader failed"); ++ } ++ else if (yuvreader.get()) { ++ std::list input; ++ input.push_back(m_InputParamsArray[i].strSrcFile); ++ sts = yuvreader->Init(input, m_InputParamsArray[i].DecodeId); ++ MSDK_CHECK_STATUS(sts, "m_YUVReader->Init failed"); ++ sts = m_pExtBSProcArray.back()->SetReader(yuvreader); ++ MSDK_CHECK_STATUS(sts, "m_pExtBSProcArray.back()->SetReader failed"); ++ } ++ ++ std::unique_ptr writer(new CSmplBitstreamWriter()); ++ sts = writer->Init(m_InputParamsArray[i].strDstFile); ++ ++ sts = m_pExtBSProcArray.back()->SetWriter(writer); ++ MSDK_CHECK_STATUS(sts, "m_pExtBSProcArray.back()->SetWriter failed"); ++ ++ if (Sink == m_InputParamsArray[i].eMode) { ++ /* N_to_1 mode */ ++ if ((VppComp == m_InputParamsArray[i].eModeExt) || ++ (VppCompOnly == m_InputParamsArray[i].eModeExt)) { ++ // Taking buffers from tail because they are stored in m_pBufferArray in reverse order ++ // So, by doing this we'll fill buffers properly according to order from par file ++ pBuffer = m_pBufferArray[m_pBufferArray.size() - 1 - BufCounter].get(); ++ BufCounter++; ++ } ++ else /* 1_to_N mode*/ ++ { ++ pBuffer = m_pBufferArray[m_pBufferArray.size() - 1].get(); ++ } ++ pSinkPipeline = pThreadPipeline->pPipeline.get(); ++ } ++ else if (Source == m_InputParamsArray[i].eMode) { ++ /* N_to_1 mode */ ++ if ((VppComp == m_InputParamsArray[i].eModeExt) || ++ (VppCompOnly == m_InputParamsArray[i].eModeExt)) { ++ pBuffer = m_pBufferArray[m_pBufferArray.size() - 1].get(); ++ } ++ else /* 1_to_N mode*/ ++ { ++ pBuffer = m_pBufferArray[BufCounter].get(); ++ BufCounter++; ++ } ++ } ++ else { ++ pBuffer = NULL; ++ } ++ ++ /**/ ++ /* Vector stored linearly in the memory !*/ ++ m_InputParamsArray[i].pVppCompDstRects = m_VppDstRects.empty() ? NULL : &m_VppDstRects[0]; ++ ++ // if session has VPP plus ENCODE only (-i::source option) ++ // use decode source session as input ++ sts = MFX_ERR_MORE_DATA; ++ if (Source == m_InputParamsArray[i].eMode) { ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ sts = CheckAndFixAdapterDependency(i, pSinkPipeline); ++ MSDK_CHECK_STATUS(sts, "CheckAndFixAdapterDependency failed"); ++ // force implementation type based on iGfx/dGfx parameters ++ if (m_InputParamsArray[i].libType != MFX_IMPL_SOFTWARE) { ++ ForceImplForSession(i); ++ sts = m_pLoader->EnumImplementations(m_deviceID, m_adapterNum); ++ MSDK_CHECK_STATUS(sts, "EnumImplementations(m_deviceID, m_adapterNum) failed"); ++ } ++#endif ++ sts = pThreadPipeline->pPipeline->Init(&m_InputParamsArray[i], ++ m_pAllocArray[i].get(), ++ hdls[i], ++ pSinkPipeline, ++ pBuffer, ++ m_pExtBSProcArray.back().get(), ++ m_pLoader.get()); ++ } ++ else { ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ sts = CheckAndFixAdapterDependency(i, pParentPipeline); ++ MSDK_CHECK_STATUS(sts, "CheckAndFixAdapterDependency failed"); ++ // force implementation type based on iGfx/dGfx parameters ++ if (m_InputParamsArray[i].libType != MFX_IMPL_SOFTWARE) { ++ ForceImplForSession(i); ++ sts = m_pLoader->EnumImplementations(m_deviceID, m_adapterNum); ++ MSDK_CHECK_STATUS(sts, "EnumImplementations(m_deviceID, m_adapterNum) failed"); ++ } ++#endif ++ sts = pThreadPipeline->pPipeline->Init(&m_InputParamsArray[i], ++ m_pAllocArray[i].get(), ++ hdls[i], ++ pParentPipeline, ++ pBuffer, ++ m_pExtBSProcArray.back().get(), ++ m_pLoader.get()); ++ } ++ ++ MSDK_CHECK_STATUS(sts, "pThreadPipeline->pPipeline->Init failed"); ++ ++ if (!pParentPipeline && m_InputParamsArray[i].bIsJoin) ++ pParentPipeline = pThreadPipeline->pPipeline.get(); ++ ++ // set the session's start status (like it is waiting) ++ pThreadPipeline->startStatus = MFX_WRN_DEVICE_BUSY; ++ // set other session's parameters ++ pThreadPipeline->implType = m_InputParamsArray[i].libType; ++ m_pThreadContextArray.push_back(std::move(pThreadPipeline)); ++ ++ mfxVersion ver = { { 0, 0 } }; ++ sts = m_pThreadContextArray[i]->pPipeline->QueryMFXVersion(&ver); ++ MSDK_CHECK_STATUS(sts, "m_pThreadContextArray[i]->pPipeline->QueryMFXVersion failed"); ++ ++ PrintInfo(i, &m_InputParamsArray[i], &ver); ++ } ++ ++ for (i = 0; i < m_InputParamsArray.size(); i++) { ++ sts = m_pThreadContextArray[i]->pPipeline->CompleteInit(); ++ MSDK_CHECK_STATUS(sts, "m_pThreadContextArray[i]->pPipeline->CompleteInit failed"); ++ ++ if (m_pThreadContextArray[i]->pPipeline->GetJoiningFlag()) ++ msdk_printf(MSDK_STRING("Session %d was joined with other sessions\n"), i); ++ else ++ msdk_printf(MSDK_STRING("Session %d was NOT joined with other sessions\n"), i); ++ ++ m_pThreadContextArray[i]->pPipeline->SetPipelineID(i); ++ } ++ ++ msdk_printf(MSDK_STRING("\n")); ++ ++ return sts; ++ ++} // mfxStatus Launcher::Init() ++ ++void Launcher::Run() { ++ msdk_printf(MSDK_STRING("Transcoding started\n")); ++ ++ // mark start time ++ m_StartTime = GetTick(); ++ ++ // Robust flag is applied to every seession if enabled in one ++ if (m_pThreadContextArray[0]->pPipeline->GetRobustFlag()) { ++ DoRobustTranscoding(); ++ } ++ else { ++ DoTranscoding(); ++ } ++ ++ msdk_printf(MSDK_STRING("\nTranscoding finished\n")); ++ ++} // mfxStatus Launcher::Init() ++ ++void Launcher::DoTranscoding() { ++ auto RunTranscodeRoutine = [](ThreadTranscodeContext* context) { ++ context->handle = std::async(std::launch::async, [context]() { ++ context->TranscodeRoutine(); ++ }); ++ }; ++ ++ bool isOverlayUsed = false; ++ for (const auto& context : m_pThreadContextArray) { ++ MSDK_CHECK_POINTER_NO_RET(context); ++ RunTranscodeRoutine(context.get()); ++ ++ MSDK_CHECK_POINTER_NO_RET(context->pPipeline); ++ isOverlayUsed = isOverlayUsed || context->pPipeline->IsOverlayUsed(); ++ } ++ ++ // Transcoding threads waiting cycle ++ bool aliveNonOverlaySessions = true; ++ while (aliveNonOverlaySessions) { ++ aliveNonOverlaySessions = false; ++ ++ for (size_t i = 0; i < m_pThreadContextArray.size(); ++i) { ++ if (!m_pThreadContextArray[i]->handle.valid()) ++ continue; ++ ++ //Payslip interval to check the state of working threads: ++ //such interval is usually a realtime, i.e. for 30 fps this would be 33ms, ++ //66ms typically mean either 1/fps or 2/fps payslip checks. ++ auto waitSts = m_pThreadContextArray[i]->handle.wait_for(std::chrono::milliseconds(66)); ++ if (waitSts == std::future_status::ready) { ++ // Invoke get() of the handle just to reset the valid state. ++ // This allows to skip already processed sessions ++ m_pThreadContextArray[i]->handle.get(); ++ ++ // Session is completed, let's check for its status ++ if (m_pThreadContextArray[i]->transcodingSts < MFX_ERR_NONE) { ++ // Stop all the sessions if an error happened in one ++ // But do not stop in robust mode when gpu hang's happened ++ if (m_pThreadContextArray[i]->transcodingSts != MFX_ERR_GPU_HANG || ++ !m_pThreadContextArray[i]->pPipeline->GetRobustFlag()) { ++ msdk_stringstream ss; ++ ss << MSDK_STRING("\n\n session ") << i << MSDK_STRING(" [") ++ << m_pThreadContextArray[i]->pPipeline->GetSessionText() ++ << MSDK_STRING("] failed with status ") ++ << StatusToString(m_pThreadContextArray[i]->transcodingSts) ++ << MSDK_STRING(" shutting down the application...") << std::endl ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ ++ for (const auto& context : m_pThreadContextArray) { ++ context->pPipeline->StopSession(); ++ } ++ } ++ } ++ else if (m_pThreadContextArray[i]->transcodingSts > MFX_ERR_NONE) { ++ msdk_stringstream ss; ++ ss << MSDK_STRING("\n\n session ") << i << MSDK_STRING(" [") ++ << m_pThreadContextArray[i]->pPipeline->GetSessionText() ++ << MSDK_STRING("] returned warning status ") ++ << StatusToString(m_pThreadContextArray[i]->transcodingSts) << std::endl ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ } ++ } ++ else { ++ aliveNonOverlaySessions = aliveNonOverlaySessions || ++ !m_pThreadContextArray[i]->pPipeline->IsOverlayUsed(); ++ } ++ } ++ ++ // Stop overlay sessions ++ // Note: Overlay sessions never stop themselves so they should be forcibly stopped ++ // after stopping of all non-overlay sessions ++ if (!aliveNonOverlaySessions && isOverlayUsed) { ++ // Sending stop message ++ for (const auto& context : m_pThreadContextArray) { ++ if (context->pPipeline->IsOverlayUsed()) { ++ context->pPipeline->StopSession(); ++ } ++ } ++ ++ // Waiting for them to be stopped ++ for (const auto& context : m_pThreadContextArray) { ++ if (!context->handle.valid()) ++ continue; ++ ++ context->handle.wait(); ++ } ++ } ++ } ++} ++ ++void Launcher::DoRobustTranscoding() { ++ mfxStatus sts = MFX_ERR_NONE; ++ ++ // Cycle for handling MFX_ERR_GPU_HANG during transcoding ++ // If it's returned, reset all the pipelines and start over from the last point ++ bool bGPUHang = false; ++ for (;;) { ++ if (bGPUHang) { ++ for (size_t i = 0; i < m_pThreadContextArray.size(); i++) { ++ sts = m_pThreadContextArray[i]->pPipeline->Reset(m_pLoader.get()); ++ if (sts) { ++ msdk_printf( ++ MSDK_STRING("\n[WARNING] GPU Hang recovery wasn't succeed. Exiting...\n")); ++ return; ++ } ++ } ++ bGPUHang = false; ++ msdk_printf(MSDK_STRING("\n[WARNING] Successfully recovered. Continue transcoding.\n")); ++ } ++ ++ DoTranscoding(); ++ ++ for (size_t i = 0; i < m_pThreadContextArray.size(); i++) { ++ if (m_pThreadContextArray[i]->transcodingSts == MFX_ERR_GPU_HANG) { ++ bGPUHang = true; ++ } ++ } ++ if (!bGPUHang) ++ break; ++ msdk_printf(MSDK_STRING("\n[WARNING] GPU Hang has happened. Trying to recover...\n")); ++ } ++} ++ ++mfxStatus Launcher::ProcessResult() { ++ FILE* pPerfFile = m_parser.GetPerformanceFile(); ++ ++ msdk_stringstream ssTranscodingTime; ++ ssTranscodingTime << std::endl ++ << MSDK_STRING("Common transcoding time is ") << GetTime(m_StartTime) ++ << MSDK_STRING(" sec") << std::endl; ++ ++ m_parser.PrintParFileName(); ++ ++ msdk_printf(MSDK_STRING("%s"), ssTranscodingTime.str().c_str()); ++ if (pPerfFile) { ++ msdk_fprintf(pPerfFile, MSDK_STRING("%s"), ssTranscodingTime.str().c_str()); ++ } ++ ++ mfxStatus FinalSts = MFX_ERR_NONE; ++ msdk_printf(MSDK_STRING( ++ "-------------------------------------------------------------------------------\n")); ++ ++ for (mfxU32 i = 0; i < m_pThreadContextArray.size(); i++) { ++ mfxStatus transcodingSts = m_pThreadContextArray[i]->transcodingSts; ++ mfxF64 workTime = m_pThreadContextArray[i]->working_time; ++ mfxU32 framesNum = m_pThreadContextArray[i]->numTransFrames; ++ ++ if (!FinalSts) ++ FinalSts = transcodingSts; ++ ++ msdk_string SessionStsStr = transcodingSts ? msdk_string(MSDK_STRING("FAILED")) ++ : msdk_string((MSDK_STRING("PASSED"))); ++ ++ msdk_stringstream ss; ++ ss << MSDK_STRING("*** session ") << i << MSDK_STRING(" [") ++ << m_pThreadContextArray[i]->pPipeline->GetSessionText() << MSDK_STRING("] ") ++ << SessionStsStr << MSDK_STRING(" (") << StatusToString(transcodingSts) ++ << MSDK_STRING(") ") << workTime << MSDK_STRING(" sec, ") << framesNum ++ << MSDK_STRING(" frames, ") << std::fixed << std::setprecision(3) << framesNum / workTime ++ << MSDK_STRING(" fps") << std::endl ++ << m_parser.GetLine(i) << std::endl ++ << std::endl; ++ ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ if (pPerfFile) { ++ msdk_fprintf(pPerfFile, MSDK_STRING("%s"), ss.str().c_str()); ++ } ++ } ++ msdk_printf(MSDK_STRING( ++ "-------------------------------------------------------------------------------\n")); ++ ++ msdk_stringstream ssTest; ++ ssTest << std::endl ++ << MSDK_STRING("The test ") ++ << (FinalSts ? msdk_string(MSDK_STRING("FAILED")) : msdk_string(MSDK_STRING("PASSED"))) ++ << std::endl; ++ ++ msdk_printf(MSDK_STRING("%s"), ssTest.str().c_str()); ++ if (pPerfFile) { ++ msdk_fprintf(pPerfFile, MSDK_STRING("%s"), ssTest.str().c_str()); ++ } ++ return FinalSts; ++} // mfxStatus Launcher::ProcessResult() ++ ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++mfxStatus Launcher::QueryAdapters() { ++ mfxU32 num_adapters_available; ++ ++ mfxStatus sts = MFXQueryAdaptersNumber(&num_adapters_available); ++ MFX_CHECK_STS(sts); ++ ++ // no adapters on the machine, able to use software implementation ++ if (!num_adapters_available) { ++ return MFX_ERR_NONE; ++ } ++ ++ m_DisplaysData.resize(num_adapters_available); ++ m_Adapters = { m_DisplaysData.data(), mfxU32(m_DisplaysData.size()), 0u }; ++ ++ sts = MFXQueryAdapters(nullptr, &m_Adapters); ++ MFX_CHECK_STS(sts); ++ ++ return MFX_ERR_NONE; ++} ++ ++void Launcher::ForceImplForSession(mfxU32 idxSession) { ++ if (m_InputParamsArray[idxSession].libType == MFX_IMPL_SOFTWARE) ++ return; ++ ++ //change only 8 bit of the implementation. Don't touch type of frames ++ mfxIMPL impl = m_InputParamsArray[idxSession].libType & mfxI32(~0xFF); ++ ++ mfxU32 idx = GetPreferredAdapterNum(m_Adapters, m_InputParamsArray[idxSession]); ++ switch (m_Adapters.Adapters[idx].Number) { ++ case 0: ++ impl |= MFX_IMPL_HARDWARE; ++ break; ++ case 1: ++ impl |= MFX_IMPL_HARDWARE2; ++ break; ++ case 2: ++ impl |= MFX_IMPL_HARDWARE3; ++ break; ++ case 3: ++ impl |= MFX_IMPL_HARDWARE4; ++ break; ++ ++ default: ++ // try searching on all display adapters ++ impl |= MFX_IMPL_HARDWARE_ANY; ++ break; ++ } ++ ++ m_InputParamsArray[idxSession].libType = impl; ++ m_adapterNum = m_Adapters.Adapters[idx].Number; ++ m_deviceID = m_Adapters.Adapters[idx].Platform.DeviceId; ++} ++ ++mfxStatus Launcher::CheckAndFixAdapterDependency(mfxU32 idxSession, ++ CTranscodingPipeline* pParentPipeline) { ++ if (!pParentPipeline) ++ return MFX_ERR_NONE; ++ ++ // Inherited sessions must have the same adapter as parent ++ if ((pParentPipeline->IsPrefferiGfx() || pParentPipeline->IsPrefferdGfx()) && ++ !m_InputParamsArray[idxSession].bPrefferiGfx && ++ !m_InputParamsArray[idxSession].bPrefferdGfx) { ++ m_InputParamsArray[idxSession].bPrefferiGfx = pParentPipeline->IsPrefferiGfx(); ++ m_InputParamsArray[idxSession].bPrefferdGfx = pParentPipeline->IsPrefferdGfx(); ++ msdk_stringstream ss; ++ ss << MSDK_STRING("\n\n session with index: ") << idxSession ++ << MSDK_STRING(" adapter type was forced to ") ++ << (pParentPipeline->IsPrefferiGfx() ? MSDK_STRING("integrated") ++ : MSDK_STRING("discrete")) ++ << std::endl ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ ++ return MFX_ERR_NONE; ++ } ++ ++ // App can't change initialization of the previous session (parent session) ++ if (!pParentPipeline->IsPrefferiGfx() && !pParentPipeline->IsPrefferdGfx() && ++ (m_InputParamsArray[idxSession].bPrefferiGfx || ++ m_InputParamsArray[idxSession].bPrefferdGfx)) { ++ msdk_stringstream ss; ++ ss << MSDK_STRING("\n\n session with index: ") << idxSession ++ << MSDK_STRING(" failed because parent session [") << pParentPipeline->GetSessionText() ++ << MSDK_STRING("] doesn't have explicit adapter setting") << std::endl ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ // Inherited sessions must have the same adapter as parent ++ if (pParentPipeline->IsPrefferiGfx() && !m_InputParamsArray[idxSession].bPrefferiGfx) { ++ msdk_stringstream ss; ++ ss << MSDK_STRING("\n\n session with index: ") << idxSession ++ << MSDK_STRING(" failed because it has different adapter type with parent session [") ++ << pParentPipeline->GetSessionText() << MSDK_STRING("]") << std::endl ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ // Inherited sessions must have the same adapter as parent ++ if (pParentPipeline->IsPrefferdGfx() && !m_InputParamsArray[idxSession].bPrefferdGfx) { ++ msdk_stringstream ss; ++ ss << MSDK_STRING("\n\n session with index: ") << idxSession ++ << MSDK_STRING(" failed because it has different adapter type with parent session [") ++ << pParentPipeline->GetSessionText() << MSDK_STRING("]") << std::endl ++ << std::endl; ++ msdk_printf(MSDK_STRING("%s"), ss.str().c_str()); ++ ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ return MFX_ERR_NONE; ++} ++#endif //(_WIN32 || _WIN64) && (MFX_VERSION >= 1031) ++ ++mfxStatus Launcher::VerifyCrossSessionsOptions() { ++ bool IsSinkPresence = false; ++ bool IsSourcePresence = false; ++ bool IsHeterSessionJoin = false; ++ bool IsFirstInTopology = true; ++ ++ mfxU16 minAsyncDepth = 0; ++ bool bUseExternalAllocator = false; ++ bool bSingleTexture = false; ++ ++#if (MFX_VERSION >= 1025) ++ bool allMFEModesEqual = true; ++ bool allMFEFramesEqual = true; ++ bool allMFESessionsJoined = true; ++ ++ mfxU16 usedMFEMaxFrames = 0; ++ mfxU16 usedMFEMode = 0; ++ ++ for (mfxU32 i = 0; i < m_InputParamsArray.size(); i++) { ++ // loop over all sessions and check mfe-specific params ++ // for mfe is required to have sessions joined, HW impl ++ if (m_InputParamsArray[i].numMFEFrames > 1) { ++ usedMFEMaxFrames = m_InputParamsArray[i].numMFEFrames; ++ for (mfxU32 j = 0; j < m_InputParamsArray.size(); j++) { ++ if (m_InputParamsArray[j].numMFEFrames && ++ m_InputParamsArray[j].numMFEFrames != usedMFEMaxFrames) { ++ m_InputParamsArray[j].numMFEFrames = usedMFEMaxFrames; ++ allMFEFramesEqual = false; ++ m_InputParamsArray[j].MFMode = m_InputParamsArray[j].MFMode < MFX_MF_AUTO ++ ? MFX_MF_AUTO ++ : m_InputParamsArray[j].MFMode; ++ } ++ if (m_InputParamsArray[j].bIsJoin == false) { ++ allMFESessionsJoined = false; ++ m_InputParamsArray[j].bIsJoin = true; ++ } ++ } ++ } ++ if (m_InputParamsArray[i].MFMode >= MFX_MF_AUTO) { ++ usedMFEMode = m_InputParamsArray[i].MFMode; ++ for (mfxU32 j = 0; j < m_InputParamsArray.size(); j++) { ++ if (m_InputParamsArray[j].MFMode && m_InputParamsArray[j].MFMode != usedMFEMode) { ++ m_InputParamsArray[j].MFMode = usedMFEMode; ++ allMFEModesEqual = false; ++ } ++ if (m_InputParamsArray[j].bIsJoin == false) { ++ allMFESessionsJoined = false; ++ m_InputParamsArray[j].bIsJoin = true; ++ } ++ } ++ } ++ } ++ if (!allMFEFramesEqual) ++ msdk_printf( ++ MSDK_STRING( ++ "WARNING: All sessions for MFE should have the same number of MFE frames!\n used ammount of frame for MFE: %d\n"), ++ (int)usedMFEMaxFrames); ++ if (!allMFEModesEqual) ++ msdk_printf( ++ MSDK_STRING( ++ "WARNING: All sessions for MFE should have the same mode!\n, used mode: %d\n"), ++ (int)usedMFEMode); ++ if (!allMFESessionsJoined) ++ msdk_printf(MSDK_STRING( ++ "WARNING: Sessions for MFE should be joined! All sessions forced to be joined\n")); ++#endif ++ ++ for (mfxU32 i = 0; i < m_InputParamsArray.size(); i++) { ++ // Any plugin or static frame alpha blending ++ // CPU rotate plugin works with opaq frames in native mode ++ if ((m_InputParamsArray[i].nRotationAngle && m_InputParamsArray[i].eMode != Native) || ++ m_InputParamsArray[i].bOpenCL || m_InputParamsArray[i].EncoderFourCC || ++ m_InputParamsArray[i].DecoderFourCC || m_InputParamsArray[i].nVppCompSrcH || ++ m_InputParamsArray[i].nVppCompSrcW) { ++ bUseExternalAllocator = true; ++ } ++ ++ if (m_InputParamsArray[i].bSingleTexture) { ++ bSingleTexture = true; ++ } ++ ++ // All sessions have to know about timeout ++ if (m_InputParamsArray[i].nTimeout && (m_InputParamsArray[i].eMode == Sink)) { ++ for (mfxU32 j = 0; j < m_InputParamsArray.size(); j++) { ++ if (m_InputParamsArray[j].MaxFrameNumber != MFX_INFINITE) { ++ msdk_printf(MSDK_STRING( ++ "\"-timeout\" option isn't compatible with \"-n\". \"-n\" will be ignored.\n")); ++ for (mfxU32 k = 0; k < m_InputParamsArray.size(); k++) { ++ m_InputParamsArray[k].MaxFrameNumber = MFX_INFINITE; ++ } ++ break; ++ } ++ } ++ msdk_printf(MSDK_STRING("Timeout %d seconds has been set to all sessions\n"), ++ m_InputParamsArray[i].nTimeout); ++ for (mfxU32 j = 0; j < m_InputParamsArray.size(); j++) { ++ m_InputParamsArray[j].nTimeout = m_InputParamsArray[i].nTimeout; ++ } ++ } ++ ++ // All sessions have to know if robust mode enabled ++ if (m_InputParamsArray[i].bRobustFlag) { ++ for (mfxU32 j = 0; j < m_InputParamsArray.size(); j++) { ++ m_InputParamsArray[j].bRobustFlag = m_InputParamsArray[i].bRobustFlag; ++ } ++ } ++ ++ if (Source == m_InputParamsArray[i].eMode) { ++ if (m_InputParamsArray[i].nAsyncDepth < minAsyncDepth) { ++ minAsyncDepth = m_InputParamsArray[i].nAsyncDepth; ++ } ++ // topology definition ++ if (!IsSinkPresence) { ++ PrintError(MSDK_STRING( ++ "Error in par file. Decode source session must be declared BEFORE encode sinks \n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ IsSourcePresence = true; ++ ++ if (IsFirstInTopology) { ++ if (m_InputParamsArray[i].bIsJoin) ++ IsHeterSessionJoin = true; ++ else ++ IsHeterSessionJoin = false; ++ } ++ else { ++ if (m_InputParamsArray[i].bIsJoin && !IsHeterSessionJoin) { ++ PrintError(MSDK_STRING( ++ "Error in par file. All heterogeneous sessions must be joined \n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (!m_InputParamsArray[i].bIsJoin && IsHeterSessionJoin) { ++ PrintError(MSDK_STRING( ++ "Error in par file. All heterogeneous sessions must be NOT joined \n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ ++ if (IsFirstInTopology) ++ IsFirstInTopology = false; ++ } ++ else if (Sink == m_InputParamsArray[i].eMode) { ++ minAsyncDepth = m_InputParamsArray[i].nAsyncDepth; ++ IsSinkPresence = true; ++ ++ if (IsFirstInTopology) { ++ if (m_InputParamsArray[i].bIsJoin) ++ IsHeterSessionJoin = true; ++ else ++ IsHeterSessionJoin = false; ++ } ++ else { ++ if (m_InputParamsArray[i].bIsJoin && !IsHeterSessionJoin) { ++ PrintError(MSDK_STRING( ++ "Error in par file. All heterogeneous sessions must be joined \n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (!m_InputParamsArray[i].bIsJoin && IsHeterSessionJoin) { ++ PrintError(MSDK_STRING( ++ "Error in par file. All heterogeneous sessions must be NOT joined \n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ ++ if (IsFirstInTopology) ++ IsFirstInTopology = false; ++ } ++ if (MFX_IMPL_SOFTWARE != m_InputParamsArray[i].libType) { ++ // TODO: can we avoid ifdef and use MFX_IMPL_VIA_VAAPI? ++#if defined(_WIN32) || defined(_WIN64) ++ if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(m_InputParamsArray[i].libType)) { ++ m_eDevType = MFX_HANDLE_D3D11_DEVICE; ++ m_accelerationMode = MFX_ACCEL_MODE_VIA_D3D11; ++ } ++ else { ++ m_eDevType = MFX_HANDLE_D3D9_DEVICE_MANAGER; ++ m_accelerationMode = MFX_ACCEL_MODE_VIA_D3D9; ++ } ++#elif defined(LIBVA_SUPPORT) ++ m_eDevType = MFX_HANDLE_VA_DISPLAY; ++ m_accelerationMode = MFX_ACCEL_MODE_VIA_VAAPI; ++#endif ++ } ++ } ++ ++ // Async depth between inter-sessions should be equal to the minimum async depth of all these sessions. ++ for (mfxU32 i = 0; i < m_InputParamsArray.size(); i++) { ++ if ((m_InputParamsArray[i].eMode == Source) || (m_InputParamsArray[i].eMode == Sink)) { ++ m_InputParamsArray[i].nAsyncDepth = minAsyncDepth; ++ } ++ } ++ ++ if (IsSinkPresence && !IsSourcePresence) { ++ PrintError(MSDK_STRING("Error: Sink must be defined")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (bSingleTexture) { ++ bool showWarning = false; ++ for (mfxU32 j = 0; j < m_InputParamsArray.size(); j++) { ++ if (!m_InputParamsArray[j].bSingleTexture) { ++ showWarning = true; ++ } ++ m_InputParamsArray[j].bSingleTexture = true; ++ } ++ if (showWarning) { ++ msdk_printf(MSDK_STRING( ++ "WARNING: At least one session has -single_texture_d3d11 option, all other sessions are modified to have this setting enabled al well.\n")); ++ } ++ } ++ ++ return MFX_ERR_NONE; ++ ++} // mfxStatus Launcher::VerifyCrossSessionsOptions() ++ ++mfxStatus Launcher::CreateSafetyBuffers() { ++ SafetySurfaceBuffer* pBuffer = NULL; ++ ++ for (mfxU32 i = 0; i < m_InputParamsArray.size(); i++) { ++ /* this is for 1 to N case*/ ++ if ((Source == m_InputParamsArray[i].eMode) && (Native == m_InputParamsArray[0].eModeExt)) { ++ pBuffer = new SafetySurfaceBuffer(pBuffer); ++ m_pBufferArray.push_back(std::unique_ptr(pBuffer)); ++ } ++ ++ /* And N_to_1 case: composition should be enabled! ++ * else it is logic error */ ++ if ((Source != m_InputParamsArray[i].eMode) && ++ ((VppComp == m_InputParamsArray[0].eModeExt) || ++ (VppCompOnly == m_InputParamsArray[0].eModeExt))) { ++ pBuffer = new SafetySurfaceBuffer(pBuffer); ++ m_pBufferArray.push_back(std::unique_ptr(pBuffer)); ++ } ++ } ++ return MFX_ERR_NONE; ++ ++} // mfxStatus Launcher::CreateSafetyBuffers ++ ++void Launcher::Close() { ++ while (m_pThreadContextArray.size()) { ++ m_pThreadContextArray[m_pThreadContextArray.size() - 1].reset(); ++ m_pThreadContextArray.pop_back(); ++ } ++ ++ m_pAllocArray.clear(); ++ m_pBufferArray.clear(); ++ m_pExtBSProcArray.clear(); ++ m_pAllocParams.clear(); ++ m_hwdevs.clear(); ++ ++} // void Launcher::Close() ++ ++#if defined(_WIN32) || defined(_WIN64) ++int _tmain(int argc, TCHAR* argv[]) ++#else ++int main(int argc, char* argv[]) ++#endif ++{ ++ mfxStatus sts; ++ Launcher transcode; ++ if (argc < 2) { ++ msdk_printf(MSDK_STRING( ++ "[ERROR] Command line is empty. Use -? for getting help on available options.\n")); ++ return 0; ++ } ++ ++ sts = transcode.Init(argc, argv); ++ if (sts == MFX_WRN_OUT_OF_RANGE) { ++ // There's no error in parameters parsing, but we should not continue further. For instance, in case of -? option ++ return MFX_ERR_NONE; ++ } ++ ++ fflush(stdout); ++ fflush(stderr); ++ ++ MSDK_CHECK_STATUS(sts, "transcode.Init failed"); ++ ++ transcode.Run(); ++ ++ sts = transcode.ProcessResult(); ++ fflush(stdout); ++ fflush(stderr); ++ MSDK_CHECK_STATUS(sts, "transcode.ProcessResult failed"); ++ ++ return 0; ++} +diff --git a/tools/legacy/sample_multi_transcode/src/transcode_utils.cpp b/tools/legacy/sample_multi_transcode/src/transcode_utils.cpp +new file mode 100644 +index 0000000..db26c82 +--- /dev/null ++++ b/tools/legacy/sample_multi_transcode/src/transcode_utils.cpp +@@ -0,0 +1,2765 @@ ++/******************************************************************************\ ++Copyright (c) 2005-2020, Intel Corporation ++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. ++ ++This sample was distributed or derived from the Intel's Media Samples package. ++The original version of this sample may be obtained from https://software.intel.com/en-us/intel-media-server-studio ++or https://software.intel.com/en-us/media-client-solutions-support. ++\**********************************************************************************/ ++ ++#include "mfx_samples_config.h" ++#include "plugin_utils.h" ++ ++#if defined(_WIN32) || defined(_WIN64) ++ #include ++ #include ++ #include ++ #include "d3d11_allocator.h" ++ #include "d3d_allocator.h" ++#else ++ #include ++ #include "vaapi_allocator.h" ++#endif ++ ++#include "sysmem_allocator.h" ++#include "transcode_utils.h" ++ ++#include "version.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++using namespace TranscodingSample; ++ ++// parsing defines ++#define IS_SEPARATOR(ch) ((ch) <= ' ' || (ch) == '=') ++#define VAL_CHECK(val, argIdx, argName) \ ++ { \ ++ if (val) { \ ++ PrintError(MSDK_STRING("Input argument number %d \"%s\" require more parameters"), \ ++ argIdx, \ ++ argName); \ ++ return MFX_ERR_UNSUPPORTED; \ ++ } \ ++ } ++ ++#define SIZE_CHECK(cond) \ ++ { \ ++ if (cond) { \ ++ PrintError(MSDK_STRING("Buffer is too small")); \ ++ return MFX_ERR_UNSUPPORTED; \ ++ } \ ++ } ++ ++#ifndef MFX_VERSION ++ #error MFX_VERSION not defined ++#endif ++ ++msdk_tick TranscodingSample::GetTick() { ++ return msdk_time_get_tick(); ++} ++ ++mfxF64 TranscodingSample::GetTime(msdk_tick start) { ++ static msdk_tick frequency = msdk_time_get_frequency(); ++ ++ return MSDK_GET_TIME(msdk_time_get_tick(), start, frequency); ++} ++ ++void TranscodingSample::PrintError(const msdk_char* strErrorMessage, ...) { ++ if (strErrorMessage) { ++ msdk_printf(MSDK_STRING("ERROR: ")); ++ va_list args; ++ va_start(args, strErrorMessage); ++ msdk_vprintf(strErrorMessage, args); ++ va_end(args); ++ msdk_printf( ++ MSDK_STRING("\nUsage: sample_multi_transcode [options] [--] pipeline-description\n")); ++ msdk_printf(MSDK_STRING(" or: sample_multi_transcode [options] -par ParFile\n")); ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING("Run application with -? option to get full help text.\n\n")); ++ } ++} ++ ++void TranscodingSample::PrintHelp() { ++ msdk_printf(MSDK_STRING("Multi Transcoding Sample Version %s\n\n"), ++ GetMSDKSampleVersion().c_str()); ++ msdk_printf(MSDK_STRING("Command line parameters\n")); ++ ++ msdk_printf(MSDK_STRING("Usage: sample_multi_transcode [options] [--] pipeline-description\n")); ++ msdk_printf(MSDK_STRING(" or: sample_multi_transcode [options] -par ParFile\n")); ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING(" -stat \n")); ++ msdk_printf(MSDK_STRING(" Output statistic every N transcoding cycles\n")); ++ msdk_printf(MSDK_STRING(" -stat-log \n")); ++ msdk_printf(MSDK_STRING( ++ " Output statistic to the specified file (opened in append mode)\n")); ++ msdk_printf(MSDK_STRING(" -stat-per-frame \n")); ++ msdk_printf(MSDK_STRING( ++ " Output per-frame latency values to a file (opened in append mode). The file name will be for an input sesssion: _input_ID_.log\n")); ++ msdk_printf(MSDK_STRING( ++ " or, for output session: _output_ID_.log; - a number of a session.\n")); ++ ++ msdk_printf(MSDK_STRING("Options:\n")); ++ // (" ............xx ++ msdk_printf(MSDK_STRING(" -? Print this help and exit\n")); ++ msdk_printf(MSDK_STRING(" -p \n")); ++ msdk_printf(MSDK_STRING(" Collect performance statistics in specified file\n")); ++ msdk_printf(MSDK_STRING(" -timeout \n")); ++ msdk_printf(MSDK_STRING(" Set time to run transcoding in seconds\n")); ++ msdk_printf(MSDK_STRING(" -greedy \n")); ++ msdk_printf( ++ MSDK_STRING(" Use greedy formula to calculate number of surfaces\n")); ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING("Pipeline description (general options):\n")); ++ msdk_printf(MSDK_STRING(" -i::h265|h264|mpeg2|vc1|mvc|jpeg|vp9|av1 \n")); ++ msdk_printf(MSDK_STRING(" Set input file and decoder type\n")); ++ msdk_printf(MSDK_STRING(" -i::i420|nv12 \n")); ++ msdk_printf(MSDK_STRING(" Set raw input file and color format\n")); ++ msdk_printf(MSDK_STRING( ++ " -i::rgb4_frame Set input rgb4 file for compositon. File should contain just one single frame (-vpp_comp_src_h and -vpp_comp_src_w should be specified as well).\n")); ++ msdk_printf(MSDK_STRING(" -o::h265|h264|mpeg2|mvc|jpeg|vp9|raw \n")); ++ msdk_printf(MSDK_STRING(" Set output file and encoder type\n")); ++ msdk_printf(MSDK_STRING(" -sw|-hw|-hw_d3d11|-hw_d3d9\n")); ++ msdk_printf(MSDK_STRING(" SDK implementation to use: \n")); ++ msdk_printf(MSDK_STRING( ++ " -hw - platform-specific on default display adapter (default)\n")); ++ msdk_printf(MSDK_STRING( ++ " -hw_d3d11 - platform-specific via d3d11 (d3d11 is default for win)\n")); ++ msdk_printf(MSDK_STRING(" -hw_d3d9 - platform-specific via d3d9\n")); ++ msdk_printf(MSDK_STRING(" -sw - software\n")); ++#if defined(LINUX32) || defined(LINUX64) ++ msdk_printf(MSDK_STRING(" -device /path/to/device - set graphics device for processing\n")); ++ msdk_printf( ++ MSDK_STRING(" For example: '-device /dev/dri/card0'\n")); ++ msdk_printf( ++ MSDK_STRING(" '-device /dev/dri/renderD128'\n")); ++ msdk_printf(MSDK_STRING( ++ " If not specified, defaults to the first Intel device found on the system\n")); ++#endif ++#if (defined(_WIN64) || defined(_WIN32)) && (MFX_VERSION >= 1031) ++ msdk_printf( ++ MSDK_STRING(" [-dGfx] - preffer processing on dGfx (by default system decides)\n")); ++ msdk_printf( ++ MSDK_STRING(" [-iGfx] - preffer processing on iGfx (by default system decides)\n")); ++#endif ++#if (MFX_VERSION >= 1025) ++ msdk_printf(MSDK_STRING( ++ " -mfe_frames maximum number of frames to be combined in multi-frame encode pipeline")); ++ msdk_printf(MSDK_STRING(" 0 - default for platform will be used\n")); ++ msdk_printf(MSDK_STRING( ++ " -mfe_mode 0|1|2|3 multi-frame encode operation mode - should be the same for all sessions\n")); ++ msdk_printf(MSDK_STRING( ++ " 0, MFE operates as DEFAULT mode, decided by SDK if MFE enabled\n")); ++ msdk_printf(MSDK_STRING(" 1, MFE is disabled\n")); ++ msdk_printf(MSDK_STRING(" 2, MFE operates as AUTO mode\n")); ++ msdk_printf(MSDK_STRING(" 3, MFE operates as MANUAL mode\n")); ++ ++ msdk_printf(MSDK_STRING( ++ " -mfe_timeout multi-frame encode timeout in milliseconds - set per sessions control\n")); ++#endif ++ ++#ifdef ENABLE_MCTF ++ #if !defined ENABLE_MCTF_EXT ++ msdk_printf(MSDK_STRING(" -mctf [Strength]\n")); ++ msdk_printf(MSDK_STRING(" Strength is an optional value; it is in range [0...20]\n")); ++ msdk_printf(MSDK_STRING(" value 0 makes MCTF operates in auto mode;\n")); ++ msdk_printf(MSDK_STRING( ++ " Strength: integer, [0...20]. Default value is 0.Might be a CSV filename (upto 15 symbols); if a string is convertable to an integer, integer has a priority over filename\n")); ++ msdk_printf(MSDK_STRING( ++ " In fixed-strength mode, MCTF strength can be adjusted at framelevel;\n")); ++ msdk_printf(MSDK_STRING(" If no Strength is given, MCTF operates in auto mode.\n")); ++ #else ++ msdk_printf(MSDK_STRING(" -mctf MctfMode:BitsPerPixel:Strength:ME:Overlap:DB\n")); ++ msdk_printf(MSDK_STRING( ++ " every parameter may be missed; in this case default value is used.\n")); ++ msdk_printf(MSDK_STRING(" MctfMode: 0 - spatial filter\n")); ++ msdk_printf(MSDK_STRING(" MctfMode: 1- temporal filtering, 1 backward reference\n")); ++ msdk_printf( ++ MSDK_STRING(" MctfMode: 2- temporal filtering, 1 backward & 1 forward reference\n")); ++ msdk_printf(MSDK_STRING( ++ " MctfMode: 3- temporal filtering, 2 backward & 2 forward references\n")); ++ msdk_printf(MSDK_STRING(" MctfMode: other values: force default mode to be used\n")); ++ msdk_printf(MSDK_STRING( ++ " BitsPerPixel: float, valid range [0...12.0]; if exists, is used for automatic filter strength adaptation. Default is 0.0\n")); ++ msdk_printf(MSDK_STRING( ++ " Strength: integer, [0...20]. Default value is 0.Might be a CSV filename (upto 15 symbols); if a string is convertable to an integer, integer has a priority over filename\n")); ++ msdk_printf(MSDK_STRING( ++ " ME: Motion Estimation precision; 0 - integer ME (default); 1 - quater-pel ME\n")); ++ msdk_printf(MSDK_STRING( ++ " Overlap: 0 - do not apply overlap ME (default); 1 - to apply overlap ME\n")); ++ msdk_printf(MSDK_STRING( ++ " DB: 0 - do not apply deblock Filter (default); 1 - to apply Deblock Filter\n")); ++ #endif //ENABLE_MCTF_EXT ++#endif //ENABLE_MCTF ++ ++ msdk_printf(MSDK_STRING( ++ " -robust Recover from gpu hang errors as they come (by resetting components)\n")); ++ msdk_printf(MSDK_STRING(" -robust:soft Recover from gpu hang errors by inserting an IDR\n")); ++ ++ msdk_printf(MSDK_STRING(" -async Depth of asynchronous pipeline. default value 1\n")); ++ msdk_printf(MSDK_STRING( ++ " -join Join session with other session(s), by default sessions are not joined\n")); ++ msdk_printf(MSDK_STRING( ++ " -priority Use priority for join sessions. 0 - Low, 1 - Normal, 2 - High. Normal by default\n")); ++ msdk_printf(MSDK_STRING(" -threads num Number of session internal threads to create\n")); ++ msdk_printf( ++ MSDK_STRING(" -n Number of frames to transcode\n") MSDK_STRING( ++ " (session ends after this number of frames is reached). \n") ++ MSDK_STRING( ++ " In decoding sessions (-o::sink) this parameter limits number\n") ++ MSDK_STRING(" of frames acquired from decoder.\n") MSDK_STRING( ++ " In encoding sessions (-o::source) and transcoding sessions \n") ++ MSDK_STRING( ++ " this parameter limits number of frames sent to encoder.\n")); ++ ++ msdk_printf( ++ MSDK_STRING(" -MemType::video Force usage of external video allocator (default)\n")); ++ msdk_printf(MSDK_STRING(" -MemType::system Force usage of external system allocator\n")); ++ msdk_printf(MSDK_STRING(" -MemType::opaque Force usage of internal allocator\n")); ++ ++ msdk_printf(MSDK_STRING(" -MemModel::GeneralAlloc (default)\n")); ++ msdk_printf(MSDK_STRING(" Force usage of:\n")); ++ msdk_printf( ++ MSDK_STRING(" External allocator in the case of video/system memory type\n")); ++ msdk_printf( ++ MSDK_STRING(" Internal allocator in the case of opaque memory type\n")); ++ msdk_printf(MSDK_STRING( ++ " -MemModel::VisibleIntAlloc Force usage of internal allocation with manual surfaces control\n")); ++ msdk_printf(MSDK_STRING( ++ " -MemModel::HiddenIntAlloc Force usage of internal allocation without manual surfaces control\n")); ++ ++ msdk_printf(MSDK_STRING(" -dec::sys Set dec output to system memory\n")); ++ msdk_printf(MSDK_STRING(" -vpp::sys Set vpp output to system memory\n")); ++ msdk_printf(MSDK_STRING(" -vpp::vid Set vpp output to video memory\n")); ++ msdk_printf(MSDK_STRING(" -fps \n")); ++ msdk_printf(MSDK_STRING(" Transcoding frame rate limit\n")); ++ msdk_printf(MSDK_STRING(" -pe Set encoding plugin for this particular session.\n")); ++ msdk_printf(MSDK_STRING( ++ " This setting overrides plugin settings defined by SET clause.\n")); ++ msdk_printf(MSDK_STRING(" -pd Set decoding plugin for this particular session.\n")); ++ msdk_printf(MSDK_STRING( ++ " This setting overrides plugin settings defined by SET clause.\n")); ++ msdk_printf(MSDK_STRING( ++ " Supported values: hevcd_sw, hevcd_hw, hevce_sw, hevce_gacc, hevce_hw, vp8d_hw, vp8e_hw, vp9d_hw, vp9e_hw, camera_hw, capture_hw, h264_la_hw, ptir_hw, hevce_fei_hw\n")); ++ msdk_printf(MSDK_STRING(" Direct GUID number can be used as well\n")); ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING("Pipeline description (encoding options):\n")); ++ MOD_SMT_PRINT_HELP; ++ msdk_printf(MSDK_STRING(" -b \n")); ++ msdk_printf( ++ MSDK_STRING(" Encoded bit rate, valid for H.264, MPEG2 and MVC encoders\n")); ++ msdk_printf(MSDK_STRING( ++ " -bm Bitrate multiplier. Use it when required bitrate isn't fit into 16-bit\n")); ++ msdk_printf(MSDK_STRING( ++ " Affects following parameters: InitialDelayInKB, BufferSizeInKB, TargetKbps, MaxKbps\n")); ++ msdk_printf(MSDK_STRING(" -f \n")); ++ msdk_printf( ++ MSDK_STRING(" Video frame rate for the FRC and deinterlace options\n")); ++ msdk_printf(MSDK_STRING(" -fe \n")); ++ msdk_printf(MSDK_STRING( ++ " Video frame rate for the FRC and deinterlace options (deprecated, will be removed in next versions).\n")); ++ msdk_printf(MSDK_STRING(" -override_decoder_framerate \n")); ++ msdk_printf(MSDK_STRING( ++ " Forces decoder output framerate to be set to provided value (overwriting actual framerate from decoder)\n")); ++ msdk_printf(MSDK_STRING(" -override_encoder_framerate \n")); ++ msdk_printf(MSDK_STRING( ++ " Overwrites framerate of stream going into encoder input with provided value (this option does not enable FRC, it just ovewrites framerate value)\n")); ++ msdk_printf(MSDK_STRING(" -override_encoder_picstruct \n")); ++ msdk_printf(MSDK_STRING(" Overwrites encoder picstruct with specific value")); ++ msdk_printf(MSDK_STRING( ++ " -u Target usage. Valid for H.265, H.264, MPEG2 and MVC encoders. Expected values:\n")); ++ msdk_printf(MSDK_STRING( ++ " veryslow(quality), slower, slow, medium(balanced), fast, faster, veryfast(speed)\n")); ++ msdk_printf(MSDK_STRING( ++ " -q Quality parameter for JPEG encoder; in range [1,100], 100 is the best quality\n")); ++ msdk_printf(MSDK_STRING(" -l numSlices Number of slices for encoder; default value 0 \n")); ++ msdk_printf(MSDK_STRING(" -mss maxSliceSize \n")); ++ msdk_printf(MSDK_STRING( ++ " Maximum slice size in bytes. Supported only with -hw and h264 codec. This option is not compatible with -l option.\n")); ++ msdk_printf(MSDK_STRING(" -BitrateLimit:\n")); ++ msdk_printf(MSDK_STRING( ++ " Turn this flag ON to set bitrate limitations imposed by the SDK encoder. Off by default.\n")); ++ msdk_printf(MSDK_STRING( ++ " -la Use the look ahead bitrate control algorithm (LA BRC) for H.264 encoder. Supported only with -hw option on 4th Generation Intel Core processors. \n")); ++ msdk_printf(MSDK_STRING( ++ " -lad depth Depth parameter for the LA BRC, the number of frames to be analyzed before encoding. In range [0,100] (0 - default: auto-select by mediasdk library).\n")); ++ msdk_printf( ++ MSDK_STRING(" May be 1 in the case when -mss option is specified \n")); ++ msdk_printf(MSDK_STRING( ++ " -la_ext Use external LA plugin (compatible with h264 & hevc encoders)\n")); ++ msdk_printf(MSDK_STRING(" -vbr Variable bitrate control\n")); ++ msdk_printf(MSDK_STRING(" -cbr Constant bitrate control\n")); ++ msdk_printf(MSDK_STRING(" -vcm Video Conferencing Mode (VCM) bitrate control\n")); ++ msdk_printf(MSDK_STRING(" -hrd Maximum possible size of any compressed frames \n")); ++ msdk_printf(MSDK_STRING(" -wb \n")); ++ msdk_printf(MSDK_STRING(" Maximum bitrate for sliding window\n")); ++ msdk_printf(MSDK_STRING(" -ws Sliding window size in frames\n")); ++ msdk_printf(MSDK_STRING(" -gop_size Size of GOP structure in frames \n")); ++ msdk_printf(MSDK_STRING(" -dist Distance between I- or P- key frames \n")); ++ msdk_printf(MSDK_STRING(" -num_ref Number of reference frames\n")); ++ msdk_printf(MSDK_STRING(" -bref Arrange B frames in B pyramid reference structure\n")); ++ msdk_printf(MSDK_STRING( ++ " -nobref Do not use B-pyramid (by default the decision is made by library)\n")); ++ msdk_printf(MSDK_STRING(" -bpyr Enable B pyramid\n")); ++ msdk_printf( ++ MSDK_STRING(" -gpb: - Enable or disable Generalized P/B frames\n")); ++#if (MFX_VERSION >= 1026) ++ msdk_printf(MSDK_STRING(" -TransformSkip:- Enable or disable TransformSkip\n")); ++#endif ++ msdk_printf(MSDK_STRING(" -trows - Number of rows for tiled encoding\n")); ++ msdk_printf(MSDK_STRING(" -tcols - Number of columns for tiled encoding\n")); ++ msdk_printf(MSDK_STRING(" -CodecProfile - Specifies codec profile\n")); ++ msdk_printf(MSDK_STRING(" -CodecLevel - Specifies codec level\n")); ++ msdk_printf(MSDK_STRING(" -GopOptFlag:closed - Closed gop\n")); ++ msdk_printf(MSDK_STRING(" -GopOptFlag:strict - Strict gop\n")); ++ msdk_printf(MSDK_STRING(" -AdaptiveI: - Turn Adaptive I frames on/off\n")); ++ msdk_printf(MSDK_STRING(" -AdaptiveB: - Turn Adaptive B frames on/off\n")); ++ msdk_printf(MSDK_STRING( ++ " -InitialDelayInKB - The decoder starts decoding after the buffer reaches the initial size InitialDelayInKB, \n\ ++ which is equivalent to reaching an initial delay of InitialDelayInKB*8000/TargetKbps ms\n")); ++ msdk_printf(MSDK_STRING( ++ " -MaxKbps - For variable bitrate control, specifies the maximum bitrate at which \n\ ++ the encoded data enters the Video Buffering Verifier buffer\n")); ++ msdk_printf(MSDK_STRING(" -gpucopy:: Enable or disable GPU copy mode\n")); ++ msdk_printf(MSDK_STRING( ++ " -repartitioncheck:: Enable or disable RepartitionCheckEnable mode\n")); ++ msdk_printf(MSDK_STRING( ++ " -cqp Constant quantization parameter (CQP BRC) bitrate control method\n")); ++ msdk_printf(MSDK_STRING( ++ " (by default constant bitrate control method is used), should be used along with -qpi, -qpp, -qpb.\n")); ++#if (MFX_VERSION >= 1022) ++ msdk_printf(MSDK_STRING( ++ " -qpi Constant quantizer for I frames (if bitrace control method is CQP). In range [1,51]. 0 by default, i.e.no limitations on QP.\n")); ++ msdk_printf(MSDK_STRING( ++ " -qpp Constant quantizer for P frames (if bitrace control method is CQP). In range [1,51]. 0 by default, i.e.no limitations on QP.\n")); ++ msdk_printf(MSDK_STRING( ++ " -qpb Constant quantizer for B frames (if bitrace control method is CQP). In range [1,51]. 0 by default, i.e.no limitations on QP.\n")); ++#endif ++ msdk_printf(MSDK_STRING( ++ " -DisableQPOffset Disable QP adjustment for GOP pyramid-level frames\n")); ++ msdk_printf(MSDK_STRING( ++ " -lowpower: Turn this option ON to enable QuickSync Fixed Function (low-power HW) encoding mode\n")); ++#if (MFX_VERSION >= 1027) ++ msdk_printf(MSDK_STRING( ++ " [-TargetBitDepthLuma] - Encoding target bit depth for luma samples, by default same as source one.\n")); ++ msdk_printf(MSDK_STRING( ++ " [-TargetBitDepthChroma] - Encoding target bit depth for chroma samples, by default same as source one.\n")); ++#endif ++#if MFX_VERSION >= 1022 ++ msdk_printf(MSDK_STRING(" -roi_file \n")); ++ msdk_printf(MSDK_STRING( ++ " Set Regions of Interest for each frame from \n")); ++ msdk_printf(MSDK_STRING(" -roi_qpmap Use QP map to emulate ROI for CQP mode\n")); ++ msdk_printf(MSDK_STRING(" -extmbqp Use external MBQP map\n")); ++#endif //MFX_VERSION >= 1022 ++ msdk_printf(MSDK_STRING( ++ " -AvcTemporalLayers [array:Layer.Scale] Configures the temporal layers hierarchy\n")); ++ msdk_printf(MSDK_STRING( ++ " -BaseLayerPID Sets priority ID for the base layer\n")); ++ msdk_printf(MSDK_STRING( ++ " -SPSId Sets sequence parameter set ID\n")); ++ msdk_printf( ++ MSDK_STRING(" -PPSId Sets picture parameter set ID\n")); ++ msdk_printf(MSDK_STRING( ++ " -PicTimingSEI: Enables or disables picture timing SEI\n")); ++ msdk_printf(MSDK_STRING( ++ " -NalHrdConformance: Enables or disables picture HRD conformance\n")); ++ msdk_printf(MSDK_STRING( ++ " -VuiNalHrdParameters: Enables or disables NAL HRD parameters in VUI header\n")); ++ ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING("Pipeline description (vpp options):\n")); ++ msdk_printf(MSDK_STRING(" -deinterlace Forces VPP to deinterlace input stream\n")); ++ msdk_printf(MSDK_STRING( ++ " -deinterlace::ADI Forces VPP to deinterlace input stream using ADI algorithm\n")); ++ msdk_printf(MSDK_STRING( ++ " -deinterlace::ADI_SCD Forces VPP to deinterlace input stream using ADI_SCD algorithm\n")); ++ msdk_printf(MSDK_STRING( ++ " -deinterlace::ADI_NO_REF Forces VPP to deinterlace input stream using ADI no ref algorithm\n")); ++ msdk_printf(MSDK_STRING( ++ " -deinterlace::BOB Forces VPP to deinterlace input stream using BOB algorithm\n")); ++ msdk_printf(MSDK_STRING( ++ " -detail Enables detail (edge enhancement) filter with provided level(0..100)\n")); ++ msdk_printf(MSDK_STRING( ++ " -denoise Enables denoise filter with provided level (0..100)\n")); ++ msdk_printf( ++ MSDK_STRING(" -FRC::PT Enables FRC filter with Preserve Timestamp algorithm\n")); ++ msdk_printf( ++ MSDK_STRING(" -FRC::DT Enables FRC filter with Distributed Timestamp algorithm\n")); ++ msdk_printf( ++ MSDK_STRING(" -FRC::INTERP Enables FRC filter with Frame Interpolation algorithm\n")); ++ msdk_printf(MSDK_STRING(" -scaling_mode Specifies scaling mode (lowpower/quality)\n")); ++ msdk_printf(MSDK_STRING( ++ " -ec::nv12|rgb4|yuy2|nv16|p010|p210|y210|y410|p016|y216|y416 Forces encoder input to use provided chroma mode\n")); ++ msdk_printf(MSDK_STRING( ++ " -dc::nv12|rgb4|yuy2|p010|y210|y410|p016|y216 Forces decoder output to use provided chroma mode\n")); ++ msdk_printf(MSDK_STRING( ++ " NOTE: chroma transform VPP may be automatically enabled if -ec/-dc parameters are provided\n")); ++ msdk_printf(MSDK_STRING( ++ " -angle 180 Enables 180 degrees picture rotation user module before encoding\n")); ++ msdk_printf(MSDK_STRING( ++ " -opencl Uses implementation of rotation plugin (enabled with -angle option) through Intel(R) OpenCL\n")); ++ msdk_printf(MSDK_STRING( ++ " -w Destination picture width, invokes VPP resize or decoder fixed function resize engine (if -dec_postproc specified)\n")); ++ msdk_printf(MSDK_STRING( ++ " -h Destination picture height, invokes VPP resize or decoder fixed function resize engine (if -dec_postproc specified)\n")); ++ msdk_printf(MSDK_STRING(" -field_processing t2t|t2b|b2t|b2b|fr2fr - Field Copy feature\n")); ++ msdk_printf(MSDK_STRING( ++ " -WeightedPred::default|implicit Enambles weighted prediction usage\n")); ++ msdk_printf(MSDK_STRING( ++ " -WeightedBiPred::default|implicit Enambles weighted bi-prediction usage\n")); ++ msdk_printf(MSDK_STRING( ++ " -ir_type - Intra refresh type. 0 - no refresh, 1 - vertical refresh, 2 - horisontal refresh, 3 - slice refresh\n")); ++ msdk_printf(MSDK_STRING( ++ " -ir_cycle_size - Number of pictures within refresh cycle starting from 2\n")); ++ msdk_printf(MSDK_STRING( ++ " -ir_qp_delta - QP difference for inserted intra MBs. This is signed value in [-51, 51] range\n")); ++ msdk_printf(MSDK_STRING( ++ " -ir_cycle_dist - Distance between the beginnings of the intra-refresh cycles in frames\n")); ++ msdk_printf(MSDK_STRING( ++ " -LowDelayBRC - strictly obey average frame size set by MaxKbps\n")); ++ msdk_printf(MSDK_STRING( ++ " -amfs: - adaptive max frame size. If set on, P or B frame size can exceed MaxFrameSize when the scene change is detected.\ ++ It can benefit the video quality \n")); ++ msdk_printf(MSDK_STRING( ++ " -mfs - maximum frame size in bytes. Supported only with h264 and hevc codec for VBR mode.\n")); ++ ++#if (MFX_VERSION >= 1024) ++ msdk_printf(MSDK_STRING( ++ " -extbrc:: Enables external BRC for AVC and HEVC encoders\n")); ++#endif ++#if (MFX_VERSION >= 1026) ++ msdk_printf( ++ MSDK_STRING(" -ExtBrcAdaptiveLTR: Set AdaptiveLTR for implicit extbrc")); ++#endif ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp Enables composition from several decoding sessions. Result is written to the file\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_only Enables composition from several decoding sessions. Result is shown on screen\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_num_tiles Quantity of tiles for composition. if equal to 0 tiles processing ignored\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_dst_x X position of this stream in composed stream (should be used in decoder session)\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_dst_y Y position of this stream in composed stream (should be used in decoder session)\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_dst_h Height of this stream in composed stream (should be used in decoder session)\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_dst_w Width of this stream in composed stream (should be used in decoder session)\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_src_h Width of this stream in composed stream (should be used in decoder session)\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_src_w Width of this stream in composed stream (should be used in decoder session)\n")); ++#if MFX_VERSION >= 1023 ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_tile_id Tile_id for current channel of composition (should be used in decoder session)\n")); ++#endif ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_dump Dump of VPP Composition's output into file. Valid if with -vpp_comp* options\n")); ++ msdk_printf(MSDK_STRING( ++ " -vpp_comp_dump null_render Disabling rendering after VPP Composition. This is for performance measurements\n")); ++#if MFX_VERSION >= 1022 ++ msdk_printf(MSDK_STRING( ++ " -dec_postproc Resize after decoder using direct pipe (should be used in decoder session)\n")); ++ msdk_printf( ++ MSDK_STRING(" -single_texture_d3d11 single texture mode for d3d11 allocator \n")); ++#endif //MFX_VERSION >= 1022 ++ msdk_printf(MSDK_STRING( ++ " -preset Use particular preset for encoding parameters\n")); ++ msdk_printf(MSDK_STRING(" -pp Print preset parameters\n")); ++ ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING("ParFile format:\n")); ++ msdk_printf(MSDK_STRING( ++ " ParFile is extension of what can be achieved by setting pipeline in the command\n")); ++ msdk_printf(MSDK_STRING( ++ "line. For more information on ParFile format see readme-multi-transcode.pdf\n")); ++ msdk_printf(MSDK_STRING("\n")); ++ msdk_printf(MSDK_STRING("Examples:\n")); ++ msdk_printf(MSDK_STRING(" sample_multi_transcode -i::mpeg2 in.mpeg2 -o::h264 out.h264\n")); ++ msdk_printf( ++ MSDK_STRING(" sample_multi_transcode -i::mvc in.mvc -o::mvc out.mvc -w 320 -h 240\n")); ++} ++ ++void TranscodingSample::PrintInfo(mfxU32 session_number, sInputParams* pParams, mfxVersion* pVer) { ++ msdk_char buf[2048]; ++ MSDK_CHECK_POINTER_NO_RET(pVer); ++ ++ if ((MFX_IMPL_AUTO <= pParams->libType) && (MFX_IMPL_HARDWARE4 >= pParams->libType)) { ++ msdk_printf(MSDK_STRING("MFX %s Session %d API ver %d.%d parameters: \n"), ++ (MFX_IMPL_SOFTWARE == pParams->libType) ? MSDK_STRING("SOFTWARE") ++ : MSDK_STRING("HARDWARE"), ++ session_number, ++ pVer->Major, ++ pVer->Minor); ++ } ++ ++ if (0 == pParams->DecodeId) ++ msdk_printf(MSDK_STRING("Input video: From parent session\n")); ++ else ++ msdk_printf(MSDK_STRING("Input video: %s\n"), CodecIdToStr(pParams->DecodeId).c_str()); ++ ++ // means that source is parent session ++ if (0 == pParams->EncodeId) ++ msdk_printf(MSDK_STRING("Output video: To child session\n")); ++ else ++ msdk_printf(MSDK_STRING("Output video: %s\n"), CodecIdToStr(pParams->EncodeId).c_str()); ++ if (PrintDllInfo(buf, MSDK_ARRAY_LEN(buf), pParams)) ++ msdk_printf(MSDK_STRING("MFX dll: %s\n"), buf); ++ msdk_printf(MSDK_STRING("\n")); ++} ++ ++bool TranscodingSample::PrintDllInfo(msdk_char* buf, mfxU32 buf_size, sInputParams* pParams) { ++#if defined(_WIN32) || defined(_WIN64) ++ HANDLE hCurrent = GetCurrentProcess(); ++ HMODULE* pModules; ++ DWORD cbNeeded; ++ int nModules; ++ if (NULL == EnumProcessModules(hCurrent, NULL, 0, &cbNeeded)) ++ return false; ++ ++ nModules = cbNeeded / sizeof(HMODULE); ++ ++ pModules = new HMODULE[nModules]; ++ if (NULL == pModules) { ++ return false; ++ } ++ if (NULL == EnumProcessModules(hCurrent, pModules, cbNeeded, &cbNeeded)) { ++ delete[] pModules; ++ return false; ++ } ++ ++ for (int i = 0; i < nModules; i++) { ++ GetModuleFileName(pModules[i], buf, buf_size); ++ if (_tcsstr(buf, MSDK_STRING("libmfxhw")) && (MFX_IMPL_SOFTWARE != pParams->libType)) { ++ delete[] pModules; ++ return true; ++ } ++ else if (_tcsstr(buf, MSDK_STRING("libmfxsw")) && (MFX_IMPL_SOFTWARE == pParams->libType)) { ++ delete[] pModules; ++ return true; ++ } ++ } ++ delete[] pModules; ++ return false; ++#else ++ return false; ++#endif ++} ++ ++CmdProcessor::CmdProcessor() { ++ m_SessionParamId = 0; ++ m_SessionArray.clear(); ++ m_decoderPlugins.clear(); ++ m_encoderPlugins.clear(); ++ m_PerfFILE = NULL; ++ m_parName = NULL; ++ m_nTimeout = 0; ++ statisticsWindowSize = 0; ++ statisticsLogFile = NULL; ++ DumpLogFileName.clear(); ++ shouldUseGreedyFormula = false; ++ bRobustFlag = false; ++ bSoftRobustFlag = false; ++ ++} //CmdProcessor::CmdProcessor() ++ ++CmdProcessor::~CmdProcessor() { ++ m_SessionArray.clear(); ++ m_decoderPlugins.clear(); ++ m_encoderPlugins.clear(); ++ if (m_PerfFILE) ++ fclose(m_PerfFILE); ++ if (statisticsLogFile) ++ fclose(statisticsLogFile); ++ ++} //CmdProcessor::~CmdProcessor() ++ ++void CmdProcessor::PrintParFileName() { ++ if (m_parName && m_PerfFILE) { ++ msdk_fprintf(m_PerfFILE, MSDK_STRING("Input par file: %s\n\n"), m_parName); ++ } ++} ++ ++msdk_string CmdProcessor::GetLine(mfxU32 n) { ++ if (m_lines.size() > n) ++ return m_lines[n]; ++ return msdk_string(); ++} ++ ++mfxStatus CmdProcessor::ParseCmdLine(int argc, msdk_char* argv[]) { ++ FILE* parFile = NULL; ++ mfxStatus sts = MFX_ERR_UNSUPPORTED; ++ ++ if (1 == argc) { ++ PrintError(MSDK_STRING("Too few parameters"), NULL); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ --argc; ++ ++argv; ++ ++ while (argv[0]) { ++ if (0 == msdk_strcmp(argv[0], MSDK_STRING("-par"))) { ++ --argc; ++ ++argv; ++ if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: no argument given for '-par' option\n")); ++ } ++ m_parName = argv[0]; ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-timeout"))) { ++ --argc; ++ ++argv; ++ if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: no argument given for '-timeout' option\n")); ++ } ++ if (MFX_ERR_NONE != msdk_opt_read(argv[0], m_nTimeout)) { ++ msdk_printf(MSDK_STRING("error: -timeout \"%s\" is invalid"), argv[0]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-robust"))) { ++ bRobustFlag = true; ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-robust:soft"))) { ++ bSoftRobustFlag = true; ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-?"))) { ++ PrintHelp(); ++ return MFX_WRN_OUT_OF_RANGE; ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-greedy"))) { ++ shouldUseGreedyFormula = true; ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-p"))) { ++ if (m_PerfFILE) { ++ msdk_printf(MSDK_STRING("error: only one performance file is supported")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ --argc; ++ ++argv; ++ if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: no argument given for '-p' option\n")); ++ } ++ MSDK_FOPEN(m_PerfFILE, argv[0], MSDK_STRING("w")); ++ if (NULL == m_PerfFILE) { ++ msdk_printf(MSDK_STRING("error: performance file \"%s\" not found"), argv[0]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("--"))) { ++ // just skip separator "--" which delimits cmd options and pipeline settings ++ break; ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-stat"))) { ++ --argc; ++ ++argv; ++ if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: no argument given for 'stat' option\n")); ++ } ++ if (MFX_ERR_NONE != msdk_opt_read(argv[0], statisticsWindowSize)) { ++ msdk_printf(MSDK_STRING("error: stat \"%s\" is invalid"), argv[0]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-stat-log"))) { ++ if (statisticsLogFile) { ++ msdk_printf(MSDK_STRING("error: only one statistics file is supported")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ --argc; ++ ++argv; ++ if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: no argument given for 'stat-log' option\n")); ++ } ++ MSDK_FOPEN(statisticsLogFile, argv[0], MSDK_STRING("w")); ++ if (NULL == statisticsLogFile) { ++ msdk_printf(MSDK_STRING("error: statistics file \"%s\" not found"), argv[0]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[0], MSDK_STRING("-stat-per-frame"))) { ++ if (!DumpLogFileName.empty()) { ++ msdk_printf(MSDK_STRING("error: only one dump file is supported")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ --argc; ++ ++argv; ++ if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: no argument given for 'stat-dump' option\n")); ++ } ++ DumpLogFileName = argv[0]; ++ } ++ else { ++ break; ++ } ++ --argc; ++ ++argv; ++ } ++ ++ msdk_printf(MSDK_STRING("Multi Transcoding Sample Version %s\n\n"), ++ GetMSDKSampleVersion().c_str()); ++ ++ //Read pipeline from par file ++ if (m_parName && !argv[0]) { ++ MSDK_FOPEN(parFile, m_parName, MSDK_STRING("r")); ++ if (NULL == parFile) { ++ msdk_printf(MSDK_STRING("error: ParFile \"%s\" not found\n"), m_parName); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (NULL != m_parName) ++ msdk_printf(MSDK_STRING("Par file is: %s\n\n"), m_parName); ++ ++ sts = ParseParFile(parFile); ++ ++ if (MFX_ERR_NONE != sts) { ++ fclose(parFile); ++ return sts; ++ } ++ ++ fclose(parFile); ++ } ++ //Read pipeline from cmd line ++ else if (!argv[0]) { ++ msdk_printf(MSDK_STRING("error: pipeline description not found\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ else if (argv[0] && m_parName) { ++ msdk_printf(MSDK_STRING( ++ "error: simultaneously enabling parfile and description pipeline from command line forbidden\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ else { ++ sts = ParseParamsForOneSession(argc, argv); ++ if (MFX_ERR_NONE != sts) { ++ msdk_printf(MSDK_STRING("error: pipeline description is invalid\n")); ++ return sts; ++ } ++ } ++ ++ return sts; ++ ++} //mfxStatus CmdProcessor::ParseCmdLine(int argc, msdk_char *argv[]) ++ ++mfxStatus CmdProcessor::ParseParFile(FILE* parFile) { ++ mfxStatus sts = MFX_ERR_UNSUPPORTED; ++ if (!parFile) ++ return MFX_ERR_UNSUPPORTED; ++ ++ mfxU32 currPos = 0; ++ mfxU32 lineIndex = 0; ++ ++ // calculate file size ++ fseek(parFile, 0, SEEK_END); ++ mfxU32 fileSize = ftell(parFile) + 1; ++ fseek(parFile, 0, SEEK_SET); ++ ++ // allocate buffer for parsing ++ std::unique_ptr parBuf(new msdk_char[fileSize]); ++ msdk_char* pCur; ++ ++ while (currPos < fileSize) { ++ pCur = /*_fgetts*/ msdk_fgets(parBuf.get(), fileSize, parFile); ++ if (!pCur) ++ return MFX_ERR_NONE; ++ while (pCur[currPos] != '\n' && pCur[currPos] != 0) { ++ currPos++; ++ if (pCur + currPos >= parBuf.get() + fileSize) ++ return sts; ++ } ++ // zero string ++ if (!currPos) ++ continue; ++ ++ sts = TokenizeLine(pCur, currPos); ++ MSDK_CHECK_STATUS(sts, "TokenizeLine failed"); ++ ++ currPos = 0; ++ lineIndex++; ++ } ++ ++ return MFX_ERR_NONE; ++ ++} //mfxStatus CmdProcessor::ParseParFile(FILE *parFile) ++ ++// calculate length of string literal, including leading and trailing " ++// pTempLine = start of string (must begin with ") ++// length = remaining characters in pTempLine ++// returns length of string, or 0 if error ++mfxU32 CmdProcessor::GetStringLength(msdk_char* pTempLine, mfxU32 length) { ++ mfxU32 i; ++ ++ // error - no leading " found ++ if (pTempLine[0] != '\"') ++ return 0; ++ ++ for (i = 1; i < length; i++) { ++ if (pTempLine[i] == '\"') ++ break; ++ } ++ ++ // error - no closing " found ++ if (i == length) ++ return 0; ++ ++ return i + 1; ++} ++ ++mfxStatus CmdProcessor::TokenizeLine(msdk_char* pLine, mfxU32 length) { ++ mfxU32 i, strArgLen; ++ const mfxU8 maxArgNum = 255; ++ msdk_char* argv[maxArgNum + 1]; ++ mfxU32 argc = 0; ++ std::unique_ptr pMemLine(new msdk_char[length + 2]); ++ ++ msdk_char* pTempLine = pMemLine.get(); ++ pTempLine[0] = ' '; ++ pTempLine++; ++ ++ MSDK_MEMCPY_BUF(pTempLine, 0, length * sizeof(msdk_char), pLine, length * sizeof(msdk_char)); ++ ++ // parse into command streams ++ for (i = 0; i < length; i++) { ++ // check if separator ++ if (IS_SEPARATOR(pTempLine[-1]) && !IS_SEPARATOR(pTempLine[0])) { ++ argv[argc++] = pTempLine; ++ if (argc > maxArgNum) { ++ PrintError(MSDK_STRING("Too many parameters (reached maximum of %d)"), maxArgNum); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ ++ if (*pTempLine == '\"') { ++ strArgLen = GetStringLength(pTempLine, length - i); ++ if (!strArgLen) { ++ PrintError(MSDK_STRING("Error parsing string literal")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ // remove leading and trailing ", bump pointer ahead to next argument ++ pTempLine[0] = ' '; ++ pTempLine[strArgLen - 1] = ' '; ++ pTempLine += strArgLen; ++ i += strArgLen; ++ } ++ ++ if (*pTempLine == ' ' || *pTempLine == '\r' || *pTempLine == '\n') { ++ *pTempLine = 0; ++ } ++ pTempLine++; ++ } ++ ++ // EOL for last parameter ++ pTempLine[0] = 0; ++ ++ return ParseParamsForOneSession(argc, argv); ++} ++ ++#if MFX_VERSION >= 1022 ++bool CmdProcessor::isspace(char a) { ++ return (std::isspace(a) != 0); ++} ++ ++bool CmdProcessor::is_not_allowed_char(char a) { ++ return (std::isdigit(a) == 0) && (std::isspace(a) == 0) && (a != ';') && (a != '-'); ++} ++ ++bool CmdProcessor::ParseROIFile(const msdk_char* roi_file_name, ++ std::vector& m_ROIData) { ++ FILE* roi_file = NULL; ++ MSDK_FOPEN(roi_file, roi_file_name, MSDK_STRING("rb")); ++ ++ m_ROIData.clear(); ++ ++ if (roi_file) { ++ // read file to buffer ++ fseek(roi_file, 0, SEEK_END); ++ long file_size = ftell(roi_file); ++ rewind(roi_file); ++ std::vector buffer(file_size); ++ char* roi_data = &buffer[0]; ++ if (file_size < 0 || (size_t)file_size != fread(roi_data, 1, file_size, roi_file)) { ++ fclose(roi_file); ++ return false; ++ } ++ fclose(roi_file); ++ ++ // search for not allowed characters ++ char* not_allowed_char = std::find_if(roi_data, roi_data + file_size, is_not_allowed_char); ++ if (not_allowed_char != (roi_data + file_size)) { ++ return false; ++ } ++ ++ // get unformatted roi data ++ std::string unformatted_roi_data; ++ unformatted_roi_data.clear(); ++ std::remove_copy_if(roi_data, ++ roi_data + file_size, ++ std::inserter(unformatted_roi_data, unformatted_roi_data.end()), ++ isspace); ++ ++ // split data to items ++ std::stringstream unformatted_roi_data_ss(unformatted_roi_data); ++ std::vector items; ++ items.clear(); ++ std::string item; ++ while (std::getline(unformatted_roi_data_ss, item, ';')) { ++ items.push_back(item); ++ } ++ ++ // parse data and store roi data for each frame ++ unsigned int item_ind = 0; ++ while (1) { ++ if (item_ind >= items.size()) ++ break; ++ ++ mfxExtEncoderROI frame_roi; ++ std::memset(&frame_roi, 0, sizeof(frame_roi)); ++ frame_roi.Header.BufferId = MFX_EXTBUFF_ENCODER_ROI; ++ #if (MFX_VERSION >= 1022) ++ frame_roi.ROIMode = MFX_ROI_MODE_QP_DELTA; ++ #endif ++ ++ int roi_num = std::atoi(items[item_ind].c_str()); ++ if (roi_num < 0 || roi_num > (int)(sizeof(frame_roi.ROI) / sizeof(frame_roi.ROI[0]))) { ++ m_ROIData.clear(); ++ return false; ++ } ++ if ((item_ind + 5 * roi_num) >= items.size()) { ++ m_ROIData.clear(); ++ return false; ++ } ++ ++ for (int i = 0; i < roi_num; i++) { ++ // do not handle out of range integer errors ++ frame_roi.ROI[i].Left = std::atoi(items[item_ind + i * 5 + 1].c_str()); ++ frame_roi.ROI[i].Top = std::atoi(items[item_ind + i * 5 + 2].c_str()); ++ frame_roi.ROI[i].Right = std::atoi(items[item_ind + i * 5 + 3].c_str()); ++ frame_roi.ROI[i].Bottom = std::atoi(items[item_ind + i * 5 + 4].c_str()); ++ #if (MFX_VERSION >= 1022) ++ frame_roi.ROI[i].DeltaQP = (mfxI16)std::atoi(items[item_ind + i * 5 + 5].c_str()); ++ #endif ++ } ++ frame_roi.NumROI = (mfxU16)roi_num; ++ m_ROIData.push_back(frame_roi); ++ item_ind = item_ind + roi_num * 5 + 1; ++ } ++ } ++ else { ++ return false; ++ } ++ return true; ++} ++#endif //MFX_VERSION >= 1022 ++#ifdef ENABLE_MCTF ++ ++// returns a pointer to start of argument with a number argn; ++// if failes to find argn, returns NULL ++msdk_char* ParseArgn(msdk_char* pIn, mfxU32 argn, msdk_char separator) { ++ msdk_char* pstr = pIn; ++ if (!argn) ++ return pIn; ++ else { ++ for (mfxU32 n = 0; n != argn; ++n) { ++ while (separator != *pstr && msdk_char('\0') != *pstr) ++ ++pstr; ++ if (msdk_char('\0') == *pstr) ++ return NULL; ++ else ++ ++pstr; ++ } ++ return pstr; ++ } ++}; ++ ++template ++bool ArgConvert(msdk_char* pIn, ++ mfxU32 argn, ++ const msdk_char* pattern, ++ T* pArg, ++ const T& ArgDefault, ++ mfxU32& NumOfGoodConverts) { ++ bool bConvertIsOk = false; ++ msdk_char* pargs = ParseArgn(pIn, argn, msdk_char(':')); ++ if (pargs) { ++ if (!msdk_sscanf(pargs, pattern, pArg)) ++ *pArg = ArgDefault; ++ else { ++ ++NumOfGoodConverts; ++ bConvertIsOk = true; ++ } ++ }; ++ return bConvertIsOk; ++} ++ ++//template ++bool ArgConvert(msdk_char* pIn, ++ mfxU32 argn, ++ const msdk_char* pattern, ++ msdk_char* pArg, ++ mfxU32 MaxChars2Read, ++ mfxU32& NumOfGoodConverts) { ++ bool bConvertIsOk = false; ++ msdk_char* pargs = ParseArgn(pIn, argn, msdk_char(':')); ++ if (pargs) { ++ // lets calculate length of potential name: ++ msdk_char* temp(pargs); ++ while (*temp != msdk_char(':') && *temp != msdk_char('\0')) ++ ++temp; ++ std::iterator_traits::difference_type distance = std::distance(pargs, temp); ++ if (distance < std::iterator_traits::difference_type(MaxChars2Read)) { ++ if (msdk_sscanf(pargs, pattern, pArg, MaxChars2Read)) { ++ ++NumOfGoodConverts; ++ bConvertIsOk = true; ++ } ++ }; ++ }; ++ return bConvertIsOk; ++} ++ ++void ParseMCTFParams(msdk_char* strInput[], mfxU32 nArgNum, mfxU32& curArg, sInputParams* pParams) { ++ mfxU32& i = curArg; ++ if (0 == msdk_strcmp(strInput[i], MSDK_STRING("-mctf"))) { ++ pParams->mctfParam.mode = VPP_FILTER_ENABLED_DEFAULT; ++ pParams->mctfParam.params.FilterStrength = 0; ++ pParams->mctfParam.rtParams.Reset(); ++ bool bFSByValue = true; ++ #if defined ENABLE_MCTF_EXT ++ pParams->mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_2REF; // default ++ pParams->mctfParam.params.BitsPerPixelx100k = 0; ++ pParams->mctfParam.params.Deblocking = MFX_CODINGOPTION_OFF; ++ pParams->mctfParam.params.Overlap = MFX_CODINGOPTION_OFF; ++ pParams->mctfParam.params.MVPrecision = MFX_MVPRECISION_INTEGER; ++ #endif ++ ++ if (i + 1 < nArgNum) { ++ mfxU16 _strength(0); ++ mfxU32 strength_idx = 0; ++ mfxU32 ParsedArgsNumber = 0; ++ const mfxU32 max_name_len = 15; ++ const mfxU32 max_elems_in_file = 10000; ++ msdk_stringstream file_pattern; ++ file_pattern << MSDK_STRING("%") << max_name_len << MSDK_STRING("ls:%*c") << std::ends; ++ msdk_char _tmp_str[max_name_len + 1]; ++ memset(_tmp_str, 0, sizeof(_tmp_str)); ++ #if defined ENABLE_MCTF_EXT ++ strength_idx = 2; ++ #endif ++ //the order of arguments is: ++ // MctfMode:BitsPerPixel:Strength:ME:Overlap:DB ++ // try to read fs defined as a value: ++ bool res = ArgConvert(strInput[i + 1], ++ strength_idx, ++ MSDK_STRING("%hd:%*c"), ++ &_strength, ++ _strength, ++ ParsedArgsNumber); ++ if (!res) { ++ bFSByValue = false; ++ // if it was not possible, try to get a file-name (upto 15 chars): ++ res = ArgConvert(strInput[i + 1], ++ strength_idx, ++ file_pattern.str().c_str(), ++ &(_tmp_str[0]), ++ max_name_len, ++ ParsedArgsNumber); ++ if (res) { ++ msdk_fstream fs_file(_tmp_str, std::ios_base::in); ++ if (!fs_file.is_open()) { ++ msdk_printf(MSDK_STRING( ++ "MCTF Filter-strength file is not exist; decay to default FS value;.\n")); ++ bFSByValue = true; ++ } ++ else { ++ mfxU32 nOfRTParams(0); ++ for (msdk_string line; std::getline(fs_file, line, msdk_char(',')) && ++ nOfRTParams < max_elems_in_file; ++ ++nOfRTParams) { ++ // currently, there is just 1 param in the file; ++ sMctfRunTimeParam tmp; ++ if (msdk_sscanf(line.c_str(), ++ MSDK_STRING("%hu:%*c"), ++ &(tmp.FilterStrength))) ++ pParams->mctfParam.rtParams.RunTimeParams.push_back(tmp); ++ else { ++ msdk_printf(MSDK_STRING( ++ "there was an error met during parsing FS file;.only a few values were parsed.\n")); ++ break; ++ } ++ } ++ } ++ } ++ else ++ bFSByValue = true; ++ } ++ #if defined ENABLE_MCTF_EXT ++ mfxU16 _refnum(2); ++ mfxF64 _bitsperpixel(0.0); ++ mfxU16 _me_precision(0); ++ mfxU16 _overlap(0); ++ mfxU16 _deblock(0); ++ ++ ArgConvert(strInput[i + 1], ++ 0, ++ MSDK_STRING("%hd:%*c"), ++ &_refnum, ++ _refnum, ++ ParsedArgsNumber); ++ ArgConvert(strInput[i + 1], ++ 1, ++ MSDK_STRING("%lf:%*c"), ++ &_bitsperpixel, ++ _bitsperpixel, ++ ParsedArgsNumber); ++ ArgConvert(strInput[i + 1], ++ 3, ++ MSDK_STRING("%hd:%*c"), ++ &_me_precision, ++ _me_precision, ++ ParsedArgsNumber); ++ ArgConvert(strInput[i + 1], ++ 4, ++ MSDK_STRING("%hd:%*c"), ++ &_overlap, ++ _overlap, ++ ParsedArgsNumber); ++ ArgConvert(strInput[i + 1], ++ 5, ++ MSDK_STRING("%hd:%*c"), ++ &_deblock, ++ _deblock, ++ ParsedArgsNumber); ++ #endif ++ if (0 == ParsedArgsNumber) { ++ pParams->mctfParam.mode = VPP_FILTER_ENABLED_DEFAULT; ++ msdk_printf(MSDK_STRING("MCTF works in default mode; no parameters are passed.\n")); ++ } ++ else { ++ pParams->mctfParam.mode = VPP_FILTER_ENABLED_CONFIGURED; ++ pParams->mctfParam.rtParams.Restart(); ++ if (bFSByValue) { ++ pParams->mctfParam.params.FilterStrength = _strength; ++ } ++ else { ++ // take very first FS value from the file and use it as a value for FilterStrength ++ if (pParams->mctfParam.rtParams.GetCurParam()) { ++ pParams->mctfParam.params.FilterStrength = ++ pParams->mctfParam.rtParams.GetCurParam()->FilterStrength; ++ } ++ } ++ #if defined ENABLE_MCTF_EXT ++ pParams->mctfParam.params.BitsPerPixelx100k = ++ mfxU32(_bitsperpixel * MCTF_BITRATE_MULTIPLIER); ++ switch (_refnum) { ++ case 0: ++ pParams->mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_SPATIAL; ++ break; ++ case 1: ++ pParams->mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_1REF; ++ break; ++ case 2: ++ pParams->mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_2REF; ++ break; ++ case 3: ++ pParams->mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_4REF; ++ break; ++ default: ++ pParams->mctfParam.params.TemporalMode = MFX_MCTF_TEMPORAL_MODE_UNKNOWN; ++ }; ++ switch (_deblock) { ++ case 0: ++ pParams->mctfParam.params.Deblocking = MFX_CODINGOPTION_OFF; ++ break; ++ case 1: ++ pParams->mctfParam.params.Deblocking = MFX_CODINGOPTION_ON; ++ break; ++ default: ++ pParams->mctfParam.params.Deblocking = MFX_CODINGOPTION_UNKNOWN; ++ }; ++ switch (_overlap) { ++ case 0: ++ pParams->mctfParam.params.Overlap = MFX_CODINGOPTION_OFF; ++ break; ++ case 1: ++ pParams->mctfParam.params.Overlap = MFX_CODINGOPTION_ON; ++ break; ++ default: ++ pParams->mctfParam.params.Overlap = MFX_CODINGOPTION_UNKNOWN; ++ }; ++ switch (_me_precision) { ++ case 0: ++ pParams->mctfParam.params.MVPrecision = MFX_MVPRECISION_INTEGER; ++ break; ++ case 1: ++ pParams->mctfParam.params.MVPrecision = MFX_MVPRECISION_QUARTERPEL; ++ break; ++ default: ++ pParams->mctfParam.params.MVPrecision = MFX_MVPRECISION_UNKNOWN; ++ }; ++ #endif ++ } ++ if (ParsedArgsNumber) ++ i++; ++ } ++ else { ++ msdk_printf(MSDK_STRING("MCTF works in default mode; no parameters are passed.\n")); ++ } ++ } ++} ++#endif ++ ++// return values: ++// 0 if argv[i] is processed successfully (MFX_ERR_NONE) ++// < 1 if argv[i] is processed and generates an error OR argv[i] is not processed (no match) ++mfxStatus ParseAdditionalParams(msdk_char* argv[], ++ mfxU32 argc, ++ mfxU32& i, ++ TranscodingSample::sInputParams& InputParams) { ++ if (0 == msdk_strcmp(argv[i], MSDK_STRING("-AvcTemporalLayers"))) { ++ InputParams.nAvcTemp = 1; ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ mfxU16 arr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; ++ int j, k; ++ k = msdk_sscanf(argv[i + 1], ++ MSDK_STRING("%hu %hu %hu %hu %hu %hu %hu %hu"), ++ &arr[0], ++ &arr[1], ++ &arr[2], ++ &arr[3], ++ &arr[4], ++ &arr[5], ++ &arr[6], ++ &arr[7]); ++ if (k != 8) { ++ PrintError(argv[0], MSDK_STRING("Invalid number of layers for AvcTemporalLayers")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ for (j = 0; j < 8; j++) { ++ InputParams.nAvcTemporalLayers[j] = arr[j]; ++ } ++ i += 1; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-BaseLayerPID"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nBaseLayerPID)) { ++ PrintError(argv[0], MSDK_STRING("BaseLayerPID is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-SPSId"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nSPSId)) { ++ PrintError(argv[0], MSDK_STRING("SPSId is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-PPSId"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nPPSId)) { ++ PrintError(argv[0], MSDK_STRING("PPSId is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-lowpower:on"))) { ++ InputParams.enableQSVFF = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-lowpower:off"))) { ++ InputParams.enableQSVFF = false; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-PicTimingSEI:on"))) { ++ InputParams.nPicTimingSEI = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-PicTimingSEI:off"))) { ++ InputParams.nPicTimingSEI = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-NalHrdConformance:on"))) { ++ InputParams.nNalHrdConformance = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-NalHrdConformance:off"))) { ++ InputParams.nNalHrdConformance = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-VuiNalHrdParameters:on"))) { ++ InputParams.nVuiNalHrdParameters = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-VuiNalHrdParameters:off"))) { ++ InputParams.nVuiNalHrdParameters = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-BitrateLimit:on"))) { ++ InputParams.BitrateLimit = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-BitrateLimit:off"))) { ++ InputParams.BitrateLimit = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-AdaptiveI:on"))) { ++ InputParams.AdaptiveI = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-AdaptiveI:off"))) { ++ InputParams.AdaptiveI = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-AdaptiveB:on"))) { ++ InputParams.AdaptiveB = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-AdaptiveB:off"))) { ++ InputParams.AdaptiveB = MFX_CODINGOPTION_OFF; ++ } ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-iGfx"))) { ++ InputParams.bPrefferiGfx = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-dGfx"))) { ++ InputParams.bPrefferdGfx = true; ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-dec::sys"))) { ++ InputParams.DecOutPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; ++ } ++#ifdef ENABLE_MCTF ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-mctf"))) { ++ ParseMCTFParams(argv, argc, i, &InputParams); ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ext_allocator")) || ++ 0 == msdk_strcmp(argv[i], MSDK_STRING("-MemType::video"))) { ++ InputParams.bForceSysMem = false; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-sys")) || ++ 0 == msdk_strcmp(argv[i], MSDK_STRING("-MemType::system"))) { ++ InputParams.bForceSysMem = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-opaq")) || ++ 0 == msdk_strcmp(argv[i], MSDK_STRING("-MemType::opaque"))) { ++ msdk_printf(MSDK_STRING( ++ "WARNING: -opaq option is ignored, opaque memory support is disabled in opeVPL.\n")); ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-memory"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nMemoryModel)) { ++ PrintError(MSDK_STRING("-memory %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.nMemoryModel < 1 || InputParams.nMemoryModel > 3) { ++ PrintError(MSDK_STRING(" \"%s\" memory type is invalid. Default (1) will be used."), ++ argv[i]); ++ InputParams.nMemoryModel = GENERAL_ALLOC; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-MemModel::GeneralAlloc"))) { ++ InputParams.nMemoryModel = GENERAL_ALLOC; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-MemModel::VisibleIntAlloc"))) { ++ InputParams.nMemoryModel = VISIBLE_INT_ALLOC; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-MemModel::HiddenIntAlloc"))) { ++ InputParams.nMemoryModel = HIDDEN_INT_ALLOC; ++ } ++#if (MFX_VERSION >= 1027) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-TargetBitDepthLuma"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.TargetBitDepthLuma)) { ++ PrintError(MSDK_STRING("TargetBitDepthLuma param is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-TargetBitDepthChroma"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.TargetBitDepthChroma)) { ++ PrintError(MSDK_STRING("TargetBitDepthChroma param is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++#endif ++ else { ++ // no matching argument was found ++ return MFX_ERR_NOT_FOUND; ++ } ++ ++ return MFX_ERR_NONE; ++} ++ ++mfxStatus ParseVPPCmdLine(msdk_char* argv[], ++ mfxU32 argc, ++ mfxU32& index, ++ TranscodingSample::sInputParams* params, ++ mfxU32& skipped) { ++ if (0 == msdk_strcmp(argv[index], MSDK_STRING("-denoise"))) { ++ VAL_CHECK(index + 1 == argc, index, argv[index]); ++ index++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[index], params->DenoiseLevel) || ++ !(params->DenoiseLevel >= 0 && params->DenoiseLevel <= 100)) { ++ PrintError(NULL, MSDK_STRING("-denoise \"%s\" is invalid"), argv[index]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ skipped += 2; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-detail"))) { ++ VAL_CHECK(index + 1 == argc, index, argv[index]); ++ index++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[index], params->DetailLevel) || ++ !(params->DetailLevel >= 0 && params->DetailLevel <= 100)) { ++ PrintError(NULL, MSDK_STRING("-detail \"%s\" is invalid"), argv[index]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ skipped += 2; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-FRC::PT"))) { ++ params->FRCAlgorithm = MFX_FRCALGM_PRESERVE_TIMESTAMP; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-FRC::DT"))) { ++ params->FRCAlgorithm = MFX_FRCALGM_DISTRIBUTED_TIMESTAMP; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-FRC::INTERP"))) { ++ params->FRCAlgorithm = MFX_FRCALGM_FRAME_INTERPOLATION; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-deinterlace"))) { ++ params->bEnableDeinterlacing = true; ++ params->DeinterlacingMode = 0; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-deinterlace::ADI"))) { ++ params->bEnableDeinterlacing = true; ++ params->DeinterlacingMode = MFX_DEINTERLACING_ADVANCED; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-deinterlace::ADI_SCD"))) { ++ params->bEnableDeinterlacing = true; ++ params->DeinterlacingMode = MFX_DEINTERLACING_ADVANCED_SCD; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-deinterlace::BOB"))) { ++ params->bEnableDeinterlacing = true; ++ params->DeinterlacingMode = MFX_DEINTERLACING_BOB; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-deinterlace::ADI_NO_REF"))) { ++ params->bEnableDeinterlacing = true; ++ params->DeinterlacingMode = MFX_DEINTERLACING_ADVANCED_NOREF; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-scaling_mode"))) { ++ VAL_CHECK(index + 1 == argc, index, argv[index]); ++ index++; ++ if (0 == msdk_strcmp(argv[index], MSDK_STRING("lowpower"))) ++ params->ScalingMode = MFX_SCALING_MODE_LOWPOWER; ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("quality"))) ++ params->ScalingMode = MFX_SCALING_MODE_QUALITY; ++ else { ++ PrintError(NULL, MSDK_STRING("-scaling_mode \"%s\" is invalid"), argv[index]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::rgb4"))) { ++ params->EncoderFourCC = MFX_FOURCC_RGB4; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::yuy2"))) { ++ params->EncoderFourCC = MFX_FOURCC_YUY2; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::nv12"))) { ++ params->EncoderFourCC = MFX_FOURCC_NV12; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::nv16"))) { ++ params->EncoderFourCC = MFX_FOURCC_NV16; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::p010"))) { ++ params->EncoderFourCC = MFX_FOURCC_P010; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::p210"))) { ++ params->EncoderFourCC = MFX_FOURCC_P210; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::p010"))) { ++ params->DecoderFourCC = MFX_FOURCC_P010; ++ return MFX_ERR_NONE; ++ } ++#if (MFX_VERSION >= 1031) ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::p016"))) { ++ params->DecoderFourCC = MFX_FOURCC_P016; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::y216"))) { ++ params->DecoderFourCC = MFX_FOURCC_Y216; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::y416"))) { ++ params->DecoderFourCC = MFX_FOURCC_Y216; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::p016"))) { ++ params->EncoderFourCC = MFX_FOURCC_P016; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::y216"))) { ++ params->EncoderFourCC = MFX_FOURCC_Y216; ++ return MFX_ERR_NONE; ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::rgb4"))) { ++ params->DecoderFourCC = MFX_FOURCC_RGB4; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::yuy2"))) { ++ params->DecoderFourCC = MFX_FOURCC_YUY2; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::nv12"))) { ++ params->DecoderFourCC = MFX_FOURCC_NV12; ++ return MFX_ERR_NONE; ++ } ++#if (MFX_VERSION >= 1027) ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::y210"))) { ++ params->DecoderFourCC = MFX_FOURCC_Y210; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-dc::y410"))) { ++ params->DecoderFourCC = MFX_FOURCC_Y410; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::y210"))) { ++ params->EncoderFourCC = MFX_FOURCC_Y210; ++ return MFX_ERR_NONE; ++ } ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-ec::y410"))) { ++ params->EncoderFourCC = MFX_FOURCC_Y410; ++ return MFX_ERR_NONE; ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("-field_processing"))) { ++ VAL_CHECK(index + 1 == argc, index, argv[index]); ++ index++; ++ if (0 == msdk_strcmp(argv[index], MSDK_STRING("t2t"))) ++ params->fieldProcessingMode = FC_T2T; ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("t2b"))) ++ params->fieldProcessingMode = FC_T2B; ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("b2t"))) ++ params->fieldProcessingMode = FC_B2T; ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("b2b"))) ++ params->fieldProcessingMode = FC_B2B; ++ else if (0 == msdk_strcmp(argv[index], MSDK_STRING("fr2fr"))) ++ params->fieldProcessingMode = FC_FR2FR; ++ else { ++ PrintError(NULL, MSDK_STRING("-field_processing \"%s\" is invalid"), argv[index]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ return MFX_ERR_NONE; ++ } ++ ++ return MFX_ERR_MORE_DATA; ++} ++ ++mfxStatus CmdProcessor::ParseParamsForOneSession(mfxU32 argc, msdk_char* argv[]) { ++ mfxStatus sts = MFX_ERR_NONE; ++ mfxStatus stsExtBuf = MFX_ERR_NONE; ++ mfxStatus stsAddlParams = MFX_ERR_NONE; ++ mfxU32 skipped = 0; ++ ++ // save original cmd line for debug purpose ++ msdk_stringstream cmd; ++ for (mfxU32 i = 0; i < argc; i++) ++ cmd << argv[i] << MSDK_STRING(" "); ++ m_lines.push_back(cmd.str()); ++ ++ TranscodingSample::sInputParams InputParams; ++ if (m_nTimeout) ++ InputParams.nTimeout = m_nTimeout; ++ if (bRobustFlag) ++ InputParams.bRobustFlag = true; ++ if (bSoftRobustFlag) ++ InputParams.bSoftRobustFlag = true; ++ ++ InputParams.shouldUseGreedyFormula = shouldUseGreedyFormula; ++ ++ InputParams.statisticsWindowSize = statisticsWindowSize; ++ InputParams.statisticsLogFile = statisticsLogFile; ++ ++ //bind to a dump-log-file name ++ InputParams.DumpLogFileName = DumpLogFileName; ++ ++ if (0 == msdk_strcmp(argv[0], MSDK_STRING("set"))) { ++ if (argc != 3) { ++ msdk_printf(MSDK_STRING("error: number of arguments for 'set' options is wrong")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ sts = ParseOption__set(argv[1], argv[2]); ++ return sts; ++ } ++ // default implementation ++ InputParams.libType = MFX_IMPL_HARDWARE_ANY; ++#if defined(_WIN32) || defined(_WIN64) ++ InputParams.libType = MFX_IMPL_HARDWARE_ANY | MFX_IMPL_VIA_D3D11; ++#endif ++ InputParams.eModeExt = Native; ++ ++ for (mfxU32 i = 0; i < argc; i++) { ++ // process multi-character options ++ if ((0 == msdk_strncmp(MSDK_STRING("-i::"), argv[i], msdk_strlen(MSDK_STRING("-i::")))) && ++ (0 != msdk_strncmp(argv[i] + 4, ++ MSDK_STRING("source"), ++ msdk_strlen(MSDK_STRING("source"))))) { ++ sts = StrFormatToCodecFormatFourCC(argv[i] + 4, InputParams.DecodeId); ++ if (sts != MFX_ERR_NONE) { ++ return MFX_ERR_UNSUPPORTED; ++ } ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ SIZE_CHECK((msdk_strlen(argv[i]) + 1) > MSDK_ARRAY_LEN(InputParams.strSrcFile)); ++ msdk_opt_read(argv[i], InputParams.strSrcFile); ++ if (InputParams.eMode == Source) { ++ switch (InputParams.DecodeId) { ++ case MFX_CODEC_MPEG2: ++ case MFX_CODEC_HEVC: ++ case MFX_CODEC_AVC: ++ case MFX_CODEC_VC1: ++ case MFX_CODEC_VP9: ++ case MFX_CODEC_AV1: ++ case CODEC_MVC: ++ case MFX_CODEC_JPEG: ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ if (InputParams.DecodeId == CODEC_MVC) { ++ InputParams.DecodeId = MFX_CODEC_AVC; ++ InputParams.bIsMVC = true; ++ } ++ } ++ else if ((0 == ++ msdk_strncmp(MSDK_STRING("-o::"), argv[i], msdk_strlen(MSDK_STRING("-o::")))) && ++ (0 != msdk_strncmp(argv[i] + 4, ++ MSDK_STRING("sink"), ++ msdk_strlen(MSDK_STRING("sink"))))) { ++ sts = StrFormatToCodecFormatFourCC(argv[i] + 4, InputParams.EncodeId); ++ ++ if (sts != MFX_ERR_NONE) { ++ return MFX_ERR_UNSUPPORTED; ++ } ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ SIZE_CHECK((msdk_strlen(argv[i]) + 1) > MSDK_ARRAY_LEN(InputParams.strDstFile)); ++ msdk_opt_read(argv[i], InputParams.strDstFile); ++ if (InputParams.eMode == Sink || InputParams.bIsMVC) { ++ switch (InputParams.EncodeId) { ++ case MFX_CODEC_MPEG2: ++ case MFX_CODEC_HEVC: ++ case MFX_CODEC_AVC: ++ case MFX_CODEC_JPEG: ++ case MFX_CODEC_DUMP: ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ if (InputParams.EncodeId == CODEC_MVC) { ++ if (InputParams.eMode == Sink) ++ return MFX_ERR_UNSUPPORTED; ++ ++ InputParams.EncodeId = MFX_CODEC_AVC; ++ InputParams.bIsMVC = true; ++ } ++ } ++#if MFX_VERSION >= 1022 ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-roi_file"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ ++ msdk_char strRoiFile[MSDK_MAX_FILENAME_LEN]; ++ SIZE_CHECK((msdk_strlen(argv[i]) + 1) > MSDK_ARRAY_LEN(strRoiFile)); ++ msdk_opt_read(argv[i], strRoiFile); ++ ++ if (!ParseROIFile(strRoiFile, InputParams.m_ROIData)) { ++ PrintError(MSDK_STRING("Incorrect ROI file: \"%s\" "), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-p"))) { ++ if (m_PerfFILE) { ++ msdk_printf(MSDK_STRING("error: only one performance file is supported")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ --argc; ++ ++argv; ++ if (!argv[i]) { ++ msdk_printf(MSDK_STRING("error: no argument given for '-p' option\n")); ++ } ++ MSDK_FOPEN(m_PerfFILE, argv[i], MSDK_STRING("w")); ++ if (NULL == m_PerfFILE) { ++ msdk_printf(MSDK_STRING("error: performance file \"%s\" not found"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-roi_qpmap"))) { ++ InputParams.bROIasQPMAP = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-extmbqp"))) { ++ InputParams.bExtMBQP = true; ++ } ++#endif //MFX_VERSION >= 1022 ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-sw"))) { ++ InputParams.libType = MFX_IMPL_SOFTWARE; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-hw"))) { ++#if defined(_WIN32) || defined(_WIN64) ++ InputParams.libType = MFX_IMPL_HARDWARE_ANY | MFX_IMPL_VIA_D3D11; ++#elif defined(LIBVA_SUPPORT) ++ InputParams.libType = MFX_IMPL_HARDWARE_ANY; ++#endif ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-hw_d3d11"))) { ++ InputParams.libType = MFX_IMPL_HARDWARE_ANY | MFX_IMPL_VIA_D3D11; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-hw_d3d9"))) { ++ InputParams.libType = MFX_IMPL_HARDWARE_ANY | MFX_IMPL_VIA_D3D9; ++ } ++#if (defined(LINUX32) || defined(LINUX64)) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-device"))) { ++ if (!InputParams.strDevicePath.empty()) { ++ msdk_printf(MSDK_STRING("error: you can specify only one device\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ InputParams.strDevicePath = argv[++i]; ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-perf_opt"))) { ++ InputParams.bIsPerf = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-robust"))) { ++ InputParams.bRobustFlag = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-robust:soft"))) { ++ InputParams.bSoftRobustFlag = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-threads"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nThreadsNum)) { ++ PrintError(MSDK_STRING("Threads number is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-f"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ // Temporary check for giving priority to -fe option ++ if (!InputParams.dVPPOutFramerate) { ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.dVPPOutFramerate)) { ++ PrintError(MSDK_STRING("FrameRate \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-fe"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.dVPPOutFramerate)) { ++ PrintError(MSDK_STRING("FrameRate \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-fps"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nFPS)) { ++ PrintError(MSDK_STRING("FPS limit \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-b"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nBitRate)) { ++ PrintError(MSDK_STRING("BitRate \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-bm"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nBitRateMultiplier)) { ++ PrintError(MSDK_STRING("Bitrate multiplier \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-wb"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.WinBRCMaxAvgKbps)) { ++ PrintError(MSDK_STRING("Maximum bitrate for sliding window \"%s\" is invalid"), ++ argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ws"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.WinBRCSize)) { ++ PrintError(MSDK_STRING("Sliding window size \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-hrd"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.BufferSizeInKB)) { ++ PrintError(MSDK_STRING("Frame buffer size \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-dist"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.GopRefDist)) { ++ PrintError(MSDK_STRING("GOP reference distance \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-gop_size"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.GopPicSize)) { ++ PrintError(MSDK_STRING("GOP size \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-num_ref"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.NumRefFrame)) { ++ PrintError(MSDK_STRING("Number of reference frames \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-trows"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nEncTileRows)) { ++ PrintError(MSDK_STRING("Encoding tile row count \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-tcols"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nEncTileCols)) { ++ PrintError(MSDK_STRING("Encoding tile column count \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-CodecLevel"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.CodecLevel)) { ++ PrintError(MSDK_STRING("CodecLevel \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-CodecProfile"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.CodecProfile)) { ++ PrintError(MSDK_STRING("CodecProfile \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-MaxKbps"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.MaxKbps)) { ++ PrintError(MSDK_STRING("MaxKbps \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-InitialDelayInKB"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.InitialDelayInKB)) { ++ PrintError(MSDK_STRING("InitialDelayInKB \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-GopOptFlag:closed"))) { ++ InputParams.GopOptFlag = MFX_GOP_CLOSED; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-GopOptFlag:strict"))) { ++ InputParams.GopOptFlag = MFX_GOP_STRICT; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-bref"))) { ++ InputParams.nBRefType = MFX_B_REF_PYRAMID; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-nobref"))) { ++ InputParams.nBRefType = MFX_B_REF_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-gpb:on"))) { ++ InputParams.GPB = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-gpb:off"))) { ++ InputParams.GPB = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-TransformSkip:on"))) { ++ InputParams.nTransformSkip = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-TransformSkip:off"))) { ++ InputParams.nTransformSkip = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-u"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ InputParams.nTargetUsage = StrToTargetUsage(argv[i]); ++ if (!InputParams.nTargetUsage) { ++ PrintError(MSDK_STRING(" \"%s\" target usage is invalid. Balanced will be used."), ++ argv[i]); ++ InputParams.nTargetUsage = MFX_TARGETUSAGE_BALANCED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-WeightedPred::default"))) { ++ InputParams.WeightedPred = MFX_WEIGHTED_PRED_DEFAULT; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-WeightedPred::implicit"))) { ++ InputParams.WeightedPred = MFX_WEIGHTED_PRED_IMPLICIT; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-WeightedBiPred::default"))) { ++ InputParams.WeightedBiPred = MFX_WEIGHTED_PRED_DEFAULT; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-WeightedBiPred::implicit"))) { ++ InputParams.WeightedBiPred = MFX_WEIGHTED_PRED_IMPLICIT; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-q"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nQuality)) { ++ PrintError(MSDK_STRING(" \"%s\" quality is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-w"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nDstWidth)) { ++ PrintError(MSDK_STRING("width \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-h"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nDstHeight)) { ++ PrintError(MSDK_STRING("height \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-l"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nSlices)) { ++ PrintError(MSDK_STRING("numSlices \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-mss"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nMaxSliceSize)) { ++ PrintError(MSDK_STRING("maxSliceSize \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-async"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nAsyncDepth)) { ++ PrintError(MSDK_STRING("async \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-join"))) { ++ InputParams.bIsJoin = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-priority"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.priority)) { ++ PrintError(MSDK_STRING("priority \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-i::source"))) { ++ if (InputParams.eMode != Native) { ++ PrintError(NULL, "-i::source cannot be used here"); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ InputParams.eMode = Source; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-o::sink"))) { ++ if (InputParams.eMode != Native) { ++ PrintError(NULL, "-o::sink cannot be used here"); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ InputParams.eMode = Sink; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ /* NB! numSurf4Comp should be equal to Number of decoding session */ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.numSurf4Comp)) { ++ PrintError(MSDK_STRING("-n \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ /* This is can init early */ ++ if (InputParams.eModeExt == Native) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_only"))) { ++ /* for VPP comp with rendering we have to use ext allocator */ ++#ifdef LIBVA_SUPPORT ++ InputParams.libvaBackend = MFX_LIBVA_DRM; ++#endif ++ ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ /* NB! numSurf4Comp should be equal to Number of decoding session */ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.numSurf4Comp)) { ++ PrintError(MSDK_STRING("-n \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ /* This is can init early */ ++ if (InputParams.eModeExt == Native) ++ InputParams.eModeExt = VppCompOnly; ++ } ++ else if (0 == msdk_strncmp(MSDK_STRING("-vpp_comp_dump"), ++ argv[i], ++ msdk_strlen(MSDK_STRING("-vpp_comp_dump")))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ SIZE_CHECK((msdk_strlen(argv[i]) + 1) > MSDK_ARRAY_LEN(InputParams.strDumpVppCompFile)); ++ msdk_opt_read(argv[i], InputParams.strDumpVppCompFile); ++ } ++#if defined(LIBVA_X11_SUPPORT) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-rx11"))) { ++ InputParams.libvaBackend = MFX_LIBVA_X11; ++ } ++#endif ++ ++#if defined(LIBVA_WAYLAND_SUPPORT) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-rwld"))) { ++ InputParams.nRenderWinX = 0; ++ InputParams.nRenderWinY = 0; ++ InputParams.bPerfMode = false; ++ InputParams.libvaBackend = MFX_LIBVA_WAYLAND; ++ } ++#endif ++ ++#if defined(LIBVA_DRM_SUPPORT) ++ else if (0 == msdk_strncmp(argv[i], MSDK_STRING("-rdrm"), 5)) { ++ InputParams.libvaBackend = MFX_LIBVA_DRM_MODESET; ++ InputParams.monitorType = getMonitorType(&argv[i][5]); ++ if (argv[i][5]) { ++ if (argv[i][5] != '-') { ++ PrintError(MSDK_STRING("unsupported monitor type")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ InputParams.monitorType = getMonitorType(&argv[i][6]); ++ if (InputParams.monitorType >= MFX_MONITOR_MAXNUMBER) { ++ PrintError(MSDK_STRING("unsupported monitor type")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else { ++ InputParams.monitorType = MFX_MONITOR_AUTO; // that's case of "-rdrm" pure option ++ } ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp::sys"))) { ++ InputParams.VppOutPattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp::vid"))) { ++ InputParams.VppOutPattern = MFX_IOPATTERN_OUT_VIDEO_MEMORY; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_dst_x"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompDstX)) { ++ PrintError(MSDK_STRING("vpp_comp_dst_x %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_dst_y"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompDstY)) { ++ PrintError(MSDK_STRING("-vpp_comp_dst_y %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_dst_w"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompDstW)) { ++ PrintError(MSDK_STRING("-vpp_comp_dst_w %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_dst_h"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompDstH)) { ++ PrintError(MSDK_STRING("-vpp_comp_dst_h %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_src_w"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompSrcW)) { ++ PrintError(MSDK_STRING("-vpp_comp_src_w %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_src_h"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompSrcH)) { ++ PrintError(MSDK_STRING("-vpp_comp_src_h %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_num_tiles"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.numTiles4Comp)) { ++ PrintError(MSDK_STRING("-vpp_comp_num_tiles %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.eModeExt != VppCompOnly) ++ InputParams.eModeExt = VppCompOnly; ++ } ++#if MFX_VERSION >= 1023 ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_tile_id"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nVppCompTileId)) { ++ PrintError(MSDK_STRING("-vpp_comp_tile_id %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vpp_comp_render"))) { ++ if (InputParams.eModeExt != VppComp) ++ InputParams.eModeExt = VppComp; ++ } ++#if MFX_VERSION >= 1022 ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-dec_postproc"))) { ++ InputParams.bDecoderPostProcessing = true; ++ } ++#endif //MFX_VERSION >= 1022 ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-n"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.MaxFrameNumber)) { ++ PrintError(MSDK_STRING("-n %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-angle"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nRotationAngle)) { ++ PrintError(MSDK_STRING("-angle %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if (InputParams.strVPPPluginDLLPath[0] == '\0') { ++ msdk_opt_read(MSDK_CPU_ROTATE_PLUGIN, InputParams.strVPPPluginDLLPath); ++ } ++ } ++#if (MFX_VERSION >= 1025) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-mfe_frames"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.numMFEFrames)) { ++ PrintError(MSDK_STRING("-mfe_frames %s num frames is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-mfe_mode"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.MFMode)) { ++ PrintError(MSDK_STRING("-mfe_mode %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-mfe_timeout"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.mfeTimeout)) { ++ PrintError(MSDK_STRING("-mfe_timeout %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-timeout"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nTimeout)) { ++ PrintError(MSDK_STRING("-timeout %s is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ skipped += 2; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-dump"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.strMfxParamsDumpFile)) { ++ PrintError(MSDK_STRING("Dump file name \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-robust"))) { ++ InputParams.bRobustFlag = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-opencl"))) { ++ msdk_opt_read(MSDK_OCL_ROTATE_PLUGIN, InputParams.strVPPPluginDLLPath); ++ InputParams.bOpenCL = true; ++ } ++ ++ // output PicStruct ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-la_ext"))) { ++ InputParams.bEnableExtLA = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-la"))) { ++ InputParams.bLABRC = true; ++ InputParams.nRateControlMethod = MFX_RATECONTROL_LA; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vbr"))) { ++ InputParams.nRateControlMethod = MFX_RATECONTROL_VBR; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-cbr"))) { ++ InputParams.nRateControlMethod = MFX_RATECONTROL_CBR; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-bpyr"))) { ++ InputParams.bEnableBPyramid = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-vcm"))) { ++ InputParams.nRateControlMethod = MFX_RATECONTROL_VCM; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-lad"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ InputParams.nRateControlMethod = MFX_RATECONTROL_LA; ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.nLADepth)) { ++ PrintError(MSDK_STRING("look ahead depth \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-pe"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ InputParams.encoderPluginParams = ParsePluginGuid(argv[i + 1]); ++ if (AreGuidsEqual(InputParams.encoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ PrintError(MSDK_STRING("Invalid encoder guid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ i++; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-pd"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ InputParams.decoderPluginParams = ParsePluginGuid(argv[i + 1]); ++ if (AreGuidsEqual(InputParams.decoderPluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ PrintError(MSDK_STRING("Invalid decoder guid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ i++; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-override_decoder_framerate"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.dDecoderFrameRateOverride)) { ++ PrintError(MSDK_STRING("Framerate \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-override_encoder_framerate"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.dEncoderFrameRateOverride)) { ++ PrintError(MSDK_STRING("Framerate \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-override_encoder_picstruct"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ i++; ++ if (MFX_ERR_NONE != msdk_opt_read(argv[i], InputParams.EncoderPicstructOverride)) { ++ PrintError(MSDK_STRING("Picstruct \"%s\" is invalid"), argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-gpucopy::on"))) { ++ InputParams.nGpuCopyMode = MFX_GPUCOPY_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-gpucopy::off"))) { ++ InputParams.nGpuCopyMode = MFX_GPUCOPY_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-repartitioncheck::on"))) { ++ InputParams.RepartitionCheckMode = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-repartitioncheck::off"))) { ++ InputParams.RepartitionCheckMode = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-cqp"))) { ++ InputParams.nRateControlMethod = MFX_RATECONTROL_CQP; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-qpi"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nQPI)) { ++ PrintError(MSDK_STRING("Quantizer for I frames is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-qpp"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nQPP)) { ++ PrintError(MSDK_STRING("Quantizer for P frames is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-qpb"))) { ++ VAL_CHECK(i + 1 == argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nQPB)) { ++ PrintError(MSDK_STRING("Quantizer for B frames is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-DisableQPOffset"))) { ++ InputParams.bDisableQPOffset = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-qsv-ff"))) { ++ InputParams.enableQSVFF = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-single_texture_d3d11"))) { ++ InputParams.bSingleTexture = true; ++ } ++#if (MFX_VERSION >= 1024) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-extbrc::on"))) { ++ InputParams.nExtBRC = EXTBRC_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-extbrc::off"))) { ++ InputParams.nExtBRC = EXTBRC_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-extbrc::implicit"))) { ++ InputParams.nExtBRC = EXTBRC_IMPLICIT; ++ } ++#endif ++#if (MFX_VERSION >= 1026) ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ExtBrcAdaptiveLTR:on"))) { ++ InputParams.ExtBrcAdaptiveLTR = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ExtBrcAdaptiveLTR:off"))) { ++ InputParams.ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF; ++ } ++ ++#endif ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-pp"))) { ++ InputParams.shouldPrintPresets = true; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-preset"))) { ++ msdk_char presetName[MSDK_MAX_FILENAME_LEN]; ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], presetName)) { ++ PrintError(MSDK_STRING("Preset Name is not defined")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ InputParams.PresetMode = CPresetManager::PresetNameToMode(presetName); ++ if (InputParams.PresetMode == PRESET_MAX_MODES) { ++ PrintError(MSDK_STRING("Preset Name is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ir_type"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.IntRefType)) { ++ PrintError(MSDK_STRING("Intra refresh type is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ir_cycle_size"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.IntRefCycleSize)) { ++ PrintError(MSDK_STRING("IR refresh cycle size param is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ir_qp_delta"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.IntRefQPDelta)) { ++ PrintError(MSDK_STRING("IR QP delta param is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-ir_cycle_dist"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.IntRefCycleDist)) { ++ PrintError(MSDK_STRING("IR cycle distance param is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-LowDelayBRC"))) { ++ InputParams.LowDelayBRC = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-amfs:on"))) { ++ InputParams.nAdaptiveMaxFrameSize = MFX_CODINGOPTION_ON; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-amfs:off"))) { ++ InputParams.nAdaptiveMaxFrameSize = MFX_CODINGOPTION_OFF; ++ } ++ else if (0 == msdk_strcmp(argv[i], MSDK_STRING("-mfs"))) { ++ VAL_CHECK(i + 1 >= argc, i, argv[i]); ++ if (MFX_ERR_NONE != msdk_opt_read(argv[++i], InputParams.nMaxFrameSize)) { ++ PrintError(MSDK_STRING("MaxFrameSize is invalid")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ MOD_SMT_PARSE_INPUT ++ else if ((stsExtBuf = ParseVPPCmdLine(argv, argc, i, &InputParams, skipped)) != ++ MFX_ERR_MORE_DATA) { ++ if (stsExtBuf == MFX_ERR_UNSUPPORTED) { ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ else { ++ // WA for compiler error C1061 (too many chained else-if clauses) ++ // ParseAdditionalParams returns: ++ // 0 if argv[i] is processed successfully by this function ++ // < 1 if argv[i] is processed and generates an error ++ // OR ++ // if argv[i] was not processed (did not match any switches) ++ stsAddlParams = ParseAdditionalParams(argv, argc, i, InputParams); ++ ++ // either unrecognized parameter, or parse error with recognized parameter ++ if (stsAddlParams) { ++ if (stsAddlParams == MFX_ERR_NOT_FOUND) ++ PrintError(MSDK_STRING("Invalid input argument number %d %s"), i, argv[i]); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ } ++ ++ if (skipped < argc) { ++ sts = VerifyAndCorrectInputParams(InputParams); ++ MSDK_CHECK_STATUS(sts, "VerifyAndCorrectInputParams failed"); ++ m_SessionArray.push_back(InputParams); ++ } ++ ++ return MFX_ERR_NONE; ++ ++} //mfxStatus CmdProcessor::ParseParamsForOneSession(msdk_char *pLine, mfxU32 length) ++ ++mfxStatus CmdProcessor::ParseOption__set(msdk_char* strCodecType, msdk_char* strPluginGuid) { ++ mfxU32 codecid = 0; ++ mfxU32 type = 0; ++ sPluginParams pluginParams; ++ ++ //Parse codec type - decoder or encoder ++ if (0 == msdk_strncmp(MSDK_STRING("-i::"), strCodecType, 4)) { ++ type = MSDK_VDECODE; ++ } ++ else if (0 == msdk_strncmp(MSDK_STRING("-o::"), strCodecType, 4)) { ++ type = MSDK_VENCODE; ++ } ++ else { ++ msdk_printf(MSDK_STRING("error: incorrect definition codec type (must be -i:: or -o::)\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (StrFormatToCodecFormatFourCC(strCodecType + 4, codecid) != MFX_ERR_NONE) { ++ msdk_printf(MSDK_STRING("error: codec is unknown\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (!IsPluginCodecSupported(codecid)) { ++ msdk_printf(MSDK_STRING("error: codec is unsupported\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ pluginParams = ParsePluginGuid(strPluginGuid); ++ if (AreGuidsEqual(pluginParams.pluginGuid, MSDK_PLUGINGUID_NULL)) { ++ msdk_printf(MSDK_STRING("error: invalid codec guid\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (type == MSDK_VDECODE) ++ m_decoderPlugins.insert(std::pair(codecid, pluginParams)); ++ else ++ m_encoderPlugins.insert(std::pair(codecid, pluginParams)); ++ ++ return MFX_ERR_NONE; ++}; ++ ++mfxStatus CmdProcessor::VerifyAndCorrectInputParams(TranscodingSample::sInputParams& InputParams) { ++ if (0 == msdk_strlen(InputParams.strSrcFile) && ++ (InputParams.eMode == Sink || InputParams.eMode == Native)) { ++ PrintError(MSDK_STRING("Source file name not found")); ++ return MFX_ERR_UNSUPPORTED; ++ }; ++ ++ if (0 == msdk_strlen(InputParams.strDstFile) && ++ (InputParams.eMode == Source || InputParams.eMode == Native || ++ InputParams.eMode == VppComp) && ++ InputParams.eModeExt != VppCompOnly) { ++ PrintError(MSDK_STRING("Destination file name not found")); ++ return MFX_ERR_UNSUPPORTED; ++ }; ++ ++ if (MFX_CODEC_JPEG != InputParams.EncodeId && MFX_CODEC_MPEG2 != InputParams.EncodeId && ++ MFX_CODEC_AVC != InputParams.EncodeId && MFX_CODEC_HEVC != InputParams.EncodeId && ++ MFX_CODEC_VP9 != InputParams.EncodeId && MFX_CODEC_DUMP != InputParams.EncodeId && ++ InputParams.eMode != Sink && InputParams.eModeExt != VppCompOnly) { ++ PrintError(MSDK_STRING("Unknown encoder\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (MFX_CODEC_MPEG2 != InputParams.DecodeId && MFX_CODEC_AVC != InputParams.DecodeId && ++ MFX_CODEC_HEVC != InputParams.DecodeId && MFX_CODEC_VC1 != InputParams.DecodeId && ++ MFX_CODEC_JPEG != InputParams.DecodeId && MFX_CODEC_VP9 != InputParams.DecodeId && ++ MFX_CODEC_VP8 != InputParams.DecodeId && MFX_CODEC_AV1 != InputParams.DecodeId && ++ MFX_CODEC_RGB4 != InputParams.DecodeId && MFX_CODEC_NV12 != InputParams.DecodeId && ++ MFX_CODEC_I420 != InputParams.DecodeId && InputParams.eMode != Source) { ++ PrintError(MSDK_STRING("Unknown decoder\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (MFX_CODEC_I420 == InputParams.DecodeId || MFX_CODEC_NV12 == InputParams.DecodeId) { ++ InputParams.rawInput = true; ++ } ++ else { ++ InputParams.rawInput = false; ++ } ++ ++ if (MFX_CODEC_RGB4 == InputParams.DecodeId && ++ (!InputParams.nVppCompSrcH || !InputParams.nVppCompSrcW)) { ++ PrintError(MSDK_STRING( ++ "VppCompSrcH and VppCompSrcW must be specified in case of -i::rgb4_frame\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((!InputParams.FRCAlgorithm && !InputParams.bEnableDeinterlacing) && ++ InputParams.dVPPOutFramerate) { ++ msdk_printf(MSDK_STRING( ++ "-f option is ignored, it can be used with FRC or deinterlace options only. \n")); ++ InputParams.dVPPOutFramerate = 0; ++ } ++ ++ if (InputParams.FRCAlgorithm && InputParams.bEnableExtLA) { ++ PrintError(MSDK_STRING("-la_ext and FRC options cannot be used together\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (InputParams.nQuality && InputParams.EncodeId && (MFX_CODEC_JPEG != InputParams.EncodeId)) { ++ PrintError(MSDK_STRING("-q option is supported only for JPEG encoder\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((InputParams.nTargetUsage || InputParams.nBitRate) && ++ (MFX_CODEC_JPEG == InputParams.EncodeId)) { ++ PrintError(MSDK_STRING( ++ "-b and -u options are supported only for H.264, MPEG2 and MVC encoders. For JPEG encoder use -q\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ // valid target usage range is: [MFX_TARGETUSAGE_BEST_QUALITY .. MFX_TARGETUSAGE_BEST_SPEED] (at the moment [1..7]) ++ // If target usage is kept unknown - presets manager will fill in proper value ++ if ((InputParams.nTargetUsage < MFX_TARGETUSAGE_UNKNOWN) || ++ (InputParams.nTargetUsage > MFX_TARGETUSAGE_BEST_SPEED)) { ++ PrintError(NULL, "Unsupported target usage"); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ // Ignoring user-defined Async Depth for LA ++ if (InputParams.nMaxSliceSize) { ++ InputParams.nAsyncDepth = 1; ++ } ++ ++ // For decoder session of inter-session case, let's set AsyncDepth to 4 by default ++ if (InputParams.eMode == Sink && !InputParams.nAsyncDepth) { ++ InputParams.nAsyncDepth = 4; ++ } ++ ++ if (InputParams.bLABRC && !(InputParams.libType & MFX_IMPL_HARDWARE_ANY)) { ++ PrintError(MSDK_STRING("Look ahead BRC is supported only with -hw option!")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (InputParams.bLABRC && (InputParams.EncodeId != MFX_CODEC_AVC) && ++ (InputParams.eMode == Source)) { ++ PrintError(MSDK_STRING("Look ahead BRC is supported only with H.264 encoder!")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((InputParams.nRateControlMethod == MFX_RATECONTROL_LA || ++ InputParams.nRateControlMethod == MFX_RATECONTROL_LA_EXT || ++ InputParams.nRateControlMethod == MFX_RATECONTROL_LA_ICQ || ++ InputParams.nRateControlMethod == MFX_RATECONTROL_LA_HRD) && ++ (InputParams.nLADepth > 100)) { ++ PrintError(MSDK_STRING( ++ "Unsupported value of -lad parameter, must be in range [1,100] or 0 for automatic selection")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((InputParams.nMaxSliceSize) && !(InputParams.libType & MFX_IMPL_HARDWARE_ANY)) { ++ PrintError(MSDK_STRING("MaxSliceSize option is supported only with -hw option!")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ if ((InputParams.nMaxSliceSize) && (InputParams.nSlices)) { ++ PrintError(MSDK_STRING("-mss and -l options are not compatible!")); ++ } ++ if ((InputParams.nMaxSliceSize) && (InputParams.EncodeId != MFX_CODEC_AVC)) { ++ PrintError(MSDK_STRING("MaxSliceSize option is supported only with H.264 encoder!")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if (InputParams.BitrateLimit == MFX_CODINGOPTION_UNKNOWN) { ++ InputParams.BitrateLimit = MFX_CODINGOPTION_OFF; ++ } ++ ++ if (InputParams.enableQSVFF && InputParams.eMode == Sink) { ++ msdk_printf(MSDK_STRING( ++ "WARNING: -lowpower(-qsv-ff) option is not valid for decoder-only sessions, this parameter will be ignored.\n")); ++ } ++ ++ std::map::iterator it; ++ ++ // Set decoder plugins parameters only if they were not set before ++ if (!memcmp(InputParams.decoderPluginParams.pluginGuid.Data, ++ MSDK_PLUGINGUID_NULL.Data, ++ sizeof(MSDK_PLUGINGUID_NULL)) && ++ !strcmp(InputParams.decoderPluginParams.strPluginPath, "")) { ++ it = m_decoderPlugins.find(InputParams.DecodeId); ++ if (it != m_decoderPlugins.end()) ++ InputParams.decoderPluginParams = it->second; ++ } ++ else { ++ // Decoding plugin was set manually, so let's check if codec supports plugins ++ if (!IsPluginCodecSupported(InputParams.DecodeId)) { ++ msdk_printf(MSDK_STRING("error: decoder does not support plugins\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ ++ // Set encoder plugins parameters only if they were not set before ++ if (!memcmp(InputParams.encoderPluginParams.pluginGuid.Data, ++ MSDK_PLUGINGUID_NULL.Data, ++ sizeof(MSDK_PLUGINGUID_NULL)) && ++ !strcmp(InputParams.encoderPluginParams.strPluginPath, "")) { ++ it = m_encoderPlugins.find(InputParams.EncodeId); ++ if (it != m_encoderPlugins.end()) ++ InputParams.encoderPluginParams = it->second; ++ } ++ else { ++ // Encoding plugin was set manually, so let's check if codec supports plugins ++ if (!IsPluginCodecSupported(InputParams.EncodeId)) { ++ msdk_printf(MSDK_STRING("error: encoder does not support plugins\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ } ++ ++ if (InputParams.EncoderFourCC && InputParams.eMode == Sink) { ++ msdk_printf(MSDK_STRING( ++ "WARNING: -ec option is used in session without encoder, this parameter will be ignored \n")); ++ } ++ ++ if (InputParams.DecoderFourCC && InputParams.eMode != Native && InputParams.eMode != Sink) { ++ msdk_printf(MSDK_STRING( ++ "WARNING: -dc option is used in session without decoder, this parameter will be ignored \n")); ++ } ++ ++ if (InputParams.EncoderFourCC && InputParams.EncoderFourCC != MFX_FOURCC_NV12 && ++ InputParams.EncoderFourCC != MFX_FOURCC_RGB4 && ++ InputParams.EncoderFourCC != MFX_FOURCC_YUY2 && InputParams.EncodeId == MFX_CODEC_DUMP) { ++ PrintError(MSDK_STRING( ++ "-o::raw option can be used with NV12, RGB4 and YUY2 color formats only.\n")); ++ return MFX_ERR_UNSUPPORTED; ++ } ++ ++ if ((InputParams.nEncTileRows || InputParams.nEncTileCols) && ++ (InputParams.EncodeId != MFX_CODEC_HEVC) ++#if (MFX_VERSION >= 1029) ++ && (InputParams.EncodeId != MFX_CODEC_VP9) ++#endif ++ ) { ++ msdk_printf(MSDK_STRING("WARNING: -trows and -tcols are only supported for") ++#if (MFX_VERSION >= 1029) ++ MSDK_STRING(" VP9 and") ++#endif ++ MSDK_STRING(" HEVC encoder, these parameters will be ignored.\n")); ++ InputParams.nEncTileRows = 0; ++ InputParams.nEncTileCols = 0; ++ } ++ ++#if (defined(_WIN32) || defined(_WIN64)) && (MFX_VERSION >= 1031) ++ if (InputParams.bPrefferiGfx && InputParams.bPrefferdGfx) { ++ msdk_printf(MSDK_STRING("WARNING: both dGfx and iGfx flags set. iGfx will be preffered\n")); ++ InputParams.bPrefferdGfx = false; ++ } ++#endif ++ ++ return MFX_ERR_NONE; ++} //mfxStatus CmdProcessor::VerifyAndCorrectInputParams(TranscodingSample::sInputParams &InputParams) ++ ++bool CmdProcessor::GetNextSessionParams(TranscodingSample::sInputParams& InputParams) { ++ if (!m_SessionArray.size()) ++ return false; ++ if (m_SessionParamId == m_SessionArray.size()) { ++ return false; ++ } ++ InputParams = m_SessionArray[m_SessionParamId]; ++ ++ m_SessionParamId++; ++ return true; ++ ++} //bool CmdProcessor::GetNextSessionParams(TranscodingSample::sInputParams &InputParams) +-- +2.31.1 + diff --git a/recipes-multimedia/onevpl/onevpl/0001-Remove-duplicate-MFXVideoDECODE_VPP-from-samples.patch b/recipes-multimedia/onevpl/onevpl/0001-Remove-duplicate-MFXVideoDECODE_VPP-from-samples.patch new file mode 100644 index 00000000..8470e418 --- /dev/null +++ b/recipes-multimedia/onevpl/onevpl/0001-Remove-duplicate-MFXVideoDECODE_VPP-from-samples.patch @@ -0,0 +1,62 @@ +From 0b74a78b99822bce5ea197513dd5683f41badd7b Mon Sep 17 00:00:00 2001 +From: Jon Recker +Date: Mon, 29 Mar 2021 09:59:03 -0700 +Subject: [PATCH] Remove duplicate MFXVideoDECODE_VPP from samples + +Upstream-Status: Submitted +--- + .../sample_common/include/sample_vpl_common.h | 38 ------------------- + 1 file changed, 38 deletions(-) + +diff --git a/tools/legacy/sample_common/include/sample_vpl_common.h b/tools/legacy/sample_common/include/sample_vpl_common.h +index 4450b7f..016955a 100644 +--- a/tools/legacy/sample_common/include/sample_vpl_common.h ++++ b/tools/legacy/sample_common/include/sample_vpl_common.h +@@ -49,44 +49,6 @@ public: + } + }; + +-class MFXVideoDECODE_VPP { +-public: +- explicit MFXVideoDECODE_VPP(mfxSession session) { +- m_session = session; +- } +- virtual ~MFXVideoDECODE_VPP(void) {} +- +- virtual mfxStatus Init(mfxVideoParam *decode_par, +- mfxVideoChannelParam **vpp_par_array, +- mfxU32 num_vpp_par) { +- return MFXVideoDECODE_VPP_Init(m_session, decode_par, vpp_par_array, num_vpp_par); +- } +- +- 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 Reset(mfxVideoParam *decode_par, +- mfxVideoChannelParam **vpp_par_array, +- mfxU32 num_vpp_par) { +- return MFXVideoDECODE_VPP_Reset(m_session, decode_par, vpp_par_array, num_vpp_par); +- } +- +- virtual mfxStatus GetChannelParam(mfxVideoChannelParam *par, mfxU32 channel_id) { +- return MFXVideoDECODE_VPP_GetChannelParam(m_session, par, channel_id); +- } +- +-protected: +- mfxSession m_session; // (mfxSession) handle to the owning session +-}; +- + #endif + + #endif //__SAMPLE_VPL_COMMON_H__ +-- +2.31.1 + diff --git a/recipes-multimedia/onevpl/onevpl/0001-Update-headers-to-oneAPI-spec-v2.3-e170992.patch b/recipes-multimedia/onevpl/onevpl/0001-Update-headers-to-oneAPI-spec-v2.3-e170992.patch new file mode 100644 index 00000000..030b395c --- /dev/null +++ b/recipes-multimedia/onevpl/onevpl/0001-Update-headers-to-oneAPI-spec-v2.3-e170992.patch @@ -0,0 +1,741 @@ +From bb2f6199088879568e31f91f6d9b7aa737c5aa04 Mon Sep 17 00:00:00 2001 +From: Jon Recker +Date: Wed, 9 Jun 2021 10:39:10 +0800 +Subject: [PATCH] Update headers to oneAPI-spec v2.3 (e170992) + +Upstream-Status: Submitted +--- + api/vpl/mfx.h | 25 ++++++++ + api/vpl/mfxcommon.h | 9 ++- + api/vpl/mfxdefs.h | 86 ++++++++++++------------- + api/vpl/mfxdispatcher.h | 4 +- + api/vpl/mfximplcaps.h | 4 +- + api/vpl/mfxsession.h | 11 +++- + api/vpl/mfxstructures.h | 137 ++++++++++++++++++++++------------------ + api/vpl/mfxvideo++.h | 76 ++++++++++++++++++++++ + 8 files changed, 238 insertions(+), 114 deletions(-) + create mode 100644 api/vpl/mfx.h + +diff --git a/api/vpl/mfx.h b/api/vpl/mfx.h +new file mode 100644 +index 0000000..32fc50b +--- /dev/null ++++ b/api/vpl/mfx.h +@@ -0,0 +1,25 @@ ++/*############################################################################ ++ # Copyright (C) 2021 Intel Corporation ++ # ++ # SPDX-License-Identifier: MIT ++ ############################################################################*/ ++ ++#ifndef __MFX_H__ ++#define __MFX_H__ ++ ++#include "mfxdefs.h" ++#include "mfxcommon.h" ++#include "mfxstructures.h" ++#include "mfxdispatcher.h" ++#include "mfximplcaps.h" ++#include "mfxsession.h" ++#include "mfxvideo.h" ++#include "mfxadapter.h" ++ ++#include "mfxbrc.h" ++#include "mfxmvc.h" ++#include "mfxpcp.h" ++#include "mfxvp8.h" ++#include "mfxjpeg.h" ++ ++#endif /* __MFXDEFS_H__ */ +diff --git a/api/vpl/mfxcommon.h b/api/vpl/mfxcommon.h +index 90a2f3d..9884aa4 100644 +--- a/api/vpl/mfxcommon.h ++++ b/api/vpl/mfxcommon.h +@@ -172,7 +172,7 @@ typedef struct { + } mfxExtThreadsParam; + MFX_PACK_END() + +-/*! The PlatformCodeName enumerator itemizes microarchitecture code names for the Legacy mode. ++/*! The PlatformCodeName enumerator itemizes product code names for platforms. + For details about Intel code names, see ark.intel.com. */ + enum { + MFX_PLATFORM_UNKNOWN = 0, /*!< Unknown platform. */ +@@ -192,6 +192,10 @@ enum { + MFX_PLATFORM_JASPERLAKE = 32, /*!< Code name Jasper Lake. */ + MFX_PLATFORM_ELKHARTLAKE = 33, /*!< Code name Elkhart Lake. */ + MFX_PLATFORM_TIGERLAKE = 40, /*!< Code name Tiger Lake. */ ++ MFX_PLATFORM_ROCKETLAKE = 42, /*!< Code name Rocket Lake. */ ++ MFX_PLATFORM_ALDERLAKE_S = 43, /*!< Code name Alder Lake S. */ ++ MFX_PLATFORM_ALDERLAKE_P = 44, /*!< Code name Alder Lake P. */ ++ MFX_PLATFORM_ARCTICSOUND_P = 45, /*!< Code name Arctic Sound P. */ + MFX_PLATFORM_KEEMBAY = 50, /*!< Code name Keem Bay. */ + }; + +@@ -370,7 +374,6 @@ typedef enum { + MFX_ACCEL_MODE_VIA_HDDLUNITE = 0x0500, /*!< Hardware acceleration goes through the HDDL* Unite*. */ + } mfxAccelerationMode; + +- + #define MFX_ACCELERATIONMODESCRIPTION_VERSION MFX_STRUCT_VERSION(1, 0) + + MFX_PACK_BEGIN_STRUCT_W_PTR() +@@ -438,7 +441,7 @@ typedef struct { + mfxU16 reserved[3]; /*!< Reserved for future use. */ + mfxU16 NumExtParam; /*!< The number of extra configuration structures attached to this structure. */ + mfxExtBuffer **ExtParam; /*!< Points to an array of pointers to the extra configuration structures; see the ExtendedBufferID enumerator for a list of extended configurations. */ +- mfxU32 VendorImplID; /*!< Vendor specific number with given implementation ID. Represents the same filed from mfxImplDescription. */ ++ mfxU32 VendorImplID; /*!< Vendor specific number with given implementation ID. Represents the same field from mfxImplDescription. */ + mfxU32 reserved2[3]; /*!< Reserved for future use. */ + } mfxInitializationParam; + MFX_PACK_END() +diff --git a/api/vpl/mfxdefs.h b/api/vpl/mfxdefs.h +index 14cece0..dfd9f98 100644 +--- a/api/vpl/mfxdefs.h ++++ b/api/vpl/mfxdefs.h +@@ -8,7 +8,7 @@ + #define __MFXDEFS_H__ + + #define MFX_VERSION_MAJOR 2 +-#define MFX_VERSION_MINOR 2 ++#define MFX_VERSION_MINOR 3 + + // MFX_VERSION - version of API that 'assumed' by build may be provided externally + // if it omitted then latest stable API derived from Major.Minor is assumed +@@ -27,7 +27,7 @@ + /*! The corresponding version of the Intel(r) Media SDK legacy API that is used as a basis + for the current API. */ + +-#define MFX_LEGACY_VERSION 1034 ++#define MFX_LEGACY_VERSION 1035 + + + #ifdef __cplusplus +@@ -90,47 +90,47 @@ extern "C" + #endif + + #ifndef MFX_DEPRECATED_OFF +- #if defined(__cplusplus) && __cplusplus >= 201402L +- #define MFX_DEPRECATED [[deprecated]] +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg [[deprecated]] +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) +- #elif defined(__clang__) +- #define MFX_DEPRECATED __attribute__((deprecated)) +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) +- #elif defined(__INTEL_COMPILER) +- #if (defined(_WIN32) || defined(_WIN64)) +- #define MFX_DEPRECATED __declspec(deprecated) +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) +- #elif defined(__linux__) +- #define MFX_DEPRECATED __attribute__((deprecated)) +- #if defined(__cplusplus) +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) +- #else +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg +- #endif +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) +- #endif +- #elif defined(_MSC_VER) && _MSC_VER > 1200 // VS 6 doesn't support deprecation +- #define MFX_DEPRECATED __declspec(deprecated) +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) +- #elif defined(__GNUC__) +- #define MFX_DEPRECATED __attribute__((deprecated)) +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) +- #else +- #define MFX_DEPRECATED +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) +- #endif +-#else +- #define MFX_DEPRECATED +- #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg +- #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) +-#endif +- ++ #if defined(__cplusplus) && __cplusplus >= 201402L ++ #define MFX_DEPRECATED [[deprecated]] ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg [[deprecated]] ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) ++ #elif defined(__clang__) ++ #define MFX_DEPRECATED __attribute__((deprecated)) ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) ++ #elif defined(__INTEL_COMPILER) ++ #if (defined(_WIN32) || defined(_WIN64)) ++ #define MFX_DEPRECATED __declspec(deprecated) ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) ++ #elif defined(__linux__) ++ #define MFX_DEPRECATED __attribute__((deprecated)) ++ #if defined(__cplusplus) ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) ++ #else ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg ++ #endif ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) ++ #endif ++ #elif defined(_MSC_VER) && _MSC_VER > 1200 // VS 6 doesn't support deprecation ++ #define MFX_DEPRECATED __declspec(deprecated) ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) __pragma(deprecated(arg)) ++ #elif defined(__GNUC__) ++ #define MFX_DEPRECATED __attribute__((deprecated)) ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg __attribute__((deprecated)) ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) ++ #else ++ #define MFX_DEPRECATED ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) ++ #endif ++ #else ++ #define MFX_DEPRECATED ++ #define MFX_DEPRECATED_ENUM_FIELD_INSIDE(arg) arg ++ #define MFX_DEPRECATED_ENUM_FIELD_OUTSIDE(arg) ++ #endif ++ + typedef unsigned char mfxU8; /*!< Unsigned integer, 8 bit type. */ + typedef char mfxI8; /*!< Signed integer, 8 bit type. */ + typedef short mfxI16; /*!< Signed integer, 16 bit type. */ +diff --git a/api/vpl/mfxdispatcher.h b/api/vpl/mfxdispatcher.h +index 8db716b..86ecea3 100644 +--- a/api/vpl/mfxdispatcher.h ++++ b/api/vpl/mfxdispatcher.h +@@ -1,5 +1,5 @@ + /*############################################################################ +- # Copyright (C) Intel Corporation ++ # Copyright (C) 2020 Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ +@@ -193,7 +193,7 @@ mfxStatus MFX_CDECL MFXCreateSession(mfxLoader loader, mfxU32 i, mfxSession* ses + + /*! + @brief +- Destroys handle allocated by the MFXQueryImplsCapabilities function. ++ Destroys handle allocated by the MFXEnumImplementations function. + + @param[in] loader Loader handle. + @param[in] hdl Handle to destroy. Can be equal to NULL. +diff --git a/api/vpl/mfximplcaps.h b/api/vpl/mfximplcaps.h +index 16851d0..514a1c4 100644 +--- a/api/vpl/mfximplcaps.h ++++ b/api/vpl/mfximplcaps.h +@@ -1,5 +1,5 @@ + /*############################################################################ +- # Copyright (C) Intel Corporation ++ # Copyright (C) 2020 Intel Corporation + # + # SPDX-License-Identifier: MIT + ############################################################################*/ +@@ -33,7 +33,7 @@ mfxHDL* MFX_CDECL MFXQueryImplsDescription(mfxImplCapsDeliveryFormat format, mfx + + /*! + @brief +- Destroys the handle allocated by the MFXQueryImplsCapabilities function. ++ Destroys the handle allocated by the MFXQueryImplsDescription function. + Implementation must remember which handles are released. Once the last handle is released, this function must release memory + allocated for the array of handles. + +diff --git a/api/vpl/mfxsession.h b/api/vpl/mfxsession.h +index e9c7127..7e2493a 100644 +--- a/api/vpl/mfxsession.h ++++ b/api/vpl/mfxsession.h +@@ -49,6 +49,9 @@ typedef struct _mfxSession *mfxSession; + MFX_ERR_UNSUPPORTED The function cannot find the desired legacy Intel(r) Media SDK implementation or version. + + @since This function is available since API version 1.0. ++ ++ @deprecated Deprecated in API version 2.3. Use MFXLoad and MFXCreateSession to initialize the session. ++ Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. + */ + MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSession *session); + +@@ -56,8 +59,7 @@ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSes + @brief + Creates and initializes a session in the legacy mode for compatibility with Intel(r) Media SDK applications. + This function is deprecated starting from API version 2.0, applications must use MFXLoad with mfxCreateSession +- to select the implementation and initialize the session. +- ++ to select the implementation and initialize the session. + + Call this function before calling any other API functions. + If the desired implementation specified by ``par`` is MFX_IMPL_AUTO, the function will search for +@@ -72,7 +74,7 @@ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSes + For example, if an application uses only H.264 decoding as described in API v1.0, the application should initialize the library with API v1.0. This ensures backward compatibility. + + The argument ``par.ExternalThreads`` specifies threading mode. Value 0 means that the implementation should create and +- handle work threads internally (this is essentially the equivalent of the regular MFXInit). I ++ handle work threads internally (this is essentially the equivalent of the regular MFXInit). + + @param[in] par mfxInitParam structure that indicates the desired implementation, minimum library version and desired threading mode. + @param[out] session Pointer to the session handle. +@@ -82,6 +84,9 @@ MFX_DEPRECATED mfxStatus MFX_CDECL MFXInit(mfxIMPL impl, mfxVersion *ver, mfxSes + MFX_ERR_UNSUPPORTED The function cannot find the desired implementation or version. + + @since This function is available since API version 1.14. ++ ++ @deprecated Deprecated in API version 2.3. Use MFXLoad and MFXCreateSession to initialize the session. ++ Use MFX_DEPRECATED_OFF macro to turn off the deprecation message visualization. + */ + MFX_DEPRECATED mfxStatus MFX_CDECL MFXInitEx(mfxInitParam par, mfxSession *session); + +diff --git a/api/vpl/mfxstructures.h b/api/vpl/mfxstructures.h +index f285979..94d8d25 100644 +--- a/api/vpl/mfxstructures.h ++++ b/api/vpl/mfxstructures.h +@@ -40,13 +40,13 @@ MFX_PACK_BEGIN_USUAL_STRUCT() + /*! Specifies properties of video frames. See also "Configuration Parameter Constraints" chapter. */ + typedef struct { + mfxU32 reserved[4]; /*!< Reserved for future use. */ +- /*! The unique ID of each VPP channel set by application. It's required that during Init/Reset application fills ChannelId for +- each mfxVideoChannelParam provided by the application and the SDK sets it back to the correspondent +- mfxSurfaceArray::mfxFrameSurface1 to distinguish different channels. It's expected that surfaces for some channels might be +- returned with some delay so application has to use mfxFrameInfo::ChannelId to distinguish what returned surface belongs to +- what VPP channel. Decoder's initialization parameters are always sent through channel with mfxFrameInfo::ChannelId equals to ++ /*! The unique ID of each VPP channel set by application. It's required that during Init/Reset application fills ChannelId for ++ each mfxVideoChannelParam provided by the application and the SDK sets it back to the correspondent ++ mfxSurfaceArray::mfxFrameSurface1 to distinguish different channels. It's expected that surfaces for some channels might be ++ returned with some delay so application has to use mfxFrameInfo::ChannelId to distinguish what returned surface belongs to ++ what VPP channel. Decoder's initialization parameters are always sent through channel with mfxFrameInfo::ChannelId equals to + zero. It's allowed to skip setting of decoder's parameters for simplified decoding procedure */ +- mfxU16 ChannelId; ++ mfxU16 ChannelId; + /*! Number of bits used to represent luma samples. + @note Not all codecs and implementations support this value. Use the Query API function to check if this feature is supported. */ + mfxU16 BitDepthLuma; +@@ -552,22 +552,22 @@ typedef struct mfxFrameSurfaceInterface { + MFX_ERR_UNKNOWN Any internal error. + */ + mfxStatus (MFX_CDECL *Synchronize)(mfxFrameSurface1* surface, mfxU32 wait); +- ++ + /*! @brief +- The library calls the function after complete of associated video operation +- notifying the application that frame surface is ready. +- +- @attention This is callback function and intended to be called by +- the library only. +- +- It is expected that the function is low-intrusive designed otherwise it may +- impact performance. ++ The library calls the function after complete of associated video operation ++ notifying the application that frame surface is ready. ++ ++ @attention This is callback function and intended to be called by ++ the library only. ++ ++ It is expected that the function is low-intrusive designed otherwise it may ++ impact performance. + + @param[in] sts The status of completed operation. + + */ + void (MFX_CDECL *OnComplete)(mfxStatus sts); +- ++ + mfxHDL reserved2[3]; + } mfxFrameSurfaceInterface; + MFX_PACK_END() +@@ -719,22 +719,22 @@ typedef struct { + return MFX_ERR_REALLOC_SURFACE. See the CodingOptionValue enumerator for values of this option. Use the Query API + function to check if this feature is supported. */ + mfxU16 EnableReallocRequest; +- /*! Special parameter for AV1 decoder. Indicates presence/absence of film grain parameters in bitstream. +- Also controls decoding behavior for streams with film grain parameters. MFXVideoDECODE_DecodeHeader returns nonzero FilmGrain ++ /*! Special parameter for AV1 decoder. Indicates presence/absence of film grain parameters in bitstream. ++ Also controls decoding behavior for streams with film grain parameters. MFXVideoDECODE_DecodeHeader returns nonzero FilmGrain + for streams with film grain parameters and zero for streams w/o them. Decoding with film grain requires additional output surfaces. + If FilmGrain` is non-zero then MFXVideoDECODE_QueryIOSurf will request more surfaces in case of external allocated video memory at decoder output. + FilmGrain is passed to MFXVideoDECODE_Init function to control decoding operation for AV1 streams with film grain parameters. +- If FilmGrain is nonzero decoding of each frame require two output surfaces (one for reconstructed frame and one for output frame with film grain applied). ++ If FilmGrain is nonzero decoding of each frame require two output surfaces (one for reconstructed frame and one for output frame with film grain applied). + The decoder returns MFX_ERR_MORE_SURFACE from MFXVideoDECODE_DecodeFrameAsync if it has insufficient output surfaces to decode frame. +- Application can forcibly disable the feature passing zero value of `FilmGrain` to `MFXVideoDECODE_Init`. +- In this case the decoder will output reconstructed frames w/o film grain applied. ++ Application can forcibly disable the feature passing zero value of `FilmGrain` to `MFXVideoDECODE_Init`. ++ In this case the decoder will output reconstructed frames w/o film grain applied. + Application can retrieve film grain parameters for a frame by attaching extended buffer mfxExtAV1FilmGrainParam to mfxFrameSurface1. + If stream has no film grain parameters `FilmGrain` passed to `MFXVideoDECODE_Init` is ignored by the decoder. */ + mfxU16 FilmGrain; + /*! If not zero, it forces SDK to attempt to decode bitstream even if a decoder may not support all features associated with given CodecLevel. Decoder may produce visual artifacts. Only AVC decoder supports this field. */ + mfxU16 IgnoreLevelConstrain; + /*! This flag is used to disable output of main decoding channel. When it's ON SkipOutput = MFX_CODINGOPTION_ON decoder outputs only video processed channels. For pure decode this flag should be always disabled. */ +- mfxU16 SkipOutput; ++ mfxU16 SkipOutput; + mfxU16 reserved2[4]; + }; + struct { /* JPEG Decoding Options */ +@@ -898,7 +898,7 @@ enum { + MFX_LEVEL_AVC_6 =60, + MFX_LEVEL_AVC_61 =61, + MFX_LEVEL_AVC_62 =62, +- /*! @} */ ++ /*! @} */ + + /*! @{ */ + /* MPEG2 Profiles. */ +@@ -1484,8 +1484,7 @@ typedef struct { + mfxU16 WinBRCSize; + + /*! When rate control method is MFX_RATECONTROL_QVBR, this parameter specifies quality factor. +-Values are in the 1 to 51 range, +- where 1 corresponds to the best quality. ++ Values are in the 1 to 51 range, where 1 corresponds to the best quality. + */ + mfxU16 QVBRQuality; + /*! +@@ -1678,6 +1677,7 @@ Values are in the 1 to 51 range, + This parameter is valid only during initialization. + */ + mfxU16 AdaptiveCQM; ++ + mfxU16 reserved[162]; + } mfxExtCodingOption3; + MFX_PACK_END() +@@ -2024,13 +2024,16 @@ enum { + See the mfxExtInCrops structure for details. + */ + MFX_EXTBUFF_CROPS = MFX_MAKEFOURCC('C', 'R', 'O', 'P'), +- ++ + /*! + See the mfxExtAV1FilmGrainParam structure for more details. + */ +- MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM = MFX_MAKEFOURCC('A','1','F','G') ++ MFX_EXTBUFF_AV1_FILM_GRAIN_PARAM = MFX_MAKEFOURCC('A','1','F','G'), + +- ++ /*! ++ See the mfxExtHyperModeParam structure for more details. ++ */ ++ MFX_EXTBUFF_HYPER_MODE_PARAM = MFX_MAKEFOURCC('H', 'Y', 'P', 'M') + }; + + /* VPP Conf: Do not use certain algorithms */ +@@ -2488,10 +2491,10 @@ MFX_PACK_BEGIN_STRUCT_W_PTR() + Each filter may be included in the pipeline in one of two different ways: + + @li Adding a filter ID to this structure. In this method, +- the default filter parameters are used. +- ++ the default filter parameters are used. ++ + @li Attaching a filter configuration structure directly to the mfxVideoParam structure. +- In this method, adding filter ID to the mfxExtVPPDoUse structure is optional. ++ In this method, adding filter ID to the mfxExtVPPDoUse structure is optional. + + See Table “Configurable VPP filters” for complete list of + configurable filters, their IDs, and configuration structures. +@@ -2590,7 +2593,7 @@ MFX_PACK_BEGIN_USUAL_STRUCT() + + On some platforms this filter is not supported. To query its support, the application should use the same approach that it uses + to configure VPP filters: adding the filter ID to the mfxExtVPPDoUse structure or by attaching the mfxExtVPPImageStab structure +- directly to the mfxVideoParam structure and calling the MFXVideoVPP_Query function. ++ directly to the mfxVideoParam structure and calling the MFXVideoVPP_Query function. + + If this filter is supported, the function returns a MFX_ERR_NONE + status and copies the content of the input structure to the output structure. If the filter is not supported, the function returns MFX_WRN_FILTER_SKIPPED, removes the +@@ -2617,14 +2620,14 @@ enum { + + MFX_PACK_BEGIN_USUAL_STRUCT() + /*! +- Configures the HDR SEI message. ++ Configures the HDR SEI message. + + If the application attaches this structure to the mfxEncodeCtrl structure +- at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. ++ at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. + + If the application attaches this + structure to the mfxVideoParam structure during initialization or reset, the encoder inserts the HDR SEI message based on InsertPayloadToggle. +- ++ + Field semantics are defined in ITU-T* H.265 Annex D. + */ + typedef struct { +@@ -2633,10 +2636,10 @@ typedef struct { + + mfxU16 InsertPayloadToggle; /*!< InsertHDRPayload enumerator value. */ + mfxU16 DisplayPrimariesX[3]; /*!< Color primaries for a video source in increments of 0.00002. Consist of RGB x coordinates and +- define how to convert colors from RGB color space to CIE XYZ color space. Fields range is ++ define how to convert colors from RGB color space to CIE XYZ color space. Fields range is + 0 to 50000. */ + mfxU16 DisplayPrimariesY[3]; /*!< Color primaries for a video source in increments of 0.00002. Consists of RGB y coordinates and +- defines how to convert colors from RGB color space to CIE XYZ color space. Field range is ++ defines how to convert colors from RGB color space to CIE XYZ color space. Field range is + 0 to 50000. */ + mfxU16 WhitePointX; /*!< White point X coordinate. */ + mfxU16 WhitePointY; /*!< White point Y coordinate. */ +@@ -2649,14 +2652,14 @@ MFX_PACK_END() + + MFX_PACK_BEGIN_USUAL_STRUCT() + /*! +- Configures the HDR SEI message. ++ Configures the HDR SEI message. + + If the application attaches this structure to the mfxEncodeCtrl +- structure at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. ++ structure at runtime, the encoder inserts the HDR SEI message for the current frame and ignores InsertPayloadToggle. + + If the application + attaches this structure to the mfxVideoParam structure during initialization or reset, the encoder inserts the HDR SEI message based on +- InsertPayloadToggle. ++ InsertPayloadToggle. + + Field semantics are defined in ITU-T* H.265 Annex D. + */ +@@ -3659,12 +3662,8 @@ enum { + MFX_SCALING_MODE_DEFAULT = 0, /*!< Default scaling mode. The library selects the most appropriate scaling method. */ + MFX_SCALING_MODE_LOWPOWER = 1, /*!< Low power scaling mode which is applicable for library implementations. + The exact scaling algorithm is defined by the library. */ +- MFX_SCALING_MODE_QUALITY = 2, /*!< The best quality scaling mode. */ +- +- ++ MFX_SCALING_MODE_QUALITY = 2, /*!< The best quality scaling mode. */ + MFX_SCALING_MODE_VENDOR = 1000, /*!< The enumeration to separate common scaling controls above and vendor specific. */ +- +- + MFX_SCALING_MODE_INTEL_GEN_COMPUTE = MFX_SCALING_MODE_VENDOR + 1, /*! The mode to run scaling operation on Execution Units (EUs). */ + MFX_SCALING_MODE_INTEL_GEN_VDBOX = MFX_SCALING_MODE_VENDOR + 2, /*! The special optimization mode where scaling operation running on SFC (Scaler & Format Converter) is coupled with VDBOX (also known as Multi-Format Codec fixed-function engine). This mode is applicable for DECODE_VPP domain functions. */ + MFX_SCALING_MODE_INTEL_GEN_VEBOX = MFX_SCALING_MODE_VENDOR + 3 /*! The special optimization mode where scaling operation running on SFC is coupled with VEBOX (HW video processing pipe). */ +@@ -4040,14 +4039,14 @@ MFX_PACK_BEGIN_USUAL_STRUCT() + */ + typedef struct { + mfxExtBuffer Header; /*!< Extension buffer header. Header.BufferId must be equal to MFX_EXTBUFF_VPP_MCTF. */ +- mfxU16 FilterStrength; /*!< Value in range of 0 to 20 (inclusive) to indicate the filter strength of MCTF. ++ mfxU16 FilterStrength; /*!< Value in range of 0 to 20 (inclusive) to indicate the filter strength of MCTF. + + The strength of the MCTF process controls the degree of possible change of pixel values eligible for MCTF - the greater the strength value, the larger the change. It is a dimensionless quantity - values in the range of 1 to 20 inclusively imply strength; value 0 stands for AUTO mode and is + valid during initialization or reset only + + If an invalid value is given, it is fixed to the default value of 0. + If the field value is in the range of 1 to 20 inclusive, MCTF operates in fixed-strength mode with the given strength of MCTF process. +- ++ + At runtime, values of 0 and greater than 20 are ignored. */ + mfxU16 reserved[27]; + } mfxExtVppMctf; +@@ -4160,7 +4159,7 @@ typedef struct { + } mfxExtDeviceAffinityMask; + MFX_PACK_END() + +-/*! The FilmGrainFlags enumerator itemizes flags in AV1 film grain parameters. ++/*! The FilmGrainFlags enumerator itemizes flags in AV1 film grain parameters. + The flags are equivalent to respective syntax elements from film_grain_params() section of uncompressed header. */ + enum { + MFX_FILM_GRAIN_NO = 0, /*!< Film grain isn't added to this frame. */ +@@ -4196,7 +4195,7 @@ typedef struct { + mfxAV1FilmGrainPoint PointCb[10]; /*!< The array of points for Cb component. */ + mfxAV1FilmGrainPoint PointCr[10]; /*!< The array of points for Cr component. */ + +- mfxU8 GrainScalingMinus8; /*!< The shift – 8 applied to the values of the chroma component. The grain_scaling_minus_8 can take values of 0..3 and ++ mfxU8 GrainScalingMinus8; /*!< The shift – 8 applied to the values of the chroma component. The grain_scaling_minus_8 can take values of 0..3 and + determines the range and quantization step of the standard deviation of film grain.*/ + mfxU8 ArCoeffLag; /*!< The number of auto-regressive coefficients for luma and chroma.*/ + +@@ -4204,8 +4203,8 @@ typedef struct { + mfxU8 ArCoeffsCbPlus128[25]; /*!< Auto-regressive coefficients used for the Cb plane. */ + mfxU8 ArCoeffsCrPlus128[25]; /*!< The number of points for the piece-wise linear scaling function of the Cr component.*/ + +- mfxU8 ArCoeffShiftMinus6; /*!< The range of the auto-regressive coefficients. +- Values of 0, 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of ++ mfxU8 ArCoeffShiftMinus6; /*!< The range of the auto-regressive coefficients. ++ Values of 0, 1, 2, and 3 correspond to the ranges for auto-regressive coefficients of + [-2, 2), [-1, 1), [-0.5, 0.5) and [-0.25, 0.25) respectively.*/ + mfxU8 GrainScaleShift; /*!< Downscaling factor of the grain synthesis process for the Gaussian random numbers .*/ + +@@ -4229,8 +4228,8 @@ MFX_PACK_BEGIN_STRUCT_W_PTR() + typedef struct mfxSurfaceArray + { + mfxHDL Context; /*!< The context of the memory interface. User should not touch (change, set, null) this pointer. */ +- mfxStructVersion Version; /*!< The version of the structure. */ +- mfxU16 reserved[3]; ++ mfxStructVersion Version; /*!< The version of the structure. */ ++ mfxU16 reserved[3]; + /*! @brief + Increments the internal reference counter of the surface. The surface is not destroyed until the surface is released using the (*Release) function. (*AddRef) should be used each time a new link to the surface is created (for example, copy structure) for proper surface management. + +@@ -4242,11 +4241,11 @@ typedef struct mfxSurfaceArray + MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. + +- */ +- mfxStatus (*AddRef)(struct mfxSurfaceArray* surface_array); ++ */ ++ mfxStatus (*AddRef)(struct mfxSurfaceArray* surface_array); + /*! @brief +- Decrements the internal reference counter of the surface. (*Release) should be called after using the (*AddRef) function to add a +- surface or when allocation logic requires it. ++ Decrements the internal reference counter of the surface. (*Release) should be called after using the (*AddRef) function to add a ++ surface or when allocation logic requires it. + + @param[in] surface_array Valid mfxSurfaceArray. + +@@ -4257,7 +4256,7 @@ typedef struct mfxSurfaceArray + MFX_ERR_UNDEFINED_BEHAVIOR If Reference Counter of surface is zero before call. \n + MFX_ERR_UNKNOWN Any internal error. + */ +- mfxStatus (*Release)(struct mfxSurfaceArray* surface_array); ++ mfxStatus (*Release)(struct mfxSurfaceArray* surface_array); + + /*! @brief + Returns current reference counter of mfxSurfaceArray structure. +@@ -4270,10 +4269,10 @@ typedef struct mfxSurfaceArray + MFX_ERR_NULL_PTR If surface or counter is NULL. \n + MFX_ERR_INVALID_HANDLE If mfxSurfaceArray->Context is invalid (for example NULL). \n + MFX_ERR_UNKNOWN Any internal error. +- */ ++ */ + mfxStatus (*GetRefCounter)(struct mfxSurfaceArray* surface_array, mfxU32* counter); + +- mfxFrameSurface1** Surfaces; /*!< The array of pointers to mfxFrameSurface1. mfxFrameSurface1 surfaces are allocated by the same ++ mfxFrameSurface1** Surfaces; /*!< The array of pointers to mfxFrameSurface1. mfxFrameSurface1 surfaces are allocated by the same + agent who allocates mfxSurfaceArray. */ + mfxU32 NumSurfaces; /*!