diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/CMakeLists.txt b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/CMakeLists.txt
new file mode 100644
index 0000000..37a31a8
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright (c) 2017-2020 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+
+add_subdirectory(asg-hevc)
+add_subdirectory(bs_parser_hevc)
+add_subdirectory(bs_parser_hevc/tools/hevc_fei_extractor)
+add_subdirectory(tracer)
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/CMakeLists.txt b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/CMakeLists.txt
new file mode 100644
index 0000000..1322ac2
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/CMakeLists.txt
@@ -0,0 +1,16 @@
+find_path( FEI_INCLUDE mfxfeihevc.h PATHS ${MFX_INCLUDE} )
+
+include_directories (
+ ${CMAKE_CURRENT_SOURCE_DIR}/../../samples/sample_common/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+list( APPEND LIBS sample_common )
+
+set( defs " -DMFX_VERSION_USE_LATEST " )
+set(DEPENDENCIES libmfx)
+
+make_executable( shortname universal )
+
+install( TARGETS ${target} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} )
+set( defs "" )
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/asg-hevc.vcxproj b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/asg-hevc.vcxproj
new file mode 100644
index 0000000..a52d7ae
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/asg-hevc.vcxproj
@@ -0,0 +1,205 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {270C4BB6-C45C-4541-8F9C-47D30C4744F1}
+ Win32Proj
+ 10.0.17134.0
+
+
+
+ Application
+ true
+ v141
+
+
+ Application
+ false
+ v141
+
+
+ Application
+ true
+ v141
+
+
+ Application
+ false
+ v141
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(ProjectName)\
+
+
+ false
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(ProjectName)\
+
+
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(ProjectName)\
+
+
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(ProjectName)\
+ false
+
+
+
+ MFX_VERSION_USE_LATEST;_WIN32;WIN32;_DEBUG;NOMINMAX;MFX_DEPRECATED_OFF; _UNICODE;UNICODE;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ Level3
+ ProgramDatabase
+ Disabled
+ $(ProjectDir)\include;$(ProjectDir)\..\..\api\include;$(ProjectDir)\..\..\samples\sample_common\include\vm;$(ProjectDir)\..\..\samples\sample_common\src;$(ProjectDir)\..\..\samples\sample_common\include;$(INTELMEDIASDKROOT)\include;%(AdditionalIncludeDirectories)
+ false
+
+
+ MachineX86
+ DebugFastLink
+ Console
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\lib\;$(INTELMEDIASDKROOT)\lib\$(Platform);%(AdditionalLibraryDirectories)
+
+
+
+
+ MFX_VERSION_USE_LATEST;_WIN32;WIN32;NDEBUG;NOMINMAX;MFX_DEPRECATED_OFF; _UNICODE;UNICODE;%(PreprocessorDefinitions)
+ MultiThreaded
+ Level3
+ ProgramDatabase
+ $(ProjectDir)\include;$(ProjectDir)\..\..\api\include;$(ProjectDir)\..\..\samples\sample_common\include\vm;$(ProjectDir)\..\..\samples\sample_common\src;$(ProjectDir)\..\..\samples\sample_common\include;$(INTELMEDIASDKROOT)\include;%(AdditionalIncludeDirectories)
+ false
+
+
+ MachineX86
+ true
+ Console
+ true
+ true
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\lib\;$(INTELMEDIASDKROOT)\lib\$(Platform);%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; sample_common.lib;%(AdditionalDependencies)
+
+
+
+
+ $(ProjectDir)\include;$(ProjectDir)\..\..\api\include;$(ProjectDir)\..\..\samples\sample_common\include\vm;$(ProjectDir)\..\..\samples\sample_common\src;$(ProjectDir)\..\..\samples\sample_common\include;$(INTELMEDIASDKROOT)\include;%(AdditionalIncludeDirectories)
+
+
+
+
+ Level3
+
+
+
+
+ true
+ MFX_VERSION_USE_LATEST;_WIN64;WIN64;_DEBUG;NOMINMAX;MFX_DEPRECATED_OFF; _UNICODE;UNICODE;%(PreprocessorDefinitions)
+ MultiThreadedDebug
+ ProgramDatabase
+
+
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\lib\;$(INTELMEDIASDKROOT)\lib\$(Platform);%(AdditionalLibraryDirectories)
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; sample_common.lib;%(AdditionalDependencies)
+ Console
+
+
+
+
+ $(ProjectDir)\include;$(ProjectDir)\..\..\api\include;$(ProjectDir)\..\..\samples\sample_common\include\vm;$(ProjectDir)\..\..\samples\sample_common\src;$(ProjectDir)\..\..\samples\sample_common\include;$(INTELMEDIASDKROOT)\include;%(AdditionalIncludeDirectories)
+
+
+
+
+ Level3
+ true
+ MFX_VERSION_USE_LATEST;_WIN64;WIN64;NDEBUG;NOMINMAX;MFX_DEPRECATED_OFF; _UNICODE;UNICODE;%(PreprocessorDefinitions)
+ true
+ MultiThreaded
+
+
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\lib\;$(INTELMEDIASDKROOT)\lib\$(Platform);%(AdditionalLibraryDirectories)
+ Console
+ kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib; sample_common.lib;%(AdditionalDependencies)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {5fadb243-53c3-4776-a20f-8bd65c10cf41}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/asg-hevc.vcxproj.filters b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/asg-hevc.vcxproj.filters
new file mode 100644
index 0000000..239f930
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/asg-hevc.vcxproj.filters
@@ -0,0 +1,111 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/asglog.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/asglog.h
new file mode 100644
index 0000000..68c1b33
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/asglog.h
@@ -0,0 +1,135 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASGLOG_H__
+#define __ASGLOG_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+#include
+#include
+#include
+
+#include "mfxdefs.h"
+#include "block_structures.h"
+
+//Logger object, basically a tee into cout and log file
+class ASGLog
+{
+public:
+ //Tuple field designations
+ enum { MVX = 0, MVY = 1, REFIDX = 2 };
+
+ void Init(const InputParams& params)
+ {
+ m_bVerbose = params.m_bVerbose;
+ if (params.m_bUseLog)
+ {
+ m_LogFileOutput.open(params.m_LogFileName.c_str(), std::ofstream::out);
+ if (!m_LogFileOutput.is_open())
+ {
+ throw std::string("ERROR: ASGLog: unable to open log file");
+ }
+ }
+ }
+
+ //Convenient ofstream-style operator<< with chaining feature
+ template
+ ASGLog& operator<<(const T& output)
+ {
+ if (m_bVerbose)
+ {
+ std::cout << output;
+ }
+ if (m_LogFileOutput.is_open())
+ {
+ m_LogFileOutput << output;
+ }
+ return *this;
+ }
+
+ //Specialization for basic block info output
+ ASGLog& operator<< (const CTUDescriptor& outCTU)
+ {
+ return (*this << "CTU " << static_cast(outCTU));
+ }
+
+ ASGLog& operator<< (const CUBlock& outCU)
+ {
+ return (*this << "CU " << static_cast(outCU));
+ }
+
+ ASGLog& operator<< (const PUBlock& outPU)
+ {
+ return (*this << "PU " << static_cast(outPU));
+ }
+
+ //Specialization for basic block info output
+ ASGLog& operator<< (const BaseBlock& outBB)
+ {
+ std::stringstream ss;
+ ss << outBB.m_BHeight << "x" << outBB.m_BWidth <<
+ " (" << outBB.m_AdrX << ";" << outBB.m_AdrY << ")";
+ return (*this << ss.str());
+ }
+
+ //Specialization for MV log output
+ ASGLog& operator<< (const std::tuple& MV)
+ {
+ std::stringstream ss;
+
+ ss << "(" << std::get(MV) << ";" << std::get(MV) << ";" << std::get(MV) << ")";
+
+ return (*this << ss.str());
+ }
+
+ //Specialization for I/O stream manipulators (i.e. std::endl)
+ ASGLog& operator<< (std::ostream&(*pMan)(std::ostream&))
+ {
+ if (m_bVerbose)
+ {
+ std::cout << *pMan;
+ }
+ if (m_LogFileOutput.is_open())
+ {
+ m_LogFileOutput << *pMan;
+ }
+ return *this;
+ }
+ ~ASGLog()
+ {
+ if (m_LogFileOutput.is_open())
+ {
+ m_LogFileOutput.close();
+ }
+ }
+
+private:
+ bool m_bVerbose = false;
+ std::ofstream m_LogFileOutput;
+};
+
+#endif // MFX_VERSION > 1024
+
+#endif //__ASGLOG_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/block_structures.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/block_structures.h
new file mode 100644
index 0000000..d326a2b
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/block_structures.h
@@ -0,0 +1,349 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __BLOCK_STRUCTURES_H__
+#define __BLOCK_STRUCTURES_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "inter_test.h"
+#include "intra_test.h"
+#include "util_defs.h"
+
+enum COLOR_COMPONENT {
+ LUMA_Y = 0,
+ CHROMA_U = 1,
+ CHROMA_V = 2
+};
+
+enum PRED_TYPE {
+ INTRA_PRED = 0,
+ INTER_PRED = 1,
+};
+
+struct RefSampleAvail
+{
+ //parameter answers the question whether samples in the extention of left border to the bottom are final ones
+ //and won't be overwritten by any following blocks
+ bool LeftDown;
+ //parameter answers the question whether samples in the extention of above border to the right are final ones
+ //and won't be overwritten by any following blocks
+ bool UpRight;
+ RefSampleAvail(bool leftdown = true, bool upright = true) : LeftDown(leftdown), UpRight(upright) {}
+};
+
+//base block structure with size and coordinates
+struct BaseBlock {
+ mfxU32 m_AdrX;
+ mfxU32 m_AdrY;
+ mfxU32 m_BWidth;
+ mfxU32 m_BHeight;
+
+ BaseBlock(mfxU32 adrX = 0, mfxU32 adrY = 0, mfxU32 bWidth = 0, mfxU32 bHeight = 0)
+ : m_AdrX(adrX),
+ m_AdrY(adrY),
+ m_BWidth(bWidth),
+ m_BHeight(bHeight)
+ {}
+
+ // Returns true if two rectangles intersect or closer to each other than specified by x_sp and y_sp
+ bool CheckForIntersect(const BaseBlock& other_block, mfxU32 x_sp = 0, mfxU32 y_sp = 0) const
+ {
+ return !((m_AdrX >= other_block.m_AdrX + other_block.m_BWidth + x_sp ||
+ other_block.m_AdrX >= m_AdrX + m_BWidth + x_sp) // If one rectangle is on side of other
+
+ || (m_AdrY >= other_block.m_AdrY + other_block.m_BHeight + y_sp ||
+ other_block.m_AdrY >= m_AdrY + m_BHeight + y_sp)); // If one rectangle is above other
+ }
+
+ //Returns true if the block is inside frame boundaries
+ bool IsInRange(const mfxFrameInfo& info) const
+ {
+ return ((info.Width > 0 && info.Height > 0) &&
+ (m_AdrX + m_BWidth <= (mfxU32)info.Width) &&
+ (m_AdrY + m_BHeight <= (mfxU32)info.Height));
+ }
+
+ //Returns true if the block is inside another block
+ bool IsInBlock(const BaseBlock& otherBlock) const
+ {
+ return (m_AdrX >= otherBlock.m_AdrX && m_AdrX + m_BWidth <= otherBlock.m_AdrX + otherBlock.m_BWidth
+ && m_AdrY >= otherBlock.m_AdrY && m_AdrY + m_BHeight <= otherBlock.m_AdrY + otherBlock.m_BHeight);
+ }
+
+ void GetChildBlock(std::vector& childrenBlocks) const;
+ void GetChildRefSampleInfo(const RefSampleAvail & currAvail, const BaseBlock & ctu, std::vector& childrenRefSampleAvail) const;
+
+ bool operator==(const BaseBlock& rhs) const
+ {
+ return (m_AdrX == rhs.m_AdrX && m_AdrY == rhs.m_AdrY &&
+ m_BWidth == rhs.m_BWidth && m_BHeight == rhs.m_BHeight);
+ }
+};
+
+//Struct representing a single node in a quad-tree
+struct QuadTreeNode
+{
+ std::shared_ptr m_pParent;
+ std::vector m_Children;
+ mfxU8 m_Level;
+ QuadTreeNode() : m_pParent(nullptr), m_Level(0) {}
+ QuadTreeNode(std::shared_ptr pParent, mfxU8 level) :
+ m_pParent(pParent),
+ m_Level(level)
+ {}
+ void MakeChildren()
+ {
+ for (mfxU32 i = 0; i < 4; i++)
+ {
+ QuadTreeNode node(std::make_shared(this), m_Level + 1);
+ m_Children.push_back(node);
+ }
+ }
+};
+
+//Structure representing a quad-tree as a whole
+struct QuadTree
+{
+ QuadTreeNode root;
+ void Clear()
+ {
+ root.m_Children.clear();
+ }
+ bool IsEmpty()
+ {
+ return root.m_Children.empty();
+ }
+
+ //This recursive function fills outVec with BaseBlocks, coordinates and sizes of which correspond to
+ //the quad-tree structure specified by the quad-tree root node and the base size and coordinates of
+ //the "root node "
+ void GetQuadTreeBlocksRecur(QuadTreeNode & node, mfxU32 baseAdrX, mfxU32 baseAdrY, mfxU32 baseSize, std::vector& outVec);
+ //this function is a modification of the one above
+ //it keeps track of refSamples availability for every block
+ //thus it outputs outVec of IntraBlock structures and is used when intra prediction is enabled
+
+ //now algorithm works fine assuming that CTUs cannot lie next to each other
+ //but it limits some cases for intra/inter mix
+
+ void GetQuadTreeRefSampleAvailVector(QuadTreeNode & node, BaseBlock & currBlock, const BaseBlock & ctu, std::vector& outVec);
+
+ //TODO: develop this function taking into account that INTER coded noise blocks are written prior to INTRA prediction
+ //and include available refSamples for it
+ void GetQuadTreeRefSampleAvailVectorRecur(QuadTreeNode & node, BaseBlock& currBlock, const RefSampleAvail& currAvail, const BaseBlock& CTU, std::vector& outVec);
+};
+
+//block handling patch data which was generated via intra prediction
+struct PatchBlock : BaseBlock
+{
+ std::unique_ptr PatchData;
+ mfxU8 *m_YPlane = nullptr;
+ mfxU8 *m_UPlane = nullptr;
+ mfxU8 *m_VPlane = nullptr;
+
+ //Copy constructor
+ PatchBlock(const PatchBlock& rhs);
+
+ //Assignment operator
+ PatchBlock& operator=(const PatchBlock& rhs);
+
+ PatchBlock(const BaseBlock& BB);
+
+ //constructor that memsets PatchBlock with the particurlar sample
+ PatchBlock(const BaseBlock& BB, mfxU8 y_comp, mfxU8 u_comp, mfxU8 v_comp);
+
+ //constructor that fills PatchBlock with coresponding data from the otherPatch
+ PatchBlock(const BaseBlock& dstBlock, const PatchBlock& srcBlock);
+
+ //constructor that filles PatchBlock with coresponding data from the surface
+ PatchBlock(const BaseBlock& BB, const ExtendedSurface& surf);
+
+ //distance between current PatchBlock and other_patch counted as a sum of abs differences between luma components over all samples
+ mfxU32 CalcYSAD(const PatchBlock& otherPatch) const;
+
+ //AdrX and AdrY are given in the luma plane space (i.e. raw frame coords)
+ mfxU8 GetSampleI420(COLOR_COMPONENT comp, mfxU32 AdrX, mfxU32 AdrY) const;
+
+ //Inserts refPatch into this PatchBlock, if refPatch is located inside this PatchBlock
+ void InsertAnotherPatch(const PatchBlock & refPatch);
+};
+
+//Structure representing a prediction unit
+struct PUBlock : BaseBlock
+{
+ PUBlock(mfxU32 adrX = 0, mfxU32 adrY = 0, mfxU32 bWidth = 0, mfxU32 bHeight = 0) :
+ BaseBlock(adrX, adrY, bWidth, bHeight),
+ m_MV(),
+ m_MVP(),
+ predFlagL0(false),
+ predFlagL1(false)
+ {}
+
+ // Attention: MV and MVP are given in quarter-sample units. Consider scaling when working with PUMotionVector.
+ PUMotionVector m_MV; //Contains complete motion vector (i.e. predictor + additional vector inside SW)
+ PUMotionVector m_MVP; //Contains motion vector predictor only
+
+ // Index of this PU's MVP inside the generation pool
+ // 4 predictors are in pool, valid values are in range [0, 3]
+ // -1 indicates no MVP was applied to this PU's MV
+ mfxI16 usedMVPIndex = -1;
+
+ // Index of the generation pool used to choose MVP from for this PU
+ // -1 indicates no MVP was applied to this PU's MV
+ mfxI16 usedMVPPoolNo = -1;
+
+ // Prediction flags
+ bool predFlagL0;
+ bool predFlagL1;
+
+ //Returns a BaseBlock with coordinates that are shifted by the m_MV L0 motion vector
+ //relative to the current PU position
+ BaseBlock GetShiftedBaseBlock(REF_LIST_INDEX list) const;
+
+ //Returns true if both the block itself and blocks shifted by
+ //L0 and L1 motion vectors are inside frame boundaries
+ bool IsPUInRange(const mfxFrameInfo& info) const
+ {
+ mfxI64 posXL0 = (mfxI64)m_AdrX + (m_MV.MV[0].x >> 2);
+ mfxI64 posYL0 = (mfxI64)m_AdrY + (m_MV.MV[0].y >> 2);
+
+ mfxI64 posXL1 = (mfxI64)m_AdrX + (m_MV.MV[1].x >> 2);
+ mfxI64 posYL1 = (mfxI64)m_AdrY + (m_MV.MV[1].y >> 2);
+
+ //TODO: This may lead to slow performance for tightly packed test CTUs
+ return (IsInRange(info) &&
+ posXL0 >= 0 && (posXL0 + m_BWidth <= info.Width) &&
+ posYL0 >= 0 && (posYL0 + m_BHeight <= info.Height)&&
+ posXL1 >= 0 && (posXL1 + m_BWidth <= info.Width) &&
+ posYL1 >= 0 && (posYL1 + m_BHeight <= info.Height));
+ }
+
+ //For VERIFY purposes. Will only work correctly if ASG PU with correct predFlags is on the left-hand side
+ bool operator==(const PUBlock& rhs) const
+ {
+ return (static_cast(*this) == static_cast(rhs) &&
+ (predFlagL0 == rhs.predFlagL0) && (predFlagL1 == rhs.predFlagL1) &&
+ (!predFlagL0 || m_MV.GetL0MVTuple() == rhs.m_MV.GetL0MVTuple()) &&
+ (!predFlagL1 || m_MV.GetL1MVTuple() == rhs.m_MV.GetL1MVTuple()));
+ }
+};
+
+//Structure representing a transform unit
+struct TUBlock : BaseBlock
+{
+ //different intra modes can be set for luma and chroma
+ INTRA_MODE m_IntraModeLuma = INTRA_MODE::DC;
+ INTRA_MODE m_IntraModeChroma = INTRA_MODE::DC;
+ RefSampleAvail m_RefSampleAvail;
+
+ TUBlock(const BaseBlock& base) : BaseBlock(base) {}
+ TUBlock(const BaseBlock& base, INTRA_MODE intraModeLuma, INTRA_MODE intraModeChroma) :
+ BaseBlock(base),
+ m_IntraModeLuma(intraModeLuma),
+ m_IntraModeChroma(intraModeChroma)
+ {}
+};
+
+//Structure representing a coding unit
+struct CUBlock : BaseBlock
+{
+ // Quadtree representing TU structure
+ QuadTree m_TUQuadTree;
+ PRED_TYPE m_PredType = INTRA_PRED; //intra or inter
+ INTRA_PART_MODE m_IntraPartMode = INTRA_NONE; //partitioning into different intra modes
+ INTER_PART_MODE m_InterPartMode = INTER_NONE; //partitioning into PUs
+ std::vector m_PUVec; //PU and TU partitioning can be
+ std::vector m_TUVec; //performed independently
+
+ CUBlock(const BaseBlock& base) : BaseBlock(base) {}
+
+ void BuildPUsVector(INTER_PART_MODE mode);
+
+ //For VERIFY purposes
+ bool operator==(const CUBlock& rhs) const
+ {
+ return (static_cast(*this) == static_cast(rhs) &&
+ m_PUVec == rhs.m_PUVec);
+ }
+};
+
+// Descriptor of CTU
+struct CTUDescriptor : BaseBlock
+{
+ // Coordinates in CTUs
+ mfxU32 m_AdrXInCTU = 0;
+ mfxU32 m_AdrYInCTU = 0;
+
+ // Quadtree representing CU structure
+ QuadTree m_CUQuadTree;
+
+ // Contains CU blocks according to the m_CUQuadTree structure
+ // Gets filled in GetCUVecInCTU
+ std::vector m_CUVec;
+
+ // Contains MVP pools used in MV generator for PUs inside this CTU
+ // Gets filled in DumpMVPPools
+ std::vector> m_MVPGenPools;
+
+ CTUDescriptor(mfxU32 addr_x = 0, mfxU32 addr_y = 0, mfxU32 b_addr_x = 0, mfxU32 b_addr_y = 0, mfxU32 b_width = 0, mfxU32 b_height = 0)
+ : BaseBlock(b_addr_x, b_addr_y, b_width, b_height)
+ , m_AdrXInCTU(addr_x)
+ , m_AdrYInCTU(addr_y)
+ {};
+
+ bool operator==(const CTUDescriptor& rhs) const
+ {
+ return (m_AdrXInCTU == rhs.m_AdrXInCTU &&
+ m_AdrYInCTU == rhs.m_AdrYInCTU &&
+ m_CUVec == rhs.m_CUVec);
+ }
+
+ std::vector GetTotalPUsVec() const
+ {
+ std::vector retVec;
+ for (auto& CU : m_CUVec)
+ {
+ retVec.insert(retVec.end(), CU.m_PUVec.begin(), CU.m_PUVec.end());
+ }
+ return retVec;
+ }
+};
+
+using FrameOccRefBlockRecord = std::map>;
+
+struct InterpolWorkBlock : BaseBlock
+{
+ InterpolWorkBlock() {};
+ InterpolWorkBlock(const BaseBlock& block) :
+ BaseBlock(block),
+ m_YArr(block.m_BHeight * block.m_BWidth, LUMA_DEFAULT),
+ m_UArr(block.m_BHeight / 2 * block.m_BWidth / 2, CHROMA_DEFAULT),
+ m_VArr(block.m_BHeight / 2 * block.m_BWidth / 2, CHROMA_DEFAULT)
+ {}
+ std::vector m_YArr;
+ std::vector m_UArr;
+ std::vector m_VArr;
+};
+
+#endif // MFX_VERSION
+
+#endif //__BLOCK_STRUCTURES_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_change_descriptor.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_change_descriptor.h
new file mode 100644
index 0000000..76ee9e8
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_change_descriptor.h
@@ -0,0 +1,138 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_FRAME_CHANGE_DESCRIPTOR_H__
+#define __ASG_HEVC_FRAME_CHANGE_DESCRIPTOR_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "block_structures.h"
+#include "inputparameters.h"
+
+// Descriptor containing all information about frame
+struct FrameChangeDescriptor
+{
+ FRAME_MARKER m_changeType = SKIP; // type of frame
+ mfxU16 m_testType = UNDEFINED_TYPE; // test type (i.e. use or not split or use)
+ PROCESSING_MODE m_procMode = UNDEFINED_MODE; // processing mode
+ mfxU32 m_frameNumber = 0; // frame number in display order
+ ExtendedSurface* m_frame = nullptr; // ExtendedSurface for current frame
+ mfxU16 m_frameType = MFX_FRAMETYPE_UNKNOWN; // Frame type, used for bi-prediction decision
+ bool m_bUseBiDirSW = true; // Whether or not bi-directional search window should be used
+ // instead of one-directional
+
+ std::vector m_vCTUdescr; // vector of generated blocks inside current frame
+
+ std::list m_refDescrList0; // L0 list
+ std::list m_refDescrList1; // L1 list
+
+ std::vector m_OccupiedRefBlocks; // vector of blocks on the current frame
+ // already taken by PUs from other frames
+
+ mfxU32 GetFrameCropW() const
+ {
+ return m_frame ? m_frame->Info.CropW : 0;
+ }
+ mfxU32 GetFrameCropH() const
+ {
+ return m_frame ? m_frame->Info.CropH : 0;
+ }
+
+ FrameOccRefBlockRecord BackupOccupiedRefBlocks()
+ {
+ FrameOccRefBlockRecord ret;
+ for (const FrameChangeDescriptor& descr : m_refDescrList0)
+ {
+ ret[descr.m_frameNumber] = descr.m_OccupiedRefBlocks;
+ }
+
+ for (const FrameChangeDescriptor& descr : m_refDescrList1)
+ {
+ ret[descr.m_frameNumber] = descr.m_OccupiedRefBlocks;
+ }
+ return ret;
+ }
+
+ void RestoreOccupiedRefBlocks(FrameOccRefBlockRecord& bak)
+ {
+ for (FrameChangeDescriptor& descr : m_refDescrList0)
+ {
+ if (bak.find(descr.m_frameNumber) != bak.end())
+ {
+ descr.m_OccupiedRefBlocks = std::move(bak[descr.m_frameNumber]);
+ }
+ else
+ {
+ throw std::string("ERROR: RestoreOccupiedRefBlocks: occupied block data not found in backup for L0");
+ }
+ }
+
+ for (FrameChangeDescriptor& descr : m_refDescrList1)
+ {
+ if (bak.find(descr.m_frameNumber) != bak.end())
+ {
+ descr.m_OccupiedRefBlocks = std::move(bak[descr.m_frameNumber]);
+ }
+ else
+ {
+ throw std::string("ERROR: RestoreOccupiedRefBlocks: occupied block data not found in backup for L1");
+ }
+ }
+ return;
+ }
+
+ bool IsNewPUValid(const PUBlock & newPU) const
+ {
+ return newPU.IsPUInRange(m_frame->Info) &&
+ !CheckNewPUForIntersection(newPU);
+ }
+
+ bool CheckNewPUForIntersection(const PUBlock & newPU) const
+ {
+ if (newPU.predFlagL0)
+ {
+ const auto& frameDescrL0 = std::next(m_refDescrList0.begin(), newPU.m_MV.RefIdx.RefL0);
+ BaseBlock shiftPU_L0 = newPU.GetShiftedBaseBlock(L0);
+ for (const auto& occBlock : frameDescrL0->m_OccupiedRefBlocks)
+ {
+ if (occBlock.CheckForIntersect(shiftPU_L0)) return true;
+ }
+ }
+
+ if (newPU.predFlagL1)
+ {
+ const auto& frameDescrL1 = std::next(m_refDescrList1.begin(), newPU.m_MV.RefIdx.RefL1);
+ BaseBlock shiftPU_L1 = newPU.GetShiftedBaseBlock(L1);
+ for (const auto& occBlock : frameDescrL1->m_OccupiedRefBlocks)
+ {
+ if (occBlock.CheckForIntersect(shiftPU_L1)) return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+
+#endif
+
+#endif // __ASG_HEVC_FRAME_CHANGE_DESCRIPTOR_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_marker.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_marker.h
new file mode 100644
index 0000000..3f5b360
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_marker.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_FRAME_MAKER_H__
+#define __ASG_FRAME_MAKER_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "inputparameters.h"
+
+inline bool GenerateInterMBs(mfxU16 test_type) { return !!(test_type & (~(GENERATE_INTRA | GENERATE_SPLIT))); }
+inline bool HasBFramesInGOP(mfxU16 refDist) { return refDist > 1; }
+
+class FrameMarker
+{
+public:
+ void PreProcessStreamConfig(InputParams & params);
+private:
+ void BuildRefLists(const InputParams & params);
+ void TagFrames(const InputParams & params);
+ bool HasAlreadyUsedRefs(mfxU32 frame, mfxU8 list);
+ void SetRefList(mfxU32 frame, mfxU8 list, std::vector & refFrames, mfxU32 & num_gen);
+
+ std::vector m_vProcessingParams; // FrameProcessingParam for entire stream
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_FRAME_MAKER_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_processor.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_processor.h
new file mode 100644
index 0000000..044488a
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_processor.h
@@ -0,0 +1,172 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_FRAME_PROCESSOR_H__
+#define __ASG_HEVC_FRAME_PROCESSOR_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+#include
+
+#include "util_defs.h"
+
+#include "block_structures.h"
+#include "frame_change_descriptor.h"
+#include "intra_test.h"
+#include "inter_test.h"
+#include "mvmvp_processor.h"
+#include "random_generator.h"
+
+class FrameProcessor
+{
+public:
+ FrameProcessor() = default;
+
+ void Init(const InputParams ¶ms);
+
+ void ProcessFrame(FrameChangeDescriptor & frame_descr);
+
+ // For verification
+ void GenQuadTreeInCTUWithBitMask(CTUDescriptor& CTU, mfxU32 bitMask);
+
+private:
+
+ //work with particular samples in the frame
+ bool IsSampleAvailable(mfxU32 X, mfxU32 Y);
+ mfxU8 GetSampleI420(COLOR_COMPONENT comp, mfxU32 AdrX, mfxU32 AdrY, mfxFrameSurface1* surf);
+
+ void GenRandomQuadTreeStructure(QuadTree & QT, mfxU8 minDepth, mfxU8 maxDepth);
+ void GenCUVecInCTU(CTUDescriptor & ctu, mfxU16 test_type);
+ void GenRandomTUQuadTreeInCU(CUBlock & cu_block);
+ void GenRandomCUQuadTreeInCTU(CTUDescriptor & ctu);
+ void GetRefSampleAvailFlagsForTUsInCTU(CTUDescriptor & CTU);
+ //checking if reference samples for INTRA prediction of the current block are mostly constant
+ //TODO: develop flexible criterion of mostly uniform ref samples
+ bool IsBlockUniform(const BaseBlock& block, PatchBlock& tempFrame);
+ void AlterBorderSamples(const BaseBlock& block, PatchBlock& tempFrame);
+ //counting the particurlar intra mode prediction for TU
+ void MakeTUIntraPrediction(const TUBlock& refBlock, PatchBlock& targetBlock);
+ //worst intra mode is found here in order to reach more contrast
+ void ChooseContrastIntraMode(const BaseBlock & block, std::vector& tu_block_vec, PatchBlock& frame);
+ //function that makes intra prediction for refBlock of particular colorComp plane and saves it into currPlane buffer
+ void GetIntraPredPlane(const BaseBlock& refBlock, INTRA_MODE currMode, const PatchBlock& frame, COLOR_COMPONENT colorComp, mfxU8* currPlane);
+ //function that makes a patch from refBlock with all color components intra predicted
+ PatchBlock GetIntraPatchBlock(const TUBlock & refBlock, const PatchBlock& patch);
+ //intra prediction for particluar TU block and particular intra mode is made here
+ void MakeIntraPredInCTU(CTUDescriptor & ctu, FrameChangeDescriptor & descr);
+
+ //only TU tree intraPartitionMode is determined here
+ void MakeIntraCU(CUBlock & cu_block);
+ void MakeInterCU(CUBlock & cu_block, mfxU16 test_type);
+ mfxU8 CeilLog2(mfxU32 size);
+ //methods used for INTRA prediction
+
+ //filling vector with adjacent samples
+ //all coordinates and sizes here are measured in samples of colorComp
+ void FillIntraRefSamples(mfxU32 cSize, mfxU32 cAdrX, mfxU32 cAdrY, const PatchBlock& frame, COLOR_COMPONENT colorComp, std::vector& refSamples);
+
+ //choosing filter for the vector of reference samples and making it if needed
+ void ThreeTapFilter(std::vector& RefSamples, mfxU8 size);
+ void StrongFilter(std::vector& RefSamples, mfxU8 size);
+ FILTER_TYPE ChooseFilter(std::vector& RefSamples, mfxU8 size, INTRA_MODE intra_type);
+ FILTER_TYPE MakeFilter(std::vector& RefSamples, mfxU8 size, INTRA_MODE type);
+
+ //making a projection if needed
+ mfxU8 MakeProjRefArray(const std::vector& RefSamples, mfxU8 size, const IntraParams& IntraMode, std::vector& ProjRefSamples);
+
+ //generating prediction using a perticular mode and saving it in IntraPatch structure
+ void PlanarPrediction(const std::vector& RefSamples, mfxU8 size, mfxU8 * patch);
+ void DCPrediction(const std::vector& RefSamples, mfxU8 size, mfxU8 * patch);
+ void AngularPrediction(const std::vector& RefSamples, mfxU8 size, IntraParams& IntraMode, mfxU8 * patch);
+ void MakePostFilter(const std::vector& RefSamples, mfxU8 cSize, INTRA_MODE currMode, mfxU8* currPlane);
+ void GenerateIntraPrediction(const std::vector& RefSamples, mfxU8 blockSize, INTRA_MODE currMode, mfxU8* currPlane);
+
+ //function generating INTRA prediction for TU leaves of the tree
+ void ApplyTUIntraPrediction(const TUBlock & block, ExtendedSurface& surf);
+ void ApplyIntraPredInCTU(const CTUDescriptor & CTU, FrameChangeDescriptor & frame_descr);
+ void PutPatchIntoFrame(const PatchBlock & BP, mfxFrameSurface1& surf);
+ //end of intra methods
+
+ //methods used for INTER prediction
+ void GenPredFlagsForPU(PUBlock & PU, mfxU16 frameType);
+ void ApplyInterPredInCTU(CTUDescriptor & CTU, FrameChangeDescriptor & frame_descr);
+
+ void GenCTUParams(FrameChangeDescriptor & frame_descr);
+ void GenAndApplyPrediction(FrameChangeDescriptor & frame_descr);
+ bool MakeInterPredInCTU(CTUDescriptor & CTU, FrameChangeDescriptor & frameDescr);
+
+ void PutNoiseBlocksIntoFrames(const PUBlock & pu, const FrameChangeDescriptor & frameDescr, mfxU32 num_coeff = 12, mfxU32 level = 48);
+ void FillInBlock4x4(mfxU32 num_coeff, mfxU32 level, mfxU8 block[16]);
+ void FillDeltaBlocks4x4(mfxI8 blockL0[16], mfxI8 blockL1[16]);
+ void ApplyDeltaPerPixel(const PUBlock & PU, const mfxI8 deltaBlock[16], const mfxU8 inBlock[16], mfxU8 outBlock[16]);
+ void Inverse4x4(mfxI32 *src, mfxU32 s_pitch, mfxI32 *dst, mfxU32 d_pitch);
+ void PutBlock4x4(mfxU32 x0, mfxU32 y0, mfxU8 block[16], mfxFrameSurface1 * surf);
+ mfxU8 ClipIntToChar(mfxI32 x);
+ void TraceBackAndPutBlockIntoFrame(const PUBlock & PU, FrameChangeDescriptor & descr);
+ InterpolWorkBlock GetInterpolWorkBlockPreWP(const BaseBlock & PU, std::pair fractOffset, mfxFrameSurface1 * surfTo);
+ PatchBlock ApplyDefaultWeightedPrediction(InterpolWorkBlock & workBlockL0);
+ PatchBlock ApplyDefaultWeightedPrediction(InterpolWorkBlock & workBlockL0, InterpolWorkBlock & workBlockL1);
+
+ mfxU8 SetCorrectMVPBlockSize(mfxU8 mvpBlockSizeParam);
+
+ void UnlockSurfaces(FrameChangeDescriptor & frame_descr);
+
+ void GenRandomQuadTreeSubstrRecur(QuadTreeNode & node, mfxU8 minDepth, mfxU8 maxDepth);
+ // For verification
+ void GenQuadTreeWithBitMaskRecur(QuadTreeNode& node, mfxU32 bitMask);
+ // Used only in quarter-pixel interpolation. Luma sample value should fit in mfxI32.
+ mfxI32 GetClippedSample(COLOR_COMPONENT comp, mfxI32 AdrX, mfxI32 AdrY, mfxFrameSurface1* surf);
+
+ mfxI32 CalculateLumaPredictionSamplePreWP(const std::pair& refSampleLocationFull,
+ const std::pair& refSampleLocationFract, mfxFrameSurface1* refSurface);
+
+ mfxI32 ApplyVerticalSubSampleLumaFilter(mfxU32 x, mfxU32 y, mfxFrameSurface1 * refSurface, const mfxI32* coeff);
+ mfxI32 ApplyHorizontalSubSampleLumaFilter(mfxU32 x, mfxU32 y, mfxFrameSurface1 * refSurface, const mfxI32* coeff);
+
+ // These function used in only in CalculateLumaPredictionSamplePreWP
+ // In specifictation default weighted prediction is the final scaling step for sample prediction. (p.168)
+ mfxU8 GetDefaultWeightedPredSample(mfxI32 predSampleLX);
+ mfxU8 GetDefaultWeightedPredSample(mfxI32 predSampleL0, mfxI32 predSampleL1);
+
+ mfxU32 m_Height = 0; // in pixels
+ mfxU32 m_Width = 0;
+ mfxU32 m_HeightInCTU = 0; // in CTUs
+ mfxU32 m_WidthInCTU = 0;
+ mfxU32 m_CropH = 0; // Unaligned size
+ mfxU32 m_CropW = 0;
+
+ mfxU16 m_SubPelMode = 0; // Valid values are: 0, 1 or 3
+
+ bool m_IsForceExtMVPBlockSize = false;
+ mfxU32 m_ForcedExtMVPBlockSize = 0;
+ mfxU32 m_GenMVPBlockSize = 0;
+
+ CTUStructure m_CTUStr; // Some parameters related to CTU generation, i.e. restrictions on CTUs
+
+ PROCESSING_MODE m_ProcMode = UNDEFINED_MODE; // processing mode
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_HEVC_FRAME_PROCESSOR_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_reorder.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_reorder.h
new file mode 100644
index 0000000..b8647d2
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/frame_reorder.h
@@ -0,0 +1,146 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_FRAME_REORDER_H__
+#define __ASG_FRAME_REORDER_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+#include
+#include "inputparameters.h"
+
+enum NALU_TYPE
+{
+ TRAIL_N = 0,
+ TRAIL_R,
+ RASL_N,
+ RASL_R,
+ IDR_W_RADL,
+ CRA_NUT
+};
+
+inline bool isBFF(mfxVideoParam const & video)
+{
+ return ((video.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_BOTTOM) == MFX_PICSTRUCT_FIELD_BOTTOM);
+}
+
+mfxI32 GetFrameNum(bool bField, mfxI32 Poc, bool bSecondField);
+
+mfxU8 GetFrameType(
+ mfxVideoParam const & video,
+ mfxU32 pictureOrder,
+ bool isPictureOfLastFrame);
+
+class FrameReorder
+{
+public:
+ FrameReorder(const InputParams & params) :
+ m_nMaxFrames(params.m_numFrames),
+ m_BRefType(params.m_BRefType),
+ m_GopOptFlag(params.m_GopOptFlag),
+ m_NumRef(params.m_NumRef),
+ m_UseGPB(params.m_UseGPB),
+ m_NumRefActiveP(params.m_NumRefActiveP),
+ m_NumRefActiveBL0(params.m_NumRefActiveBL0),
+ m_NumRefActiveBL1(params.m_NumRefActiveBL1),
+ m_lastIdr(0),
+ m_anchorPOC(-1)
+ {};
+ ExternalFrame CreateExternalFrame(mfxI32 order, const mfxVideoParam& param);
+ inline size_t GetBufferedQueueSize() const
+ {
+ return m_queue.size();
+ };
+private:
+ mfxU32 m_nMaxFrames;
+ mfxU16 m_BRefType;
+ mfxU16 m_GopOptFlag;
+ mfxU16 m_NumRef;
+ bool m_UseGPB;
+ mfxU16 m_NumRefActiveP;
+ mfxU16 m_NumRefActiveBL0;
+ mfxU16 m_NumRefActiveBL1;
+
+ class LastReorderedFieldInfo
+ {
+ public:
+ mfxI32 m_poc;
+ bool m_bReference;
+ bool m_bFirstField;
+
+ LastReorderedFieldInfo() :
+ m_poc(-1),
+ m_bReference(false),
+ m_bFirstField(false) {}
+
+ void Reset()
+ {
+ m_poc = -1;
+ m_bReference = false;
+ m_bFirstField = false;
+ }
+ void SaveInfo(Frame const & frame)
+ {
+ m_poc = frame.Poc;
+ m_bReference = ((frame.Type & MFX_FRAMETYPE_REF) != 0);
+ m_bFirstField = !frame.bSecondField;
+ }
+ void CorrectFrameInfo(Frame & frame)
+ {
+ if (!isCorrespondSecondField(frame))
+ return;
+ // copy params to the 2nd field
+ if (m_bReference)
+ frame.Type |= MFX_FRAMETYPE_REF;
+ }
+ bool isCorrespondSecondField(Frame const & frame)
+ {
+ if (m_poc + 1 != frame.Poc || !frame.bSecondField || !m_bFirstField)
+ return false;
+ return true;
+ }
+ bool bFirstField() { return m_bFirstField; }
+ };
+
+ typedef std::vector FrameArray;
+ typedef std::vector ::iterator FrameIterator;
+ FrameArray m_queue;
+ LastReorderedFieldInfo m_lastFieldInfo;
+ FrameArray m_dpb;
+ mfxI32 m_lastIdr; // for POC calculation
+ mfxI32 m_anchorPOC; // for P-Pyramid
+ Frame m_lastFrame;
+
+ mfxU8 GetNALUType(Frame const & frame, bool isRAPIntra);
+ bool HasL1(mfxI32 poc);
+ mfxU32 BRefOrder(mfxU32 displayOrder, mfxU32 begin, mfxU32 end, mfxU32 counter, bool & ref);
+ mfxU32 GetBiFrameLocation(mfxU32 displayOrder, mfxU32 num, bool &ref);
+ mfxU32 BPyrReorder(const std::vector & bframes);
+ FrameIterator Reorder(bool flush, bool bFields);
+ FrameIterator Reorder(FrameIterator begin, FrameIterator end, bool flush, bool bFields);
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_FRAME_REORDER_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/generator.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/generator.h
new file mode 100644
index 0000000..c11343b
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/generator.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __GENERATOR_H__
+#define __GENERATOR_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "refcontrol.h"
+#include "test_processor.h"
+
+class Generator : public TestProcessor {
+public:
+ explicit Generator() {}
+
+ ~Generator() {}
+
+private:
+ void Init() override;
+
+ // Get surface and load new YUV frame from file to it
+ ExtendedSurface* PrepareSurface() override;
+
+ // Save all data
+ void DropFrames() override;
+ void DropBuffers(ExtendedSurface& surf) override;
+ virtual void SavePSData() override;
+
+ CSmplYUVReader m_FileReader;
+ CSmplYUVWriter m_FileWriter;
+ BufferWriter m_BufferWriter;
+};
+
+#endif // MFX_VERSION
+
+#endif // __GENERATOR_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/hevc_defs.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/hevc_defs.h
new file mode 100644
index 0000000..fd8f7da
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/hevc_defs.h
@@ -0,0 +1,72 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __HEVC_DEFS_H__
+#define __HEVC_DEFS_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+//HEVC standard-defined limits on block sizes in terms of luma samples
+
+//CTUs
+#define HEVC_MIN_CTU_SIZE 16
+#define HEVC_MAX_CTU_SIZE 64
+
+#define HEVC_MIN_LOG2_CTU_SIZE 4
+#define HEVC_MAX_LOG2_CTU_SIZE 6
+
+//CUs
+//Min size is 8x8, max size is equal to current CTU size
+#define HEVC_MIN_CU_SIZE 8
+#define HEVC_MIN_LOG2_CU_SIZE 3
+
+//PUs
+//Min size is either 4x8 or 8x4, max size is equal to current CU size
+#define HEVC_MIN_PU_SIZE_LO 4
+#define HEVC_MIN_PU_SIZE_HI 8
+
+//TUs
+//Min size is 4x4, max size is 32x32 (cannot be larger than CU min size)
+#define HEVC_MIN_TU_SIZE 4
+#define HEVC_MAX_TU_SIZE 32
+
+#define HEVC_MIN_LOG2_TU_SIZE 2
+#define HEVC_MAX_LOG2_TU_SIZE 5
+
+//Maximum QP value
+#define HEVC_MAX_QP 51
+
+// Luma sub-sample interpolation filter
+#define LUMA_SUBSAMPLE_INTERPOLATION_FILTER_POSITIONS 4
+#define LUMA_TAPS_NUMBER 8
+
+const mfxI32 LUMA_SUBSAMPLE_FILTER_COEFF[LUMA_SUBSAMPLE_INTERPOLATION_FILTER_POSITIONS][LUMA_TAPS_NUMBER] =
+{
+ { 0, 0, 0, 1, 0, 0, 0, 0 },
+ { -1, 4, -10, 58, 17, -5, 1, 0 },
+ { -1, 4, -11, 40, 40, -11, 4, -1 },
+ { 0, 1, -5, 17, 58, -10, 4, -1 },
+};
+
+#endif // MFX_VERSION
+
+#endif //__HEVC_DEFS_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/inputparameters.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/inputparameters.h
new file mode 100644
index 0000000..f01df8e
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/inputparameters.h
@@ -0,0 +1,234 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_INPUT_PARAMETERS_H__
+#define __ASG_HEVC_INPUT_PARAMETERS_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+#include
+#include
+
+#include "base_allocator.h"
+#include "hevc_defs.h"
+#include "util_defs.h"
+
+enum PROCESSING_MODE
+{
+ UNDEFINED_MODE = 0,
+ GENERATE,
+ VERIFY
+};
+
+// TODO: use std::bitset instead
+enum
+{
+ UNDEFINED_TYPE = 0,
+ GENERATE_MV = 1 << 0,
+ GENERATE_PREDICTION = 1 << 1,
+ GENERATE_SPLIT = 1 << 2,
+ GENERATE_INTRA = 1 << 3,
+ GENERATE_INTER = 1 << 4,
+ GENERATE_PICSTRUCT = 1 << 5,
+ GENERATE_REPACK_CTRL = 1 << 6
+};
+
+enum FRAME_MARKER
+{
+ GEN = 1,
+ MOD = 2,
+ SKIP = 3
+};
+
+// Restrictions on CTU for generation of noisy blocks
+struct CTUStructure
+{
+ //Below are default values that should be most relaxed
+ mfxU32 log2CTUSize = HEVC_MIN_LOG2_CTU_SIZE;
+ mfxU32 CTUSize = 1 << log2CTUSize;
+ mfxU32 minLog2CUSize = HEVC_MIN_LOG2_CU_SIZE;
+ mfxU32 maxLog2CUSize = HEVC_MIN_LOG2_CTU_SIZE; //NB: can be less than CTU size inside asg-hevc
+ //Standard specifies that CTU size is set equal to
+ //1 << maxLog2CUSize, but this is for encoder only:
+ //inside asg-hevc, we will maintain this separate upper
+ //limit on max CU size
+
+ mfxU32 minLog2TUSize = HEVC_MIN_LOG2_TU_SIZE; //Must be less than minLog2CUSize
+ mfxU32 maxLog2TUSize = HEVC_MIN_LOG2_CTU_SIZE;
+ mfxU32 maxTUQTDepth = HEVC_MAX_LOG2_CTU_SIZE - HEVC_MIN_LOG2_TU_SIZE; //Overrides min TU size while
+ //building TU quadtree in CU
+ mfxU32 CTUMaxNum = 128;
+ mfxU32 MVRange = 12;
+ mfxU32 CTUDist = 3; //Default minimum distance between generated CTU blocks in terms of CTU
+
+ bool bCUToPUSplit = true; //Whether or not CUs should be further split into PUs
+ bool bForceSymmetricPU = false; //Support only symmetric modes for CU into PU partioning
+
+ inline mfxU32 GetMaxNumCuInCtu()
+ {
+ return (1 << (2 * (log2CTUSize - HEVC_MIN_LOG2_CU_SIZE)));
+ }
+};
+
+struct Frame
+{
+ mfxU32 DisplayOrder = 0xffffffff;
+ mfxU32 Type = MFX_FRAMETYPE_UNKNOWN;
+ mfxU8 NalType = 0xff;
+ mfxI32 Poc = -1;
+ mfxU32 Bpo = 0xffffffff;
+ bool bSecondField = false;
+ bool bBottomField = false;
+ mfxI32 LastRAP = -1;
+ mfxI32 IPoc = -1;
+ mfxI32 PrevIPoc = -1;
+ mfxI32 NextIPoc = -1;
+};
+
+struct ExternalFrame
+{
+ mfxU32 DisplayOrder;
+ mfxU32 Type;
+ mfxU8 NalType;
+ mfxI32 Poc;
+ bool bSecondField;
+ bool bBottomField;
+ std::vector ListX[2];
+};
+
+// Structure which used for initial stream marking
+
+struct FrameProcessingParam
+{
+ FRAME_MARKER Mark = SKIP;
+ std::vector ReferencesL0;
+ std::vector ReferencesL1;
+
+ mfxU32 DisplayOrder = 0xffffffff;
+ mfxU32 EncodedOrder = 0xffffffff;
+
+ mfxU32 Type = MFX_FRAMETYPE_UNKNOWN;
+ std::vector ListX[2];
+
+ FrameProcessingParam & operator= (const ExternalFrame& rhs)
+ {
+ DisplayOrder = rhs.DisplayOrder;
+ Type = rhs.Type;
+ ListX[0] = rhs.ListX[0];
+ ListX[1] = rhs.ListX[1];
+
+ return *this;
+ }
+};
+
+struct Thresholds
+{
+ // asg should exit with non-zero if MV/split-passrate is lower than threshold
+ mfxU32 mvThres = 0;
+ mfxU32 splitThres = 0;
+};
+
+class InputParams
+{
+public:
+
+ void ParseInputString(msdk_char **strInput, mfxU8 nArgNum);
+
+ mfxU16 m_TestType = UNDEFINED_TYPE;
+ PROCESSING_MODE m_ProcMode = UNDEFINED_MODE;
+
+ mfxU32 m_width = 0;
+ mfxU32 m_height = 0;
+ mfxU32 m_numFrames = 0;
+
+ mfxU16 m_PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
+ mfxU16 m_BRefType = MFX_B_REF_OFF;
+ mfxU16 m_GopOptFlag = 0;
+ mfxU16 m_GopSize = 1;
+ mfxU16 m_RefDist = 1;
+ mfxU16 m_NumRef = 1;
+ mfxU16 m_nIdrInterval = 0xffff;
+ mfxU16 m_NumRefActiveP = 3;
+ mfxU16 m_NumRefActiveBL0 = 3;
+ mfxU16 m_NumRefActiveBL1 = 1;
+ bool m_UseGPB = true;
+
+ // Which blocks to use (it might be possible to forbid CUs of some sizes)
+ // TODO: extend and add to code
+ mfxU16 m_block_size_mask = 3; // 0 - invalid, 001 - 16x16, 010 - 32x32, 100 - 64x64
+
+ // Specifies which sub pixel precision mode is used in motion prediction.
+ // Valid values are: 0 ; 1 ; 3 (integer, half, quarter). 0x0 is default
+ mfxU16 m_SubPixelMode = 0;
+
+ bool m_bVerbose = false;
+ bool m_bPrintHelp = false;
+ bool m_bUseLog = false;
+
+ // Specifies the external MVP block size which is written to mfxFeiHevcEncMVPredictors::BlockSize
+ // Valid values are: 0 ; 1; 2; 3 (no MVP, MVP enabled for 16x16/32x32/64x64 block)
+ bool m_bIsForceExtMVPBlockSize = false;
+ mfxU32 m_ForcedExtMVPBlockSize = 0;
+
+ // Specifies MVP block size used in the actual generation
+ // Valid values are the same as for m_ForcedExtMVPBlockSize
+ mfxU32 m_GenMVPBlockSize = 0;
+
+ // For repack ctrl
+ mfxU32 m_NumAddPasses = 8; // Number of additional passes w/o first pass with clear QP value
+ mfxU8 m_DeltaQP[8] = {1,2,3,3,4,4,4,4};
+ mfxU8 m_InitialQP = 26;
+
+ msdk_string m_InputFileName;
+ msdk_string m_OutputFileName;
+
+ msdk_string m_LogFileName;
+
+ msdk_string m_PredBufferFileName; // filename for predictors ext buffer output
+ msdk_string m_PicStructFileName; // filename for pictures structure output
+
+ msdk_string m_PakCtuBufferFileName; // filename for PAK CTU ext buffer input
+ msdk_string m_PakCuBufferFileName; // filename for PAK CU ext buffer input
+
+ msdk_string m_RepackCtrlFileName; // filename for repack constrol output/input
+ msdk_string m_RepackStrFileName; // filename for multiPakStr input
+ msdk_string m_RepackStatFileName; // filename for repack stat input
+
+ CTUStructure m_CTUStr;
+
+ Thresholds m_Thresholds;
+ // Actual number of MV predictors enabled in FEI ENCODE. Used in verification mode
+ mfxU16 m_NumMVPredictors = 4;
+
+ std::vector m_vProcessingParams; // FrameProcessingParam for entire stream
+
+private:
+ mfxU16 ParseSubPixelMode(msdk_char * strRawSubPelMode);
+ int GetIntArgument(msdk_char ** strInput, mfxU8 index, mfxU8 nArgNum);
+ msdk_string GetStringArgument(msdk_char ** strInput, mfxU8 index, mfxU8 nArgNum);
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_HEVC_INPUT_PARAMETERS_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/inter_test.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/inter_test.h
new file mode 100644
index 0000000..b6d9d99
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/inter_test.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//Some consts and enums for intra prediction
+
+#ifndef __INTER_TEST_H__
+#define __INTER_TEST_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "mfxdefs.h"
+
+enum INTER_PART_MODE {
+ INTER_NONE = -1,
+ INTER_2Nx2N = 0,
+ INTER_2NxN,
+ INTER_Nx2N,
+ INTER_NxN,
+ INTER_2NxnU,
+ INTER_2NxnD,
+ INTER_nLx2N,
+ INTER_nRx2N
+};
+const mfxU32 INTER_PART_MODE_NUM = 8;
+const mfxU32 INTER_8x8CU_PART_MODE_NUM = 3; //For 8x8 CUs only first 3 modes are available
+const mfxU32 INTER_SYMM_PART_MODE_NUM = 4; //First 4 modes are symmetric
+
+#endif // MFX_VERSION
+
+#endif //__INTER_TEST_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/intra_test.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/intra_test.h
new file mode 100644
index 0000000..8c0f464
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/intra_test.h
@@ -0,0 +1,141 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//Some consts and enums for intra prediction
+
+#ifndef __INTRA_TEST_H__
+#define __INTRA_TEST_H__
+
+#include "mfxvideo.h"
+#include
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "mfxdefs.h"
+
+enum INTRA_PART_MODE {
+ INTRA_NONE = -1,
+ INTRA_2Nx2N = 0,
+ INTRA_NxN = 1
+};
+
+enum INTRA_MODE {
+ NONE = -1,
+ PLANAR = 0,
+ DC = 1,
+ ANG2 = 2,
+ ANG3 = 3,
+ ANG4 = 4,
+ ANG5 = 5,
+ ANG6 = 6,
+ ANG7 = 7,
+ ANG8 = 8,
+ ANG9 = 9,
+ ANG10_HOR = 10,
+ ANG11 = 11,
+ ANG12 = 12,
+ ANG13 = 13,
+ ANG14 = 14,
+ ANG15 = 15,
+ ANG16 = 16,
+ ANG17 = 17,
+ ANG18 = 18,
+ ANG19 = 19,
+ ANG20 = 20,
+ ANG21 = 21,
+ ANG22 = 22,
+ ANG23 = 23,
+ ANG24 = 24,
+ ANG25 = 25,
+ ANG26_VER = 26,
+ ANG27 = 27,
+ ANG28 = 28,
+ ANG29 = 29,
+ ANG30 = 30,
+ ANG31 = 31,
+ ANG32 = 32,
+ ANG33 = 33,
+ ANG34 = 34
+};
+const mfxU32 INTRA_MODE_NUM = 35; //Planar + DC + 33 angular modes (2 thru 34)
+
+enum INTRA_DIR {
+ HORIZONTAL,
+ VERTICAL,
+ DIR_NOT_SPECIFIED
+};
+
+enum FILTER_TYPE {
+ NO_FILTER,
+ THREE_TAP_FILTER,
+ STRONG_INTRA_SMOOTHING_FILTER
+};
+
+const mfxI8 angParam[] = { 32, 26, 21, 17, 13, 9, 5, 2, 0, -2, -5, -9, -13, -17, -21, -26, -32 };
+const mfxI32 inverseAngParam[] = { -256, -315, -390, -482, -630, -910, -1638, -4096 };
+
+inline bool isValidIntraMode(INTRA_MODE mode)
+{
+ // NONE is not a valid mode to operate
+ return PLANAR <= mode && mode <= ANG34;
+}
+
+struct IntraParams {
+ INTRA_MODE intraMode = NONE;
+ INTRA_DIR direction = DIR_NOT_SPECIFIED;
+ mfxI8 intraPredAngle = 0;
+ mfxI32 invAngle = 0;
+
+ IntraParams(INTRA_MODE mode)
+ : intraMode(mode)
+ {
+ if (!isValidIntraMode(mode))
+ {
+ throw std::string("ERROR: IntraParams: incorrect intra mode");
+ }
+
+ if (intraMode == PLANAR || intraMode == DC)
+ {
+ return;
+ }
+
+ if (intraMode < ANG18)
+ {
+ direction = HORIZONTAL;
+ intraPredAngle = angParam[intraMode - 2];
+
+ if (intraMode > ANG10_HOR)
+ invAngle = inverseAngParam[18 - intraMode];
+ }
+ else
+ {
+ direction = VERTICAL;
+ intraPredAngle = -angParam[intraMode - 18];
+
+ if (intraMode < ANG26_VER)
+ invAngle = inverseAngParam[intraMode - 18];
+ }
+ }
+};
+
+#endif // MFX_VERSION
+
+#endif // !__INTRA_TEST_H__
+
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/mvmvp_processor.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/mvmvp_processor.h
new file mode 100644
index 0000000..f0368ca
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/mvmvp_processor.h
@@ -0,0 +1,132 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_MVMVP_PROCESSOR_H__
+#define __ASG_HEVC_MVMVP_PROCESSOR_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+#include
+
+#include "block_structures.h"
+#include "frame_change_descriptor.h"
+#include "random_generator.h"
+
+class MVMVPProcessor
+{
+public:
+ MVMVPProcessor() = delete;
+
+ MVMVPProcessor(mfxU32 extGenMVPBlockSize, mfxU16 extSubPelMode) :
+ m_GenMVPBlockSize(extGenMVPBlockSize),
+ m_SubPelMode(extSubPelMode), m_DoUseIntra(false) {}
+
+ // Initiates an MVMVPProcessor with data from CTU
+ void InitMVPGridData(const CTUDescriptor& CTU, const FrameChangeDescriptor & frameDescr);
+
+ bool GenValidMVMVPForPU(PUBlock & PU, const FrameChangeDescriptor & frameDescr);
+
+ bool GenValidMVForPU(PUBlock & PU, const FrameChangeDescriptor & frameDescr);
+
+ void FillFrameMVPExtBuffer(FrameChangeDescriptor& frameDescr);
+
+ void GetMVPPools(std::vector> &outMVPPools);
+
+private:
+
+ //Structure representing a single MVP block
+ struct MVPBlock : BaseBlock
+ {
+ MVPBlock(mfxU32 adrX = 0, mfxU32 adrY = 0, mfxU32 bWidth = 0, mfxU32 bHeight = 0) :
+ BaseBlock(adrX, adrY, bWidth, bHeight), mvpPoolGroupNo(MVP_INVALID_POOL_GROUP) {}
+
+ // No. of generation MVP pool group
+ // For each two MVP blocks from the same group
+ // MVP pools should be equal
+ mfxI32 mvpPoolGroupNo = MVP_INVALID_POOL_GROUP;
+
+ bool IsAlreadyInGroup() const { return mvpPoolGroupNo != MVP_INVALID_POOL_GROUP; }
+
+ bool IsInGroup(mfxI32 extGroupNo) const { return mvpPoolGroupNo == extGroupNo; }
+
+ void SetGroup(mfxI32 extGroupNo) { mvpPoolGroupNo = extGroupNo; }
+
+ mfxI32 GetGroupNo() const { return mvpPoolGroupNo; }
+ };
+
+ static constexpr mfxI32 MVP_INVALID_POOL_GROUP = -1;
+ mfxU32 m_GenMVPBlockSize = 0;
+ mfxU16 m_SubPelMode = 0;
+
+ std::vector m_mvpBlockGrid;
+
+ // Type to store 32x32 MVP blocks. First value is actual BaseBlock
+ // Second one is no. (m_mvpBlockGrid) of left upper 16x16 block in the group
+ typedef std::pair MVP32x32BlockGroup;
+
+ std::vector> m_mvpPools;
+
+ // Checking test case type
+ bool m_DoUseIntra = false;
+
+ // Custom hasher used in unordered_map
+ struct BaseBlockHasher
+ {
+ std::size_t operator() (const BaseBlock& key) const
+ {
+ return std::hash()(key.m_AdrX) ^ ((std::hash()(key.m_AdrY) << 1) >> 1)
+ ^ (std::hash()(key.m_BHeight) << 1) ^ (std::hash()(key.m_BWidth) >> 1);
+ }
+ };
+
+ std::unordered_map m_PUtoMVPPoolGroupMap;
+
+ PUMotionVector GenerateMVP(const CTUDescriptor& CTU, const FrameChangeDescriptor& frameChangeDescr);
+
+ PUMotionVector GenerateMV(const FrameChangeDescriptor& frameDescr);
+
+ mfxI32 GetRandomMVComponent(mfxI32 lower, mfxI32 upper);
+
+ // Functions used to put all PUs in CTU and MVP blocks in the correct MVP pool groups
+ // according to INTER splitting and MVPBlockSize parameter
+ // All these functions return actual number of MVP pool groups to generate
+ mfxI32 ConstructMVPPoolGroups(const CTUDescriptor& CTU);
+
+ mfxI32 PutPUAndMVPBlocksIn16x16MVPPoolGroups(const CTUDescriptor& CTU);
+ mfxI32 PutPUAndMVPBlocksIn32x32MVPPoolGroups(const CTUDescriptor& CTU);
+ mfxI32 PutPUAndMVPBlocksInSingleMVPPoolGroup(const CTUDescriptor& CTU);
+
+ // Functions used in MVP Ext buffer dumping
+
+ // Gets offset in mfxExtFeiHevcEncMVPredictors::Data buffer for the provided MVP block element
+ mfxU32 CalculateOffsetInMVPredictorsBuffer(mfxU32 bufferPitch, const MVPBlock& mvpBlock);
+
+ // Fill one mfxFeiHevcEncMVPredictors element in mfxExtFeiHevcEncMVPredictors::Data buffer
+ // associated with provided MVP block
+ void PutMVPIntoExtBuffer(const MVPBlock& mvpBlock, mfxExtFeiHevcEncMVPredictors* outputBuf);
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_HEVC_MVMVP_PROCESSOR_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/random_generator.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/random_generator.h
new file mode 100644
index 0000000..445e494
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/random_generator.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_RANDOM_GENERATOR_H__
+#define __ASG_HEVC_RANDOM_GENERATOR_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+
+#include "block_structures.h"
+
+
+class ASGRandomGenerator
+{
+public:
+ static ASGRandomGenerator& GetInstance();
+
+ mfxI32 GetRandomNumber(mfxI32 min, mfxI32 max);
+ mfxI32 GetRandomSign();
+ bool GetRandomBit();
+ mfxI32 GetRandomPicField();
+
+ // This method is considered as DEPRECATED - DO NOT USE IT IN THE FUTURE CHANGES
+ // The only purpose of this function to support previous code
+ // in order to sync with data generated with the previous ASG versions
+ void SeedGenerator(mfxU32 extSeed);
+
+private:
+ static constexpr mfxU32 DEFAULT_SEED = 1;
+
+ ASGRandomGenerator(mfxU32 seed = DEFAULT_SEED) : m_Gen(seed) {}
+
+ std::mt19937 m_Gen; // random number generator
+};
+
+// Alias for static GetInstance to use in client code
+constexpr auto GetRandomGen = &ASGRandomGenerator::GetInstance;
+
+#endif // MFX_VERSION
+
+#endif // __ASG_HEVC_RANDOM_GENERATOR_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/refcontrol.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/refcontrol.h
new file mode 100644
index 0000000..362778d
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/refcontrol.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __REFCONTROL_H__
+#define __REFCONTROL_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+
+#include "inputparameters.h"
+#include "random_generator.h"
+
+// These structures are used in asg-hevc-based PicStruct test
+
+struct PictureInfo
+{
+ mfxI32 orderCount = -1; // display order
+ mfxI32 codingOrder = -1;
+ mfxU32 frameType = MFX_FRAMETYPE_UNKNOWN; // IPB, IDR, ST/LT
+ mfxU32 picStruct = MFX_PICSTRUCT_UNKNOWN; // TF/BF
+
+ bool operator==(const PictureInfo& rhs) const
+ {
+ return codingOrder == rhs.codingOrder &&
+ orderCount == rhs.orderCount &&
+ picStruct == rhs.picStruct &&
+ frameType == rhs.frameType;
+ }
+};
+
+struct RefState
+{
+ PictureInfo picture;
+ std::vector DPB; // stores FrameOrder (POC)
+ std::vector RefListActive[2]; // (POC), any from DPB, can be repeated
+
+ void Dump(std::fstream& fp) const;
+ bool Load(std::fstream& fp); // returns false on error
+
+ bool operator==(const RefState& rhs) const
+ {
+ return
+ picture == rhs.picture &&
+ DPB == rhs.DPB &&
+ RefListActive[0] == rhs.RefListActive[0] &&
+ RefListActive[1] == rhs.RefListActive[1];
+ }
+};
+
+class RefControl
+{
+public:
+ std::vector RefLogInfo;
+
+ void Add(mfxI32 frameOrder);
+ void Encode(mfxI32 frameOrder);
+ void SetParams(const InputParams& params);
+private:
+ mfxU32 maxDPBSize = 1; // max num ref + 1 for current
+ mfxU32 maxDelay = 1; // == number of allocated surfaces used in encoder reordering
+
+ std::vector DPB; // can temporary be maxDPBSize+1, stores all active pictures
+
+ std::vector RPB; // reordered picture buffer, pic goes to DPB when coded
+
+ InputParams m_params;
+ mfxI32 m_lastIDR = 0;
+};
+
+// TODO: Replace global functions with lambdas
+bool IsOlder(const PictureInfo& a, const PictureInfo& b);
+bool IsInCodingOrder(const RefState& a, const RefState& b);
+
+
+#endif // MFX_VERSION
+
+#endif // __REFCONTROL_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/test_processor.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/test_processor.h
new file mode 100644
index 0000000..144ce92
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/test_processor.h
@@ -0,0 +1,101 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_TEST_PROCESSOR_H__
+#define __ASG_HEVC_TEST_PROCESSOR_H__
+
+#include "mfxvideo.h"
+#include "sample_defs.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+
+#include "sample_utils.h"
+#include "base_allocator.h"
+
+#include "inputparameters.h"
+#include "frame_processor.h"
+#include "util_defs.h"
+#include "asglog.h"
+
+#include "refcontrol.h"
+
+class TestProcessor
+{
+public:
+ virtual ~TestProcessor() {}
+
+ void RunTest(const InputParams & params);
+ void RunPSTest(const InputParams & params);
+
+ void RunRepackGenerate();
+ void RunRepackVerify();
+
+ static ASGLog asgLog;
+
+protected:
+ void Init(const InputParams ¶ms);
+ virtual void Init() = 0;
+
+ explicit TestProcessor() : fpPicStruct(), fpRepackCtrl(), fpRepackStr(), fpRepackStat() {}
+
+ ExtendedSurface* GetFreeSurf();
+
+ // Get surface
+ virtual ExtendedSurface* PrepareSurface() { return nullptr; }
+
+ void ChangePicture(ExtendedSurface& surf);
+
+ void PrepareDescriptor(FrameChangeDescriptor & descr, const mfxU32 frameNum);
+
+ // Save all data
+ virtual void DropFrames() {}
+ virtual void DropBuffers(ExtendedSurface& surf) {}
+ virtual void SavePSData() = 0;
+
+ // Verification mode
+ virtual void VerifyDesc(FrameChangeDescriptor & frame_descr) {}
+
+ InputParams m_InputParams;
+ std::vector m_vProcessingParams; // markers for all frames
+ std::list m_ProcessedFramesDescr; // DPB analogue
+ FrameProcessor m_FrameProcessor; // Class which performs processing of frame
+ std::list m_Surfaces; // Surface pool
+
+ std::fstream fpPicStruct;
+ RefControl m_RefControl;
+
+ std::fstream fpRepackCtrl;
+ std::fstream fpRepackStr;
+ std::fstream fpRepackStat;
+
+private:
+ //used to be global
+
+ // used once in TestProcessor
+ std::list GetReferences(const std::list & RecentProcessed, const std::vector& ref_idx);
+ // never used actually
+ std::list GetSkips(const std::list & RecentProcessed);
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_HEVC_TEST_PROCESSOR_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/util_defs.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/util_defs.h
new file mode 100644
index 0000000..24c67c1
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/util_defs.h
@@ -0,0 +1,638 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __ASG_HEVC_UTILS_H__
+#define __ASG_HEVC_UTILS_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+#include
+#include
+#include
+
+#include "mfxdefs.h"
+#include "mfxfeihevc.h"
+#include "sample_defs.h"
+
+#define CHECK_THROW_ERR(STS, MESSAGE) { \
+ if (STS < MFX_ERR_NONE)\
+ throw std::string(std::string("ERROR: (") + ConvertMfxStatusToString(STS) + std::string(") ") + MESSAGE);\
+ else if (STS > MFX_ERR_NONE) \
+ std::cout << "WARNING: (" << ConvertMfxStatusToString(STS) << ") " << MESSAGE << std::endl; \
+}
+
+#define CHECK_THROW_ERR_BOOL(EXPR, MESSAGE) { \
+ if (!EXPR) \
+ throw std::string(MESSAGE); \
+}
+
+#define ASG_HEVC_ERR_LOW_PASS_RATE 100
+
+#define LUMA_DEFAULT 0
+#define CHROMA_DEFAULT 127
+#define MAX_GEN_MV_ATTEMPTS 100
+#define MVP_BLOCK_SIZE 16
+#define MVP_PER_16x16_BLOCK 4
+#define MVMVP_SIZE_LIMIT 2048 //Hardware-imposed limit for either of MV/MVP coordinates in quarter-pixel
+ //units. To be increased in PV5
+
+#define HW_SEARCH_ELEMENT_SIZE 16 //Hardware search element size in pixels (i.e. each 16x16 block in a CTU
+ //will be searched for in a search window centered on this 16x16 block)
+
+#define LOG2_MV_COMPARE_BASE_BLOCK_SIZE 2 //While comparing MVs of ASG and FEI CTUs, motion vectors will be compared
+ //on basis of square blocks of this size
+
+#define DELTA_PIXEL_BI_DIRECT 15 // Delta for bi-prediction test. This value will be used as difference between L0 and L1 references PUs
+#define SPLIT_LOG_TABLE_SYM_WIDTH 12 //Width of a table field in split testing partition size table output
+
+//For repack ctrl
+#define HEVC_MAX_NUMPASSES 8 //Number of additional passes with delta QPs
+
+std::string ConvertMfxStatusToString(mfxStatus sts);
+
+enum REF_LIST_INDEX
+{
+ L0 = 0,
+ L1 = 1
+};
+
+template
+inline T Clip3(const T valueToClip, const T low, const T high)
+{
+ if (valueToClip < low)
+ {
+ return low;
+ }
+ else if (valueToClip > high)
+ {
+ return high;
+ }
+
+ return valueToClip;
+}
+
+// Inaccurate limits. For one directional limit is width*height <= 2000; for Bi-dir 1000
+const mfxU32 SKL_SW_LIM_OD[2] = { 48, 40 }; // One-directional Motion Estimation Search Window limit; 0 - width, 1 - height
+const mfxU32 SKL_SW_LIM_BD[2] = { 32, 32 }; // Bi-directional Motion Estimation Search Window limit; 0 - width, 1 - height
+
+
+struct PUMotionVector
+{
+ PUMotionVector(mfxU8 refl0, mfxU8 refl1, mfxI16 MV1_x, mfxI16 MV1_y, mfxI16 MV2_x, mfxI16 MV2_y)
+ {
+ RefIdx = { refl0, refl1 };
+
+ MV[0] = { MV1_x, MV1_y };
+ MV[1] = { MV2_x, MV2_y };
+ }
+
+ PUMotionVector() : PUMotionVector(0, 0, 0, 0, 0, 0) {}
+
+ PUMotionVector(const PUMotionVector& vec) = default;
+ PUMotionVector& operator= (const PUMotionVector& vec) = default;
+
+ bool CheckMVPExceedsSizeLimits() const
+ {
+ return (abs(MV[0].x) > MVMVP_SIZE_LIMIT || abs(MV[0].y) > MVMVP_SIZE_LIMIT
+ || abs(MV[1].x) > MVMVP_SIZE_LIMIT || abs(MV[1].y) > MVMVP_SIZE_LIMIT);
+ }
+
+ bool operator==(const PUMotionVector& rhs) const
+ {
+ return (MV[0].x == rhs.MV[0].x &&
+ MV[0].y == rhs.MV[0].y &&
+ MV[1].x == rhs.MV[1].x &&
+ MV[1].y == rhs.MV[1].y &&
+ RefIdx.RefL0 == rhs.RefIdx.RefL0 &&
+ RefIdx.RefL1 == rhs.RefIdx.RefL1);
+ }
+
+ // Important: refIdx is not affected, i.e. inherited from this
+ const PUMotionVector operator+ (const PUMotionVector& rhs) const
+ {
+ return PUMotionVector(RefIdx.RefL0 , RefIdx.RefL1 ,
+ MV[0].x + rhs.MV[0].x, MV[0].y + rhs.MV[0].y,
+ MV[1].x + rhs.MV[1].x, MV[1].y + rhs.MV[1].y);
+ }
+
+ inline std::tuple GetL0MVTuple() const
+ {
+ return std::make_tuple(MV[0].x, MV[0].y, (mfxU32) RefIdx.RefL0);
+ }
+
+ inline std::tuple GetL1MVTuple() const
+ {
+ return std::make_tuple(MV[1].x, MV[1].y, (mfxU32)RefIdx.RefL1);
+ }
+
+ struct {
+ mfxU8 RefL0 : 4;
+ mfxU8 RefL1 : 4;
+ } RefIdx;
+
+ mfxI16Pair MV[2]; /* index is 0 for L0 and 1 for L1 */
+};
+
+struct Counters
+{
+ //Mapping (width;height) to (total) partitioning blocks
+ struct BlockSizeMapFEI : std::map, mfxU32>
+ {
+ inline void AddBlockTotal(mfxU32 width, mfxU32 height)
+ {
+ this->operator[](std::make_pair(width, height))++;
+ }
+
+ inline mfxU32 GetTotalCount()
+ {
+ mfxU32 count = 0;
+ for (auto& blockSizeRecord : *this)
+ {
+ count += blockSizeRecord.second;
+ }
+ return count;
+ }
+
+ void PrintTable()
+ {
+ std::stringstream tmp;
+ for (auto& blockSizeRecord : *this)
+ {
+ tmp.str("");
+ tmp << blockSizeRecord.first.first << 'x' << blockSizeRecord.first.second;
+ std::cout << std::setw(SPLIT_LOG_TABLE_SYM_WIDTH) << tmp.str();
+ }
+ std::cout << std::endl;
+ for (auto& blockSizeRecord : *this)
+ {
+ std::cout << std::setw(SPLIT_LOG_TABLE_SYM_WIDTH) << blockSizeRecord.second;
+ }
+ std::cout << std::endl;
+ }
+ };
+
+ //Mapping (width;height) to (correct in FEI; total) partitioning blocks
+ struct BlockSizeMapASG : std::map, std::pair>
+ {
+ inline void AddBlockCorrect(mfxU32 width, mfxU32 height)
+ {
+ this->operator[](std::make_pair(width, height)).first++;
+ }
+
+ inline void AddBlockTotal(mfxU32 width, mfxU32 height)
+ {
+ this->operator[](std::make_pair(width, height)).second++;
+ }
+
+ inline mfxU32 GetCorrectCount()
+ {
+ mfxU32 count = 0;
+ for (auto& blockSizeRecord : *this)
+ {
+ count += blockSizeRecord.second.first;
+ }
+ return count;
+ }
+
+ inline mfxU32 GetTotalCount()
+ {
+ mfxU32 count = 0;
+ for (auto& blockSizeRecord : *this)
+ {
+ count += blockSizeRecord.second.second;
+ }
+ return count;
+ }
+
+ void PrintTable()
+ {
+ std::stringstream tmp;
+ for (auto& blockSizeRecord : *this)
+ {
+ tmp.str("");
+ tmp << blockSizeRecord.first.first << 'x' << blockSizeRecord.first.second;
+ std::cout << std::setw(SPLIT_LOG_TABLE_SYM_WIDTH) << tmp.str();
+ }
+ std::cout << std::endl;
+ for (auto& blockSizeRecord : *this)
+ {
+ tmp.str("");
+ tmp << blockSizeRecord.second.first << '/' << blockSizeRecord.second.second;
+ std::cout << std::setw(SPLIT_LOG_TABLE_SYM_WIDTH) << tmp.str();
+ }
+ std::cout << std::endl;
+ }
+ };
+
+ BlockSizeMapASG m_testPUSizeMapASG;
+ BlockSizeMapFEI m_testPUSizeMapFEI;
+
+ BlockSizeMapASG m_testCUSizeMapASG;
+ BlockSizeMapFEI m_testCUSizeMapFEI;
+
+ mfxU32 m_testCTUs = 0;
+
+ // MV
+ mfxU32 m_correctMVCmpBlocksL0 = 0;
+ mfxU32 m_correctMVCmpBlocksL1 = 0;
+ mfxU32 m_correctMVCmpBlocksBi = 0;
+
+ mfxU32 m_totalMVCmpBlocksL0 = 0;
+ mfxU32 m_totalMVCmpBlocksL1 = 0;
+ mfxU32 m_totalMVCmpBlocksBi = 0;
+
+ // Shouldn't affect test result
+ mfxU32 m_correctMVCmpBlocksL0PerMVPIndex[MVP_PER_16x16_BLOCK] = { 0, 0, 0, 0 };
+ mfxU32 m_correctMVCmpBlocksL1PerMVPIndex[MVP_PER_16x16_BLOCK] = { 0, 0, 0, 0 };
+ mfxU32 m_correctMVCmpBlocksBiPerMVPIndex[MVP_PER_16x16_BLOCK] = { 0, 0, 0, 0 };
+
+ mfxU32 m_totalMVCmpBlocksL0PerMVPIndex[MVP_PER_16x16_BLOCK] = { 0, 0, 0 ,0 };
+ mfxU32 m_totalMVCmpBlocksL1PerMVPIndex[MVP_PER_16x16_BLOCK] = { 0, 0, 0, 0 };
+ mfxU32 m_totalMVCmpBlocksBiPerMVPIndex[MVP_PER_16x16_BLOCK] = { 0, 0, 0, 0 };
+
+ //Won't affect test result
+ mfxU32 m_correctMVsL0FromBiMVCmpBlocks = 0;
+ mfxU32 m_correctMVsL1FromBiMVCmpBlocks = 0;
+
+ mfxU32 m_correctRecords = 0;
+ mfxU32 m_totalPics = 0;
+
+ //Splits
+ mfxU32 m_correctCUs = 0;
+ mfxU32 m_totalCUsASG = 0;
+ mfxU32 m_totalCUsFEI = 0;
+
+ mfxU32 m_correctPUs = 0;
+ mfxU32 m_totalPUsASG = 0;
+ mfxU32 m_totalPUsFEI = 0;
+
+ //Counters for exact matches
+ mfxU32 m_exactCTUs = 0;
+ mfxU32 m_exactCUs = 0;
+ mfxU32 m_exactPUs = 0;
+};
+
+// Wrapper on extension buffers
+class ExtendedBuffer
+{
+public:
+
+ explicit ExtendedBuffer(mfxU32 id, mfxU32 pitch, mfxU32 height)
+ {
+ switch (id)
+ {
+ // Fill buffer. Track dynamic memory with smart pointer
+
+ case MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED:
+ {
+ memset(&m_mvPred, 0, sizeof(m_mvPred));
+
+ m_mvPred.Header.BufferId = MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED;
+ m_mvPred.Header.BufferSz = sizeof(m_mvPred);
+
+ mfxU64 data_size = pitch * height * sizeof(mfxFeiHevcEncMVPredictors);
+
+ m_data.reset(new mfxU8[data_size]);
+
+ m_mvPred.Data = reinterpret_cast(m_data.get());
+ memset(m_mvPred.Data, 0, data_size);
+
+ m_mvPred.Pitch = pitch;
+ m_mvPred.Height = height;
+ break;
+ }
+ case MFX_EXTBUFF_HEVCFEI_PAK_CTU_REC:
+ {
+ memset(&m_pakCtuRecord, 0, sizeof(m_pakCtuRecord));
+
+ m_pakCtuRecord.Header.BufferId = MFX_EXTBUFF_HEVCFEI_PAK_CTU_REC;
+ m_pakCtuRecord.Header.BufferSz = sizeof(m_pakCtuRecord);
+
+ mfxU64 data_size = pitch * height * sizeof(mfxFeiHevcPakCtuRecordV0);
+
+ m_data.reset(new mfxU8[data_size]);
+
+ m_pakCtuRecord.Data = reinterpret_cast(m_data.get());
+ memset(m_pakCtuRecord.Data, 0, data_size);
+
+ m_pakCtuRecord.Pitch = pitch;
+ m_pakCtuRecord.Height = height;
+
+ break;
+ }
+ case MFX_EXTBUFF_HEVCFEI_PAK_CU_REC:
+ {
+ memset(&m_pakCuRecord, 0, sizeof(m_pakCuRecord));
+
+ m_pakCuRecord.Header.BufferId = MFX_EXTBUFF_HEVCFEI_PAK_CU_REC;
+ m_pakCuRecord.Header.BufferSz = sizeof(m_pakCuRecord);
+
+ mfxU64 data_size = pitch * height * sizeof(mfxFeiHevcPakCuRecordV0);
+ m_data.reset(new mfxU8[data_size]);
+
+ m_pakCuRecord.Data = reinterpret_cast(m_data.get());
+ memset(m_pakCuRecord.Data, 0, data_size);
+
+ m_pakCuRecord.Pitch = pitch;
+ m_pakCuRecord.Height = height;
+
+ break;
+ }
+ }
+ }
+
+ // Hold this entry first in class
+ union
+ {
+ mfxExtFeiHevcEncMVPredictors m_mvPred;
+ mfxExtFeiHevcPakCtuRecordV0 m_pakCtuRecord;
+ mfxExtFeiHevcPakCuRecordV0 m_pakCuRecord;
+ };
+
+ std::unique_ptr m_data;
+};
+
+// Wrapper on mfxFrameSurface1
+class ExtendedSurface : public mfxFrameSurface1
+{
+public:
+ //Flag to track whether the surface in the pool has been written to disk,
+ //but not reused by another frame
+ bool isWritten = false;
+ mfxU32 encodedOrder = 0xffffffff;
+
+ ExtendedSurface() = default;
+ ExtendedSurface(ExtendedSurface &&) = default;
+ ExtendedSurface(const ExtendedSurface &) = delete;
+ ExtendedSurface& operator= (const ExtendedSurface& vec) = delete;
+
+ // Fill info about current surface. Track dynamic memory by smart pointer
+ void AllocData(mfxU32 width, mfxU32 height)
+ {
+ // Only I420 is supported for now
+
+ Info.FourCC = MFX_FOURCC_YV12;
+ Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
+ Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
+
+ Info.Width = MSDK_ALIGN16(width);
+ Info.Height = (MFX_PICSTRUCT_PROGRESSIVE == Info.PicStruct) ?
+ MSDK_ALIGN16(height) : MSDK_ALIGN32(height);
+
+ Info.CropW = width;
+ Info.CropH = height;
+
+ mfxU32 size = Info.CropH * Info.CropW * 3 / 2;
+ pSurfData.reset(new mfxU8[size]);
+ memset(pSurfData.get(), 0, size); //Zero-init
+
+ Data.Y = pSurfData.get();
+ Data.U = Data.Y + Info.CropH * Info.CropW;
+ Data.V = Data.U + Info.CropH * Info.CropW / 4;
+ Data.Pitch = Info.CropW;
+ }
+
+ // Attach buffer to surface
+ //
+ // Important: after this operation, original buffer is no longer valid. All further ownership is taken by surface
+ void AttachBuffer(ExtendedBuffer & buffer)
+ {
+
+ ExtBuffers.push_back(std::move(buffer)); // Dynamic memory is moved to new instance of ExtendedBuffer
+
+ // Headers of all buffers should be in same place in memory, because union is used
+ vExtBuffersData.push_back(&ExtBuffers.back().m_mvPred.Header);
+
+ ++Data.NumExtParam;
+ Data.ExtParam = vExtBuffersData.data();
+ }
+
+ // Get attached buffer by id
+ mfxExtBuffer* GetBuffer(mfxU32 id)
+ {
+ auto it = find_if(vExtBuffersData.begin(), vExtBuffersData.end(),
+ [&](mfxExtBuffer* buffer) { return buffer->BufferId == id; });
+
+ if (it == vExtBuffersData.end())
+ throw std::string("ERROR: ExtendedSurface::GetBuffer: no buffer with id: ") + std::to_string(id);
+
+ return *it;
+ }
+
+
+ void ForceMVPBlockSizeInOutputBuffer(mfxU32 forcedBlockSize)
+ {
+ for (mfxU32 i = 0; i < Data.NumExtParam; ++i)
+ {
+ mfxExtBuffer* buffer = Data.ExtParam[i];
+ if (buffer == nullptr)
+ {
+ throw std::string("ERROR: ForceMVPBlockSizeInOutputBuffer: null pointer reference");
+ }
+ if (buffer->BufferId == MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED)
+ {
+ mfxExtFeiHevcEncMVPredictors* mvpBuff = reinterpret_cast(buffer);
+
+ for (mfxU32 i = 0; i < mvpBuff->Height * mvpBuff->Pitch; i++)
+ {
+ mvpBuff->Data[i].BlockSize = forcedBlockSize;
+ }
+ }
+ }
+ }
+
+private:
+ std::unique_ptr pSurfData; // Surface pixels
+
+ std::list ExtBuffers; // List of ext buffers
+ std::vector vExtBuffersData; // Array of pointers
+};
+
+// This class performs writing of ext buffers to appropriate file
+class BufferWriter
+{
+public:
+
+ // Start tracking of current buffer; fopen the file with file_name
+ void AddBuffer(mfxU32 id, msdk_string fileName)
+ {
+ FILE* fp = NULL;
+
+ MSDK_FOPEN(fp, fileName.c_str(), MSDK_STRING("wb"));
+
+ if (!fp)
+ throw std::string("ERROR: BufferWriter::AddBuffer : fopen_s failed");
+
+ m_bufferFileTable[id] = fp; //Add current file pointer to the map (buf ID->file)
+ }
+
+ // Find buffer's file pointer in table by buffer id and write the content.
+ void WriteBuffer(mfxExtBuffer* buffer)
+ {
+ FILE* fp;
+
+ if (m_bufferFileTable.find(buffer->BufferId) != m_bufferFileTable.end())
+ {
+ fp = m_bufferFileTable[buffer->BufferId];
+ }
+ else
+ {
+ throw std::string("ERROR: BufferWriter::WriteBuffer : unknown buffer with id: ") + std::to_string(buffer->BufferId);
+ }
+
+ switch (buffer->BufferId)
+ {
+ case MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED:
+ {
+ mfxExtFeiHevcEncMVPredictors* mvpBuff = reinterpret_cast(buffer);
+
+ auto numWritten = fwrite(mvpBuff->Data, sizeof(mfxFeiHevcEncMVPredictors) * mvpBuff->Pitch * mvpBuff->Height, 1, fp);
+
+ if (numWritten != 1)
+ throw std::string("ERROR: BufferWriter::WriteBuffer : fwrite failed");
+ }
+ break;
+
+ default:
+ throw std::string("ERROR: BufferWriter::WriteBuffer : unknown buffer with id: ") + std::to_string(buffer->BufferId);
+ break;
+ }
+
+ return;
+ }
+
+ // Zero buffer's data
+ void ResetBuffer(mfxExtBuffer* buffer)
+ {
+ switch (buffer->BufferId)
+ {
+ case MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED:
+ {
+ mfxExtFeiHevcEncMVPredictors* mvpBuff = reinterpret_cast(buffer);
+ memset(mvpBuff->Data, 0, sizeof(mfxFeiHevcEncMVPredictors) * mvpBuff->Pitch * mvpBuff->Height);
+ break;
+ }
+ default:
+ throw std::string("ERROR: BufferWriter::ResetBuffer : unknown buffer with id: ") + std::to_string(buffer->BufferId);
+ break;
+ }
+
+ return;
+ }
+
+ // Close all file pointers
+ ~BufferWriter()
+ {
+ for (auto & fp : m_bufferFileTable)
+ {
+ fflush(fp.second);
+ fclose(fp.second);
+ }
+ }
+
+private:
+ std::map m_bufferFileTable; // map of id - file pointer
+};
+
+// This class performs reading of ext buffers from appropriate file
+class BufferReader
+{
+public:
+
+ // Start tracking of current buffer; fopen the file with file_name
+ void AddBuffer(mfxU32 id, msdk_string fileName)
+ {
+ FILE* fp = NULL;
+
+ MSDK_FOPEN(fp, fileName.c_str(), MSDK_STRING("rb"));
+
+ if (!fp)
+ throw std::string("ERROR: BufferReader::AddBuffer : fopen_s failed");
+
+ m_bufferFileTable[id] = fp; //Add current file pointer to the map (buf ID->file)
+ }
+
+ // Find buffer's file pointer in table by buffer id and write the content.
+ void ReadBuffer(mfxExtBuffer* buffer) //Function for reading can read 1 CU structure per call
+ {
+ FILE* fp;
+
+ if (m_bufferFileTable.find(buffer->BufferId) != m_bufferFileTable.end())
+ {
+ fp = m_bufferFileTable[buffer->BufferId];
+ }
+ else
+ {
+ throw std::string("ERROR: BufferReader::ReadBuffer : unknown buffer with id: ") + std::to_string(buffer->BufferId);
+ }
+
+ switch (buffer->BufferId)
+ {
+ case MFX_EXTBUFF_HEVCFEI_PAK_CTU_REC:
+ {
+ mfxExtFeiHevcPakCtuRecordV0* pakCtuBuff = reinterpret_cast(buffer);
+
+ auto numRead = fread(pakCtuBuff->Data, sizeof(mfxFeiHevcPakCtuRecordV0) * pakCtuBuff->Pitch * pakCtuBuff->Height, 1, fp);
+
+ if (numRead != 1)
+ throw std::string("ERROR: BufferReader::ReadBuffer : fread failed");
+ }
+ break;
+
+ case MFX_EXTBUFF_HEVCFEI_PAK_CU_REC:
+ {
+ mfxExtFeiHevcPakCuRecordV0* pakCuBuff = reinterpret_cast(buffer);
+
+ auto numRead = fread(pakCuBuff->Data, sizeof(mfxFeiHevcPakCuRecordV0) * pakCuBuff->Pitch * pakCuBuff->Height, 1, fp);
+
+ if (numRead != 1)
+ throw std::string("ERROR: BufferReader::ReadBuffer : fread failed");
+ }
+ break;
+
+ default:
+ throw std::string("ERROR: BufferReader::ReadBuffer : unknown buffer with id: ") + std::to_string(buffer->BufferId);
+ break;
+ }
+
+ return;
+ }
+
+ // Close all file pointers
+ ~BufferReader()
+ {
+ for (auto & fp : m_bufferFileTable)
+ {
+ fflush(fp.second);
+ fclose(fp.second);
+ }
+ }
+
+private:
+ std::map m_bufferFileTable; // map of id - file pointer
+};
+
+#endif // MFX_VERSION
+
+#endif // __ASG_HEVC_UTILS_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/verifier.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/verifier.h
new file mode 100644
index 0000000..014db6a
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/include/verifier.h
@@ -0,0 +1,97 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __VERIFIER_H__
+#define __VERIFIER_H__
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "refcontrol.h"
+#include "test_processor.h"
+
+class Verifier : public TestProcessor {
+public:
+ explicit Verifier() {}
+
+ ~Verifier() {};
+
+ // Verification mode
+ void CheckStatistics(Thresholds thres);
+
+private:
+ struct MVCompareBlock : BaseBlock
+ {
+ bool predFlagL0 = false;
+ bool predFlagL1 = false;
+ bool bIsIntra = false;
+ mfxI16 usedMVPIndex = -1;
+ mfxI16 usedMVPPoolNo = -1;
+ PUMotionVector MV;
+ };
+
+ const mfxU32 MV_CMP_BLOCK_SIZE = (1 << LOG2_MV_COMPARE_BASE_BLOCK_SIZE);
+
+ std::list m_errorMsgList;
+
+ void Init() override;
+
+ // Get surface
+ ExtendedSurface* PrepareSurface() override;
+
+ // Save all data
+ void DropFrames() override;
+ virtual void SavePSData() override;
+
+ // Verification mode
+ void VerifyDesc(FrameChangeDescriptor & frame_descr) override;
+ void ExtractMVs(const CTUDescriptor& ctuDescr, std::vector& mvCmpBlocks);
+ void CompareSplits(const CTUDescriptor& ctuDescrASG, const CTUDescriptor& ctuDescrFEI);
+
+ void CompareMVs(const CTUDescriptor& asgCTUDescriptor, const CTUDescriptor& feiCTUDescriptor);
+ void CompareMVBlocks(const MVCompareBlock& asgMVCmpBlock, const MVCompareBlock& feiMVCmpBlock);
+ void CalculateTotalMVCmpBlocksInCTU(std::vector& mvCmpBlocks);
+
+ void CountExactMatches(const CTUDescriptor& asgCTUDescriptor, const CTUDescriptor& feiCTUDescriptor);
+ CTUDescriptor ConvertFeiOutInLocalStr(const mfxFeiHevcPakCtuRecordV0& ctuPakFromFEI, const ExtendedBuffer& tmpCuBuff, const mfxU32 startCuOffset);
+
+ void PrintPercentRatio(mfxU32 numerator, mfxU32 denominator);
+ bool CheckLowerThreshold(mfxU32 numerator, mfxU32 denominator, mfxU32 threshold = 100);
+
+ void CheckMVs(Thresholds threshold);
+ void CheckL0MVs(Thresholds threshold);
+ void CheckL1MVs(Thresholds threshold);
+ void CheckBiMVs(Thresholds threshold);
+
+ void CheckL0MVsPerMVPIndex(Thresholds threshold);
+ void CheckL1MVsPerMVPIndex(Thresholds threshold);
+ void CheckBiMVsPerMVPIndex(Thresholds threshold);
+
+ void CheckSplits(Thresholds threshold);
+ void CheckPicStruct();
+
+ BufferReader m_BufferReader;
+ Counters m_Counters;
+};
+
+#endif // MFX_VERSION
+
+#endif // __VERIFIER_H__
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/asg-hevc.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/asg-hevc.cpp
new file mode 100644
index 0000000..bd2de5d
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/asg-hevc.cpp
@@ -0,0 +1,94 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#include
+#include
+
+#include "inputparameters.h"
+#include "test_processor.h"
+#include "generator.h"
+#include "verifier.h"
+
+using namespace std;
+
+
+#if defined(_WIN32) || defined(_WIN64)
+mfxI32 _tmain(mfxI32 argc, msdk_char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+#if MFX_VERSION < MFX_VERSION_NEXT
+ cout << "ERROR: For correct work minimal API MFX_VERSION_NEXT version is required" << endl;
+ return -1;
+
+#else
+ try {
+ InputParams params;
+
+ params.ParseInputString(argv, argc);
+ if (params.m_bPrintHelp) {
+ return 0;
+ }
+
+ switch (params.m_ProcMode)
+ {
+ case GENERATE:
+ {
+ Generator generator;
+ generator.RunTest(params);
+ }
+ break;
+
+ case VERIFY:
+ {
+ Verifier verifier;
+ verifier.RunTest(params);
+
+ if (params.m_TestType == GENERATE_REPACK_CTRL)
+ break;
+
+ verifier.CheckStatistics(params.m_Thresholds);
+ }
+ break;
+
+ default:
+ throw std::string("ERROR: Undefined processing mode");
+ break;
+ }
+ }
+ catch (std::string& e) {
+ cout << e << endl;
+ return -1;
+ }
+ catch (int sts)
+ {
+ return sts;
+ }
+ catch (...) {
+ cout << "ERROR: Unexpected exception triggered" << endl;
+ return -1;
+ }
+ return 0;
+
+#endif // MFX_VERSION
+}
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/block_structures.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/block_structures.cpp
new file mode 100644
index 0000000..03e1040
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/block_structures.cpp
@@ -0,0 +1,364 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "block_structures.h"
+
+void BaseBlock::GetChildBlock(std::vector& childrenBlocks) const
+{
+ childrenBlocks.clear();
+ childrenBlocks.reserve(4);
+
+ //sizes and positions
+ mfxU32 childHeight = m_BHeight / 2;
+ mfxU32 childWidth = m_BWidth / 2;
+ for (mfxU32 i = 0; i < 4; i++)
+ {
+ childrenBlocks.emplace_back(m_AdrX + childWidth * (i % 2), m_AdrY + childHeight * (i / 2), childHeight, childWidth);
+ }
+}
+
+void BaseBlock::GetChildRefSampleInfo(const RefSampleAvail & currAvail, const BaseBlock & ctu, std::vector& childrenRefSampleAvail) const
+{
+ childrenRefSampleAvail.clear();
+ childrenRefSampleAvail.resize(4);
+
+ //is left down block available for children
+ childrenRefSampleAvail[0].LeftDown = true;
+ childrenRefSampleAvail[1].LeftDown = false;
+
+ if (m_AdrY + m_BHeight == ctu.m_AdrY + ctu.m_BHeight)
+ {
+ childrenRefSampleAvail[2].LeftDown = true;
+ childrenRefSampleAvail[3].LeftDown = true;
+ }
+ else
+ {
+ childrenRefSampleAvail[2].LeftDown = currAvail.LeftDown;
+ childrenRefSampleAvail[3].LeftDown = false;
+ }
+
+ //is up right block available for children
+ childrenRefSampleAvail[0].UpRight = true;
+ childrenRefSampleAvail[2].UpRight = true;
+
+ if (m_AdrX + m_BWidth == ctu.m_AdrX + ctu.m_BWidth)
+ {
+ childrenRefSampleAvail[1].UpRight = true;
+ childrenRefSampleAvail[3].UpRight = true;
+ }
+ else
+ {
+ childrenRefSampleAvail[1].UpRight = currAvail.UpRight;
+ childrenRefSampleAvail[3].UpRight = false;
+ }
+}
+
+//This recursive function fills outVec with BaseBlocks, coordinates and sizes of which correspond to
+//the quad-tree structure specified by the quad-tree root node and the base size and coordinates of
+//the "root node "
+void QuadTree::GetQuadTreeBlocksRecur(QuadTreeNode & node, mfxU32 baseAdrX, mfxU32 baseAdrY, mfxU32 baseSize, std::vector& outVec)
+{
+ if (!node.m_Children.empty())
+ {
+ for (mfxU32 i_y = 0; i_y < 2; i_y++)
+ {
+ for (mfxU32 i_x = 0; i_x < 2; i_x++)
+ {
+ QuadTreeNode& child = node.m_Children[2 * i_y + i_x];
+ mfxU32 childSize = baseSize / 2;
+ mfxU32 childAdrX = baseAdrX + i_x * childSize;
+ mfxU32 childAdrY = baseAdrY + i_y * childSize;
+ GetQuadTreeBlocksRecur(child, childAdrX, childAdrY, childSize, outVec);
+ }
+ }
+ }
+ else
+ {
+ outVec.emplace_back(baseAdrX, baseAdrY, baseSize, baseSize);
+ return;
+ }
+}
+
+void QuadTree::GetQuadTreeRefSampleAvailVector(QuadTreeNode & node, BaseBlock & currBlock, const BaseBlock & ctu, std::vector& outVec)
+{
+ RefSampleAvail helper(true, true);
+ GetQuadTreeRefSampleAvailVectorRecur(node, currBlock, helper, ctu, outVec);
+}
+
+void QuadTree::GetQuadTreeRefSampleAvailVectorRecur(QuadTreeNode & node, BaseBlock & currBlock, const RefSampleAvail& currAvail, const BaseBlock & ctu, std::vector& outVec)
+{
+ if (!node.m_Children.empty())
+ {
+ //children blocks, refSamples availability for children is counted here
+ std::vector childrenBlocks;
+ currBlock.GetChildBlock(childrenBlocks);
+ std::vector childrenRefSamplesInfo;
+ currBlock.GetChildRefSampleInfo(currAvail, ctu, childrenRefSamplesInfo);
+
+ //recursive call for children
+ for (mfxU32 i = 0; i < 4; i++)
+ {
+ GetQuadTreeRefSampleAvailVectorRecur(node.m_Children[i], childrenBlocks[i], childrenRefSamplesInfo[i], ctu, outVec);
+ }
+ }
+ else
+ {
+
+ //put leaves into outVec in depth-first order
+ outVec.emplace_back(currAvail);
+ }
+ return;
+}
+
+PatchBlock::PatchBlock(const PatchBlock & rhs) : PatchBlock(static_cast(rhs))
+{
+ memcpy(PatchData.get(), rhs.PatchData.get(), sizeof(mfxU8) * m_BWidth * m_BHeight * 3 / 2);
+}
+
+PatchBlock & PatchBlock::operator=(const PatchBlock & rhs)
+{
+ BaseBlock::operator=(rhs);
+
+ mfxU32 sq = m_BWidth * m_BHeight;
+ PatchData.reset(new mfxU8[sq * 3 / 2]);
+
+ memcpy(PatchData.get(), rhs.PatchData.get(), sizeof(mfxU8) * sq * 3 / 2);
+
+ m_YPlane = PatchData.get();
+ m_UPlane = m_YPlane + sq;
+ m_VPlane = m_UPlane + (sq / 4);
+
+ return *this;
+}
+
+PatchBlock::PatchBlock(const BaseBlock& BB) : BaseBlock(BB)
+{
+ mfxU32 sq = m_BWidth * m_BHeight;
+ PatchData.reset(new mfxU8[sq * 3 / 2]);
+ m_YPlane = PatchData.get();
+ m_UPlane = m_YPlane + sq;
+ m_VPlane = m_UPlane + (sq / 4);
+
+ memset(m_YPlane, LUMA_DEFAULT, sq);
+ memset(m_UPlane, CHROMA_DEFAULT, sq / 4);
+ memset(m_VPlane, CHROMA_DEFAULT, sq / 4);
+}
+
+//constructor that memsets PatchBlock with the particurlar sample
+PatchBlock::PatchBlock(const BaseBlock& BB, mfxU8 y_comp, mfxU8 u_comp, mfxU8 v_comp) : BaseBlock(BB)
+{
+ mfxU32 sq = m_BWidth * m_BHeight;
+ PatchData.reset(new mfxU8[sq * 3 / 2]);
+ m_YPlane = PatchData.get();
+ m_UPlane = m_YPlane + sq;
+ m_VPlane = m_UPlane + (sq / 4);
+
+ memset(m_YPlane, y_comp, sq);
+ memset(m_UPlane, u_comp, sq / 4);
+ memset(m_VPlane, v_comp, sq / 4);
+}
+
+//constructor that fills PatchBlock with coresponding data from the srcPatch
+PatchBlock::PatchBlock(const BaseBlock& dstBlock, const PatchBlock& srcBlock) : PatchBlock(dstBlock)
+{
+ if (!dstBlock.IsInBlock(srcBlock))
+ {
+ throw std::string("ERROR: PatchBlock: new PatchBlock should be located inside the old one in frame coords");
+ }
+
+ //Calculating the coords of dstBlock relative to srcBlock
+ mfxU32 offsetX = dstBlock.m_AdrX - srcBlock.m_AdrX;
+ mfxU32 offsetY = dstBlock.m_AdrY - srcBlock.m_AdrY;
+
+ for (mfxU32 i = 0; i < m_BHeight; i++)
+ {
+ memcpy(m_YPlane + i * m_BWidth, srcBlock.m_YPlane + (offsetY + i) * srcBlock.m_BWidth + offsetX, m_BWidth);
+ }
+ for (mfxU32 i = 0; i < m_BHeight / 2; i++)
+ {
+ memcpy(m_UPlane + i * (m_BWidth / 2), srcBlock.m_UPlane + (offsetY / 2 + i) * (srcBlock.m_BWidth / 2) + offsetX / 2, m_BWidth / 2);
+ memcpy(m_VPlane + i * (m_BWidth / 2), srcBlock.m_VPlane + (offsetY / 2 + i) * (srcBlock.m_BWidth / 2) + offsetX / 2, m_BWidth / 2);
+ }
+}
+
+//constructor that filles PatchBlock with coresponding data from the surface
+PatchBlock::PatchBlock(const BaseBlock & BB, const ExtendedSurface & surf) : PatchBlock(BB)
+{
+ if (!BB.IsInBlock(BaseBlock(0, 0, surf.Info.CropW, surf.Info.CropH)))
+ {
+ throw std::string("ERROR: PatchBlock: new patchBlock should be located inside the surface");
+ }
+
+ for (mfxU32 i = 0; i < m_BHeight; i++)
+ {
+ memcpy(m_YPlane + i * m_BWidth, surf.Data.Y + (m_AdrY + i) * surf.Data.Pitch + m_AdrX, m_BWidth);
+ }
+ for (mfxU32 i = 0; i < m_BHeight / 2; i++)
+ {
+ memcpy(m_UPlane + i * (m_BWidth / 2), surf.Data.U + (m_AdrY / 2 + i) * (surf.Data.Pitch / 2) + m_AdrX / 2, m_BWidth / 2);
+ memcpy(m_VPlane + i * (m_BWidth / 2), surf.Data.V + (m_AdrY / 2 + i) * (surf.Data.Pitch / 2) + m_AdrX / 2, m_BWidth / 2);
+ }
+}
+
+//distance between current PatchBlock and other_patch counted as a sum of abs differences between luma components over all samples
+mfxU32 PatchBlock::CalcYSAD(const PatchBlock & otherPatch) const
+{
+ mfxU32 curDiff = 0;
+ if (m_BHeight == otherPatch.m_BHeight && m_BWidth == otherPatch.m_BWidth)
+ {
+ for (mfxU32 i = 0; i < m_BHeight*m_BWidth; i++)
+ {
+ curDiff += abs(m_YPlane[i] - otherPatch.m_YPlane[i]);
+ }
+ }
+ else
+ {
+ throw std::string("ERROR: CalcYSAD: block size mismatch");
+ }
+ return curDiff;
+}
+
+//compAdrX and compAdrY are given in the comp color space
+mfxU8 PatchBlock::GetSampleI420(COLOR_COMPONENT comp, mfxU32 compAdrX, mfxU32 compAdrY) const
+{
+ switch (comp)
+ {
+ case LUMA_Y:
+ return m_YPlane[compAdrY * m_BWidth + compAdrX];
+ case CHROMA_U:
+ return m_UPlane[compAdrY * (m_BWidth / 2) + compAdrX];
+ case CHROMA_V:
+ return m_VPlane[compAdrY * (m_BWidth / 2) + compAdrX];
+ default:
+ throw std::string("ERROR: Trying to get unspecified component");
+ }
+}
+
+//Inserts refPatch into this PatchBlock, if refPatch is located inside this PatchBlock
+void PatchBlock::InsertAnotherPatch(const PatchBlock & refPatch)
+{
+ if (!refPatch.IsInBlock(*this))
+ {
+ throw std::string("ERROR: InsertAnotherPatch: refPatch should be inside targetPatch\n");
+ }
+
+ //Calculating coordinate offset of refPatch relative to this PatchBlock
+ mfxU32 offsetX = refPatch.m_AdrX - m_AdrX;
+ mfxU32 offsetY = refPatch.m_AdrY - m_AdrY;
+
+ //luma
+ for (mfxU32 i = 0; i < refPatch.m_BHeight; i++)
+ {
+ memcpy(m_YPlane + (offsetY + i) * m_BWidth + offsetX, refPatch.m_YPlane + i * refPatch.m_BWidth, refPatch.m_BWidth);
+ }
+ //chroma U, V
+ for (mfxU32 i = 0; i < refPatch.m_BHeight / 2; ++i)
+ {
+ memcpy(m_UPlane + (offsetY / 2 + i) * m_BWidth / 2 + offsetX / 2, refPatch.m_UPlane + i * (refPatch.m_BWidth / 2), refPatch.m_BWidth / 2);
+ memcpy(m_VPlane + (offsetY / 2 + i) * m_BWidth / 2 + offsetX / 2, refPatch.m_VPlane + i * (refPatch.m_BWidth / 2), refPatch.m_BWidth / 2);
+ }
+ return;
+}
+
+//Returns a BaseBlock with coordinates that are shifted by the m_MV motion vector
+//from the corresponding list relative to the current PU position
+BaseBlock PUBlock::GetShiftedBaseBlock(REF_LIST_INDEX list) const
+{
+ mfxI64 posX = (mfxI64) m_AdrX + (m_MV.MV[list].x >> 2);
+ mfxI64 posY = (mfxI64) m_AdrY + (m_MV.MV[list].y >> 2);
+
+ if (posX < 0 && posY < 0)
+ {
+ throw std::string("ERROR: GetShiftedBaseBlock: negative resulting block coords");
+ }
+
+ return BaseBlock((mfxU32) posX, (mfxU32) posY, m_BWidth, m_BHeight);
+}
+
+void CUBlock::BuildPUsVector(INTER_PART_MODE mode)
+{
+ switch (mode)
+ {
+ case INTER_2NxN:
+ // UP PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth, m_BHeight / 2));
+ // DOWN PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY + m_BHeight / 2, m_BWidth, m_BHeight / 2));
+ break;
+
+ case INTER_Nx2N:
+ // LEFT PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth / 2, m_BHeight));
+ // RIGHT PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX + m_BWidth / 2, m_AdrY, m_BWidth / 2, m_BHeight));
+ break;
+
+ case INTER_NxN:
+ // TOP LEFT PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth / 2, m_BHeight / 2));
+ // TOP RIGHT PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX + m_BWidth / 2, m_AdrY, m_BWidth / 2, m_BHeight / 2));
+ // BOT LEFT PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY + m_BHeight / 2, m_BWidth / 2, m_BHeight / 2));
+ // BOT RIGHT PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX + m_BWidth / 2, m_AdrY + m_BHeight / 2, m_BWidth / 2, m_BHeight / 2));
+ break;
+
+ case INTER_2NxnU:
+ // UP SMALL PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth, m_BHeight / 4));
+ // DOWN LARGE PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY + m_BHeight / 4, m_BWidth, (m_BHeight * 3) / 4));
+ break;
+
+ case INTER_2NxnD:
+ // UP LARGE PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth, (m_BHeight * 3) / 4));
+ // DOWN SMALL PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY + (m_BHeight * 3) / 4, m_BWidth, m_BHeight / 4));
+ break;
+
+ case INTER_nLx2N:
+ // LEFT SMALL PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth / 4, m_BHeight));
+ // RIGHT LARGE PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX + m_BWidth / 4, m_AdrY, (m_BWidth * 3) / 4, m_BHeight));
+ break;
+
+ case INTER_nRx2N:
+ // LEFT LARGE PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, (m_BWidth * 3) / 4, m_BHeight));
+ // RIGHT SMALL PU
+ m_PUVec.emplace_back(PUBlock(m_AdrX + (m_BWidth * 3) / 4, m_AdrY, m_BWidth / 4, m_BHeight));
+ break;
+
+ case INTER_2Nx2N:
+ default:
+ m_PUVec.emplace_back(PUBlock(m_AdrX, m_AdrY, m_BWidth, m_BHeight));
+ break;
+ }
+ return;
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_marker.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_marker.cpp
new file mode 100644
index 0000000..6e1e6de
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_marker.cpp
@@ -0,0 +1,191 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "frame_marker.h"
+#include "frame_reorder.h"
+
+void FrameMarker::PreProcessStreamConfig(InputParams & params)
+{
+ try
+ {
+ BuildRefLists(params);
+ TagFrames(params);
+
+ params.m_vProcessingParams = m_vProcessingParams;
+ }
+ catch (std::string & e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: FrameMarker::PreProcessStreamConfig");
+ }
+ return;
+}
+
+void FrameMarker::BuildRefLists(const InputParams & params)
+{
+ // Parameters for reordering
+ m_vProcessingParams.resize(params.m_numFrames);
+
+ FrameReorder reorder(params);
+
+ mfxVideoParam param = {};
+ param.mfx.GopOptFlag = params.m_GopOptFlag;
+ param.mfx.GopPicSize = params.m_GopSize;
+ param.mfx.GopRefDist = params.m_RefDist;
+ param.mfx.IdrInterval = params.m_nIdrInterval;
+ param.mfx.FrameInfo.PicStruct = params.m_PicStruct;
+
+ // Construction of the frame with correct lists
+ // Reference list creating
+ mfxU32 idxEncoded = 0;
+ for (mfxU32 idxFrame = 0; idxFrame < params.m_numFrames; ++idxFrame)
+ {
+ ExternalFrame f = reorder.CreateExternalFrame(idxFrame, param);
+ if (f.Poc != -1)
+ {
+ m_vProcessingParams.at(f.DisplayOrder) = f;
+ m_vProcessingParams.at(f.DisplayOrder).EncodedOrder = idxEncoded;
+ ++idxEncoded;
+ }
+ }
+ // Drain buffered frames
+ while (reorder.GetBufferedQueueSize() != 0)
+ {
+ ExternalFrame f = reorder.CreateExternalFrame(-1, param);
+ m_vProcessingParams.at(f.DisplayOrder) = f;
+ m_vProcessingParams.at(f.DisplayOrder).EncodedOrder = idxEncoded;
+ ++idxEncoded;
+ }
+
+ return;
+}
+
+void FrameMarker::TagFrames(const InputParams & params)
+{
+ mfxVideoParam param = {};
+ param.mfx.GopOptFlag = params.m_GopOptFlag;
+ param.mfx.GopPicSize = params.m_GopSize;
+ param.mfx.GopRefDist = params.m_RefDist;
+ param.mfx.IdrInterval = params.m_nIdrInterval;
+ param.mfx.FrameInfo.PicStruct = params.m_PicStruct;
+
+ std::vector refFramesL0;
+ std::vector refFramesL1;
+ refFramesL0.reserve(std::max(params.m_NumRefActiveP, params.m_NumRefActiveBL0));
+ refFramesL1.reserve(params.m_NumRefActiveBL1);
+
+ mfxU32 num_gen = 0, num_mod = 0;
+
+ if (GenerateInterMBs(params.m_TestType))
+ {
+ // Current test requires P/B frames
+
+ // Creating of the processing parameters for each frame
+ // It contains mark of the frame, reference frames for MOD frames (test frame)
+ // For frames with mark GEN or SKIP reference frames are empty
+ for (mfxU32 idxFrame = 0; idxFrame < params.m_numFrames; ++idxFrame)
+ {
+ // Clear references
+ refFramesL0.clear();
+ refFramesL1.clear();
+
+ // Marker shouldn't set P-frames as MOD in presets with B-frames
+ if ((m_vProcessingParams.at(idxFrame).Type & MFX_FRAMETYPE_P) && !HasBFramesInGOP(params.m_RefDist))
+ {
+ // We need to check number of available reference and their status
+ // If they already are MOD or GEN we won't use them
+ if (m_vProcessingParams.at(idxFrame).ListX[0].size() == params.m_NumRefActiveP && !HasAlreadyUsedRefs(idxFrame, 0))
+ {
+ SetRefList(idxFrame, 0, refFramesL0, num_gen);
+ m_vProcessingParams.at(idxFrame).ReferencesL0 = refFramesL0;
+ if (params.m_UseGPB)
+ {
+ SetRefList(idxFrame, 1, refFramesL1, num_gen);
+ m_vProcessingParams.at(idxFrame).ReferencesL1 = refFramesL1;
+ }
+
+ m_vProcessingParams.at(idxFrame).Mark = MOD;
+ ++num_mod;
+ }
+ }
+ else if (m_vProcessingParams.at(idxFrame).Type & MFX_FRAMETYPE_B)
+ {
+ // We need to check number of available reference and their status
+ // If they already are MOD or GEN we won't use them
+ if ((m_vProcessingParams.at(idxFrame).ListX[0].size() == params.m_NumRefActiveBL0 && !HasAlreadyUsedRefs(idxFrame, 0))
+ && (m_vProcessingParams.at(idxFrame).ListX[1].size() == params.m_NumRefActiveBL1 && !HasAlreadyUsedRefs(idxFrame, 1)))
+ {
+ SetRefList(idxFrame, 0, refFramesL0, num_gen);
+ SetRefList(idxFrame, 1, refFramesL1, num_gen);
+ m_vProcessingParams.at(idxFrame).ReferencesL0 = refFramesL0;
+ m_vProcessingParams.at(idxFrame).ReferencesL1 = refFramesL1;
+ m_vProcessingParams.at(idxFrame).Mark = MOD;
+ ++num_mod;
+ }
+ }
+ }
+ }
+ else
+ {
+ // Intra test only
+ for (mfxU32 idxFrame = 0; idxFrame < params.m_numFrames; ++idxFrame)
+ {
+ m_vProcessingParams.at(idxFrame).Mark = MOD;
+ ++num_mod;
+ }
+ }
+
+ // Check that preset is valid, i.e. at least test_frames_percent_min frames are utilized for testing
+ const mfxU32 test_frames_percent_min = 15;
+
+ mfxU32 test_frames_percent = 100 * (num_gen + num_mod) / params.m_numFrames;
+
+ if (test_frames_percent < test_frames_percent_min)
+ throw std::string("ERROR: FrameMaker::CreateProcessingParams: Current preset involves too few frames");
+}
+
+bool FrameMarker::HasAlreadyUsedRefs(mfxU32 frame, mfxU8 list)
+{
+ for (mfxU32 idxRefLX = 0; idxRefLX < m_vProcessingParams.at(frame).ListX[list].size(); ++idxRefLX)
+ {
+ if (m_vProcessingParams.at(m_vProcessingParams.at(frame).ListX[list][idxRefLX].DisplayOrder).Mark != SKIP)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+void FrameMarker::SetRefList(mfxU32 frame, mfxU8 list, std::vector & refFrames, mfxU32 & num_gen)
+{
+ for (mfxU32 idxRefLX = 0; idxRefLX < m_vProcessingParams.at(frame).ListX[list].size(); ++idxRefLX)
+ {
+ mfxU32 idxFrameLX = m_vProcessingParams.at(frame).ListX[list].at(idxRefLX).DisplayOrder;
+ refFrames.push_back(idxFrameLX);
+ m_vProcessingParams.at(idxFrameLX).Mark = GEN;
+ ++num_gen;
+ }
+ return;
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_processor.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_processor.cpp
new file mode 100644
index 0000000..5cc8fdb
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_processor.cpp
@@ -0,0 +1,1824 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "frame_processor.h"
+#include "random_generator.h"
+
+
+// Initialize parameters
+void FrameProcessor::Init(const InputParams ¶ms)
+{
+ m_CropH = params.m_height;
+ m_CropW = params.m_width;
+
+ m_CTUStr = params.m_CTUStr;
+
+ // align by CUSize
+ m_Height = MSDK_ALIGN(m_CropH, m_CTUStr.CTUSize);
+ m_Width = MSDK_ALIGN(m_CropW, m_CTUStr.CTUSize);
+
+ m_HeightInCTU = m_Height / m_CTUStr.CTUSize;
+ m_WidthInCTU = m_Width / m_CTUStr.CTUSize;
+
+ m_ProcMode = params.m_ProcMode;
+
+ m_SubPelMode = params.m_SubPixelMode;
+
+ m_IsForceExtMVPBlockSize = params.m_bIsForceExtMVPBlockSize;
+ m_ForcedExtMVPBlockSize = params.m_ForcedExtMVPBlockSize;
+ m_GenMVPBlockSize = SetCorrectMVPBlockSize(params.m_GenMVPBlockSize);
+}
+
+// Beginning of processing of current frame. Only MOD frames are processed
+
+void FrameProcessor::ProcessFrame(FrameChangeDescriptor & frame_descr)
+{
+ try
+ {
+ switch (frame_descr.m_changeType)
+ {
+ case GEN:
+ return;
+ break;
+
+ case MOD:
+ GenCTUParams(frame_descr);
+ GenAndApplyPrediction(frame_descr);
+ UnlockSurfaces(frame_descr);
+ break;
+
+ case SKIP:
+ UnlockSurfaces(frame_descr);
+ break;
+
+ default:
+ return;
+ break;
+ }
+ }
+ catch (std::string & e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: FrameProcessor::ProcessFrame");
+ }
+ return;
+}
+
+bool FrameProcessor::IsSampleAvailable(mfxU32 AdrX, mfxU32 AdrY)
+{
+ return (AdrY < m_CropH && AdrX < m_CropW);
+}
+
+// Only I420 color format are supported
+mfxU8 FrameProcessor::GetSampleI420(COLOR_COMPONENT comp, mfxU32 AdrX, mfxU32 AdrY, mfxFrameSurface1* surf)
+{
+ if (surf == nullptr)
+ {
+ throw std::string("ERROR: GetSampleI420: null pointer reference");
+ }
+
+ switch (comp)
+ {
+ case LUMA_Y:
+ return surf->Data.Y[AdrY * surf->Data.Pitch + AdrX];
+ case CHROMA_U:
+ return surf->Data.U[(AdrY / 2) * (surf->Data.Pitch / 2) + (AdrX / 2)];
+ case CHROMA_V:
+ return surf->Data.V[(AdrY / 2) * (surf->Data.Pitch / 2) + (AdrX / 2)];
+ default:
+ throw std::string("ERROR: Trying to get unspecified component");
+ }
+}
+
+mfxI32 FrameProcessor::GetClippedSample(COLOR_COMPONENT comp, mfxI32 X, mfxI32 Y, mfxFrameSurface1 * surf)
+{
+ mfxU32 clippedX = Clip3(X, 0, (mfxI32)m_CropW);
+ mfxU32 clippedY = Clip3(Y, 0, (mfxI32)m_CropH);
+
+ return GetSampleI420(comp, clippedX, clippedY, surf);
+}
+
+// These functions are to be used after applying CalculateLumaPredictionSamplePreWP
+// In specification default weighted prediction is the final scaling step for sample prediction.
+// predSampleL0 is an interpolated Luma sample value which is calculated in CalculateLumaPredictionSamplePreWP()
+// Output is final scaled and rounded Luma value which returns in CalculateLumaPredictionSamplePreWP()
+// See 8.5.3.3.4.2 "Default weighted sample prediction process" from 4.0 ITU-T H.265 (V4) 2016-12-22
+mfxU8 FrameProcessor::GetDefaultWeightedPredSample(mfxI32 predSampleLx)
+{
+ // These shift and offset variables are defined in H265 standard for 8 bit color depth
+ constexpr mfxU16 shift1 = 6;
+ constexpr mfxU16 offset1 = 1 << (shift1 - 1); // 2^5 = 32
+
+ constexpr mfxI32 upperBound = (1 << 8) - 1; // 2^8 - 1 = 255
+ mfxI32 predSample = (predSampleLx + offset1) >> shift1;
+
+ return mfxU8(Clip3(predSample, 0, upperBound));
+}
+
+// Alternative in case working with B-frames
+mfxU8 FrameProcessor::GetDefaultWeightedPredSample(mfxI32 predSampleL0, mfxI32 predSampleL1)
+{
+ // These shift and offset variables are defined in H265 standard for 8 bit color depth
+ mfxU16 shift2 = 7;
+ mfxU16 offset2 = 1 << (shift2 - 1); // 2^6 = 64
+
+ mfxI32 upperBound = (1 << 8) - 1; // 2^8 - 1 = 255
+
+ mfxI32 predSample = (predSampleL0 + predSampleL1 + offset2) >> shift2;
+
+ return mfxU8(Clip3(predSample, 0, upperBound));
+}
+
+void FrameProcessor::GenRandomQuadTreeStructure(QuadTree& QT, mfxU8 minDepth, mfxU8 maxDepth)
+{
+ if (!QT.IsEmpty())
+ {
+ QT.Clear();
+ }
+
+ GenRandomQuadTreeSubstrRecur(QT.root, minDepth, maxDepth);
+}
+
+void FrameProcessor::GenRandomQuadTreeSubstrRecur(QuadTreeNode& node, mfxU8 minDepth, mfxU8 maxDepth)
+{
+ if (node.m_Level < minDepth ||
+ (node.m_Level < maxDepth && GetRandomGen().GetRandomBit()))
+ {
+ node.MakeChildren();
+ for (auto& child : node.m_Children)
+ {
+ GenRandomQuadTreeSubstrRecur(child, minDepth, maxDepth);
+ }
+ }
+ return;
+}
+
+//Make a quad-tree structure inside ctu's QuadTree from FEI output
+void FrameProcessor::GenQuadTreeInCTUWithBitMask(CTUDescriptor& CTU, mfxU32 bitMask)
+{
+ if (bitMask & 1)
+ {
+ CTU.m_CUQuadTree.root.MakeChildren();
+ GenQuadTreeWithBitMaskRecur(CTU.m_CUQuadTree.root, bitMask >> 1);
+ }
+
+ return;
+}
+
+void FrameProcessor::GenQuadTreeWithBitMaskRecur(QuadTreeNode& node, mfxU32 bitMask)
+{
+ for (mfxU32 i = 0; i < 4; i++)
+ {
+ if (bitMask & (1 << i))
+ {
+ node.m_Children[i].MakeChildren();
+
+ if (node.m_Children[i].m_Level < 2)
+ {
+ GenQuadTreeWithBitMaskRecur(node.m_Children[i], bitMask >> 4 * (i + 1));
+ }
+ }
+ }
+
+ return;
+}
+
+//Fills CU vector inside CTU with correct CU blocks in CTU quad-tree z-scan order
+//For each CU, depending on the test type, its prediction mode is selected
+//and further CU partitioning/mode selection is made (i.e. PU and TU partitioning
+//and per TU intra mode selection)
+void FrameProcessor::GenCUVecInCTU(CTUDescriptor& ctu, mfxU16 testType)
+{
+ QuadTree& QT = ctu.m_CUQuadTree;
+ std::vector tmpVec;
+ QT.GetQuadTreeBlocksRecur(QT.root, ctu.m_AdrX, ctu.m_AdrY, ctu.m_BHeight, tmpVec);
+
+ for (auto& block : tmpVec)
+ {
+ CUBlock cu_block(block);
+
+ if (testType & GENERATE_INTER && testType & GENERATE_INTRA)
+ {
+ cu_block.m_PredType = (GetRandomGen().GetRandomBit()) ?
+ INTRA_PRED : INTER_PRED;
+ }
+ else if (testType & GENERATE_INTER)
+ {
+ cu_block.m_PredType = INTER_PRED;
+ }
+ else
+ {
+ cu_block.m_PredType = INTRA_PRED;
+ }
+
+ if (cu_block.m_PredType == INTRA_PRED)
+ {
+ MakeIntraCU(cu_block);
+ }
+ else if (cu_block.m_PredType == INTER_PRED)
+ {
+ MakeInterCU(cu_block, testType);
+ }
+
+ ctu.m_CUVec.push_back(cu_block);
+ }
+}
+
+void FrameProcessor::GetRefSampleAvailFlagsForTUsInCTU(CTUDescriptor & CTU)
+{
+ QuadTree& QT = CTU.m_CUQuadTree;
+ std::vector CURefSampleAvailVec;
+ //CTU is set with RefSamples available in both directions here.
+ //this should be made by guaranteeing that CTUs are far from each other
+ //(at least one initial CTU between two substituted CTUs in both directions)
+ QT.GetQuadTreeRefSampleAvailVector(QT.root, CTU, CTU, CURefSampleAvailVec);
+
+ if (CURefSampleAvailVec.size() != CTU.m_CUVec.size())
+ {
+ throw std::string("ERROR: GetRefSampleAvailFlagsForTUsInCTU: mismatching CU and RefSampleAvail vector sizes");
+ }
+
+ for (mfxU32 i = 0; i < CTU.m_CUVec.size(); i++)
+ {
+ CUBlock & CU = CTU.m_CUVec[i];
+ if (CU.m_PredType == INTRA_PRED)
+ {
+ QuadTree& RQT = CU.m_TUQuadTree;
+ std::vector TURefSampleAvailVec;
+
+ RQT.GetQuadTreeRefSampleAvailVectorRecur(RQT.root, CU, CURefSampleAvailVec[i], CTU, TURefSampleAvailVec);
+ for (mfxU32 j = 0; j < CU.m_TUVec.size(); j++)
+ {
+ TUBlock& TU = CU.m_TUVec[j];
+ TU.m_RefSampleAvail = TURefSampleAvailVec[j];
+ }
+ }
+ }
+}
+
+void FrameProcessor::GenRandomTUQuadTreeInCU(CUBlock& cu_block)
+{
+ QuadTree& quadTreeTU = cu_block.m_TUQuadTree;
+ mfxU32 minTUDepth = std::max(0, mfxI32(CeilLog2(cu_block.m_BHeight) - m_CTUStr.maxLog2TUSize));
+ mfxU32 maxTUDepth = std::min(CeilLog2(cu_block.m_BHeight) - m_CTUStr.minLog2TUSize, m_CTUStr.maxTUQTDepth);
+
+ GenRandomQuadTreeStructure(quadTreeTU, minTUDepth, maxTUDepth);
+}
+
+
+//Make a quad-tree structure inside ctu's QuadTree so that all CU blocks inside CTU
+//have a size smaller than specified by maxLog2CUSize and larger than specified by minLog2CUSize
+void FrameProcessor::GenRandomCUQuadTreeInCTU(CTUDescriptor& ctu)
+{
+ QuadTree& quadTreeCU = ctu.m_CUQuadTree;
+ mfxU32 minCUDepth = std::max(0, mfxI32(CeilLog2(ctu.m_BHeight) - m_CTUStr.maxLog2CUSize));
+ mfxU32 maxCUDepth = CeilLog2(ctu.m_BHeight) - m_CTUStr.minLog2CUSize;
+ GenRandomQuadTreeStructure(quadTreeCU, minCUDepth, maxCUDepth);
+}
+
+//TODO:
+bool FrameProcessor::IsBlockUniform(const BaseBlock& block, PatchBlock& frame)
+{
+ return false;
+}
+
+//TODO:
+void FrameProcessor::AlterBorderSamples(const BaseBlock& block, PatchBlock& frame)
+{
+
+}
+
+void FrameProcessor::ChooseContrastIntraMode(const BaseBlock& block, std::vector& block_vec, PatchBlock& frame)
+{
+ if (IsBlockUniform(block, frame))
+ {
+ AlterBorderSamples(block, frame);
+ }
+
+ //distance between initial block and intra predicted patch should be maximized
+ mfxU32 maxDist = 0; //max num of diff that can be reached is 32x32x256 = 2^18
+ //initial block filled with samples from the frame
+ PatchBlock refBlock(block, frame);
+ //here Patch with max distance from the initBlock will be stored
+ PatchBlock maxDistPatch(block);
+ //mode corresponding to maxDistPatch
+ INTRA_MODE maxDistMode = PLANAR;
+
+ //choose TUs inside block
+ std::vector TUInCurrBlock;
+ for (auto& TU : block_vec)
+ {
+ if (TU.IsInBlock(block))
+ {
+ TUInCurrBlock.emplace_back(TU);
+ }
+ }
+
+ //check whether there is TU inside block with no left-down or up-right refSamples available
+ //if so, we can't use corresponding modes and we limit maxModeAvail minModeAvail
+ // and minAngModeAvail in appropriate manner
+ //if left-down samples aren't available, modes 2 - 9 are prohibited
+ //if up-right samples aren't available, modes 27 - 34 are prohibited
+ //in both cases planar mode is prohibited because it uses samples p[-1][N] and p[N][-1]
+ //in coordinates relative to the block, where N is the size of block
+ //see HEVC algorighms and structures page 101(112)
+ //Vivienne Sze Madhukar Budagavi Gary J.Sullivan High Efficiency Video Coding(HEVC) Algorithms and Architectures 2014
+
+ mfxU32 minModeAvail = INTRA_MODE::PLANAR;
+ mfxU32 minAngModeAvail = INTRA_MODE::ANG2;
+ mfxU32 maxModeAvail = INTRA_MODE::ANG34;
+ for (auto& TU : TUInCurrBlock)
+ {
+ if (!TU.m_RefSampleAvail.LeftDown)
+ {
+ minAngModeAvail = INTRA_MODE::ANG10_HOR;
+ minModeAvail = INTRA_MODE::DC;
+ }
+ if (!TU.m_RefSampleAvail.UpRight)
+ {
+ maxModeAvail = INTRA_MODE::ANG26_VER;
+ minModeAvail = INTRA_MODE::DC;
+ }
+ }
+
+ for (mfxU32 i = minModeAvail; i <= maxModeAvail; i++)
+ {
+ if (i < INTRA_MODE::ANG2 || i >= minAngModeAvail)
+ {
+ //iterate over TUs of current CU and save predicted TUs into frame
+ for (auto& TU : TUInCurrBlock)
+ {
+ TU.m_IntraModeChroma = TU.m_IntraModeLuma = INTRA_MODE(i);
+ MakeTUIntraPrediction(TU, frame);
+ }
+ //get curPatch from frame
+ PatchBlock curPatch(block, frame);
+ //count distance between initial block and current patch
+ mfxU32 curDist = refBlock.CalcYSAD(curPatch);
+ //save patch which is the farthest from the initial CU block
+ if (curDist > maxDist)
+ {
+ maxDist = curDist;
+ maxDistPatch = curPatch;
+ maxDistMode = INTRA_MODE(i);
+ }
+ }
+ }
+
+ for (auto& TU : block_vec)
+ {
+ if (TU.IsInBlock(block))
+ {
+ //for now chroma intra mode is set equal to luma intra mode
+ TU.m_IntraModeChroma = TU.m_IntraModeLuma = maxDistMode;
+ }
+ }
+
+ frame.InsertAnotherPatch(maxDistPatch);
+
+ return;
+}
+
+//Generates a quad-tree TU structure inside the cu_block and fills the TU block vector
+//inside cu_block with correct TU blocks corresponding to the CU quad-tree TU structure
+//Selects an intra mode for each generated TU
+void FrameProcessor::MakeIntraCU(CUBlock& cu_block)
+{
+ QuadTree& QT = cu_block.m_TUQuadTree;
+ GenRandomTUQuadTreeInCU(cu_block);
+
+ std::vector tmpVec;
+ QT.GetQuadTreeBlocksRecur(QT.root, cu_block.m_AdrX, cu_block.m_AdrY, cu_block.m_BHeight, tmpVec);
+ cu_block.m_TUVec.clear();
+ for (auto& block : tmpVec)
+ {
+ cu_block.m_TUVec.emplace_back(TUBlock(block, PLANAR, PLANAR));
+ }
+
+ mfxU32 minCUSize = 1 << m_CTUStr.minLog2CUSize;
+ //Special case for CUs of size equal to minCUSize:
+ //we can choose intra mode for every quarter
+ //see last paragraph on p.228(238) in HEVC Algorithms and Architectures
+ if (cu_block.m_BHeight == minCUSize && cu_block.m_BWidth == minCUSize
+ && tmpVec.size() >= 4 && GetRandomGen().GetRandomBit())
+ {
+ cu_block.m_IntraPartMode = INTRA_NxN;
+ }
+ else
+ {
+ cu_block.m_IntraPartMode = INTRA_2Nx2N;
+ }
+}
+
+void FrameProcessor::MakeIntraPredInCTU(CTUDescriptor& ctu, FrameChangeDescriptor & descr)
+{
+ ExtendedSurface& surf = *descr.m_frame;
+ //save frame data in temporary patchBlock
+ PatchBlock framePatchBlock(BaseBlock(0, 0, surf.Info.CropW, surf.Info.CropH), surf);
+ for (auto& cu : ctu.m_CUVec)
+ {
+ if (cu.m_PredType == INTRA_PRED)
+ {
+ if (cu.m_IntraPartMode == INTRA_NxN)
+ {
+ std::vector childrenBlocks;
+ cu.GetChildBlock(childrenBlocks);
+ for (mfxU32 i = 0; i < 4; i++)
+ {
+ //choose the most contrast intra mode for every quarter of CU
+ ChooseContrastIntraMode(childrenBlocks[i], cu.m_TUVec, framePatchBlock);
+ }
+ }
+ else
+ {
+ ChooseContrastIntraMode(cu, cu.m_TUVec, framePatchBlock);
+ }
+ }
+ }
+}
+
+//Chooses the inter partitioning mode for the CU and fills the PU vector inside it with PUs
+//corresponding to the chosen mode
+void FrameProcessor::MakeInterCU(CUBlock& cu_block, mfxU16 testType)
+{
+ INTER_PART_MODE mode = INTER_PART_MODE::INTER_NONE;
+
+ mfxU32 max_mode_num = -1;
+
+ if (!(testType & GENERATE_SPLIT) || !m_CTUStr.bCUToPUSplit)
+ {
+ mode = INTER_PART_MODE::INTER_2Nx2N; //If no split is specified or CU to PU split is forbidden,
+ //the CU will contain a single PU
+ }
+ else
+ {
+ if (cu_block.m_BHeight == 8 && cu_block.m_BWidth == 8)
+ {
+ //Minimum PU size is 4x8 or 8x4, which means that only first 3 inter partitioning
+ //modes are available for 8x8 CU
+ //Condition when only symmetric modes are supported in case of 8x8 CU is satisfied by default
+ max_mode_num = INTER_8x8CU_PART_MODE_NUM - 1;
+ }
+ else if (m_CTUStr.bForceSymmetricPU)
+ {
+ //No check for 8x8 CU case here. It is already processed
+ max_mode_num = INTER_SYMM_PART_MODE_NUM - 1;
+ }
+ else
+ {
+ max_mode_num = INTER_PART_MODE_NUM - 1;
+ }
+
+ bool isCUMinSized = (CeilLog2(cu_block.m_BHeight) == m_CTUStr.minLog2CUSize);
+ // CU split into 4 square PUs is only allowed for the CUs
+ // of the smallest size (see p.61-62 of doi:10.1007/978-3-319-06895-4)
+ do
+ {
+ mode = (INTER_PART_MODE) GetRandomGen().GetRandomNumber(0, max_mode_num);
+ }
+ while (!isCUMinSized && mode == INTER_PART_MODE::INTER_NxN);
+
+ }
+
+ cu_block.BuildPUsVector(mode);
+ cu_block.m_InterPartMode = mode;
+}
+
+mfxU8 FrameProcessor::CeilLog2(mfxU32 size)
+{
+ mfxU8 ret = 0;
+ while (size > 1)
+ {
+ size /= 2;
+ ret++;
+ }
+ return ret;
+}
+
+// First round of generation: choose CTU on current MOD frame
+//
+// FrameChangeDescriptor & frameDescr - descriptor of current MOD frame
+
+void FrameProcessor::GenCTUParams(FrameChangeDescriptor & frame_descr)
+{
+ mfxI32 maxAttempt = 100;
+
+ // Try no more than maxAttempt times to generate no more than m_CTUStr.CTUMaxNum CTUs
+ for (mfxI32 i = 0; i < maxAttempt && frame_descr.m_vCTUdescr.size() < m_CTUStr.CTUMaxNum; ++i)
+ {
+ // TODO: this part could be improved with aggregate initialization
+ CTUDescriptor tempCTUDsc;
+
+ // Do not choose last CTU in row/column to avoid effects of alignment
+ // m_WidthInCTU-1 is a coordinate of last CTU in row
+ tempCTUDsc.m_AdrXInCTU = GetRandomGen().GetRandomNumber(0, m_WidthInCTU - 2);
+ tempCTUDsc.m_AdrYInCTU = GetRandomGen().GetRandomNumber(0, m_HeightInCTU - 2);
+
+ // Calculate pixel coordinates and size
+ tempCTUDsc.m_AdrX = tempCTUDsc.m_AdrXInCTU * m_CTUStr.CTUSize;
+ tempCTUDsc.m_AdrY = tempCTUDsc.m_AdrYInCTU * m_CTUStr.CTUSize;
+ tempCTUDsc.m_BWidth = tempCTUDsc.m_BHeight = m_CTUStr.CTUSize;
+
+ // Checks if current CTU intersects with or is too close to any of already generated
+ auto it = find_if(frame_descr.m_vCTUdescr.begin(), frame_descr.m_vCTUdescr.end(),
+ [&](const CTUDescriptor& dscr){ return dscr.CheckForIntersect(tempCTUDsc, m_CTUStr.CTUSize * m_CTUStr.CTUDist, m_CTUStr.CTUSize * m_CTUStr.CTUDist); });
+
+ if (it == frame_descr.m_vCTUdescr.end())
+ {
+ // If no intersection, put generated block to vector
+ frame_descr.m_vCTUdescr.push_back(std::move(tempCTUDsc));
+ }
+ }
+
+ return;
+}
+
+// Second round of test: Generate partitions and MVs. Write down pixels to MOD and all reference GEN frames
+// Remove a CTU generated in the previous round from the test set
+// if it is impossible to place it without intersecting other CTUs
+//
+// FrameChangeDescriptor & frameDescr - descriptor of current MOD frame
+
+void FrameProcessor::GenAndApplyPrediction(FrameChangeDescriptor & frameDescr)
+{
+ // Iterate over all generated in GenCTUParams CTUs (see round 1)
+ auto it_ctu = frameDescr.m_vCTUdescr.begin();
+
+ if (!(frameDescr.m_testType & GENERATE_SPLIT))
+ {
+ //If no split is specified, set min/max CU size to CTU size
+ //so that the CTU quad-tree only contains single node after generation
+ m_CTUStr.minLog2CUSize = CeilLog2(m_CTUStr.CTUSize);
+ m_CTUStr.maxLog2CUSize = CeilLog2(m_CTUStr.CTUSize);
+ }
+
+
+ while (it_ctu != frameDescr.m_vCTUdescr.end())
+ {
+ auto &CTU = *it_ctu;
+
+ //make a tree and save CUs into the vector inside CTU
+ GenRandomCUQuadTreeInCTU(CTU);
+ GenCUVecInCTU(CTU, frameDescr.m_testType);
+ if (frameDescr.m_testType & GENERATE_INTRA)
+ {
+ GetRefSampleAvailFlagsForTUsInCTU(CTU);
+ }
+
+ FrameOccRefBlockRecord bak = frameDescr.BackupOccupiedRefBlocks();
+
+ bool bMVGenSuccess = true;
+ if (frameDescr.m_testType & GENERATE_INTER)
+ {
+ bMVGenSuccess = MakeInterPredInCTU(CTU, frameDescr);
+ }
+ if (bMVGenSuccess)
+ {
+ //Inter prediction must be applied first
+ //because intra blocks should use noise pixels from
+ //adjacent inter CUs and not unchanged picture pixels
+ //in the same spot
+ ApplyInterPredInCTU(CTU, frameDescr);
+
+ //most contrast intra mode is chosen here
+ MakeIntraPredInCTU(CTU, frameDescr);
+ ApplyIntraPredInCTU(CTU, frameDescr);
+ it_ctu++;
+ }
+ else
+ {
+ //Unable to put the CTU into reference frames without intersection
+ //Restore backup reference block info:
+ frameDescr.RestoreOccupiedRefBlocks(bak);
+
+ //Remove current CTU from the test block list and updating the iterator
+ it_ctu = frameDescr.m_vCTUdescr.erase(it_ctu);
+ }
+ }
+
+ return;
+}
+
+//Generates MV and MVP for all PUs in CTU
+bool FrameProcessor::MakeInterPredInCTU(CTUDescriptor& CTU, FrameChangeDescriptor& frameDescr)
+{
+ // First, need to construct an MVP grid and vector pools according to CTU partioning
+ MVMVPProcessor mvmvpProcessor(m_GenMVPBlockSize, m_SubPelMode);
+
+ if (frameDescr.m_testType & GENERATE_PREDICTION)
+ {
+ mvmvpProcessor.InitMVPGridData(CTU, frameDescr);
+ }
+
+ for (auto& CU : CTU.m_CUVec)
+ {
+ if (CU.m_PredType == INTER_PRED)
+ {
+ for (auto& PU : CU.m_PUVec)
+ {
+ // Set prediction flags for each PU
+ GenPredFlagsForPU(PU, frameDescr.m_frameType);
+
+ bool bMVGenSuccess = false;
+ if (frameDescr.m_testType & GENERATE_PREDICTION)
+ {
+ bMVGenSuccess = mvmvpProcessor.GenValidMVMVPForPU(PU, frameDescr);
+ }
+ else
+ {
+ bMVGenSuccess = mvmvpProcessor.GenValidMVForPU(PU, frameDescr);
+ }
+
+ if (bMVGenSuccess)
+ {
+ // Store the shifted PU as a BaseBlock in the corresponding reference frame descriptor
+ if (PU.predFlagL0)
+ {
+ auto itL0 = std::next(frameDescr.m_refDescrList0.begin(), PU.m_MV.RefIdx.RefL0);
+ itL0->m_OccupiedRefBlocks.emplace_back(PU.GetShiftedBaseBlock(L0));
+ }
+
+ if (PU.predFlagL1)
+ {
+ auto itL1 = std::next(frameDescr.m_refDescrList1.begin(), PU.m_MV.RefIdx.RefL1);
+ itL1->m_OccupiedRefBlocks.emplace_back(PU.GetShiftedBaseBlock(L1));
+ }
+ }
+ else
+ {
+ //MV prediction has failed; need to discard the whole CTU
+ return false;
+ }
+ }
+ }
+ }
+
+ //MVs for all PUs in CTU have been generated
+
+ // If predictors required, put them to ext buffer
+ if (frameDescr.m_testType & GENERATE_PREDICTION && frameDescr.m_procMode == GENERATE)
+ {
+ //Only output predictors if CTU contains at least one inter CU
+ auto it = std::find_if(CTU.m_CUVec.begin(), CTU.m_CUVec.end(),
+ [](const CUBlock& CU) { return CU.m_PredType == INTER_PRED; });
+
+ if (it != CTU.m_CUVec.end())
+ {
+ mvmvpProcessor.FillFrameMVPExtBuffer(frameDescr);
+ }
+ }
+
+ if ((frameDescr.m_testType & GENERATE_PREDICTION) && frameDescr.m_procMode == VERIFY)
+ {
+ mvmvpProcessor.GetMVPPools(CTU.m_MVPGenPools);
+ }
+
+ return true;
+}
+
+
+void FrameProcessor::GenPredFlagsForPU(PUBlock & PU, mfxU16 frameType)
+{
+ PU.predFlagL0 = true; // Set prediction flag for P-frames
+ if (frameType & MFX_FRAMETYPE_B)
+ {
+ // Each PU requires 1 or more reference
+ mfxI32 maxValue = 2;
+ if (PU.m_BWidth == 4 || PU.m_BHeight == 4)
+ maxValue = 1; // For PUs 8x4 or 4x8 we can use only unidirectional prediction
+
+ switch (GetRandomGen().GetRandomNumber(0, maxValue))
+ {
+ case 0:
+ PU.predFlagL0 = true;
+ PU.predFlagL1 = false;
+ break;
+ case 1:
+ PU.predFlagL0 = false;
+ PU.predFlagL1 = true;
+ break;
+ case 2:
+ PU.predFlagL0 = true;
+ PU.predFlagL1 = true;
+ break;
+ }
+ }
+
+ return;
+}
+
+//Iterates over CUs in CTU and applies inter prediction for inter CUs
+void FrameProcessor::ApplyInterPredInCTU(CTUDescriptor& CTU, FrameChangeDescriptor & frameDescr)
+{
+ for (auto& CU : CTU.m_CUVec)
+ {
+ if (CU.m_PredType == INTER_PRED)
+ {
+ for (auto& PU : CU.m_PUVec)
+ {
+ // Advance to reference descriptor of desired frame
+ // NB: using reverse iterator here because RefIdx starts counting from the end of the list
+
+ // Generate noisy PU in GEN frames pixels
+ // This function should be called in both (generate and verify) modes, because includes work with random generator
+ PutNoiseBlocksIntoFrames(PU, frameDescr);
+
+ // Trace back those pixels (using q-pel interpolation if required) and put to current MOD frame
+ // This function should be called only in the generate mode
+ if (m_ProcMode == GENERATE)
+ {
+ TraceBackAndPutBlockIntoFrame(PU, frameDescr);
+ }
+ }
+ }
+ }
+}
+
+// Generate and put noisy pixels to surface surf, which corresponds to block BP coordinates
+
+// Fill the block with 4x4 noise blocks
+void FrameProcessor::PutNoiseBlocksIntoFrames(const PUBlock & PU, const FrameChangeDescriptor & frameDescr, mfxU32 num_coeff, mfxU32 level)
+{
+ BaseBlock BPL0, BPL1;
+
+ mfxFrameSurface1* refSurfL0 = nullptr;
+ mfxFrameSurface1* refSurfL1 = nullptr;
+
+ if (PU.predFlagL0)
+ {
+ if (frameDescr.m_refDescrList0.size() <= PU.m_MV.RefIdx.RefL0)
+ {
+ throw std::string("ERROR: PutNoiseBlockIntoFrames: incorrect reference index for list 0");
+ }
+ auto &refDescrL0 = *next(frameDescr.m_refDescrList0.begin(), PU.m_MV.RefIdx.RefL0);
+
+ // Get frame of reference GEN frame
+ refSurfL0 = refDescrL0.m_frame;
+ if (refSurfL0 == nullptr)
+ {
+ throw std::string("ERROR: PutNoiseBlockIntoFrames: null pointer reference");
+ }
+
+ BPL0 = PU.GetShiftedBaseBlock(L0);
+ }
+
+ if (PU.predFlagL1)
+ {
+ if (frameDescr.m_refDescrList1.size() <= PU.m_MV.RefIdx.RefL1)
+ {
+ throw std::string("ERROR: PutNoiseBlockIntoFrames: incorrect reference index for list 1");
+ }
+ auto &refDescrL1 = *next(frameDescr.m_refDescrList1.begin(), PU.m_MV.RefIdx.RefL1);
+
+ // Get frame of reference GEN frame
+ refSurfL1 = refDescrL1.m_frame;
+ if (refSurfL1 == nullptr)
+ {
+ throw std::string("ERROR: PutNoiseBlockIntoFrames: null pointer reference");
+ }
+
+ BPL1 = PU.GetShiftedBaseBlock(L1);
+ }
+
+ //Check that PU can be subdivided evenly into 4x4 blocks
+ if (PU.m_BWidth % 4 || PU.m_BHeight % 4)
+ {
+ throw std::string("ERROR: PutNoiseBlockIntoFrame: invalid block size");
+ }
+ mfxU32 Block4x4NumX = PU.m_AdrX / 4;
+ mfxU32 Block4x4NumY = PU.m_AdrY / 4;
+ mfxU32 FrameWidthIn4x4Blocks = (m_Width + 3) / 4;
+ mfxU32 FrameHeightIn4x4Blocks = (m_Height + 3) / 4;
+
+ mfxU32 seedOff = frameDescr.m_frame->Data.FrameOrder * FrameWidthIn4x4Blocks * FrameHeightIn4x4Blocks;
+ mfxU32 seed = 0;
+
+ mfxU32 BPWidthIn4x4Blocks = PU.m_BWidth / 4;
+ mfxU32 BPHeightIn4x4Blocks = PU.m_BHeight / 4;
+ mfxU8 block[16] = {}, blockAdjusted[16] = {};
+ mfxI8 blockDeltaL0[16] = {}, blockDeltaL1[16] = {};
+
+ for (mfxU32 i = 0; i < BPHeightIn4x4Blocks; i++)
+ {
+ for (mfxU32 j = 0; j < BPWidthIn4x4Blocks; j++)
+ {
+ //Calculate seed from the 4x4 block position inside the PU
+ seed = seedOff + FrameWidthIn4x4Blocks * (Block4x4NumY + i) + Block4x4NumX + j;
+ GetRandomGen().SeedGenerator(seed);
+
+ //Calculate noise pixel values
+ FillInBlock4x4(num_coeff, level, block);
+
+ //Calculate delta for difference between L0 and L1 references
+ if (PU.predFlagL0 && PU.predFlagL1)
+ FillDeltaBlocks4x4(blockDeltaL0, blockDeltaL1);
+
+ if (m_ProcMode == GENERATE)
+ {
+ if (PU.predFlagL0)
+ {
+ ApplyDeltaPerPixel(PU, blockDeltaL0, block, blockAdjusted);
+ PutBlock4x4(BPL0.m_AdrX + j * 4, BPL0.m_AdrY + i * 4, blockAdjusted, refSurfL0);
+ }
+
+ if (PU.predFlagL1)
+ {
+ ApplyDeltaPerPixel(PU, blockDeltaL1, block, blockAdjusted);
+ PutBlock4x4(BPL1.m_AdrX + j * 4, BPL1.m_AdrY + i * 4, blockAdjusted, refSurfL1);
+ }
+ }
+ }
+ }
+}
+
+// Fill block[16] with noise pixels, using up to num_coeff first random DCT coefficients
+// in the range of (-level; +level)
+void FrameProcessor::FillInBlock4x4(mfxU32 num_coeff, mfxU32 level, mfxU8 block[16])
+{
+ if (block == nullptr)
+ {
+ throw std::string("ERROR: FillInBlock4x4: null pointer reference");
+ }
+
+ if (num_coeff < 1 || num_coeff > 16)
+ {
+ throw std::string("\nERROR: Wrong num_coeff in FrameProcessor::FillInBlock4x4");
+ }
+ if (level > 255)
+ {
+ throw std::string("\nERROR: Wrong level in FrameProcessor::FillInBlock4x4");
+ }
+
+ mfxI32 coeff[16];
+ mfxI32 pixels[16];
+ mfxU32 scan[16] = { 0,1,4,8,5,2,3,6,9,12,13,10,7,11,14,15 };
+ memset(coeff, 0, sizeof(coeff));
+ for (mfxU32 i = 0; i < num_coeff; i++)
+ {
+ coeff[scan[i]] = level* GetRandomGen().GetRandomNumber(0, 256) / 256 - level / 2;
+ }
+ if (m_ProcMode == GENERATE)
+ {
+ Inverse4x4(coeff, 4, pixels, 4);
+ for (mfxU32 i = 0; i < 16; i++)
+ {
+ block[i] = ClipIntToChar(128 + pixels[i]);
+ }
+ }
+
+ return;
+}
+
+void FrameProcessor::FillDeltaBlocks4x4(mfxI8 blockL0[16], mfxI8 blockL1[16])
+{
+ if (blockL0 == nullptr || blockL1 == nullptr)
+ {
+ throw std::string("ERROR: FillDeltaBlocks4x4: null pointer reference");
+ }
+
+ for (mfxU32 i = 0; i < 16; i++)
+ {
+ blockL0[i] = GetRandomGen().GetRandomNumber(0, DELTA_PIXEL_BI_DIRECT);
+ blockL1[i] = -blockL0[i];
+ }
+
+
+ return;
+}
+
+void FrameProcessor::ApplyDeltaPerPixel(const PUBlock & PU, const mfxI8 deltaBlock[16], const mfxU8 inBlock[16], mfxU8 outBlock[16])
+{
+ if (inBlock == nullptr || outBlock == nullptr)
+ {
+ throw std::string("ERROR: ApplyDeltaPerPixel: null pointer reference");
+ }
+
+ for (mfxU8 i = 0; i < 16; i++)
+ {
+ outBlock[i] = ClipIntToChar(inBlock[i] + deltaBlock[i]);
+ }
+
+ return;
+}
+
+mfxU8 FrameProcessor::ClipIntToChar(mfxI32 x)
+{
+ if (x < 0)
+ return 0;
+ else if (x > 255)
+ return 255;
+
+ return (mfxU8)x;
+}
+
+//Perform inverse 4x4 DCT
+void FrameProcessor::Inverse4x4(mfxI32 *src, mfxU32 s_pitch, mfxI32 *dst, mfxU32 d_pitch)
+{
+ if (src == nullptr || dst == nullptr)
+ {
+ throw std::string("ERROR: Inverse4x4: null pointer reference");
+ }
+ const mfxU32 BLOCK_SIZE = 4;
+ mfxI32 tmp[16];
+ mfxI32 *pTmp = tmp, *pblock;
+ mfxI32 p0, p1, p2, p3;
+ mfxI32 t0, t1, t2, t3;
+
+ // Horizontal
+ for (mfxU32 i = 0; i < BLOCK_SIZE; i++)
+ {
+ pblock = src + i*s_pitch;
+ t0 = *(pblock++);
+ t1 = *(pblock++);
+ t2 = *(pblock++);
+ t3 = *(pblock);
+
+ p0 = t0 + t2;
+ p1 = t0 - t2;
+ p2 = (t1 >> 1) - t3;
+ p3 = t1 + (t3 >> 1);
+
+ *(pTmp++) = p0 + p3;
+ *(pTmp++) = p1 + p2;
+ *(pTmp++) = p1 - p2;
+ *(pTmp++) = p0 - p3;
+ }
+
+ // Vertical
+ for (mfxU32 i = 0; i < BLOCK_SIZE; i++)
+ {
+ pTmp = tmp + i;
+ t0 = *pTmp;
+ t1 = *(pTmp += BLOCK_SIZE);
+ t2 = *(pTmp += BLOCK_SIZE);
+ t3 = *(pTmp += BLOCK_SIZE);
+
+ p0 = t0 + t2;
+ p1 = t0 - t2;
+ p2 = (t1 >> 1) - t3;
+ p3 = t1 + (t3 >> 1);
+
+ *(dst + 0 * d_pitch + i) = p0 + p3;
+ *(dst + 1 * d_pitch + i) = p1 + p2;
+ *(dst + 2 * d_pitch + i) = p1 - p2;
+ *(dst + 3 * d_pitch + i) = p0 - p3;
+ }
+}
+
+void FrameProcessor::PutBlock4x4(mfxU32 x0, mfxU32 y0, mfxU8 block[16], mfxFrameSurface1* surf)
+{
+ if (surf == nullptr)
+ {
+ throw std::string("ERROR: PutBlock4x4: null pointer reference");
+ }
+ //put block in the current frame, x0, y0 pixel coordinates
+ for (mfxU32 y = 0; y < 4; y++)
+ {
+ for (mfxU32 x = 0; x < 4; x++)
+ {
+ *(surf->Data.Y + (y0 + y)* surf->Data.Pitch + x0 + x) = block[4 * y + x];
+ *(surf->Data.U + ((y0 + y) / 2) * (surf->Data.Pitch / 2) + (x0 + x) / 2) = CHROMA_DEFAULT;
+ *(surf->Data.V + ((y0 + y) / 2) * (surf->Data.Pitch / 2) + (x0 + x) / 2) = CHROMA_DEFAULT;
+ }
+ }
+ return;
+}
+
+
+// Trace back pixels from block BP shifted by MV coordinates on GEN frame surf_from to MOD frame surf_to
+//
+// bp - block on MOD frame
+// mv - it's shift on GEN frame
+// surf_from - GEN frame surf
+// surf_to - MOD frame surf
+
+void FrameProcessor::TraceBackAndPutBlockIntoFrame(const PUBlock & PU, FrameChangeDescriptor & descr)
+{
+ std::pair fractOffsetL0(PU.m_MV.MV[0].x & 3, PU.m_MV.MV[0].y & 3);
+ std::pair fractOffsetL1(PU.m_MV.MV[1].x & 3, PU.m_MV.MV[1].y & 3);
+
+ auto itL0 = std::next(descr.m_refDescrList0.begin(), PU.m_MV.RefIdx.RefL0);
+ auto itL1 = std::next(descr.m_refDescrList1.begin(), PU.m_MV.RefIdx.RefL1);
+
+ mfxFrameSurface1* surfDest = nullptr;
+ mfxFrameSurface1* surfL0Ref = nullptr;
+ mfxFrameSurface1* surfL1Ref = nullptr;
+
+ surfDest = descr.m_frame;
+
+ if (itL0 != descr.m_refDescrList0.end())
+ {
+ surfL0Ref = itL0->m_frame;
+ }
+ else
+ {
+ throw("ERROR: TraceBackAndPutBlockIntoFrame: L0 ref not found");
+ }
+
+ if (descr.m_frameType & MFX_FRAMETYPE_B)
+ {
+ if (itL1 != descr.m_refDescrList1.end())
+ {
+ surfL1Ref = itL1->m_frame;
+ }
+ else
+ {
+ throw("ERROR: TraceBackAndPutBlockIntoFrame: L1 ref not found");
+ }
+ }
+
+ PatchBlock outPatch(PU);
+ InterpolWorkBlock workBlockL0;
+ InterpolWorkBlock workBlockL1;
+
+ if (PU.predFlagL0 && PU.predFlagL1)
+ {
+ workBlockL0 = GetInterpolWorkBlockPreWP(PU.GetShiftedBaseBlock(L0), fractOffsetL0, surfL0Ref);
+ workBlockL1 = GetInterpolWorkBlockPreWP(PU.GetShiftedBaseBlock(L1), fractOffsetL1, surfL1Ref);
+ outPatch = ApplyDefaultWeightedPrediction(workBlockL0, workBlockL1);
+ }
+ else if (PU.predFlagL0)
+ {
+ workBlockL0 = GetInterpolWorkBlockPreWP(PU.GetShiftedBaseBlock(L0), fractOffsetL0, surfL0Ref);
+ outPatch = ApplyDefaultWeightedPrediction(workBlockL0);
+ }
+ else if (PU.predFlagL1)
+ {
+ workBlockL1 = GetInterpolWorkBlockPreWP(PU.GetShiftedBaseBlock(L1), fractOffsetL1, surfL1Ref);
+ outPatch = ApplyDefaultWeightedPrediction(workBlockL1);
+ }
+ else
+ throw("ERROR: TraceBackAndPutBlockIntoFrame: predFlagL0 and predFlagL1 are equal 0");
+
+ //Adjust outPatch coords so that they correspond to the unshifted PU
+ outPatch.m_AdrX = PU.m_AdrX;
+ outPatch.m_AdrY = PU.m_AdrY;
+
+ PutPatchIntoFrame(outPatch, *surfDest);
+
+ return;
+}
+
+
+InterpolWorkBlock FrameProcessor::GetInterpolWorkBlockPreWP(const BaseBlock & blockFrom, std::pair fractOffset, mfxFrameSurface1* surfFrom)
+{
+ if (surfFrom == nullptr)
+ {
+ throw std::string("ERROR: GetInterpolWorkBlockPreWP: null pointer reference");
+ }
+ InterpolWorkBlock workBlock(blockFrom);
+
+ //Luma
+ for (mfxU32 i = 0; i < blockFrom.m_BHeight; i++)
+ {
+ for (mfxU32 j = 0; j < blockFrom.m_BWidth; j++)
+ {
+ mfxU32 offset = i * blockFrom.m_BWidth + j;
+ workBlock.m_YArr[offset] = CalculateLumaPredictionSamplePreWP(
+ std::make_pair(blockFrom.m_AdrX + j, blockFrom.m_AdrY + i), fractOffset, surfFrom);
+ }
+ }
+
+ // Chroma(YV12 / I420 only) - TODO: enable correct interpolation for chroma
+ //NB: MFX_FOURCC_YV12 is an umbrella designation for both YV12 and I420 here, as
+ //the process of copying pixel values in memory is the same
+
+ //TODO: implement proper chroma interpolation
+ if (surfFrom->Info.FourCC == MFX_FOURCC_YV12)
+ {
+ for (mfxU32 i = 0; i < blockFrom.m_BHeight / 2; ++i)
+ {
+ for (mfxU32 j = 0; j < blockFrom.m_BWidth / 2; j++)
+ {
+ mfxU32 offsetChr = i * blockFrom.m_BWidth / 2 + j;
+ workBlock.m_UArr[offsetChr] = surfFrom->Data.U[
+ (blockFrom.m_AdrY / 2 + i) * surfFrom->Data.Pitch / 2 + blockFrom.m_AdrX / 2 + j];
+ workBlock.m_VArr[offsetChr] = surfFrom->Data.V[
+ (blockFrom.m_AdrY / 2 + i) * surfFrom->Data.Pitch / 2 + blockFrom.m_AdrX / 2 + j];
+
+ //For now, just scale uninterpolated chroma so that we can call default weighted prediction
+ //on chroma components the same way we do with luma
+ workBlock.m_UArr[offsetChr] <<= 6;
+ workBlock.m_VArr[offsetChr] <<= 6;
+ }
+ }
+ }
+
+ return workBlock;
+}
+
+PatchBlock FrameProcessor::ApplyDefaultWeightedPrediction(InterpolWorkBlock & workBlockLx)
+{
+ PatchBlock outPatch(static_cast(workBlockLx));
+
+ //Luma
+ for (mfxU32 i = 0; i < outPatch.m_BHeight * outPatch.m_BWidth; i++)
+ {
+ outPatch.m_YPlane[i] = GetDefaultWeightedPredSample(workBlockLx.m_YArr[i]);
+ }
+
+ //Chroma
+ for (mfxU32 i = 0; i < outPatch.m_BHeight / 2 * outPatch.m_BWidth / 2; i++)
+ {
+ outPatch.m_UPlane[i] = GetDefaultWeightedPredSample(workBlockLx.m_UArr[i]);
+ outPatch.m_VPlane[i] = GetDefaultWeightedPredSample(workBlockLx.m_VArr[i]);
+ }
+ return outPatch;
+}
+
+PatchBlock FrameProcessor::ApplyDefaultWeightedPrediction(InterpolWorkBlock & workBlockL0, InterpolWorkBlock & workBlockL1)
+{
+ if (workBlockL0.m_BHeight != workBlockL1.m_BHeight || workBlockL0.m_BWidth != workBlockL1.m_BWidth)
+ {
+ throw std::string("ERROR: ApplyDefaultWeightedPrediction: InterpolWorkBlocks for bi-prediction must have same size");
+ }
+ PatchBlock outPatch(static_cast(workBlockL0));
+ for (mfxU32 i = 0; i < outPatch.m_BHeight * outPatch.m_BWidth; i++)
+ {
+ outPatch.m_YPlane[i] = GetDefaultWeightedPredSample(workBlockL0.m_YArr[i], workBlockL1.m_YArr[i]);
+ }
+
+ for (mfxU32 i = 0; i < outPatch.m_BHeight / 2 * outPatch.m_BWidth / 2; i++)
+ {
+ outPatch.m_UPlane[i] = GetDefaultWeightedPredSample(workBlockL0.m_UArr[i], workBlockL1.m_UArr[i]);
+ outPatch.m_VPlane[i] = GetDefaultWeightedPredSample(workBlockL0.m_VArr[i], workBlockL1.m_VArr[i]);
+ }
+
+ return outPatch;
+}
+
+mfxU8 FrameProcessor::SetCorrectMVPBlockSize(mfxU8 mvpBlockSizeParam)
+{
+ if (!mvpBlockSizeParam)
+ {
+ switch (m_CTUStr.CTUSize)
+ {
+ case 16:
+ return 1;
+ case 32:
+ return 2;
+ case 64:
+ return 3;
+ default:
+ break;
+ }
+ }
+ return mvpBlockSizeParam;
+}
+
+// Returns predicted luma value (Y) for sample with provided location on reference frame given in quarter-pixel units
+//
+// refSamplePositionFull - (xInt,yInt) Luma location on the reference frame given in full-sample units. Assumed (x,y) has correct value.
+// refSamplePositionFract - (xFract,yFract) Luma location on the reference frame given in quarter-sample units.
+// refSurface - reference frame, containing luma samples
+// Luma interpolation process described in H265 standard (p.163 - 165)
+
+mfxI32 FrameProcessor::CalculateLumaPredictionSamplePreWP(const std::pair& refSamplePositionFull,
+ const std::pair& refSamplePositionFract, mfxFrameSurface1 * refSurface)
+{
+ mfxU32 xFull = refSamplePositionFull.first;
+ mfxU32 yFull = refSamplePositionFull.second;
+ mfxU32 xFract = refSamplePositionFract.first;
+ mfxU32 yFract = refSamplePositionFract.second;
+
+ // These shift variables used below are specified in H265 spec for 8 bit Luma depth
+ // shift1 := 0
+ // shift2 := 6
+ // shift3 := 6
+
+ // Stores output of the sub-sample filtering process
+ mfxI32 interpolatedSample = 0;
+
+ /*
+ // Integer and quarter sample positions used for interpolation
+
+ A-10 O O O | A00 a00 b00 c00 | A10 O O O A20
+ d-10 O O O | d00 e00 f00 g00 | d10 O O O d20
+ h-10 O O O | h00 i00 j00 k00 | h10 O O O h20
+ n-10 O O O | n00 p00 q00 r00 | n10 O O O n20
+ */
+
+ switch (xFract)
+ {
+ case 0:
+ switch (yFract)
+ {
+ case 0:
+ // A << shift3
+ interpolatedSample = ApplyVerticalSubSampleLumaFilter(xFull, yFull,
+ refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[0]) * 64;
+ break;
+ case 1:
+ // d00 := (-A(0,-3) + 4*A(0,-2) - 10*A(0,-1) + 58*A(0,0) + 17*A(0,1) - 5*A(0,2) + A(0,3)) >> shift1
+ interpolatedSample = ApplyVerticalSubSampleLumaFilter(xFull, yFull,
+ refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[1]);
+ break;
+ case 2:
+ // h00 := (-A(0,-3) + 4*A(0,-2) - 11*A(0,-1) + 40*A(0,0) + 40*A(0,1) - 11*A(0,2) + 4*A(0,3) - A(0,4)) >> shift1
+ interpolatedSample = ApplyVerticalSubSampleLumaFilter(xFull, yFull,
+ refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[2]);
+ break;
+ case 3:
+ // n00 := (A(0,-2) - 5*A(0,-1) + 17*A(0,0) + 58*A(0,1) - 10*A(0,2) + 4*A(0,3) - A(0,4)) >> shift1
+ interpolatedSample = ApplyVerticalSubSampleLumaFilter(xFull, yFull,
+ refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[3]);
+ break;
+ default:
+ break;
+ }
+ break;
+ case 1:
+ {
+ // a0i, where i = -3..4
+ // a0i = [a(0,-3) a(0,-2) a(0,-1) a(0,0) a(0,1) a(0,2) a(0,3) a(0,4)]
+ std::vector fractUtilSamples;
+ fractUtilSamples.reserve(LUMA_TAPS_NUMBER);
+
+ for (mfxI32 i = 0; i < LUMA_TAPS_NUMBER; i++)
+ {
+ // a0i := (-A(-3,i) + 4*A(-2,i) - 10*A(-1,i) + 58*A(0,i) + 17*A(1,i) - 5*A(2,i) + A(3,i) >> shift1)
+ fractUtilSamples.push_back(ApplyHorizontalSubSampleLumaFilter(xFull,
+ yFull + (i - 3), refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[1]));
+ }
+
+ switch (yFract)
+ {
+ case 0:
+ // a00 := a(0,0)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[0], 0);
+ break;
+ case 1:
+ // e00 := (-a(0,-3) + 4*a(0,-2) - 10*a(0,-1) + 58*a(0,0) + 17*a(0,1) - 5*a(0,2) + a(0,3) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(),
+ fractUtilSamples.end(), LUMA_SUBSAMPLE_FILTER_COEFF[1], 0) / 64;
+ break;
+ case 2:
+ // i00 := (-a(0,-3) + 4*a(0,-2) - 11*a(0,-1) + 40*a(0,0) + 40*a(0,1) - 11*a(0,2) + 4*a(0,3) - a(0,4) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(),
+ fractUtilSamples.end(), LUMA_SUBSAMPLE_FILTER_COEFF[2], 0) / 64;
+ break;
+ case 3:
+ // p00 := (a(0,-2) - 5*a(0,-1) + 17*a(0,0) + 58*a(0,1) - 10*a(0,2) + 4*a(0,3) - a(0,4) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[3], 0) / 64;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 2:
+ {
+ // b0i, where i = -3..4
+ // b0i = [b(0,-3) b(0,-2) b(0,-1) b(0,0) b(0,1) b(0,2) b(0,3) b(0,4)]
+ std::vector fractUtilSamples;
+ fractUtilSamples.reserve(LUMA_TAPS_NUMBER);
+
+ for (mfxI32 i = 0; i < LUMA_TAPS_NUMBER; i++)
+ {
+ // b0i := (-A(-3,i) + 4*A(-2,i) - 11*A(-1,i) + 40*A(0,i) + 40*A(1,i) - 11*A(2,i) + 4*A(3,i) - A(4,i) >> shift1)
+ fractUtilSamples.push_back(ApplyHorizontalSubSampleLumaFilter(xFull, yFull + (i - 3),
+ refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[2]));
+ }
+
+ switch (yFract)
+ {
+ case 0:
+ // b00 := (-A(-3,0) + 4*A(-2,0) - 11*A(-1,0) + 40*A(0,0) + 40*A(1,0) - 11*A(2,0) + 4*A(3,0) - A(4,0) >> shift1)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[0], 0);
+ break;
+ case 1:
+ // f00 := (-b(0,-3) + 4*b(0,-2) - 10*b(0,-1) + 58*b(0,0) + 17*b(0,1) - 5*b(0,2) + b(0,3) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[1], 0) / 64;
+ break;
+ case 2:
+ // j00 := (-b(0,-3) + 4*b(0,-2) - 11*b(0,-1) + 40*b(0,0) + 40*b(0,1) - 11*b(0,2) + 4*b(0,3) - b(0,4) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[2], 0) / 64;
+ break;
+ case 3:
+ // q00 := (b(0,-2) - 5*b(0,-1) + 17*b(0,0) + 58*b(0,1) - 10*b(0,2) + 4*b(0,3) - b(0,4) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[3], 0) / 64;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case 3:
+ {
+ // c0i, where i = -3..4
+ // c0i = [c(0,-3) c(0,-2) c(0,-1) c(0,0) c(0,1) c(0,2) c(0,3) c(0,4)]
+ std::vector fractUtilSamples;
+ fractUtilSamples.reserve(LUMA_TAPS_NUMBER);
+
+ for (mfxI32 i = 0; i < LUMA_TAPS_NUMBER; i++)
+ {
+ // c0i := (A(-2,i) - 5*A(-1,i) + 17*A(0,i) + 58*A(1,i) - 10*A(2,i) + 4*A(3,i) - A(4,i) >> shift1)
+ fractUtilSamples.push_back(ApplyHorizontalSubSampleLumaFilter(xFull, yFull + (i - 3),
+ refSurface, LUMA_SUBSAMPLE_FILTER_COEFF[3]));
+ }
+
+ switch (yFract)
+ {
+ case 0:
+ // c00 := c(0,0)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[0], 0);
+ break;
+ case 1:
+ // g00 := (-c(0,-3) + 4*c(0,-2) - 10*c(0,-1) + 58*c(0,0) + 17*c(0,1) - 5*c(0,2) + c(0,3) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[1], 0) / 64;
+ break;
+ case 2:
+ // k00 := (-c(0,-3) + 4*c(0,-2) - 11*c(0,-1) + 40*c(0,0) + 40*c(0,1) - 11*c(0,2) + 4*c(0,3) - c(0,4) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[2], 0) / 64;
+ break;
+ case 3:
+ // r00 := (c(0,-2) - 5*c(0,-1) + 17*c(0,0) + 58*c(0,1) - 10*c(0,2) + 4*c(0,3) - c(0,4) >> shift2)
+ interpolatedSample = std::inner_product(fractUtilSamples.begin(), fractUtilSamples.end(),
+ LUMA_SUBSAMPLE_FILTER_COEFF[3], 0) / 64;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ return interpolatedSample;
+}
+
+mfxI32 FrameProcessor::ApplyVerticalSubSampleLumaFilter(mfxU32 x, mfxU32 y, mfxFrameSurface1 * refSurface, const mfxI32 * coeff)
+{
+ mfxI32 sum = 0;
+
+ for (mfxI32 i = -3; i <= 4; i++)
+ {
+ sum += coeff[i + 3] * GetClippedSample(COLOR_COMPONENT::LUMA_Y, (mfxI32)x, (mfxI32)y + i, refSurface);
+ }
+
+ return sum;
+}
+
+mfxI32 FrameProcessor::ApplyHorizontalSubSampleLumaFilter(mfxU32 x, mfxU32 y, mfxFrameSurface1 * refSurface, const mfxI32 * coeff)
+{
+ mfxI32 sum = 0;
+
+ for (mfxI32 i = -3; i <= 4; i++)
+ {
+ sum += coeff[i + 3] * GetClippedSample(COLOR_COMPONENT::LUMA_Y, (mfxI32)x + i, (mfxI32)y, refSurface);
+ }
+
+ return sum;
+}
+
+// Release processed surfaces
+
+void FrameProcessor::UnlockSurfaces(FrameChangeDescriptor & frame_descr)
+{
+ frame_descr.m_frame->Data.Locked = 0;
+
+ // Unlock all reference GEN frames recursively
+ if (frame_descr.m_refDescrList0.empty() && frame_descr.m_refDescrList1.empty()) return;
+ else
+ {
+ for (auto & ref_descr : frame_descr.m_refDescrList0)
+ {
+ UnlockSurfaces(ref_descr);
+ }
+ for (auto & ref_descr : frame_descr.m_refDescrList1)
+ {
+ UnlockSurfaces(ref_descr);
+ }
+ }
+
+ return;
+}
+
+//this function has the same behavior for any color component
+//it is more convenient to have input in the coordinates of colorComp component space
+void FrameProcessor::FillIntraRefSamples(mfxU32 cSize, mfxU32 cAdrX, mfxU32 cAdrY, const PatchBlock& frame, COLOR_COMPONENT colorComp, std::vector& refSamples)
+{
+ refSamples.clear();
+ const mfxU32 NO_SAMPLES_AVAILABLE = 0xffffffff;
+ mfxU8 prevSampleAvail = 128; //default ref sample value is 128 if no real ref samples are available
+ mfxU32 firstSampleAvailPos = NO_SAMPLES_AVAILABLE; //position of the first available ref sample in refSamples
+
+ //fill vertical part
+ mfxU32 currCAdrX = cAdrX - 1;
+ mfxU32 currCAdrY = cAdrY + 2 * cSize - 1;
+
+ for (mfxU32 i = 0; i < 2 * cSize + 1; i++, currCAdrY--)
+ {
+ if (IsSampleAvailable(currCAdrX, currCAdrY))
+ {
+ prevSampleAvail = frame.GetSampleI420(colorComp, currCAdrX, currCAdrY);
+ refSamples.push_back(prevSampleAvail);
+ if (firstSampleAvailPos == NO_SAMPLES_AVAILABLE)
+ {
+ firstSampleAvailPos = i;
+ }
+ }
+ else
+ {
+ refSamples.push_back(prevSampleAvail);
+ }
+ }
+ currCAdrX = cAdrX;
+ currCAdrY = cAdrY - 1;
+
+ //fill horizontal part
+ for (mfxU32 i = 2 * cSize + 1; i < 4 * cSize + 1; i++, currCAdrX++)
+ {
+ if (IsSampleAvailable(currCAdrX, currCAdrY))
+ {
+ prevSampleAvail = frame.GetSampleI420(colorComp, currCAdrX, currCAdrY);
+ refSamples.push_back(prevSampleAvail);
+ if (firstSampleAvailPos == NO_SAMPLES_AVAILABLE)
+ {
+ firstSampleAvailPos = i;
+ }
+ }
+ else
+ {
+ refSamples.push_back(prevSampleAvail);
+ }
+ }
+ //fill initial part with with first available ref sample value
+ if (firstSampleAvailPos != NO_SAMPLES_AVAILABLE)
+ {
+ std::fill(refSamples.begin(), refSamples.begin() + firstSampleAvailPos, refSamples[firstSampleAvailPos]);
+ }
+}
+
+FILTER_TYPE FrameProcessor::ChooseFilter(std::vector& RefSamples, mfxU8 size, INTRA_MODE mode) {
+ FILTER_TYPE filter = NO_FILTER;
+ if (mode == DC || size == 4)
+ return filter;
+ switch (size) {
+ case 8:
+ if (mode == 2 || mode == 18 || mode == 34)
+ filter = THREE_TAP_FILTER;
+ break;
+ case 16:
+ filter = THREE_TAP_FILTER;
+ if ((mode > 8 && mode < 12) || (mode > 24 && mode < 28))
+ filter = NO_FILTER;
+ break;
+ case 32:
+ filter = THREE_TAP_FILTER;
+ if (mode == ANG10_HOR || mode == ANG26_VER)
+ filter = NO_FILTER;
+ else if (std::abs(RefSamples[0] + RefSamples[2 * size] - 2 * RefSamples[size]) < 8 &&
+ std::abs(RefSamples[2 * size] + RefSamples[4 * size] - 2 * RefSamples[3 * size]) < 8)
+ filter = STRONG_INTRA_SMOOTHING_FILTER;
+ break;
+ default:
+ break;
+ }
+ return filter;
+}
+
+void FrameProcessor::ThreeTapFilter(std::vector& RefSamples, mfxU8 size) {
+ for (mfxU8 i = 1; i < (size << 2); i++)
+ RefSamples[i] = (RefSamples[i - 1] + 2 * RefSamples[i] + RefSamples[i + 1] + 2) >> 2;
+}
+
+void FrameProcessor::StrongFilter(std::vector& RefSamples, mfxU8 size) {
+ for (mfxU8 i = 1; i < 2 * size; i++)
+ RefSamples[i] = (i * RefSamples[2 * size] + (2 * size - i) * RefSamples[0] + 32) >> 6;
+ for (mfxU8 i = 1; i < 2 * size; i++)
+ RefSamples[2 * size + i] = ((2 * size - i) * RefSamples[2 * size] + i * RefSamples[4 * size] + 32) >> 6;
+}
+
+FILTER_TYPE FrameProcessor::MakeFilter(std::vector& RefSamples, mfxU8 size, INTRA_MODE mode) {
+ FILTER_TYPE filter = ChooseFilter(RefSamples, size, mode);
+ switch (filter) {
+ case NO_FILTER:
+ break;
+ case THREE_TAP_FILTER:
+ ThreeTapFilter(RefSamples, size);
+ break;
+ case STRONG_INTRA_SMOOTHING_FILTER:
+ StrongFilter(RefSamples, size);
+ break;
+ default:
+ break;
+ }
+ return filter;
+}
+
+mfxU8 FrameProcessor::MakeProjRefArray(const std::vector& RefSamples, mfxU8 size, const IntraParams& IntraMode, std::vector& ProjRefSamples)
+{
+ mfxU8 NumProj = 0;
+
+ if (IntraMode.direction == HORIZONTAL)
+ {
+ ProjRefSamples.insert(ProjRefSamples.end(), RefSamples.begin(), RefSamples.begin() + 2 * size + 1);
+ if (IntraMode.intraPredAngle < 0)
+ {
+ if (IntraMode.invAngle == 0)
+ {
+ throw std::string("ERROR: MakeProjRefArray: invAngle == 0 for angular mode with intraPredAngle < 0");
+ }
+ mfxI8 y = -1;
+ mfxI32 sampleForProjectionPos = 2 * size + ((y * IntraMode.invAngle + 128) >> 8);
+ while (sampleForProjectionPos < 4 * size + 1)
+ {
+ ProjRefSamples.push_back(RefSamples[sampleForProjectionPos]);
+ sampleForProjectionPos = 2 * size + ((--y * IntraMode.invAngle + 128) >> 8);
+ }
+ }
+ std::reverse(ProjRefSamples.begin(), ProjRefSamples.end());
+ NumProj = (mfxU8)(ProjRefSamples.size() - 2 * size - 1);
+ }
+ else if (IntraMode.direction == VERTICAL)
+ {
+ if (IntraMode.intraPredAngle < 0)
+ {
+ if (IntraMode.invAngle == 0)
+ {
+ throw std::string("ERROR: MakeProjRefArray: invAngle == 0 for angular mode with intraPredAngle < 0");
+ }
+ mfxI8 x = -1;
+ mfxI32 sampleForProjectionPos = 2 * size - ((x * IntraMode.invAngle + 128) >> 8);
+
+ while (sampleForProjectionPos > -1)
+ {
+ ProjRefSamples.push_back(RefSamples[sampleForProjectionPos]);
+ sampleForProjectionPos = 2 * size - ((--x * IntraMode.invAngle + 128) >> 8);
+ }
+
+ std::reverse(ProjRefSamples.begin(), ProjRefSamples.end());
+ }
+
+ NumProj = (mfxU8)ProjRefSamples.size();
+ ProjRefSamples.insert(ProjRefSamples.end(), RefSamples.begin() + 2 * size, RefSamples.end());
+ }
+ return NumProj;
+}
+
+void FrameProcessor::PlanarPrediction(const std::vector& RefSamples, mfxU8 size, mfxU8 * patch)
+{
+ if (patch == nullptr)
+ {
+ throw std::string("ERROR: PlanarPrediction: pointer to buffer is null\n");
+ }
+
+ for (mfxI32 y = 0; y < size; y++)
+ {
+ for (mfxI32 x = 0; x < size; x++)
+ {
+ patch[y * size + x] = (
+ (size - 1 - x) * RefSamples[2 * size - 1 - y]
+ + (x + 1) * RefSamples[3 * size + 1]
+ + (size - 1 - y) * RefSamples[2 * size + 1 + x]
+ + (y + 1) * RefSamples[size - 1]
+ + size) / (size * 2);
+ }
+ }
+
+}
+
+void FrameProcessor::DCPrediction(const std::vector& RefSamples, mfxU8 size, mfxU8 * patch)
+{
+ if (patch == nullptr)
+ {
+ throw std::string("ERROR: DCPrediction: pointer to buffer is null\n");
+ }
+
+ mfxU32 DCValue = size;
+ for (mfxI32 i = 0; i < size; i++)
+ {
+ DCValue += RefSamples[2 * size - 1 - i] + RefSamples[i + 2 * size + 1];
+ }
+ DCValue /= 2 * size;
+ memset(patch, DCValue, size*size);
+}
+
+void FrameProcessor::AngularPrediction(const std::vector& RefSamples, mfxU8 size, IntraParams& params, mfxU8 * patch) {
+ if (patch == nullptr)
+ {
+ throw std::string("ERROR: AngularPrediction: pointer to buffer is null\n");
+ }
+
+ std::vector ProjRefSamples;
+ mfxU8 NumProj = MakeProjRefArray(RefSamples, size, params, ProjRefSamples);
+ if (params.direction == HORIZONTAL)
+ for (mfxI32 y = 0; y < size; y++)
+ for (mfxI32 x = 0; x < size; x++) {
+ mfxI32 f = ((x + 1) * params.intraPredAngle) & 31;
+ mfxI32 i = ((x + 1) * params.intraPredAngle) >> 5;
+ if (f != 0)
+ patch[y * size + x] = ((32 - f) * ProjRefSamples[y + i + 1 + NumProj] + f * ProjRefSamples[y + i + 2 + NumProj] + 16) >> 5;
+ else
+ patch[y * size + x] = ProjRefSamples[y + i + 1 + NumProj];
+ }
+ else
+ for (mfxI32 y = 0; y < size; y++)
+ for (mfxI32 x = 0; x < size; x++) {
+ mfxI32 f = ((y + 1) * params.intraPredAngle) & 31;
+ mfxI32 i = ((y + 1) * params.intraPredAngle) >> 5;
+ if (f != 0)
+ patch[y * size + x] = ((32 - f) * ProjRefSamples[x + i + 1 + NumProj] + f * ProjRefSamples[x + i + 2 + NumProj] + 16) >> 5;
+ else
+ patch[y * size + x] = ProjRefSamples[x + i + 1 + NumProj];
+ }
+
+ return;
+}
+
+void FrameProcessor::GenerateIntraPrediction(const std::vector& RefSamples, mfxU8 blockSize, INTRA_MODE currMode, mfxU8* currPlane)
+{
+ if (currPlane == nullptr)
+ {
+ throw std::string("ERROR: GenerateIntraPrediction: pointer to buffer is null\n");
+ }
+
+ IntraParams params(currMode);
+
+ switch (params.intraMode)
+ {
+ case PLANAR:
+ PlanarPrediction(RefSamples, blockSize, currPlane);
+ break;
+ case DC:
+ DCPrediction(RefSamples, blockSize, currPlane);
+ break;
+ default:
+ AngularPrediction(RefSamples, blockSize, params, currPlane);
+ break;
+ }
+ return;
+}
+
+void FrameProcessor::MakePostFilter(const std::vector& RefSamples, mfxU8 size, INTRA_MODE currMode, mfxU8* lumaPlane)
+{
+ mfxU32 DCValue = lumaPlane[0];
+
+ switch (currMode)
+ {
+ case DC:
+ lumaPlane[0] = (RefSamples[2 * size - 1] + 2 * DCValue + RefSamples[2 * size + 1] + 2) >> 2;
+ for (mfxI32 x = 1; x < size; x++)
+ {
+ lumaPlane[x] = (RefSamples[2 * size + 1 + x] + 3 * DCValue + 2) >> 2;
+ }
+ for (mfxI32 y = 1; y < size; y++)
+ {
+ lumaPlane[y * size] = (RefSamples[2 * size - 1 - y] + 3 * DCValue + 2) >> 2;
+ }
+ break;
+ case ANG10_HOR:
+ for (mfxI32 x = 0; x < size; x++)
+ {
+ lumaPlane[x] = ClipIntToChar(lumaPlane[x] + ((RefSamples[2 * size + 1 + x] - RefSamples[2 * size]) >> 1));
+ }
+ break;
+ case ANG26_VER:
+ for (mfxI32 y = 0; y < size; y++)
+ {
+ lumaPlane[y * size] = ClipIntToChar(lumaPlane[y * size] + ((RefSamples[2 * size - 1 - y] - RefSamples[2 * size]) >> 1));
+ }
+ break;
+ default:
+ return;
+ }
+}
+
+void FrameProcessor::PutPatchIntoFrame(const PatchBlock & Patch, mfxFrameSurface1& surf) {
+ //luma
+ for (mfxU32 i = 0; i < Patch.m_BHeight; i++)
+ memcpy(surf.Data.Y + (Patch.m_AdrY + i) * surf.Data.Pitch + Patch.m_AdrX, Patch.m_YPlane + i * Patch.m_BWidth, Patch.m_BWidth);
+ //chroma U
+ for (mfxU32 i = 0; i < Patch.m_BHeight / 2; ++i)
+ memcpy(surf.Data.U + (Patch.m_AdrY / 2 + i) * surf.Data.Pitch / 2 + Patch.m_AdrX / 2, Patch.m_UPlane + i * (Patch.m_BWidth / 2), Patch.m_BWidth / 2);
+ //chroma V
+ for (mfxU32 i = 0; i < Patch.m_BHeight / 2; ++i)
+ memcpy(surf.Data.V + (Patch.m_AdrY / 2 + i) * surf.Data.Pitch / 2 + Patch.m_AdrX / 2, Patch.m_VPlane + i * (Patch.m_BWidth / 2), Patch.m_BWidth / 2);
+}
+
+void FrameProcessor::GetIntraPredPlane(const BaseBlock& refBlock, INTRA_MODE currMode, const PatchBlock& frame, COLOR_COMPONENT colorComp, mfxU8* currPlane)
+{
+ if (currPlane == nullptr)
+ {
+ throw std::string("ERROR: GetIntraPredPlane: pointer to buffer is null\n");
+ }
+ //here refBlock parameters are measured in samples of corresponding colorComp
+ //get reference samples for current TU
+ std::vector RefSamples;
+ //size and coords of block in current color component
+ mfxU32 cSize = (colorComp == LUMA_Y) ? refBlock.m_BHeight : (refBlock.m_BHeight / 2);
+ mfxU32 cAdrX = (colorComp == LUMA_Y) ? refBlock.m_AdrX : (refBlock.m_AdrX / 2);
+ mfxU32 cAdrY = (colorComp == LUMA_Y) ? refBlock.m_AdrY : (refBlock.m_AdrY / 2);
+
+ FillIntraRefSamples(cSize, cAdrX, cAdrY, frame, colorComp, RefSamples);
+
+ // get filter, write it into buffer and make it
+ MakeFilter(RefSamples, cSize, currMode);
+
+ //generate Prediction and return the output patch
+ GenerateIntraPrediction(RefSamples, cSize, currMode, currPlane);
+
+ if (colorComp == LUMA_Y && cSize < 32)
+ {
+ MakePostFilter(RefSamples, cSize, currMode, currPlane);
+ }
+}
+
+
+PatchBlock FrameProcessor::GetIntraPatchBlock(const TUBlock& refBlock, const PatchBlock& frame)
+{
+ PatchBlock patch(refBlock);
+ //get intra prediction for Luma plane
+ GetIntraPredPlane(refBlock, refBlock.m_IntraModeLuma, frame, LUMA_Y, patch.m_YPlane);
+ //if luma TB size > 4, fill chroma TBs of size / 2
+ if (refBlock.m_BHeight != 4)
+ {
+ GetIntraPredPlane(refBlock, refBlock.m_IntraModeChroma, frame, CHROMA_U, patch.m_UPlane);
+ GetIntraPredPlane(refBlock, refBlock.m_IntraModeChroma, frame, CHROMA_V, patch.m_VPlane);
+ return patch;
+ }
+
+ // else luma TB has size = 4, we have one chroma TB corresponding to four 4x4 luma TBs
+ //if refBlock is the lower-right block among four brothers in the RQT,
+ //fill extendedPatch of size 8x8 in luma samples with:
+ //see last paragraph before new chapter, p. 65(76) in HEVC Algorithms and Architectures
+ if (refBlock.m_AdrX % 8 == 4 && refBlock.m_AdrY % 8 == 4)
+ {
+ //three luma blocks 4x4 already put into targetBlock
+ PatchBlock extendedPatch = PatchBlock(BaseBlock(refBlock.m_AdrX - 4, refBlock.m_AdrY - 4, 8, 8), frame);
+ //luma component of size 4x4 taken from patch
+ extendedPatch.InsertAnotherPatch(patch);
+ //chroma components of size 4x4 corresponding to the union of four luma blocks mentioned above
+ GetIntraPredPlane(extendedPatch, refBlock.m_IntraModeChroma, frame, CHROMA_U, extendedPatch.m_UPlane);
+ GetIntraPredPlane(extendedPatch, refBlock.m_IntraModeChroma, frame, CHROMA_V, extendedPatch.m_VPlane);
+ return extendedPatch;
+ }
+
+ //else return only luma prediction
+ return patch;
+}
+
+void FrameProcessor::MakeTUIntraPrediction(const TUBlock& refBlock, PatchBlock& targetPatch)
+{
+ PatchBlock patch(refBlock);
+ //now the most contrast mode is determined only for luma component, chroma mode is set equal to luma mode
+ GetIntraPredPlane(refBlock, refBlock.m_IntraModeLuma, targetPatch, LUMA_Y, patch.m_YPlane);
+ //write Patch into targetPatch
+ targetPatch.InsertAnotherPatch(patch);
+}
+
+void FrameProcessor::ApplyTUIntraPrediction(const TUBlock & block, ExtendedSurface& surf)
+{
+ PatchBlock framePatchBlock(BaseBlock(0, 0, surf.Info.CropW, surf.Info.CropH), surf);
+ PatchBlock patch = GetIntraPatchBlock(block, framePatchBlock);
+ //write Patch into frame
+ PutPatchIntoFrame(patch, surf);
+}
+
+//Iterates over CUs in CTU and applies intra prediction for intra CUs inside it
+void FrameProcessor::ApplyIntraPredInCTU(const CTUDescriptor & CTU, FrameChangeDescriptor & frame_descr)
+{
+ for (auto& CU : CTU.m_CUVec)
+ {
+ if (CU.m_PredType == INTRA_PRED)
+ {
+ for (auto& TU : CU.m_TUVec)
+ {
+ ApplyTUIntraPrediction(TU, *frame_descr.m_frame);
+ }
+ }
+ }
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_reorder.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_reorder.cpp
new file mode 100644
index 0000000..e1ea32d
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/frame_reorder.cpp
@@ -0,0 +1,465 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "frame_reorder.h"
+
+mfxI32 GetFrameNum(bool bField, mfxI32 Poc, bool bSecondField)
+{
+ return bField ? (Poc + (!bSecondField)) / 2 : Poc;
+}
+
+mfxU8 GetFrameType(
+ mfxVideoParam const & video,
+ mfxU32 pictureOrder, // Picture order after last IDR
+ bool isPictureOfLastFrame)
+{
+ mfxU32 gopOptFlag = video.mfx.GopOptFlag;
+ mfxU32 gopPicSize = video.mfx.GopPicSize;
+ mfxU32 gopRefDist = video.mfx.GopRefDist;
+ mfxU32 idrPicDist = gopPicSize * (video.mfx.IdrInterval);
+
+ if (gopPicSize == 0xffff)
+ idrPicDist = gopPicSize = 0xffffffff;
+
+ bool bFields = !!(video.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_SINGLE);
+
+ mfxU32 frameOrder = bFields ? pictureOrder / 2 : pictureOrder;
+
+ bool bSecondField = bFields && (pictureOrder & 1);
+ bool bIdr = (idrPicDist ? frameOrder % idrPicDist : frameOrder) == 0;
+
+ if (bIdr)
+ return bSecondField ? (MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF) : (MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR);
+
+ if (frameOrder % gopPicSize == 0)
+ return (mfxU8)(bSecondField ? MFX_FRAMETYPE_P : MFX_FRAMETYPE_I) | MFX_FRAMETYPE_REF;
+
+ if (frameOrder % gopPicSize % gopRefDist == 0)
+ return (MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF);
+
+ if ((gopOptFlag & MFX_GOP_STRICT) == 0)
+ {
+ if (((frameOrder + 1) % gopPicSize == 0 && (gopOptFlag & MFX_GOP_CLOSED)) ||
+ (idrPicDist && (frameOrder + 1) % idrPicDist == 0) ||
+ isPictureOfLastFrame)
+ {
+ return (MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF);
+ }
+ }
+
+ return MFX_FRAMETYPE_B;
+}
+
+ExternalFrame FrameReorder::CreateExternalFrame(mfxI32 order, const mfxVideoParam& param)
+{
+ mfxI32 poc = -1;
+ ExternalFrame out = { 0xffffffff, 0, 0, poc, false, false };
+ FrameIterator itOut = m_queue.end();
+
+ bool bIsFieldCoding = !!(param.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_SINGLE);
+
+ //=================1. Get type, poc, put frame in the queue=====================
+
+ if (order >= 0)
+ {
+
+ bool isPictureOfLastFrameInGOP = ((mfxU32)order >> (mfxU32)bIsFieldCoding) == ((m_nMaxFrames - 1) >> (mfxU32)bIsFieldCoding); // EOS
+
+ Frame frame;
+
+ frame.DisplayOrder = (mfxU32)order;
+
+ frame.Type = GetFrameType(param, order - m_lastIdr, isPictureOfLastFrameInGOP); // If we will use IDR not only for first field
+ // We need to change this logic
+
+ if(frame.Type & MFX_FRAMETYPE_IDR && (order & 1))
+ throw std::string("ERROR: FrameReorder::CreateExternalFrame: Idr isn't first field");
+
+ if (frame.Type & MFX_FRAMETYPE_IDR)
+ m_lastIdr = order;
+
+ frame.Poc = order - m_lastIdr;
+ frame.bSecondField = bIsFieldCoding && (order & 1);
+ frame.bBottomField = false;
+ if (bIsFieldCoding)
+ {
+ frame.bBottomField = isBFF(param) != frame.bSecondField;
+ }
+
+ if (frame.Type & MFX_FRAMETYPE_I)
+ {
+ m_anchorPOC = frame.Poc;
+ }
+
+ m_queue.emplace_back(frame);
+ }
+
+ //=================2. Reorder frames, fill output frame poc, type, etc=====================
+ itOut = Reorder(order < 0, bIsFieldCoding);
+ if (itOut == m_queue.end())
+ return out;
+
+ out.DisplayOrder = itOut->DisplayOrder;
+
+ bool isIdr = !!(itOut->Type & MFX_FRAMETYPE_IDR);
+ bool isRef = !!(itOut->Type & MFX_FRAMETYPE_REF);
+ bool isI = !!(itOut->Type & MFX_FRAMETYPE_I);
+ bool isB = !!(itOut->Type & MFX_FRAMETYPE_B);
+
+ itOut->LastRAP = m_lastFrame.LastRAP;
+
+ if (isI)
+ {
+ itOut->IPoc = itOut->Poc;
+ itOut->PrevIPoc = m_lastFrame.IPoc;
+ itOut->NextIPoc = -1;
+ }
+ else
+ {
+ if (itOut->Poc >= m_lastFrame.IPoc)
+ {
+ itOut->IPoc = m_lastFrame.IPoc;
+ itOut->PrevIPoc = m_lastFrame.PrevIPoc;
+ itOut->NextIPoc = m_lastFrame.NextIPoc;
+ }
+ else
+ {
+ itOut->IPoc = m_lastFrame.PrevIPoc;
+ itOut->PrevIPoc = -1;
+ itOut->NextIPoc = m_lastFrame.IPoc;
+ }
+ }
+
+ out.Poc = itOut->Poc;
+ out.Type = itOut->Type;
+ out.bSecondField = itOut->bSecondField;
+ out.bBottomField = itOut->bBottomField;
+
+ //=================3. Update DPB=====================
+ if (isIdr)
+ m_dpb.clear();
+
+ if (itOut->Poc > itOut->LastRAP &&
+ m_lastFrame.Poc <= m_lastFrame.LastRAP)
+ {
+ const mfxI32 & lastRAP = itOut->LastRAP;
+ // On the 1st TRAIL remove all except IRAP
+ m_dpb.erase(std::remove_if(m_dpb.begin(), m_dpb.end(),
+ [&lastRAP](Frame const & entry) { return entry.Poc != lastRAP; }),
+ m_dpb.end());
+ }
+
+ //=================4. Construct RPL=====================
+ std::sort(m_dpb.begin(), m_dpb.end(), [](const Frame & lhs_frame, const Frame & rhs_frame)
+ {
+ return lhs_frame.Poc < rhs_frame.Poc;
+ });
+
+ std::vector & L0 = out.ListX[0];
+ std::vector & L1 = out.ListX[1];
+
+ L0.clear();
+ L1.clear();
+
+ if (!isI)
+ {
+ // Fill L0/L1
+ for (auto it = m_dpb.begin(); it != m_dpb.end(); it++)
+ {
+ bool list = it->Poc > out.Poc;
+ out.ListX[list].push_back(*it);
+ }
+
+ auto preferSamePolarity = [&out](const Frame & lhs_frame, const Frame & rhs_frame)
+ {
+ mfxI32 currFrameNum = GetFrameNum(true, out.Poc, out.bSecondField);
+
+ mfxU32 lhs_distance = std::abs(GetFrameNum(true, lhs_frame.Poc, lhs_frame.bSecondField) - currFrameNum) * 2 + ((lhs_frame.bBottomField == out.bBottomField) ? 0 : 1);
+
+ mfxU32 rhs_distance = std::abs(GetFrameNum(true, rhs_frame.Poc, rhs_frame.bSecondField) - currFrameNum) * 2 + ((rhs_frame.bBottomField == out.bBottomField) ? 0 : 1);
+
+ return lhs_distance <= rhs_distance;
+ };
+
+ auto distance = [&out](const Frame & lhs_frame, const Frame & rhs_frame)
+ {
+ mfxU32 lhs_distance = std::abs(lhs_frame.Poc - out.Poc);
+ mfxU32 rhs_distance = std::abs(rhs_frame.Poc - out.Poc);
+
+ return lhs_distance < rhs_distance;
+ };
+
+ if (bIsFieldCoding)
+ {
+ std::sort(L0.begin(), L0.end(), preferSamePolarity);
+ std::sort(L1.begin(), L1.end(), preferSamePolarity);
+ }
+ else
+ {
+ std::sort(L0.begin(), L0.end(), distance);
+ std::sort(L1.begin(), L1.end(), distance);
+ }
+
+ if ((param.mfx.GopOptFlag & MFX_GOP_CLOSED))
+ {
+ const mfxI32 & IPoc = itOut->IPoc;
+ {
+ // Remove L0 refs beyond GOP
+ L0.erase(std::remove_if(L0.begin(), L0.end(),
+ [&IPoc](const Frame & frame) { return frame.Poc < IPoc; }),
+ L0.end());
+ }
+
+ const mfxI32 & nextIPoc = itOut->NextIPoc;
+ if (nextIPoc != -1)
+ {
+ // Remove L1 refs beyond GOP
+ L1.erase(std::remove_if(L1.begin(), L1.end(),
+ [&nextIPoc](const Frame & frame) { return frame.Poc >= nextIPoc; }),
+ L1.end());
+ }
+ }
+
+ // if B's L1 is zero (e.g. in case of closed gop)
+ if (isB && !L1.size() && L0.size())
+ L1.push_back(L0[0]);
+
+ if (!isB && m_UseGPB)
+ {
+ L1 = L0;
+ std::sort(L1.begin(), L1.end(), distance);
+ }
+
+ // Remove extra entries
+ if (L0.size() > (isB ? m_NumRefActiveBL0 : m_NumRefActiveP))
+ L0.resize(isB ? m_NumRefActiveBL0 : m_NumRefActiveP);
+
+ if (L1.size() > m_NumRefActiveBL1)
+ L1.resize(m_NumRefActiveBL1);
+
+ std::sort(L0.begin(), L0.end(), distance);
+ std::sort(L1.begin(), L1.end(), distance);
+ }
+
+ //=================5. Save current frame in DPB=====================
+ if (isRef)
+ {
+ if (m_dpb.size() == m_NumRef)
+ {
+ auto toRemove = m_dpb.begin();
+
+ m_dpb.erase(toRemove);
+ }
+ m_dpb.push_back(*itOut);
+ }
+
+ itOut->NalType = GetNALUType(*itOut, !bIsFieldCoding);
+
+ if (itOut->NalType == CRA_NUT || itOut->NalType == IDR_W_RADL)
+ itOut->LastRAP = itOut->Poc;
+
+ m_lastFrame = *itOut;
+
+ m_queue.erase(itOut);
+
+ return out;
+}
+
+mfxU8 FrameReorder::GetNALUType(Frame const & frame, bool isRAPIntra)
+{
+ const bool isI = !!(frame.Type & MFX_FRAMETYPE_I);
+ const bool isRef = !!(frame.Type & MFX_FRAMETYPE_REF);
+ const bool isIDR = !!(frame.Type & MFX_FRAMETYPE_IDR);
+
+ if (isIDR)
+ return IDR_W_RADL;
+
+ if (isI && isRAPIntra)
+ {
+ return CRA_NUT;
+ }
+
+ if (frame.Poc > frame.LastRAP)
+ {
+ return isRef ? TRAIL_R : TRAIL_N;
+ }
+
+ if (isRef)
+ return RASL_R;
+ return RASL_N;
+}
+
+bool FrameReorder::HasL1(mfxI32 poc)
+{
+ for (auto it = m_dpb.begin(); it < m_dpb.end(); it++)
+ if (it->Poc > poc)
+ return true;
+ return false;
+}
+
+mfxU32 FrameReorder::BRefOrder(mfxU32 displayOrder, mfxU32 begin, mfxU32 end, mfxU32 counter, bool & ref)
+{
+ ref = (end - begin > 1);
+
+ mfxU32 pivot = (begin + end) / 2;
+ if (displayOrder == pivot)
+ return counter;
+ else if (displayOrder < pivot)
+ return BRefOrder(displayOrder, begin, pivot, counter + 1, ref);
+ else
+ return BRefOrder(displayOrder, pivot + 1, end, counter + 1 + pivot - begin, ref);
+}
+
+mfxU32 FrameReorder::GetBiFrameLocation(mfxU32 displayOrder, mfxU32 num, bool &ref)
+{
+ ref = false;
+ return BRefOrder(displayOrder, 0, num, 0, ref);
+}
+
+mfxU32 FrameReorder::BPyrReorder(const std::vector & bframes)
+{
+ mfxU32 num = (mfxU32)bframes.size();
+ if (bframes[0]->Bpo == (mfxU32)MFX_FRAMEORDER_UNKNOWN)
+ {
+ bool bRef = false;
+
+ for (mfxU32 i = 0; i < (mfxU32)bframes.size(); i++)
+ {
+ bframes[i]->Bpo = GetBiFrameLocation(i, num, bRef);
+ if (bRef)
+ bframes[i]->Type |= MFX_FRAMETYPE_REF;
+ }
+ }
+ mfxU32 minBPO = (mfxU32)MFX_FRAMEORDER_UNKNOWN;
+ mfxU32 ind = 0;
+ for (mfxU32 i = 0; i < (mfxU32)bframes.size(); i++)
+ {
+ if (bframes[i]->Bpo < minBPO)
+ {
+ ind = i;
+ minBPO = bframes[i]->Bpo;
+ }
+ }
+ return ind;
+}
+
+FrameReorder::FrameIterator FrameReorder::Reorder(bool flush, bool bFields)
+{
+ FrameIterator begin = m_queue.begin();
+ FrameIterator end = m_queue.begin();
+
+ while (end != m_queue.end())
+ {
+ if ((end != begin) && (end->Type & MFX_FRAMETYPE_IDR))
+ {
+ flush = true;
+ break;
+ }
+ end++;
+ }
+
+ if (bFields && m_lastFieldInfo.bFirstField())
+ {
+ while (begin != end && !m_lastFieldInfo.isCorrespondSecondField(*begin))
+ begin++;
+
+ if (begin != end)
+ {
+ m_lastFieldInfo.CorrectFrameInfo(*begin);
+ return begin;
+ }
+ else
+ begin = m_queue.begin();
+ }
+
+ FrameIterator top = Reorder(begin, end, flush, bFields);
+
+ if (top == end)
+ {
+ return top;
+ }
+
+ if (bFields)
+ {
+ m_lastFieldInfo.SaveInfo(*top);
+ }
+
+ return top;
+}
+
+FrameReorder::FrameIterator FrameReorder::Reorder(FrameIterator begin, FrameIterator end, bool flush, bool bFields)
+{
+ FrameIterator top = begin;
+ FrameIterator b0 = end; // 1st non-ref B with L1 > 0
+ std::vector bframes;
+
+ bool isBPyramid = !!(m_BRefType == MFX_B_REF_PYRAMID);
+
+ while (top != end && (top->Type & MFX_FRAMETYPE_B))
+ {
+ if (HasL1(top->Poc) && (!top->bSecondField))
+ {
+ if (isBPyramid)
+ bframes.push_back(top);
+ else if (top->Type & MFX_FRAMETYPE_REF)
+ {
+ if (b0 == end || (top->Poc - b0->Poc < bFields + 2))
+ return top;
+ }
+ else if (b0 == end)
+ b0 = top;
+ }
+ top++;
+ }
+
+ if (!bframes.empty())
+ {
+ return bframes[BPyrReorder(bframes)];
+ }
+
+ if (b0 != end)
+ return b0;
+
+ bool strict = !!(m_GopOptFlag & MFX_GOP_STRICT);
+ if (flush && top == end && begin != end)
+ {
+ top--;
+ if (strict)
+ top = begin;
+ else
+ top->Type = MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF;
+
+ if (top->bSecondField && top != begin)
+ {
+ top--;
+ if (strict)
+ top = begin;
+ else
+ top->Type = MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF;
+ }
+ }
+
+ return top;
+}
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/generator.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/generator.cpp
new file mode 100644
index 0000000..5387cf8
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/generator.cpp
@@ -0,0 +1,117 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "generator.h"
+
+// Processor for generation mode
+void Generator::Init()
+{
+ try
+ {
+ mfxStatus sts = m_FileReader.Init(std::list{m_InputParams.m_InputFileName}, MFX_FOURCC_I420);
+ CHECK_THROW_ERR(sts, "Generator::Init::m_FileReader.Init");
+
+ sts = m_FileWriter.Init(m_InputParams.m_OutputFileName.c_str(), 1);
+ CHECK_THROW_ERR(sts, "Generator::Init::m_FileWriter.Init");
+
+ // Add a buffer to bufferWriter
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ m_BufferWriter.AddBuffer(MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED, m_InputParams.m_PredBufferFileName);
+ }
+ catch (std::string& e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: Couldn't initialize Generator");
+ }
+ return;
+}
+
+// Get surface and load new YUV frame from file to it
+ExtendedSurface* Generator::PrepareSurface()
+{
+ ExtendedSurface* surf = GetFreeSurf();
+ if (!surf)
+ {
+ throw std::string("ERROR: Generator::PrepareSurface: Undefined reference to surface");
+ }
+ ++surf->Data.Locked;
+
+ mfxStatus sts = m_FileReader.LoadNextFrame(surf);
+ CHECK_THROW_ERR(sts, "Generator::PrepareSurface::FileReader.LoadNextFrame");
+
+ return surf;
+}
+
+void Generator::DropBuffers(ExtendedSurface& frame)
+{
+ for (mfxU32 i = 0; i < frame.Data.NumExtParam; ++i)
+ {
+ CHECK_THROW_ERR_BOOL(frame.Data.ExtParam[i], "Generator::DropFrames: surf.Data.ExtParam[i] == NULL");
+
+ // Drop data on disk
+ m_BufferWriter.WriteBuffer(frame.Data.ExtParam[i]);
+ // Zero data of written buffer
+ m_BufferWriter.ResetBuffer(frame.Data.ExtParam[i]);
+ }
+
+ return;
+}
+
+// Save all data
+//
+// Iterate through all unlocked frames and dump frame + buffers. When Locked frame met, iteration stops.
+void Generator::DropFrames()
+{
+ // Sort data by frame order and drop in DisplayOrder
+
+ // TODO / FIXME: Add EncodedOrder processing, it might be required for HEVC FEI PAK
+ m_Surfaces.sort([](ExtendedSurface& left, ExtendedSurface& right) { return left.Data.FrameOrder < right.Data.FrameOrder; });
+
+ for (ExtendedSurface& surf : m_Surfaces)
+ {
+ // If Locked surface met - stop dumping
+ if (surf.Data.Locked) break;
+
+ // If the surface has already been output, move on to the next one in frame order
+ if (surf.isWritten) continue;
+
+ // Write surface on disk
+ mfxStatus sts = m_FileWriter.WriteNextFrameI420(&surf);
+ surf.isWritten = true;
+ CHECK_THROW_ERR(sts, "Generator::DropFrames::m_FileWriter.WriteNextFrameI420");
+ }
+}
+
+void Generator::SavePSData()
+{
+ if (fpPicStruct.is_open())
+ {
+ // sort by coding order
+ std::sort(m_RefControl.RefLogInfo.begin(), m_RefControl.RefLogInfo.end(), IsInCodingOrder);
+
+ for (auto stat : m_RefControl.RefLogInfo)
+ stat.Dump(fpPicStruct);
+ }
+}
+
+#endif // MFX_VERSION
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/inputparameters.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/inputparameters.cpp
new file mode 100644
index 0000000..b78431d
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/inputparameters.cpp
@@ -0,0 +1,551 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+
+#include "inputparameters.h"
+
+using namespace std;
+
+void PrintHelp()
+{
+ printf("Usage:");
+ printf(" -i InputYUVFile -o OutputYUVFile -w width -h height -n number_of_frames_to_process\n");
+ printf(" The above params are required. If -pic_file or repack parameters are enabled, next parameters:-i InputYUVFile -o OutputYUVFile -w width -h height\n");
+ printf(" Can be removed\n");
+ //i/o/log
+ printf(" [-g num] - GOP size\n");
+ printf(" [-r num] - number of B frames plus 1\n");
+ printf(" [-x num] - DPB size in frames\n");
+ printf(" [-idr_interval num] - IDR interval in frames\n");
+ printf(" [-num_active_P num] - number of active references for P frames\n");
+ printf(" [-num_active_BL0 num] - number of active List 0 references for B frames\n");
+ printf(" [-num_active_BL1 num] - number of active List 1 references for B frames\n");
+ printf(" [-generate] - run ASG in test stream generation mode\n"); // required
+ printf(" [-verify] - run ASG in test results verification mode\n"); // required
+ printf(" [-gen_split] - enable CTU splitting\n");
+ printf(" [-no_cu_to_pu_split] - disable CU splitting into PUs\n");
+ printf(" [-force_extbuf_mvp_block_size num] - force mfxFeiHevcEncMVPredictors::BlockSize field\n");
+ printf(" in MVP output buffer to a specified value. *ALL* output \n");
+ printf(" mfxFeiHevcEncMVPredictors structs will be affected.\n");
+ printf(" Supported values are 0, 1, 2 and 3\n");
+ printf(" See MVPredictor description in HEVC FEI manual for details\n");
+ printf(" [-mvp_block_size num] - actual MVP block size used in actual generation algorithm.\n");
+ printf(" If -force_extbuf_mvp_block_size is not specified,\n");
+ printf(" this value is used in output mfxFeiHevcEncMVPredictors::BlockSize\n");
+ printf(" only for the structures for which MVPs were actually generated\n");
+ printf(" When -force_extbuf_mvp_block_size is specified and -mvp_block_size is not\n");
+ printf(" default algorithm for MVP generation is used : MVP block size equals to CTU size.\n");
+ printf(" When both -force_extbuf_mvp_block_size and -mvp_block_size are specified : the 1st one\n");
+ printf(" value is used in the output ExtBuffer regardless to actual MVP block size\n");
+ printf(" Supported values are 0, 1, 2 and 3\n");
+ printf(" [-force_symm_cu_part] - forces using only symmetric CU into PU partioning modes\n");
+ printf(" for inter prediction test\n");
+ printf(" [-gen_inter] - generate inter CUs (inter prediction test)\n");
+ printf(" [-gen_intra] - generate intra CUs (intra prediction test)\n");
+ printf(" [-gen_pred] - generate MV predictors (inter prediction test)\n");
+ printf(" [-gen_mv] - generate motion vectors inside search window (inter prediction test)\n"); // name != sense
+ printf(" If -gen_mv is not specified,\n");
+ printf(" then resulting MVs for PUs will be generated outside\n");
+ printf(" the search window only\n");
+ printf(" [-gen_repack_ctrl] - generate/verify repack control data\n");
+ printf(" [-pred_file File] - output file for MV predictors\n");
+ printf(" [-pic_file File] - output file for pictures' structure\n");
+ printf(" [-log2_ctu_size num] - log2 CTU size to be used for CU quad-tree structure\n");
+ printf(" Default is 4");
+ printf(" Cannot be less than min_log2_tu_size (described below)\n");
+ printf(" [-min_log2_tu_size num] - minimum log2 TU size to be used for quad-tree structure\n");
+ printf(" Must be less than min_log2_cu_size (described below), default is 2\n");
+ printf(" [-max_log2_tu_size num] - maximum log2 TU size to be used for quad-tree structure\n");
+ printf(" Must be less than or equal to Min(log2_ctu_size, 5), default is 4\n");
+ printf(" [-max_tu_qt_depth num] - maximum TU quad-tree depth inside CU\n");
+ printf(" Overrrides min_log2_tu_size, default is 4\n");
+ printf(" [-min_log2_cu_size num] - minimum log2 CU size to be used for quad-tree structure.\n");
+ printf(" Cannot be less than max_log2_tu_size, default is 3\n");
+ printf(" [-max_log2_cu_size num] - maximum log2 CU size to be used for quad-tree structure.\n");
+ printf(" Cannot be larger than log2_ctu_size, default is 4\n");
+ printf(" [-block_size_mask num] - bit mask specifying possible partition sizes\n");
+ printf(" [-ctu_distance num] - minimum distance between generated CTUs\n");
+ printf(" (in units of CTU), default is 3\n");
+ printf(" [-gpb_off] - specifies that regular P frames should be used, not GPB frames\n");
+ printf(" [-bref] - arrange B frames in B pyramid reference structure\n");
+ printf(" [-nobref] - do not use B-pyramid\n");
+ printf(" [-pak_ctu_file File] - input file with per CTU information\n");
+ printf(" [-pak_cu_file File] - input file with per CU information\n");
+ printf(" [-repack_ctrl_file File]- output/input file with repack control data for repack control generation/verify\n");
+ printf(" [-repack_stat_file File]- input file with repack stat data for repack control verify\n");
+ printf(" [-repack_str_file File] - input file with multiPakStr data for repack control generation/verify\n");
+ printf(" [-log File] - log output file\n");
+ printf(" [-csv File] - file to output statistics in CSV format\n"); // ignored
+ printf(" [-config ConfigFile] - input configuration file\n"); // ignored
+ printf(" [-sub_pel_mode num] - specifies sub pixel precision for motion vectors. 0 - integer, 1 - half, 3 - quarter (0 is default)\n");
+ printf(" [-mv_thres num] - threshold for motion vectors in percents (0 is default)\n");
+ printf(" [-numpredictors num] - number of MV predictors enabled. Used in verification mode to check NumMvPredictors FEI control works correctly\n");
+ printf(" - Valid values are in range [1; 4] (4 is default)\n");
+ printf(" [-split_thres num] - thresholds for partitions in percents (0 is default)\n");
+ printf(" [-DeltaQP value(s)] - array of delta QP values for repack ctrl generation, separated by a space (8 values at max)\n");
+ printf(" [-InitialQP value] - the initial QP value for repack ctrl verify (26 is default)\n");
+}
+
+void InputParams::ParseInputString(msdk_char **strInput, mfxU8 nArgNum)
+{
+ try {
+
+ //parse command line parameters
+ for (mfxU8 i = 1; i < nArgNum; ++i)
+ {
+ //Verbose mode, output to command line. Missed in Help
+ if (msdk_strcmp(strInput[i], MSDK_STRING("-verbose")) == 0
+ || msdk_strcmp(strInput[i], MSDK_STRING("-v")) == 0)
+ m_bVerbose = true;
+
+ //I/O YUV files
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-i")) == 0)
+ m_InputFileName = GetStringArgument(strInput, ++i, nArgNum);
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-o")) == 0)
+ m_OutputFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ //width
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-w")) == 0)
+ m_width = GetIntArgument(strInput, ++i, nArgNum);
+
+ //height
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-h")) == 0)
+ m_height = GetIntArgument(strInput, ++i, nArgNum);
+
+ //frame number
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-n")) == 0)
+ m_numFrames = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Encoding structure
+
+ // GOP size
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-g")) == 0)
+ m_GopSize = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Number of B frames + 1
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-r")) == 0)
+ m_RefDist = GetIntArgument(strInput, ++i, nArgNum);
+
+ // DPB size
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-x")) == 0)
+ {
+ m_NumRef = GetIntArgument(strInput, ++i, nArgNum);
+ if (m_NumRef > 16) throw std::string("ERROR: Invalid DPB size");
+ }
+
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-idr_interval")) == 0)
+ m_nIdrInterval = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Number active references for P frames
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-num_active_P")) == 0)
+ {
+ m_NumRefActiveP = GetIntArgument(strInput, ++i, nArgNum);
+ if (m_NumRefActiveP > 4) throw std::string("ERROR: Invalid num_active_P");
+ }
+
+ // Number of backward references for B frames
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-num_active_BL0")) == 0)
+ {
+ m_NumRefActiveBL0 = GetIntArgument(strInput, ++i, nArgNum);
+ if (m_NumRefActiveBL0 > 4) throw std::string("ERROR: Invalid num_active_BL0");
+ }
+
+ // Number of forward references for B frames
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-num_active_BL1")) == 0)
+ {
+ m_NumRefActiveBL1 = GetIntArgument(strInput, ++i, nArgNum);
+ if (m_NumRefActiveBL1 > 1) throw std::string("ERROR: Invalid num_active_BL1");
+ }
+
+ // Set parameters for b-pyramid
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-bref")) == 0)
+ {
+ m_BRefType = MFX_B_REF_PYRAMID;
+ }
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-nobref")) == 0)
+ {
+ m_BRefType = MFX_B_REF_OFF;
+ }
+
+ // processing mode
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-generate")) == 0)
+ m_ProcMode = GENERATE;
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-verify")) == 0)
+ m_ProcMode = VERIFY;
+
+ // test type
+
+ // Enable split of CTU
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gen_split")) == 0)
+ m_TestType |= GENERATE_SPLIT;
+
+ // Generate MVs, Inter-prediction test
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gen_mv")) == 0)
+ m_TestType |= GENERATE_MV;
+
+ // Generate Intra CUs, Intra-prediction test
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gen_intra")) == 0)
+ m_TestType |= GENERATE_INTRA;
+
+ // Generate Inter CUs, Inter-prediction test
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gen_inter")) == 0)
+ m_TestType |= GENERATE_INTER;
+
+ // Generate long MVs which are outside of SW, Inter-prediction test
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gen_pred")) == 0)
+ m_TestType |= GENERATE_PREDICTION;
+
+ // Generate or verify multi-repack control data
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gen_repack_ctrl")) == 0)
+ m_TestType |= GENERATE_REPACK_CTRL;
+
+ // Drop data to file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-pred_file")) == 0)
+ m_PredBufferFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ // Drop pictures structure to file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-pic_file")) == 0) {
+ m_PicStructFileName = GetStringArgument(strInput, ++i, nArgNum);
+ m_TestType |= GENERATE_PICSTRUCT;
+ }
+
+ // Minimum log CU size to be used for quad-tree structure
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-min_log2_cu_size")) == 0)
+ m_CTUStr.minLog2CUSize = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Maximum log CU size to be used for quad-tree structure
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-max_log2_cu_size")) == 0)
+ m_CTUStr.maxLog2CUSize = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Disable CU splitting into PUs
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-no_cu_to_pu_split")) == 0)
+ m_CTUStr.bCUToPUSplit = false;
+
+ // Force per-MVP block size in the MVP output file to a supported value
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-force_extbuf_mvp_block_size")) == 0)
+ {
+ m_ForcedExtMVPBlockSize = GetIntArgument(strInput, ++i, nArgNum);
+ m_bIsForceExtMVPBlockSize = true;
+ }
+
+ // Actual per-MVP block size used in generation algorithm
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-mvp_block_size")) == 0)
+ {
+ m_GenMVPBlockSize = GetIntArgument(strInput, ++i, nArgNum);
+ }
+
+ // Force only symmetric CU into PU partioning
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-force_symm_cu_part")) == 0)
+ {
+ m_CTUStr.bForceSymmetricPU = true;
+ }
+
+ // Log2 CTU size to be used for quad-tree structure. Also the maximum
+ // possible CU size
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-log2_ctu_size")) == 0)
+ {
+ m_CTUStr.log2CTUSize = GetIntArgument(strInput, ++i, nArgNum);
+ m_CTUStr.CTUSize = (mfxU32)(1 << m_CTUStr.log2CTUSize);
+ }
+
+ // Minimum log TU size to be used for quad-tree structure
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-min_log2_tu_size")) == 0)
+ m_CTUStr.minLog2TUSize = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Maximum log TU size to be used for quad-tree structure
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-max_log2_tu_size")) == 0)
+ m_CTUStr.maxLog2TUSize = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Maximum TU quad-tree depth inside CU
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-max_tu_qt_depth")) == 0)
+ m_CTUStr.maxTUQTDepth = GetIntArgument(strInput, ++i, nArgNum);
+
+ // which blocks to use in partitions (bitmask)
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-block_size_mask")) == 0)
+ m_block_size_mask = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Minimum distance between generated CTUs in terms of CTU
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-ctu_distance")) == 0)
+ m_CTUStr.CTUDist = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Read CTU data from file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-pak_ctu_file")) == 0)
+ m_PakCtuBufferFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ // Read CU data from file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-pak_cu_file")) == 0)
+ m_PakCuBufferFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ // Whether GPB frames should be used instead of regular P frames
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-gpb_off")) == 0)
+ m_UseGPB = false;
+
+ // Thresholds
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-mv_thres")) == 0)
+ m_Thresholds.mvThres = GetIntArgument(strInput, ++i, nArgNum);
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-split_thres")) == 0)
+ m_Thresholds.splitThres = GetIntArgument(strInput, ++i, nArgNum);
+ // Number of enabled MV predictors. For disabled predictors upper MV-threshold is ON
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-numpredictors")) == 0)
+ m_NumMVPredictors = GetIntArgument(strInput, ++i, nArgNum);
+
+ // Motion prediction precision mode
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-sub_pel_mode")) == 0)
+ {
+ if (++i < nArgNum)
+ {
+ m_SubPixelMode = ParseSubPixelMode(strInput[i]);
+ }
+ else
+ {
+ throw std::string("ERROR: sub_pel_mode require an argument");
+ }
+ }
+
+ // The multi-repack control data file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-repack_ctrl_file")) == 0)
+ m_RepackCtrlFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ // The multiPakStr data file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-repack_str_file")) == 0)
+ m_RepackStrFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ // The multi-repack stat data file
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-repack_stat_file")) == 0)
+ m_RepackStatFileName = GetStringArgument(strInput, ++i, nArgNum);
+
+ //Repack control num passes and delta QP
+ else if((msdk_strcmp(strInput[i], MSDK_STRING("-DeltaQP")) == 0))
+ {
+ mfxU32 idxQP;
+ for(idxQP = 0; idxQP < m_NumAddPasses; idxQP++)
+ {
+ if(msdk_strncmp(strInput[i+1], MSDK_STRING("-"), 1) == 0)
+ break;
+
+ m_DeltaQP[idxQP] = (mfxU8)GetIntArgument(strInput, ++i, nArgNum);
+ }
+ m_NumAddPasses = idxQP;
+ }
+
+ //Repack control initial QP
+ else if((msdk_strcmp(strInput[i], MSDK_STRING("-InitialQP")) == 0))
+ m_InitialQP = GetIntArgument(strInput, ++i, nArgNum);
+
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-log")) == 0)
+ {
+ m_bUseLog = true;
+ m_LogFileName = GetStringArgument(strInput, ++i, nArgNum);
+ }
+ //help
+ else if (msdk_strcmp(strInput[i], MSDK_STRING("-help")) == 0
+ || msdk_strcmp(strInput[i], MSDK_STRING("--help")) == 0)
+ {
+ m_bPrintHelp = true;
+ }
+ else
+ throw std::string("ERROR: Unknown input argument");
+ }
+
+ if (m_bPrintHelp)
+ {
+ PrintHelp();
+ return;
+ }
+
+ if (m_TestType == UNDEFINED_TYPE)
+ throw std::string("ERROR: Undefined test type");
+
+ if (m_ProcMode == UNDEFINED_MODE)
+ throw std::string("ERROR: Undefined mode");
+
+ if (m_numFrames == 0)
+ throw std::string("ERROR: Invalid number of frames");
+
+ if ((m_TestType & GENERATE_PICSTRUCT) && m_TestType != GENERATE_PICSTRUCT)
+ throw std::string("ERROR: Improper arguments mix with pic_struct");
+
+ if (m_TestType == GENERATE_PICSTRUCT)
+ return;
+
+ //Repack control generation checking
+ if (m_TestType & GENERATE_REPACK_CTRL)
+ {
+ if (m_TestType != GENERATE_REPACK_CTRL)
+ throw std::string("ERROR: Improper arguments mix with gen_repack_ctrl");
+
+ if (m_ProcMode == GENERATE)
+ {
+ if (m_NumAddPasses == 0 || m_NumAddPasses > HEVC_MAX_NUMPASSES)
+ throw std::string("ERROR: Wrong NumAddPasses value");
+
+ if (!m_RepackCtrlFileName.empty() && !m_RepackStrFileName.empty())
+ return;
+ else
+ throw std::string("ERROR: repack ctrl and str files required");
+ }
+ else if (m_ProcMode == VERIFY)
+ {
+ if (!m_RepackCtrlFileName.empty()
+ && !m_RepackStrFileName.empty()
+ && !m_RepackStatFileName.empty())
+ return;
+ else
+ throw std::string("ERROR: repack ctrl, str and stat files required");
+ }
+ else
+ {
+ throw std::string("ERROR: Wrong proc mode");
+ }
+ }
+
+ if (m_ProcMode == GENERATE && (m_TestType & (GENERATE_INTER | GENERATE_INTRA)) && (m_InputFileName.length() == 0 || m_OutputFileName.length() == 0))
+ throw std::string("ERROR: input and output YUV files required");
+
+ if (m_ProcMode == GENERATE && (m_TestType & GENERATE_PREDICTION)
+ && m_PredBufferFileName.length() == 0)
+ throw std::string("ERROR: To generate predictors output file is required");
+
+ if ((m_ProcMode & VERIFY) && (m_TestType & (GENERATE_INTER | GENERATE_INTRA)) && m_PakCtuBufferFileName.length() == 0)
+ throw std::string("ERROR: PAK CTU input file is required");
+
+ if ((m_ProcMode & VERIFY) && (m_TestType & (GENERATE_INTER | GENERATE_INTRA)) && m_PakCuBufferFileName.length() == 0)
+ throw std::string("ERROR: PAK CU input file is required");
+
+ if (m_width == 0 || m_height == 0)
+ throw std::string("ERROR: Invalid width or/and height values");
+
+ if (m_CTUStr.CTUSize != 16 && m_CTUStr.CTUSize != 32 && m_CTUStr.CTUSize != 64)
+ throw std::string("ERROR: Invalid CTU size specified");
+
+ if (m_block_size_mask > 3 || m_block_size_mask == 0)
+ // 64x64 blocks are unsupported on SKL
+ throw std::string("ERROR: Incorrect block_size_mask");
+
+ if (m_bIsForceExtMVPBlockSize && m_ForcedExtMVPBlockSize > 3)
+ throw std::string("ERROR: Invalid forced MVP block size specified");
+
+ if (m_GenMVPBlockSize > 3)
+ throw std::string("ERROR: Invalid actual MVP block size specified");
+
+ //Checking actual MVP block size and CTU size compatibily
+ if (m_GenMVPBlockSize != 0)
+ {
+ if ((m_CTUStr.CTUSize == 16 && m_GenMVPBlockSize > 1))
+ {
+ throw std::string("ERROR: For 16x16 CTU actual buffer MVP block size should be less or equal than CTU size");
+ }
+ else if (m_CTUStr.CTUSize == 32 && m_GenMVPBlockSize > 2)
+ {
+ throw std::string("ERROR: For 32x32 CTU actual buffer MVP block size should be less or equal than CTU size");
+ }
+ }
+
+ if ((m_TestType & (GENERATE_MV | GENERATE_PREDICTION)) && !(m_TestType & GENERATE_INTER))
+ throw std::string("ERROR: MVs can't be generated w/o -gen_inter option");
+
+ if ((m_TestType & GENERATE_SPLIT) && !(m_TestType & (GENERATE_INTER | GENERATE_INTRA)))
+ throw std::string("ERROR: Splits can't be generated w/o -gen_inter or -gen_intra option");
+
+
+ if ((m_ProcMode & VERIFY) && (m_TestType & GENERATE_INTER) && m_Thresholds.mvThres > 100)
+ throw std::string("ERROR: Incorrect threshold for MVs in the verification mode");
+
+ if ((m_ProcMode & VERIFY) && (m_TestType & (GENERATE_INTER | GENERATE_INTRA)) && m_Thresholds.splitThres > 100)
+ throw std::string("ERROR: Incorrect threshold for splits in the verification mode");
+
+ if ((m_ProcMode & VERIFY) && (m_TestType & (GENERATE_INTER | GENERATE_PREDICTION)) && m_NumMVPredictors > 4)
+ throw std::string("ERROR: Incorrect number of enabled MV predictors in the verification mode");
+
+ if (m_CTUStr.maxLog2CUSize < m_CTUStr.minLog2CUSize)
+ throw std::string("ERROR: max_log2_cu_size should be greater than or equal to min_log2_tu_size");
+
+ if ((mfxU32) 1 << m_CTUStr.maxLog2CUSize > m_CTUStr.CTUSize)
+ throw std::string("ERROR: max_log2_cu_size should be less than or equal to log2_ctu_size");
+
+ if (m_CTUStr.maxLog2TUSize < m_CTUStr.minLog2TUSize)
+ throw std::string("ERROR: max_log2_tu_size should be greater than or equal to min_log2_tu_size");
+
+ if (m_CTUStr.minLog2CUSize <= m_CTUStr.minLog2TUSize)
+ throw std::string("ERROR: min_log2_cu_size should be greater than min_log2_tu_size");
+
+ if (m_CTUStr.maxLog2TUSize > (std::min)(m_CTUStr.maxLog2CUSize, (mfxU32) 5))
+ throw std::string("ERROR: max_log2_tu_size should be less than or equal to Min( log2_ctu_size, 5)");
+ }
+ catch (std::string& e) {
+ cout << e << endl;
+ throw std::string("ERROR: InputParams::ParseInputString");
+ }
+
+ return;
+}
+
+mfxU16 InputParams::ParseSubPixelMode(msdk_char * strRawSubPelMode)
+{
+ mfxU16 pelMode = msdk_atoi(strRawSubPelMode);
+
+ switch (pelMode)
+ {
+ case 0:
+ case 1:
+ case 3:
+ return pelMode;
+ default:
+ throw std::string("ERROR: Incorrect sub_pel_mode value");
+ }
+}
+
+int InputParams::GetIntArgument(msdk_char **strInput, mfxU8 index, mfxU8 nArgNum)
+{
+ if (strInput == nullptr || *strInput == nullptr)
+ {
+ throw std::string("ERROR: GetIntArgument: null pointer reference");
+ }
+ if (index < nArgNum)
+ {
+ return msdk_atoi(strInput[index]);
+ }
+ else
+ {
+ throw std::string("ERROR: missing secondary integer argument");
+ }
+}
+
+msdk_string InputParams::GetStringArgument(msdk_char **strInput, mfxU8 index, mfxU8 nArgNum)
+{
+ if (strInput == nullptr || *strInput == nullptr)
+ {
+ throw std::string("ERROR: GetStringArgument: null pointer reference");
+ }
+ if (index < nArgNum)
+ {
+ return msdk_string(strInput[index]);
+ }
+ else
+ {
+ throw std::string("ERROR: missing secondary string argument");
+ }
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/mvmvp_processor.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/mvmvp_processor.cpp
new file mode 100644
index 0000000..144b0f8
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/mvmvp_processor.cpp
@@ -0,0 +1,734 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "mvmvp_processor.h"
+
+// Generates MVP pool groups according to PU positioning in CTU and constructed MVP blocks grid
+void MVMVPProcessor::InitMVPGridData(const CTUDescriptor& CTU, const FrameChangeDescriptor & frameDescr)
+{
+ mfxU32 gridSizeIn32x32Blocks = CTU.m_BWidth / (2 * MVP_BLOCK_SIZE);
+
+ // 16x16 MVP blocks in frame; numbers denote order in file:
+ // ++++++++++++++++++++
+ // + 0 + 1 + 4 + 5 +
+ // +++++++++++++++++ ...
+ // + 2 + 3 + 6 + 7 +
+ // +++++++++++++++++
+ // + ...
+ // Each quarter of 16x16 blocks with sequent indecies are forming a 32x32 block group
+
+ m_mvpBlockGrid.reserve(gridSizeIn32x32Blocks * gridSizeIn32x32Blocks);
+
+ if (!gridSizeIn32x32Blocks) // only one 16x16 block
+ {
+ m_mvpBlockGrid.emplace_back(CTU.m_AdrX, CTU.m_AdrY, MVP_BLOCK_SIZE, MVP_BLOCK_SIZE);
+ }
+ else
+ {
+ // Pushing MVP blocks onto the grid in zig-zag order described above
+ for (mfxU32 gridIdx = 0; gridIdx < gridSizeIn32x32Blocks * gridSizeIn32x32Blocks; ++gridIdx)
+ {
+ for (mfxU32 elemIdx = 0; elemIdx < 4; ++elemIdx)
+ {
+ m_mvpBlockGrid.emplace_back(
+ CTU.m_AdrX + (2 * (gridIdx % gridSizeIn32x32Blocks) + (elemIdx % 2)) * MVP_BLOCK_SIZE,
+ CTU.m_AdrY + (2 * (gridIdx / gridSizeIn32x32Blocks) + (elemIdx / 2)) * MVP_BLOCK_SIZE,
+ MVP_BLOCK_SIZE, MVP_BLOCK_SIZE);
+ }
+ }
+ }
+
+ mfxI32 mvpGroupsNum = ConstructMVPPoolGroups(CTU);
+
+ // All PUs are processed - constructing actual MVP pools per each group
+
+ m_mvpPools.resize(mvpGroupsNum);
+
+ for (mfxI32 groupNo = 0; groupNo < mvpGroupsNum; ++groupNo)
+ {
+ m_mvpPools[groupNo].reserve(MVP_PER_16x16_BLOCK);
+
+ for (mfxU32 mvpCount = 0; mvpCount < MVP_PER_16x16_BLOCK; ++mvpCount)
+ {
+ m_mvpPools[groupNo].emplace_back(GenerateMVP(CTU, frameDescr));
+ }
+ }
+}
+
+mfxI32 MVMVPProcessor::ConstructMVPPoolGroups(const CTUDescriptor& CTU)
+{
+ switch (m_GenMVPBlockSize)
+ {
+ case 1:
+ if (CTU.m_BWidth == 32 || CTU.m_BWidth == 64)
+ {
+ return PutPUAndMVPBlocksIn16x16MVPPoolGroups(CTU);
+ }
+ case 2:
+ if (CTU.m_BWidth == 64)
+ {
+ return PutPUAndMVPBlocksIn32x32MVPPoolGroups(CTU);
+ }
+ case 3:
+ return PutPUAndMVPBlocksInSingleMVPPoolGroup(CTU);
+
+ default:
+ throw std::string("ERROR: MVMVPProcessor: ConstructMVPPoolGroups: Incorrect m_GenMVPBlockSize used");
+ }
+}
+
+mfxI32 MVMVPProcessor::PutPUAndMVPBlocksIn16x16MVPPoolGroups(const CTUDescriptor & CTU)
+{
+ mfxI32 extMVPGroupNo = 0;
+
+ for (const auto& CU : CTU.m_CUVec)
+ {
+ if (CU.m_PredType == INTER_PRED)
+ {
+ // For all the inter PUs constructing a MVP block list which this PU has intersections with
+ for (const auto& PU : CU.m_PUVec)
+ {
+ // Construct a list with all MVP blocks which have intersections with current PU
+
+ std::list intersectedMVPBlocks;
+
+ for (const auto& mvpBlock : m_mvpBlockGrid)
+ {
+ if (PU.CheckForIntersect(mvpBlock))
+ {
+ intersectedMVPBlocks.push_back(mvpBlock);
+ }
+ }
+
+ // Checking the list validity. It should have at least 1 element
+ if (intersectedMVPBlocks.empty())
+ {
+ throw std::string("ERROR: MVMVPProcessor: PutPUAndMVPBlocksIn16x16MVPPoolGroups: Found a PU which doesn't intersect the MVP grid");
+ }
+
+ // Check if there is at least one block which is included in some group
+ // MVP blocks should have no group or be included in the one group
+ auto validGroupMVPBlock = std::find_if(intersectedMVPBlocks.begin(), intersectedMVPBlocks.end(),
+ [](const MVPBlock& block) { return block.IsAlreadyInGroup(); });
+
+ // If it exists, put all MVP blocks intersected with current PU in this group
+ if (validGroupMVPBlock != intersectedMVPBlocks.end())
+ {
+ mfxI32 firstValidGroupNo = validGroupMVPBlock->GetGroupNo();
+
+ if (std::any_of(intersectedMVPBlocks.begin(), intersectedMVPBlocks.end(),
+ [firstValidGroupNo](const MVPBlock& block)
+ { return (block.IsAlreadyInGroup() && !block.IsInGroup(firstValidGroupNo)); }))
+ {
+ throw std::string("ERROR: PutPUAndMVPBlocksIn16x16MVPPoolGroups : Found a pair of MVP blocks intersecting with current PU which are in the different MVP groups");
+ }
+ else // include all intersecting MVP blocks in the single group
+ {
+ for (MVPBlock& block : m_mvpBlockGrid)
+ {
+ if (std::find(intersectedMVPBlocks.begin(), intersectedMVPBlocks.end(), block)
+ != intersectedMVPBlocks.end())
+ {
+ block.SetGroup(firstValidGroupNo);
+ }
+ }
+ // The list is valid - set PU pool group no. with the value for MVP blocks
+ m_PUtoMVPPoolGroupMap[PU] = firstValidGroupNo;
+ }
+ }
+ else // Otherwise, put all MVP blocks in the new group
+ {
+ for (MVPBlock& block : m_mvpBlockGrid)
+ {
+ if (std::find(intersectedMVPBlocks.begin(), intersectedMVPBlocks.end(), block)
+ != intersectedMVPBlocks.end())
+ {
+ block.SetGroup(extMVPGroupNo);
+ }
+ }
+ // The list is valid - set PU pool group no. with the value for MVPs
+ m_PUtoMVPPoolGroupMap[PU] = extMVPGroupNo;
+
+ ++extMVPGroupNo;
+ }
+ }
+ }
+ }
+ return extMVPGroupNo;
+}
+
+mfxI32 MVMVPProcessor::PutPUAndMVPBlocksIn32x32MVPPoolGroups(const CTUDescriptor & CTU)
+{
+ // Special case for 64x64 CTUs and 32x32 MVP block size
+ mfxI32 extMVPGroupNo = 0;
+
+ // Construct FOUR 32x32 block groups from the 16x16 block grid
+ std::vector mvp32x32BlockGroups;
+ mvp32x32BlockGroups.reserve(4);
+
+ for (mfxU32 gridIdx = 0; gridIdx < m_mvpBlockGrid.size(); gridIdx += 4)
+ {
+ mvp32x32BlockGroups.emplace_back(BaseBlock(m_mvpBlockGrid[gridIdx].m_AdrX,
+ m_mvpBlockGrid[gridIdx].m_AdrY,
+ MVP_BLOCK_SIZE * 2, MVP_BLOCK_SIZE * 2), gridIdx);
+ }
+
+ for (const auto& CU : CTU.m_CUVec)
+ {
+ if (CU.m_PredType == INTER_PRED)
+ {
+ // For all the inter PUs constructing a list of 32x32 MVP block groups
+ // that this PU has intersections with
+ for (const auto& PU : CU.m_PUVec)
+ {
+ // Construct a list with all 32x32 MVP block groups which have intersections with current PU
+ std::list intersected32x32MVPBlocks;
+
+ for (const auto& mvp32x32Block : mvp32x32BlockGroups)
+ {
+ if (PU.CheckForIntersect(mvp32x32Block.first))
+ {
+ intersected32x32MVPBlocks.push_back(mvp32x32Block);
+ }
+ }
+
+ // Checking the list validity. It should have at least 1 element
+ if (intersected32x32MVPBlocks.empty())
+ {
+ throw std::string("ERROR: MVMVPProcessor: PutPUAndMVPBlocksIn32x32MVPPoolGroups: Found a PU which doesn't intersect the 32x32 MVP groups grid");
+ }
+
+ // Check if there is at least one block which is included in some group
+ // MVP blocks should have no group or be included in a single group
+ auto validGroupMVPBlock = std::find_if(intersected32x32MVPBlocks.begin(),
+ intersected32x32MVPBlocks.end(), [this](const MVP32x32BlockGroup& block32x32)
+ { return m_mvpBlockGrid[block32x32.second].IsAlreadyInGroup(); });
+
+ // If it exists, put all MVP blocks intersecting the current PU in this group
+ if (validGroupMVPBlock != intersected32x32MVPBlocks.end())
+ {
+ mfxI32 firstValidGroupNo = m_mvpBlockGrid[validGroupMVPBlock->second].GetGroupNo();
+
+ if (std::any_of(intersected32x32MVPBlocks.begin(),
+ intersected32x32MVPBlocks.end(), [this, firstValidGroupNo](const MVP32x32BlockGroup& block32x32)
+ { return (m_mvpBlockGrid[block32x32.second].IsAlreadyInGroup() && !m_mvpBlockGrid[block32x32.second].IsInGroup(firstValidGroupNo)); }))
+ {
+ throw std::string("ERROR: PutPUAndMVPBlocksIn32x32MVPPoolGroups : Found a pair of MVP blocks intersecting with current PU which are in the different MVP groups");
+ }
+ else // include all intersecting MVP blocks in the single group
+ {
+ for (MVPBlock& block : m_mvpBlockGrid)
+ {
+ if (std::find_if(intersected32x32MVPBlocks.begin(), intersected32x32MVPBlocks.end(),
+ [this, &block](const MVP32x32BlockGroup& block32x32)
+ { return m_mvpBlockGrid[block32x32.second] == block; }) != intersected32x32MVPBlocks.end())
+ {
+ block.SetGroup(firstValidGroupNo);
+ }
+ }
+ // The list is valid - set PU pool group no. with the value for MVP blocks
+ m_PUtoMVPPoolGroupMap[PU] = firstValidGroupNo;
+ }
+ }
+ else // Otherwise, put all MVP blocks in the new group
+ {
+ for (MVPBlock& block : m_mvpBlockGrid)
+ {
+ if (std::find_if(intersected32x32MVPBlocks.begin(), intersected32x32MVPBlocks.end(),
+ [this, &block](const MVP32x32BlockGroup& block32x32)
+ { return m_mvpBlockGrid[block32x32.second] == block; }) != intersected32x32MVPBlocks.end())
+ {
+ block.SetGroup(extMVPGroupNo);
+ }
+ }
+
+ // The list is valid - set PU pool group no. with the value for MVPs
+ m_PUtoMVPPoolGroupMap[PU] = extMVPGroupNo;
+
+ ++extMVPGroupNo;
+ }
+ }
+ }
+ }
+ return extMVPGroupNo;
+}
+
+mfxI32 MVMVPProcessor::PutPUAndMVPBlocksInSingleMVPPoolGroup(const CTUDescriptor & CTU)
+{
+ const mfxI32 extGroupNo = 0;
+
+ for (MVPBlock& block : m_mvpBlockGrid)
+ {
+ block.SetGroup(extGroupNo);
+ }
+
+ for (const auto& CU : CTU.m_CUVec)
+ {
+ if (CU.m_PredType == INTER_PRED)
+ {
+ for (const auto& PU : CU.m_PUVec)
+ {
+ m_PUtoMVPPoolGroupMap[PU] = extGroupNo;
+ }
+ }
+ }
+
+ return 1;
+}
+
+// Fills output mfxExtFeiHevcEncMVPredictors::Data with generated MVP Grid data depending on the m_GenMVPBlockSize value
+//
+// frameDescr - MOD frame descriptor. It holds ext buffers
+void MVMVPProcessor::FillFrameMVPExtBuffer(FrameChangeDescriptor& frameDescr)
+{
+ ExtendedSurface& surf = *frameDescr.m_frame;
+
+ mfxExtFeiHevcEncMVPredictors* mvpBuf =
+ reinterpret_cast(surf.GetBuffer(MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED));
+
+ m_DoUseIntra = !!(frameDescr.m_testType & GENERATE_INTRA);
+
+ switch (m_GenMVPBlockSize)
+ {
+ case 0:
+ // No MVP specified. Left buffer unchanged
+ break;
+ case 1:
+ // MVP for 16x16 blocks
+ // Iterating over all generated blocks
+ for (const auto& block : m_mvpBlockGrid)
+ {
+ PutMVPIntoExtBuffer(block, mvpBuf);
+ }
+ break;
+ case 2:
+ // MVP for 32x32 blocks
+ // Iterating over each upper-left block in the 32x32 group
+ // | 0* 1 | 4* 5 |
+ // | 2 3 | 6 7 |
+ for (std::size_t gridIdx = 0; gridIdx < m_mvpBlockGrid.size(); gridIdx += 4)
+ {
+ PutMVPIntoExtBuffer(m_mvpBlockGrid[gridIdx], mvpBuf);
+ }
+ break;
+ case 3:
+ // MVP for 64x64 blocks
+ // 16x16 blocks marked with X should be the same in the output predictors buffer
+ // ++++++++++++++++++++
+ // + X + + X + +
+ // +++++++++++++++++ ...
+ // + + + + +
+ // +++++++++++++++++
+ // + X + + X + + ...
+ // +++++++++++++++++
+ // + + + + +
+ // +++++++++++++++++
+ // + ...
+ PutMVPIntoExtBuffer(m_mvpBlockGrid[0], mvpBuf);
+ break;
+ default:
+ break;
+ }
+}
+
+
+bool MVMVPProcessor::GenValidMVMVPForPU(PUBlock & PU, const FrameChangeDescriptor & frameDescr)
+{
+ const auto mvpGroupNo = m_PUtoMVPPoolGroupMap.find(PU);
+
+ if (mvpGroupNo != m_PUtoMVPPoolGroupMap.end())
+ {
+ if (mvpGroupNo->second < 0)
+ {
+ throw std::string("ERROR: MVMVPProcessor: GenValidMVMVPForPU: Some PU has invalid MVP pool no.");
+ }
+ }
+ else
+ {
+ throw std::string("ERROR: MVMVPProcessor: GenValidMVMVPForPU: Some PU hasn't been included in MVP pool group map");
+ }
+
+ // Inter prediction test
+ // Try 100 times max to generate valid references
+ for (mfxU32 i = 0; i < MAX_GEN_MV_ATTEMPTS; ++i)
+ {
+ PUMotionVector mvSW;
+ if (frameDescr.m_testType & GENERATE_MV)
+ {
+ // If GENERATE_MV is specified, generate a vector inside SW; else, leave mvSW a zero vector
+ // Always create mv inside SW; mvp - outside SW
+ mvSW = GenerateMV(frameDescr);
+ }
+
+ std::vector mvpPoolForPU(m_mvpPools[mvpGroupNo->second]);
+
+ while (!mvpPoolForPU.empty())
+ {
+ mfxU32 localMvpIndex = GetRandomGen().GetRandomNumber(0, (mfxI32)mvpPoolForPU.size() - 1);
+
+ PU.m_MVP = mvpPoolForPU[localMvpIndex];
+
+ // Final MV; operator + used here
+ // Important: m_MV inherits refIdx from m_MVP. It is done so because MVP would be written to file if required.
+ // MV is never reported outside.
+ PU.m_MV = PU.m_MVP + mvSW;
+
+ if (frameDescr.IsNewPUValid(PU))
+ {
+ // Get index of the MVP applied to this PU from the original MVP generation pool
+ for (mfxU32 originalMvpIndex = 0; originalMvpIndex < MVP_PER_16x16_BLOCK; ++originalMvpIndex)
+ {
+ if (m_mvpPools[mvpGroupNo->second][originalMvpIndex] == PU.m_MVP)
+ {
+ PU.usedMVPPoolNo = mvpGroupNo->second;
+ PU.usedMVPIndex = originalMvpIndex;
+ }
+ }
+ return true; // MV generation for current PU succeeded
+ }
+ else
+ {
+ mvpPoolForPU.erase(mvpPoolForPU.begin() + localMvpIndex);
+ }
+ }
+ }
+ return false; //MV generation for current PU failed
+}
+
+//Attempts to generate MVs for PUs inside the CU and store the information about the blocks occupied
+//by newly generated PUs in corresponding reference frame descriptors
+bool MVMVPProcessor::GenValidMVForPU(PUBlock & PU, const FrameChangeDescriptor & frameDescr)
+{
+ if (!(frameDescr.m_testType & GENERATE_MV))
+ {
+ return true; //No MVs requested
+ }
+
+ // Inter prediction test
+ // Try 100 times max to generate valid references
+ for (mfxU32 i = 0; i < MAX_GEN_MV_ATTEMPTS; ++i)
+ {
+ // Always create mv inside SW; mvp - outside SW (if predictors are not required, mvp is zero vector)
+ PUMotionVector mvSW = GenerateMV(frameDescr);
+
+ PU.m_MVP = PUMotionVector(
+ mfxU8(GetRandomGen().GetRandomNumber(0, std::max(0, mfxU8(frameDescr.m_refDescrList0.size()) - 1))),
+ mfxU8(GetRandomGen().GetRandomNumber(0, std::max(0, mfxU8(frameDescr.m_refDescrList1.size()) - 1))),
+ mfxI16(0), mfxI16(0), mfxI16(0), mfxI16(0));
+
+ // Final MV; operator + used here
+ // Important: m_MV inherits refIdx from m_MVP. It is done so because MVP would be written to file if required.
+ // MV is never reported outside.
+ PU.m_MV = PU.m_MVP + mvSW;
+
+ // Check whether the generated PU is located inside frame boundaries
+ // Check generated PU for intersection with previous PUs pointing to other frames
+ if (frameDescr.IsNewPUValid(PU))
+ {
+ return true; //MV generation for current PU succeeded
+ }
+ }
+
+ return false; //MV generation for current PU failed
+}
+
+// Generate Motion Vector Predictor, i.e such a vector that all HW_SEARCH_ELEMENT_SIZE-sized square blocks
+// inside the CTU shifted by this vector will be located outside their own search windows (which have same
+// size but are centered each on its own search element block), and the CTU itself is still located
+// inside the frame
+// If the frame size is smaller than the search window size, generate MVP with zero spatial coordinates.
+// Function generates predictors for list 1 only on B frames (not on GPB)
+//
+// const CTUDescriptor & CTU - current CTU which should be located inside the frame with predictor applied as MV
+// const FrameChangeDescriptor & frameChangeDescr - descriptor which contains these fields:
+// mfxU8 numl0_refs / numl1_refs - current limits on number of active references
+// mfxU32 surf_width / surf_height - size of current surface
+PUMotionVector MVMVPProcessor::GenerateMVP(const CTUDescriptor & CTU, const FrameChangeDescriptor & frameChangeDescr)
+{
+ const auto& numl0_refs = frameChangeDescr.m_refDescrList0;
+ const auto& numl1_refs = frameChangeDescr.m_refDescrList1;
+
+ bool hasList1 = !numl1_refs.empty();
+
+ if (hasList1 && !frameChangeDescr.m_bUseBiDirSW)
+ {
+ throw std::string("ERROR: GenerateMVP: attempted to generate MVPs for a B-frame/GPB using unidirectional search window");
+ }
+
+ bool isB = !!(frameChangeDescr.m_frameType & MFX_FRAMETYPE_B);
+
+ const mfxU32* current_lim = frameChangeDescr.m_bUseBiDirSW ? SKL_SW_LIM_BD : SKL_SW_LIM_OD;
+
+ mfxU32 x_lim_SW = current_lim[0] / 2;
+ mfxU32 y_lim_SW = current_lim[1] / 2;
+
+ mfxI32 x_coord[2] = { 0 };
+ mfxI32 y_coord[2] = { 0 };
+
+ // Precomputing min and max possible MVP coordinates so that the MVP points outside SW but inside
+ // the frame (i.e. the CTU with applied MVP should be located outside SW and inside the frame,
+ // if possible)
+ mfxU32 x_min = x_lim_SW + HW_SEARCH_ELEMENT_SIZE / 2; //When determining min absolute shift, one should use
+ //the search element size, not the CTU size. With max
+ //CTU size is still used so that it stays inside the frame
+
+ mfxU32 x_max_pos = frameChangeDescr.GetFrameCropW()
+ - (CTU.m_BWidth + CTU.m_AdrX); //Max absolute value of MVP coord for positive
+ mfxU32 x_max_neg = CTU.m_AdrX; //and negative coordinates respectively.
+
+ mfxU32 y_min = y_lim_SW + HW_SEARCH_ELEMENT_SIZE / 2;
+
+ mfxU32 y_max_pos = frameChangeDescr.GetFrameCropH() - (CTU.m_BWidth + CTU.m_AdrY);
+ mfxU32 y_max_neg = CTU.m_AdrY;
+
+ //Crop the max coords due to hardware limitations
+ x_max_pos = std::min(x_max_pos, ((mfxU32)((MVMVP_SIZE_LIMIT >> 2) - x_lim_SW)));
+ x_max_neg = std::min(x_max_neg, ((mfxU32)((MVMVP_SIZE_LIMIT >> 2) - x_lim_SW)));
+ y_max_pos = std::min(y_max_pos, ((mfxU32)((MVMVP_SIZE_LIMIT >> 2) - y_lim_SW)));
+ y_max_neg = std::min(y_max_neg, ((mfxU32)((MVMVP_SIZE_LIMIT >> 2) - y_lim_SW)));
+
+ enum SHIFT { X_POS, X_NEG, Y_POS, Y_NEG };
+
+ std::vector availShifts;
+ availShifts.reserve(4);
+
+ if (x_min < x_max_pos) availShifts.push_back(X_POS);
+ if (x_min < x_max_neg) availShifts.push_back(X_NEG);
+ if (y_min < y_max_pos) availShifts.push_back(Y_POS);
+ if (y_min < y_max_neg) availShifts.push_back(Y_NEG);
+
+ if (!availShifts.empty())
+ {
+ for (mfxI32 i = 0; i < (isB ? 2 : 1); i++)
+ {
+ SHIFT shift = availShifts[GetRandomGen().GetRandomNumber(0, (mfxI32)(availShifts.size() - 1))];
+ switch (shift)
+ {
+ case X_POS:
+ x_coord[i] = GetRandomMVComponent(x_min, x_max_pos);
+ break;
+ case X_NEG:
+ x_coord[i] = -GetRandomMVComponent(x_min, x_max_neg);
+ break;
+ case Y_POS:
+ y_coord[i] = GetRandomMVComponent(y_min, y_max_pos);
+ break;
+ case Y_NEG:
+ y_coord[i] = -GetRandomMVComponent(y_min, y_max_neg);
+ break;
+ }
+
+ //The complementary MVP coordinate should be subjected to the HW limit as well
+ if (shift == X_POS || shift == X_NEG)
+ {
+ mfxU32 max_pos_shift_y = std::min(frameChangeDescr.GetFrameCropH() - CTU.m_BHeight - CTU.m_AdrY,
+ (mfxU32)MVMVP_SIZE_LIMIT >> 2);
+ mfxU32 max_neg_shift_y = std::min(CTU.m_AdrY, (mfxU32)MVMVP_SIZE_LIMIT >> 2);
+ y_coord[i] = GetRandomMVComponent(-(mfxI32)max_neg_shift_y, max_pos_shift_y);
+ }
+ else
+ {
+ mfxU32 max_pos_shift_x = std::min(frameChangeDescr.GetFrameCropW() - CTU.m_BWidth - CTU.m_AdrX,
+ (mfxU32)MVMVP_SIZE_LIMIT >> 2);
+ mfxU32 max_neg_shift_x = std::min(CTU.m_AdrX, (mfxU32)MVMVP_SIZE_LIMIT >> 2);
+ x_coord[i] = GetRandomMVComponent(-(mfxI32)max_neg_shift_x, max_pos_shift_x);
+ }
+ }
+ }
+
+ return PUMotionVector(
+ (mfxI32)!numl0_refs.empty() ? mfxU8(GetRandomGen().GetRandomNumber(0, (mfxI32)numl0_refs.size() - 1)) : 0,
+ (mfxI32)!numl1_refs.empty() ? mfxU8(GetRandomGen().GetRandomNumber(0, (mfxI32)numl1_refs.size() - 1)) : 0, // RefIdx struct
+ x_coord[0], // MV[0].x
+ y_coord[0], // MV[0].y
+ isB ? x_coord[1] : 0, // MV[1].x
+ isB ? y_coord[1] : 0 // MV[1].y
+ );
+}
+
+// Generates an MV so that a PU_width x PU_height-sized block shifted by this MV
+// will be located inside(sic!) SW. It doesn't generate refIdx. refIdx is generated in GenerateMVP
+// Function generates MVs for list 1 only on B frames (not on GPB)
+//
+// mfxU32 PU_width/PU_height - size of current PU
+PUMotionVector MVMVPProcessor::GenerateMV(const FrameChangeDescriptor & frameChangeDescr)
+{
+ const auto& numl1_refs = frameChangeDescr.m_refDescrList1;
+
+ bool hasList1 = !numl1_refs.empty();
+
+ if (hasList1 && !frameChangeDescr.m_bUseBiDirSW)
+ {
+ throw std::string("ERROR: GenerateMV: attempted to generate MVs for a B-frame/GPB using unidirectional search window");
+ }
+
+ bool isB = !!(frameChangeDescr.m_frameType & MFX_FRAMETYPE_B);
+
+ const mfxU32* current_lim = frameChangeDescr.m_bUseBiDirSW ? SKL_SW_LIM_BD : SKL_SW_LIM_OD;
+
+ // Just half of current SW width / height
+ mfxI32 x_lim = 0, y_lim = 0;
+
+ constexpr mfxU32 searchElementWidth = HW_SEARCH_ELEMENT_SIZE;
+ constexpr mfxU32 searchElementHeight = HW_SEARCH_ELEMENT_SIZE;
+
+ //Leave limits at zero if PU size exceeds the search window
+ if (current_lim[0] >= searchElementWidth && current_lim[1] >= searchElementHeight)
+ {
+ x_lim = (current_lim[0] - searchElementWidth) / 2;
+ y_lim = (current_lim[1] - searchElementHeight) / 2;
+ }
+
+ // Using RVO here
+ return PUMotionVector(
+ 0,
+ 0, // RefIdx struct
+ GetRandomMVComponent(-x_lim, x_lim), // MV[0].x
+ GetRandomMVComponent(-y_lim, y_lim), // MV[0].y
+ isB ? GetRandomMVComponent(-x_lim, x_lim) : 0, // MV[1].x
+ isB ? GetRandomMVComponent(-y_lim, y_lim) : 0 // MV[1].y
+ );
+}
+
+// Randomly generates single MV-component within [lower; upper] accordigly to the sub pixel precision mode
+// Where lower and upper given in full-pixel units.
+// Output component is in quarter-pixel units.
+//
+// { a = lower * 4 }
+// { b = upper * 4 }
+//
+// [a * # * a+1 * # * a+2 ... b-2 * # * b-1 * # * b]
+// For mode 0: only full-pixels a, a+1, ... b-2, b-1, b are allowed
+// For mode 1: full and half-pixels # are allowed
+// For mode 3: every quarter-pixel value is allowed
+mfxI32 MVMVPProcessor::GetRandomMVComponent(mfxI32 lower, mfxI32 upper)
+{
+ ASGRandomGenerator& randomGen = GetRandomGen();
+ switch (m_SubPelMode)
+ {
+ case 0:
+ return 4 * lower + randomGen.GetRandomNumber(0, upper - lower) * 4;
+ case 1:
+ return 4 * lower + randomGen.GetRandomNumber(0, 2 * (upper - lower)) * 2;
+ case 3:
+ return randomGen.GetRandomNumber(4 * lower, 4 * upper);
+ default:
+ throw std::string("ERROR: MVMVPProcessor: GetRandomMVComponent: Incorrect m_SubPelMode used");
+ }
+}
+
+mfxU32 MVMVPProcessor::CalculateOffsetInMVPredictorsBuffer(mfxU32 bufferPitch, const MVPBlock & mvpBlock)
+{
+ // Calculating a no. of 32x32 block corresponding to left upper pixel of the CTU MVP grid
+ // In sum below: first addendum is offset by vertical axis, second addendum is offset by horizontal axis
+ mfxU32 offsetBig = (bufferPitch / 2) * (mvpBlock.m_AdrY / (2 * MVP_BLOCK_SIZE))
+ + (mvpBlock.m_AdrX / (2 * MVP_BLOCK_SIZE));
+
+ // Calculating a postion for 16x16 block inside parent 32x32 block
+ mfxU32 offsetSmall = 2 * ((mvpBlock.m_AdrY % (2 * MVP_BLOCK_SIZE)) / MVP_BLOCK_SIZE)
+ + ((mvpBlock.m_AdrX % (2 * MVP_BLOCK_SIZE)) / MVP_BLOCK_SIZE);
+
+ return 4 * offsetBig + offsetSmall;
+}
+
+void MVMVPProcessor::PutMVPIntoExtBuffer(const MVPBlock& mvpBlock, mfxExtFeiHevcEncMVPredictors* outputMVPBuf)
+{
+ if (!outputMVPBuf)
+ {
+ throw std::string("ERROR: MVMVPProcessor: PutMVPIntoExtBuffer: Output mfxExtFeiHevcEncMVPredictors buffer is null");
+ }
+
+ mfxU32 offset = CalculateOffsetInMVPredictorsBuffer(outputMVPBuf->Pitch, mvpBlock);
+
+ mfxFeiHevcEncMVPredictors& actualPredictor = outputMVPBuf->Data[offset];
+
+ mfxI32 mvpGroupNo = mvpBlock.GetGroupNo();
+
+ // In case of INTRAxINTER test some MVP blocks
+ // may not intersect with PUs inside CTU
+ // Otherwise, all MVP blocks should be assigned with a valid group no.
+ if (mvpGroupNo < 0)
+ {
+ if (m_DoUseIntra)
+ {
+ // For such intra MVP block filling corresponding element in the buffer with ignored values
+ for (mfxU32 mvpIdx = 0; mvpIdx < MVP_PER_16x16_BLOCK; mvpIdx++)
+ {
+ actualPredictor.MV[mvpIdx][0].x = actualPredictor.MV[mvpIdx][0].y = (mfxI16)0x8000;
+ actualPredictor.MV[mvpIdx][1].x = actualPredictor.MV[mvpIdx][1].y = (mfxI16)0x8000;
+
+ actualPredictor.RefIdx[mvpIdx].RefL0 = (mfxU8)0xf;
+ actualPredictor.RefIdx[mvpIdx].RefL1 = (mfxU8)0xf;
+ }
+
+ // Nevertheless, setting BlockSize appropriately
+ actualPredictor.BlockSize = m_GenMVPBlockSize;
+
+ return;
+ }
+
+ // Otherwise, something definitely went wrong
+ throw std::string("ERROR: PutMVPIntoExtBuffer: Some MVP block has invalid MVP pool no.");
+ }
+
+ for (mfxU32 mvpIdx = 0; mvpIdx < MVP_PER_16x16_BLOCK; mvpIdx++)
+ {
+ const auto& genMVPred = m_mvpPools[mvpGroupNo][mvpIdx];
+
+ if (genMVPred.CheckMVPExceedsSizeLimits())
+ {
+ throw std::string("ERROR: PutMVPIntoExtBuffer: generated MVP size exceeds hardware limit");
+ }
+
+ actualPredictor.RefIdx[mvpIdx].RefL0 = genMVPred.RefIdx.RefL0;
+ actualPredictor.RefIdx[mvpIdx].RefL1 = genMVPred.RefIdx.RefL1;
+ actualPredictor.MV[mvpIdx][0] = genMVPred.MV[0];
+ actualPredictor.MV[mvpIdx][1] = genMVPred.MV[1];
+ }
+
+ // Assuming that, m_GenMVPBlockSize has correct value
+ actualPredictor.BlockSize = m_GenMVPBlockSize;
+
+ // Special case for 64x64 blocks - copying initialized data to the neighbour blocks
+ if (m_GenMVPBlockSize == 3)
+ {
+ if (outputMVPBuf->Pitch > 0)
+ {
+ outputMVPBuf->Data[offset + 4] = actualPredictor;
+ outputMVPBuf->Data[offset + outputMVPBuf->Pitch] = actualPredictor;
+ outputMVPBuf->Data[offset + outputMVPBuf->Pitch + 4] = actualPredictor;
+ }
+ else
+ {
+ throw std::string("ERROR: PutMVPIntoExtBuffer: mfxExtFeiHevcEncMVPredictors have zero pitch");
+ }
+ }
+}
+
+void MVMVPProcessor::GetMVPPools(std::vector>& outMVPPools)
+{
+ outMVPPools = m_mvpPools;
+}
+
+#endif // MFX_VERSION
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/random_generator.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/random_generator.cpp
new file mode 100644
index 0000000..c6295ff
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/random_generator.cpp
@@ -0,0 +1,67 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "random_generator.h"
+
+ASGRandomGenerator& ASGRandomGenerator::GetInstance()
+{
+ static ASGRandomGenerator instance;
+
+ return instance;
+}
+
+// Returns random number in range [min, max]
+mfxI32 ASGRandomGenerator::GetRandomNumber(mfxI32 min, mfxI32 max)
+{
+ std::uniform_int_distribution<> distr(min, max);
+ return distr(m_Gen);
+}
+
+// Returns +1 or -1 with probability 0.5
+mfxI32 ASGRandomGenerator::GetRandomSign()
+{
+ return GetRandomBit() ? -1 : 1;
+}
+
+// Generates 0 or 1 with probability 0.5
+bool ASGRandomGenerator::GetRandomBit()
+{
+ std::bernoulli_distribution distr(0.5);
+ return distr(m_Gen);
+}
+
+// Returns TF or BF with probability 0.5
+mfxI32 ASGRandomGenerator::GetRandomPicField()
+{
+ static const mfxI32 cases[] = { MFX_PICSTRUCT_FIELD_TOP, MFX_PICSTRUCT_FIELD_BOTTOM };
+ std::uniform_int_distribution<> distr{ 0, sizeof(cases) / sizeof(cases[0]) - 1 };
+ return cases[distr(m_Gen)];
+}
+
+void ASGRandomGenerator::SeedGenerator(mfxU32 extSeed)
+{
+ m_Gen.seed(extSeed);
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/refcontrol.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/refcontrol.cpp
new file mode 100644
index 0000000..5d30f73
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/refcontrol.cpp
@@ -0,0 +1,227 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "refcontrol.h"
+
+using namespace std;
+
+void RefState::Dump(fstream& ofs) const
+{
+ const char separator = '|';
+
+ ofs << setw(3) << picture.orderCount << ' '
+ << hex << showbase << setw(3 + 2) << picture.frameType << ' '
+ << setw(3 + 2) << picture.picStruct << dec;
+ if (ofs.fail())
+ throw std::string("ERROR: PicStruct buffer writing failed");
+ for (mfxU32 list = 0; list < 2; list++)
+ {
+ ofs << ' ' << separator;
+ for (mfxU32 i = 0; i < 8; i++)
+ ofs << ' ' << setw(3) << (i < RefListActive[list].size() ? RefListActive[list][i] : -1);
+ }
+ ofs << ' ' << separator;
+ for (mfxU32 i = 0; i < 16; i++)
+ ofs << ' ' << setw(3) << (i < DPB.size() ? DPB[i] : -1);
+ ofs << endl;
+}
+
+bool RefState::Load(fstream& ifs)
+{
+ const char separator_char = '|';
+ char separator;
+ RefState state;
+
+ ifs >> state.picture.orderCount >> hex >> state.picture.frameType >> state.picture.picStruct >> dec;
+ if (ifs.fail())
+ return false;
+
+ for (mfxU32 list = 0; list < 2; list++)
+ {
+ ifs >> separator;
+ if (ifs.fail() || separator != separator_char)
+ return false;
+ state.RefListActive[list].clear();
+ for (mfxI32 poc, i = 0; i < 8 && !(ifs >> poc).fail(); i++) {
+ if (poc >= 0)
+ state.RefListActive[list].push_back(poc);
+ }
+ }
+
+ ifs >> separator;
+ if (ifs.fail() || separator != separator_char)
+ return false;
+ state.DPB.clear();
+ for (mfxI32 poc, i = 0; i < 16 && !(ifs >> poc).fail(); i++) {
+ if (poc >= 0)
+ state.DPB.push_back(poc);
+ }
+
+ *this = state;
+ return true;
+}
+
+void RefControl::SetParams(const InputParams& params)
+{
+ m_params = params;
+ maxDelay = params.m_RefDist * 2 + 1; // 2 for fields, 1 from asyncDepth
+ maxDPBSize = params.m_NumRef + 1; // +1 to align with common msdk rules, that current frame is not counted in DPB
+}
+
+void RefControl::Encode(mfxI32 codingOrder)
+{
+ if (RPB.empty())
+ throw std::string("ERROR: PicStruct buffer frame is lost");
+
+ // select next frame to encode (no reordering for I and P)
+ mfxI32 RPBidx = 0;
+ if (RPB[0].frameType & MFX_FRAMETYPE_B)
+ {
+ mfxI32 cnt, i;
+ for (cnt = 1; cnt < static_cast(RPB.size()) &&
+ (RPB[cnt].frameType & MFX_FRAMETYPE_B) &&
+ RPB[0].orderCount + cnt == RPB[cnt].orderCount;
+ cnt++); // consequent B count
+ if (cnt < static_cast(RPB.size()) && RPB[0].orderCount + cnt == RPB[cnt].orderCount)
+ RPBidx = cnt; // consequent not B is pyramid's right base
+ else
+ {
+ for (i = 1; i < cnt; i++)
+ if ((RPB[i].frameType & MFX_FRAMETYPE_REF) && std::abs(i - cnt / 2) < std::abs(RPBidx - cnt / 2))
+ RPBidx = i; // Bref closest to center of consequent B
+ }
+ }
+
+ RefState state; // create state
+ PictureInfo& picture = state.picture;
+
+ picture = RPB[RPBidx]; // take from reordered
+ RPB.erase(RPB.begin() + RPBidx); // and remove
+ picture.codingOrder = codingOrder;
+
+ if (picture.frameType & MFX_FRAMETYPE_IDR)
+ DPB.clear();
+ // current frame occupies DPB by spec, free one place
+ if (DPB.size() == maxDPBSize)
+ DPB.erase(std::min_element(DPB.begin(), DPB.end(), IsOlder));
+
+ // fill list randomly from DPB
+ mfxU32 RefListNum[2] = { 0, 0 };
+ if (!DPB.empty())
+ {
+ if (picture.frameType & MFX_FRAMETYPE_P)
+ RefListNum[0] = m_params.m_NumRefActiveP;
+ else if (picture.frameType & MFX_FRAMETYPE_B)
+ {
+ RefListNum[0] = m_params.m_NumRefActiveBL0;
+ RefListNum[1] = m_params.m_NumRefActiveBL1;
+ }
+ if (picture.frameType & MFX_FRAMETYPE_P && m_params.m_UseGPB)
+ {
+ picture.frameType &= ~MFX_FRAMETYPE_P;
+ picture.frameType |= MFX_FRAMETYPE_B;
+ RefListNum[1] = std::min(m_params.m_NumRefActiveP, m_params.m_NumRefActiveBL1);
+ }
+ }
+
+ for (mfxU32 list = 0; list < 2; list++)
+ {
+ state.RefListActive[list].clear();
+ for (mfxU32 pic = 0; pic < RefListNum[list]; pic++)
+ {
+ state.RefListActive[list].push_back(DPB[GetRandomGen().GetRandomNumber(0, (mfxI32)DPB.size() - 1)].orderCount);
+ }
+ }
+
+ state.DPB.clear();
+ for (auto pic : DPB)
+ state.DPB.push_back(pic.orderCount);
+ std::sort(state.DPB.begin(), state.DPB.end()); // to simplify matching
+
+ // store state and put reference picture into DPB
+ RefLogInfo.emplace_back(state);
+ if (picture.frameType & MFX_FRAMETYPE_REF)
+ DPB.emplace_back(picture);
+}
+
+// assign types in display order
+// don't care about fields - must work
+void RefControl::Add(mfxI32 frameOrder)
+{
+ PictureInfo picture;
+ picture.codingOrder = -1; // randomly decided later
+ picture.orderCount = frameOrder;
+ picture.picStruct = GetRandomGen().GetRandomPicField();
+
+ mfxU16 type = 0;
+ mfxI32 poc = frameOrder - m_lastIDR;
+ mfxI32 nextIDRpoc = m_params.m_nIdrInterval*m_params.m_GopSize;
+ mfxI32 pocEnd = std::min(nextIDRpoc, static_cast(m_params.m_numFrames) - m_lastIDR); // last before IDR or last picture
+
+ if (poc == 0 || poc == nextIDRpoc)
+ {
+ type = MFX_FRAMETYPE_IDR | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_I;
+ m_lastIDR = frameOrder;
+ }
+ else if (poc % m_params.m_GopSize == 0)
+ type = MFX_FRAMETYPE_REF | MFX_FRAMETYPE_I;
+ else if (poc % m_params.m_GopSize % m_params.m_RefDist == 0 || poc + 1 == pocEnd) // also last before IDR or last picture
+ type = MFX_FRAMETYPE_REF | MFX_FRAMETYPE_P;
+ else
+ {
+ type = MFX_FRAMETYPE_B;
+ if (m_params.m_BRefType != MFX_B_REF_OFF)
+ {
+ mfxI32 bord = poc % m_params.m_GopSize % m_params.m_RefDist; // pos in consequent B [1; dist-1]
+ mfxI32 s = (pocEnd - (poc - bord) > m_params.m_RefDist) ? m_params.m_RefDist : pocEnd - (poc - bord) - 1; // real num B
+ for (; bord > 1 && s > 2; ) // 1: next to refpoint, 2: max span w/o ref
+ {
+ mfxI32 nexts = (s + 1) / 2; // middle (ref) point; left span is bigger for odds
+ if (bord == nexts) // if in the middle - mark as ref
+ {
+ type |= MFX_FRAMETYPE_REF;
+ break;
+ }
+ else if (bord > nexts) // shift to right span
+ {
+ bord -= nexts;
+ s -= nexts;
+ }
+ else {
+ s = nexts;
+ }
+ }
+ }
+ }
+
+ picture.frameType = type;
+
+ RPB.emplace_back(picture);
+}
+
+bool IsOlder(const PictureInfo& a, const PictureInfo& b) { return a.orderCount < b.orderCount; }
+
+bool IsInCodingOrder(const RefState& a, const RefState& b) { return a.picture.codingOrder < b.picture.codingOrder; }
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/test_processor.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/test_processor.cpp
new file mode 100644
index 0000000..ea25460
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/test_processor.cpp
@@ -0,0 +1,505 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include
+#include
+
+#include "frame_marker.h"
+#include "test_processor.h"
+
+ASGLog TestProcessor::asgLog;
+
+//Base
+// Entry point for all test which uses TestProcessor
+void TestProcessor::RunTest(const InputParams & params)
+{
+ try {
+ Init(params);
+
+ switch(params.m_TestType)
+ {
+ case GENERATE_PICSTRUCT:
+ RunPSTest(params);
+ return;
+ case GENERATE_REPACK_CTRL:
+ if (params.m_ProcMode == GENERATE)
+ RunRepackGenerate();
+ else //VERIFY
+ RunRepackVerify();
+ return;
+ default:
+ break;
+ }
+
+ //Check that processing parameters have correct number of elements
+ if (m_vProcessingParams.size() != m_InputParams.m_numFrames)
+ throw std::string("ERROR: Incorrect elements number in the m_vProcessingParams");
+
+ // Sort processing params into the encoded order
+ std::sort(m_vProcessingParams.begin(), m_vProcessingParams.end(),
+ [](const FrameProcessingParam& left, const FrameProcessingParam& right) { return left.EncodedOrder < right.EncodedOrder; });
+
+ auto itProcessingParam = m_vProcessingParams.begin();
+
+ // Iterate through frames
+ for (mfxU32 i = 0; i < m_InputParams.m_numFrames; ++i)
+ {
+ // Load picture and obtain a surface
+ ExtendedSurface* frame = PrepareSurface();
+
+ // Set display order for the surface
+ frame->Data.FrameOrder = i;
+
+ // Find surface with the next encoded order in the surface pool
+ auto itSurf = std::find_if(m_Surfaces.begin(), m_Surfaces.end(),
+ [&itProcessingParam](const ExtendedSurface& ext_surf) { return ext_surf.Data.FrameOrder == itProcessingParam->DisplayOrder; });
+
+ // Do next iteration if surface pool hasn't got the required surface
+ if (itSurf == m_Surfaces.end())
+ continue;
+
+ // Set encoded order for the surface
+ itSurf->encodedOrder = itProcessingParam->EncodedOrder;
+
+ // Generate all data
+ ChangePicture(*itSurf);
+
+ // Write next available frames in the display order
+ DropFrames();
+
+ if (m_InputParams.m_bIsForceExtMVPBlockSize)
+ {
+ itSurf->ForceMVPBlockSizeInOutputBuffer(m_InputParams.m_ForcedExtMVPBlockSize);
+ }
+ // Drop buffers in the encoded order
+ DropBuffers(*itSurf);
+
+ // Go to the next frame in the encoded order
+ ++itProcessingParam;
+ }
+
+ // Drain buffered frames
+ while (itProcessingParam != m_vProcessingParams.end())
+ {
+ // Find surface with the next encoded order in the surface pool
+ auto itSurf = std::find_if(m_Surfaces.begin(), m_Surfaces.end(),
+ [&itProcessingParam](const ExtendedSurface& ext_surf) { return ext_surf.Data.FrameOrder == itProcessingParam->DisplayOrder; });
+
+ // All surfaces must be into the surface pool
+ if(itSurf == m_Surfaces.end())
+ throw std::string("ERROR: Surface pool doesn't have required surface");
+
+ // Set encoded order for the surface
+ itSurf->encodedOrder = itProcessingParam->EncodedOrder;
+
+ // Generate all data
+ ChangePicture(*itSurf);
+
+ // Write next available frames in the display order
+ DropFrames();
+
+ if (m_InputParams.m_bIsForceExtMVPBlockSize)
+ {
+ itSurf->ForceMVPBlockSizeInOutputBuffer(m_InputParams.m_ForcedExtMVPBlockSize);
+ }
+ // Drop buffers in the encoded order
+ DropBuffers(*itSurf);
+
+ // Go to the next frame in the encoded order
+ ++itProcessingParam;
+ }
+ }
+ catch (std::string & e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: TestProcessor::RunTest");
+ }
+ return;
+}
+
+struct sMultiPak
+{
+ mfxU32 NumBytesInNalUnit;
+ mfxU8 SliceQP;
+};
+
+void TestProcessor::RunRepackGenerate()
+{
+ mfxU32 maxNumBytesInNalUnit = 67104768; //14 bits value with the max unit 4K: 0x3FFF*4*1024
+ mfxU32 MaxFrameSize;
+
+ sMultiPak multiPakInBin;
+
+ mfxU32 partFrame = 0;
+ ASGRandomGenerator& randomGen = GetRandomGen();
+
+ randomGen.SeedGenerator((mfxU32)time(nullptr));
+
+ for (mfxU32 countFrame = 0; countFrame < m_InputParams.m_numFrames; countFrame++)
+ {
+ partFrame = randomGen.GetRandomNumber(0, 9);
+
+ fpRepackStr.read((mfxI8 *)&multiPakInBin, sizeof(multiPakInBin));
+ if (!fpRepackStr.good())
+ throw std::string("ERROR: multiPakStr file read failed");
+
+ if (multiPakInBin.NumBytesInNalUnit > maxNumBytesInNalUnit)
+ throw std::string("ERROR: NumBytesInNalUnit more than HW limitation");
+
+ MaxFrameSize = multiPakInBin.NumBytesInNalUnit
+ - (multiPakInBin.NumBytesInNalUnit*partFrame)/10;
+ MaxFrameSize += 512; //Add a 512B window for headers.
+
+ //If max frame size exceeds 14 bits, the unit is 4KB, otherwise 32B.
+ if (MaxFrameSize >= (0x1 << 14) * 32)
+ MaxFrameSize = (MaxFrameSize + 0xFFF) & ~0xFFF; //Rounding to 4KB.
+ else
+ MaxFrameSize = (MaxFrameSize + 0x1F) & ~0x1F;//Rounding to 32B.
+
+ fpRepackCtrl.write((mfxI8 *)&MaxFrameSize, sizeof(MaxFrameSize));
+ if (!fpRepackCtrl.good())
+ throw std::string("ERROR: Repack ctrl file write failed");
+
+ fpRepackCtrl.write((mfxI8 *)&m_InputParams.m_NumAddPasses, sizeof(m_InputParams.m_NumAddPasses));
+ if (!fpRepackCtrl.good())
+ throw std::string("ERROR: Repack ctrl file write failed");
+
+ fpRepackCtrl.write((mfxI8 *)m_InputParams.m_DeltaQP, sizeof(m_InputParams.m_DeltaQP));
+ if (!fpRepackCtrl.good())
+ throw std::string("ERROR: Repack ctrl file write failed");
+ }
+}
+
+void TestProcessor::RunRepackVerify()
+{
+ sMultiPak multiPakInBin;
+ mfxExtFeiHevcRepackCtrl repackCtrl;
+ mfxI8 repackStat[64];
+ mfxU32 activeNumPasses;
+ mfxU32 activeNumPassesMinus1;
+
+ for (mfxU32 countFrame = 0; countFrame < m_InputParams.m_numFrames; countFrame++)
+ {
+ // Read repack data from files
+ activeNumPasses = -1;
+
+ fpRepackCtrl.read((mfxI8 *)&repackCtrl.MaxFrameSize, sizeof(repackCtrl.MaxFrameSize));
+ if (!fpRepackCtrl.good())
+ throw std::string("ERROR: Repack ctrl file read failed");
+
+ fpRepackCtrl.read((mfxI8 *)&repackCtrl.NumPasses, sizeof(repackCtrl.NumPasses));
+ if (!fpRepackCtrl.good())
+ throw std::string("ERROR: Repack ctrl file read failed");
+
+ fpRepackCtrl.read((mfxI8 *)&repackCtrl.DeltaQP, sizeof(repackCtrl.DeltaQP));
+ if (!fpRepackCtrl.good())
+ throw std::string("ERROR: Repack ctrl file read failed");
+
+ fpRepackStr.read((mfxI8 *)&multiPakInBin, sizeof(multiPakInBin));
+ if (!fpRepackStr.good())
+ throw std::string("ERROR: Repack str file read failed");
+
+ fpRepackStat.getline(repackStat, sizeof(repackStat));
+ if (!fpRepackStat.good())
+ throw std::string("ERROR: Repack stat file read failed");
+ std::istringstream repackStatStream(std::string(repackStat, strlen(repackStat)));
+ repackStatStream >> activeNumPasses;
+
+ // Check read repack data
+
+ if (0xFF == multiPakInBin.SliceQP)
+ {
+ // 0xFF indicates skipping
+ std::cout << "INFO: Frame " << countFrame << " in coded order skipped" << std::endl;
+ continue;
+ }
+
+ if (repackCtrl.MaxFrameSize == 0)
+ throw std::string("ERROR: Incorrect MaxFrameSize value in repack ctrl");
+
+ if ((repackCtrl.NumPasses < 1) || (repackCtrl.NumPasses > HEVC_MAX_NUMPASSES))
+ throw std::string("ERROR: Incorrect NumPasses value in repack ctrl");
+
+ if ((activeNumPasses > 0) && (activeNumPasses <= (repackCtrl.NumPasses + 1)))
+ activeNumPassesMinus1 = activeNumPasses - 1;
+ else
+ throw std::string("ERROR: Incorrect output NumPasses value in repack stat");
+
+ if ((multiPakInBin.SliceQP < m_InputParams.m_InitialQP)
+ || (multiPakInBin.SliceQP > HEVC_MAX_QP))
+ throw std::string("ERROR: Incorrect parsed QP value in repack str");
+
+ // Verify repack control result
+ std::vector validQP(repackCtrl.NumPasses + 1);
+
+ validQP[0] = m_InputParams.m_InitialQP;
+ for (mfxU32 idxPass = 0; idxPass < repackCtrl.NumPasses; ++idxPass)
+ validQP[idxPass+1] = std::min((validQP[idxPass] + repackCtrl.DeltaQP[idxPass]), HEVC_MAX_QP);
+
+ mfxU8 sliceQPParser = multiPakInBin.SliceQP;
+
+ auto it = std::find_if(validQP.begin(), validQP.end(),
+ [sliceQPParser](const mfxU8 curQP) { return curQP == sliceQPParser; });
+
+ if (it == validQP.end() || (distance(validQP.begin(), it) != activeNumPassesMinus1))
+ {
+ std::cout << "ERROR: parsed " << (mfxU32)multiPakInBin.SliceQP
+ << ", expected " << (mfxU32)*it << " for Frame "
+ << countFrame << " in coded order" << std::endl;
+ throw std::string("ERROR: QP mismatched");
+ }
+
+ if ((multiPakInBin.NumBytesInNalUnit > repackCtrl.MaxFrameSize)
+ && (multiPakInBin.SliceQP < validQP[repackCtrl.NumPasses]/*The max */))
+ {
+ std::cout << "ERROR: NumBytesInNalUnit " << multiPakInBin.NumBytesInNalUnit
+ << " MaxFrameSize " << repackCtrl.MaxFrameSize << " for Frame "
+ << countFrame << " in coded order" << std::endl;
+ throw std::string("ERROR: Max exceeded");
+ }
+ }
+}
+
+void TestProcessor::RunPSTest(const InputParams & params)
+{
+ m_RefControl.SetParams(params);
+
+ // Iterate through frames, store with random PS
+ for (mfxU32 i = 0; i < m_InputParams.m_numFrames; ++i)
+ {
+ m_RefControl.Add(i);
+ }
+
+ // Iterate through frames, encode in random order
+ for (mfxU32 i = 0; i < m_InputParams.m_numFrames; ++i)
+ {
+ m_RefControl.Encode(i);
+ }
+
+ // Dump or Load + Compare
+ SavePSData();
+}
+
+void TestProcessor::Init(const InputParams ¶ms)
+{
+ try
+ {
+ // TODO: try to use move constructor for such initialization (InputParams &&)
+ m_InputParams = params;
+
+ asgLog.Init(params);
+
+ if (params.m_TestType == GENERATE_PICSTRUCT)
+ {
+ fpPicStruct.open(params.m_PicStructFileName.c_str(), (params.m_ProcMode == VERIFY) ? std::fstream::in : std::fstream::out);
+ if (!fpPicStruct.is_open())
+ throw std::string("ERROR: PicStruct buffer open failed");
+ }
+ else if (params.m_TestType == GENERATE_REPACK_CTRL)
+ {
+ if (params.m_ProcMode == GENERATE)
+ {
+ fpRepackStr.open(params.m_RepackStrFileName.c_str(), std::fstream::in | std::fstream::binary);
+ if(!fpRepackStr.is_open())
+ throw std::string("ERROR: multiPakStr file open failed");
+
+ fpRepackCtrl.open(params.m_RepackCtrlFileName.c_str(), std::fstream::out | std::fstream::binary);
+ if (!fpRepackCtrl.is_open())
+ throw std::string("ERROR: Repack ctrl file open failed");
+ }
+ else //VERIFY
+ {
+ fpRepackStr.open(params.m_RepackStrFileName.c_str(), std::fstream::in | std::fstream::binary);
+ if(!fpRepackStr.is_open())
+ throw std::string("ERROR: multiPakStr file open failed");
+
+ fpRepackCtrl.open(params.m_RepackCtrlFileName.c_str(), std::fstream::in | std::fstream::binary);
+ if (!fpRepackCtrl.is_open())
+ throw std::string("ERROR: Repack ctrl file open failed");
+
+ fpRepackStat.open(params.m_RepackStatFileName.c_str(), std::fstream::in);
+ if (!fpRepackStat.is_open())
+ throw std::string("ERROR: Repack stat file open failed");
+ }
+ }
+ else
+ {
+ // Processing parameters creation
+ // TODO work directly to m_vProcessingParams
+ FrameMarker frameMarker;
+ frameMarker.PreProcessStreamConfig(m_InputParams);
+ m_vProcessingParams = m_InputParams.m_vProcessingParams;
+
+ m_FrameProcessor.Init(params);
+
+ Init(); // calls derived classes initialization
+ }
+ }
+ catch (std::string& e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: Couldn't initialize TestProcessor");
+ }
+}
+
+void TestProcessor::ChangePicture(ExtendedSurface & frame)
+{
+ try {
+ FrameChangeDescriptor descr;
+ PrepareDescriptor(descr, frame.encodedOrder);
+ descr.m_frame = &frame;
+
+ m_FrameProcessor.ProcessFrame(descr);
+
+ // Verification mode
+ VerifyDesc(descr);
+
+ switch (descr.m_changeType)
+ {
+ case GEN:
+ // Current GEN frame will be used as reference for MOD frame
+ m_ProcessedFramesDescr.push_back(std::move(descr));
+ break;
+
+ case SKIP:
+ break;
+
+ case MOD:
+ // After processing of MOD frame all previously saved GEN frames could be released
+ m_ProcessedFramesDescr.clear();
+ break;
+ default:
+ break;
+ }
+
+ }
+ catch (std::string & e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: TestProcessor::ChangePicture");
+ }
+ return;
+}
+
+ExtendedSurface* TestProcessor::GetFreeSurf()
+{
+ // Find unlocked frame in pool
+ auto it = std::find_if(m_Surfaces.begin(), m_Surfaces.end(),
+ [](const ExtendedSurface& ext_surf) { return (ext_surf.Data.Locked == 0 && ext_surf.isWritten); });
+
+ if (it == m_Surfaces.end())
+ {
+ // Create new surface if not found
+
+ m_Surfaces.emplace_back(ExtendedSurface());
+
+ // Allocate data for pixels
+ m_Surfaces.back().AllocData(m_InputParams.m_width, m_InputParams.m_height);
+
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ /* Data granularity is always in 16x16 blocks. However, width/height alignment
+ should be 32 because of HW requirements */
+ mfxU32 alignedWidth = 0;
+ mfxU32 alignedHeight = 0;
+
+ if (m_InputParams.m_CTUStr.CTUSize == 16 || m_InputParams.m_CTUStr.CTUSize == 32)
+ {
+ alignedWidth = MSDK_ALIGN32(m_InputParams.m_width);
+ alignedHeight = MSDK_ALIGN32(m_InputParams.m_height);
+ }
+ else if (m_InputParams.m_CTUStr.CTUSize == 64)
+ {
+ //For future 64x64 CTU applications
+ alignedWidth = MSDK_ALIGN(m_InputParams.m_width, 64);
+ alignedHeight = MSDK_ALIGN(m_InputParams.m_height, 64);
+ }
+
+ ExtendedBuffer buff(MFX_EXTBUFF_HEVCFEI_ENC_MV_PRED, alignedWidth / MVP_BLOCK_SIZE, alignedHeight / MVP_BLOCK_SIZE);
+ // Attach buffer to new frame if required
+ m_Surfaces.back().AttachBuffer(buff);
+ }
+
+ return &m_Surfaces.back();
+ }
+ else
+ {
+ //Reset the isWritten flag upon surface reuse
+ it->encodedOrder = 0xffffffff;
+ it->isWritten = false;
+ return &(*it);
+ }
+}
+
+void TestProcessor::PrepareDescriptor(FrameChangeDescriptor & descr, const mfxU32 frameNum)
+{
+ descr.m_testType = m_InputParams.m_TestType;
+ descr.m_procMode = m_InputParams.m_ProcMode;
+ descr.m_changeType = m_vProcessingParams[frameNum].Mark;
+ descr.m_frameNumber = m_vProcessingParams[frameNum].DisplayOrder;
+ descr.m_frameType = m_vProcessingParams[frameNum].Type;
+ descr.m_refDescrList0 = GetReferences(m_ProcessedFramesDescr, m_vProcessingParams[frameNum].ReferencesL0);
+ descr.m_refDescrList1 = GetReferences(m_ProcessedFramesDescr, m_vProcessingParams[frameNum].ReferencesL1);
+
+ // TODO: add support for full reference lists
+ // m_refDescrList0 contains active reference frames with lower display order in descending order
+ descr.m_refDescrList0.sort([](FrameChangeDescriptor const & lhs, FrameChangeDescriptor const & rhs) { return lhs.m_frameNumber > rhs.m_frameNumber; });
+
+ // m_refDescrList1 contains active reference frames with higher display order in ascending order
+ descr.m_refDescrList1.sort([](FrameChangeDescriptor const & lhs, FrameChangeDescriptor const & rhs) { return lhs.m_frameNumber < rhs.m_frameNumber; });
+
+ //TODO: disable for I frames?
+
+ descr.m_bUseBiDirSW = (m_vProcessingParams[frameNum].Type & MFX_FRAMETYPE_B) ||
+ ((m_vProcessingParams[frameNum].Type & MFX_FRAMETYPE_P) && m_InputParams.m_UseGPB);
+
+ return;
+}
+
+// Select references from list
+// Most recently processed frames are at the end of the return list
+std::list TestProcessor::GetReferences(const std::list & RecentProcessed, const std::vector& ref_idx)
+{
+ std::list refs_for_frame;
+
+ for (auto & frm_descr : RecentProcessed)
+ {
+ if (std::find(ref_idx.begin(), ref_idx.end(), frm_descr.m_frameNumber) != ref_idx.end())
+ refs_for_frame.emplace_back(frm_descr);
+ }
+
+ return refs_for_frame;
+}
+
+std::list TestProcessor::GetSkips(const std::list & RecentProcessed)
+{
+ std::list skips;
+
+ for (auto & frm_descr : RecentProcessed)
+ {
+ if (frm_descr.m_changeType == SKIP)
+ skips.emplace_back(frm_descr);
+ }
+
+ return skips;
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/util_defs.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/util_defs.cpp
new file mode 100644
index 0000000..e12b238
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/util_defs.cpp
@@ -0,0 +1,116 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "util_defs.h"
+
+std::string ConvertMfxStatusToString(mfxStatus sts)
+{
+ switch (sts)
+ {
+
+ case MFX_ERR_NONE: /* no error */
+ return std::string("MFX_ERR_NONE");
+
+ /* error codes <0 */
+ case MFX_ERR_NULL_PTR: /* null pointer */
+ return std::string("MFX_ERR_NULL_PTR");
+ case MFX_ERR_UNSUPPORTED: /* undeveloped feature */
+ return std::string("MFX_ERR_UNSUPPORTED");
+ case MFX_ERR_MEMORY_ALLOC: /* failed to allocate memory */
+ return std::string("MFX_ERR_MEMORY_ALLOC");
+ case MFX_ERR_NOT_ENOUGH_BUFFER: /* insufficient buffer at input/output */
+ return std::string("MFX_ERR_NOT_ENOUGH_BUFFER");
+ case MFX_ERR_INVALID_HANDLE: /* invalid handle */
+ return std::string("MFX_ERR_INVALID_HANDLE");
+ case MFX_ERR_LOCK_MEMORY: /* failed to lock the memory block */
+ return std::string("MFX_ERR_LOCK_MEMORY");
+ case MFX_ERR_NOT_INITIALIZED: /* member function called before initialization */
+ return std::string("MFX_ERR_NOT_INITIALIZED");
+ case MFX_ERR_NOT_FOUND: /* the specified object is not found */
+ return std::string("MFX_ERR_NOT_FOUND");
+ case MFX_ERR_MORE_DATA: /* expect more data at input */
+ return std::string("MFX_ERR_MORE_DATA");
+ case MFX_ERR_MORE_SURFACE: /* expect more surface at output */
+ return std::string("MFX_ERR_MORE_SURFACE");
+ case MFX_ERR_ABORTED: /* operation aborted */
+ return std::string("MFX_ERR_ABORTED");
+ case MFX_ERR_DEVICE_LOST: /* lose the HW acceleration device */
+ return std::string("MFX_ERR_DEVICE_LOST");
+ case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM: /* incompatible video parameters */
+ return std::string("MFX_ERR_INCOMPATIBLE_VIDEO_PARAM");
+ case MFX_ERR_INVALID_VIDEO_PARAM: /* invalid video parameters */
+ return std::string("MFX_ERR_INVALID_VIDEO_PARAM");
+ case MFX_ERR_UNDEFINED_BEHAVIOR: /* undefined behavior */
+ return std::string("MFX_ERR_UNDEFINED_BEHAVIOR");
+ case MFX_ERR_DEVICE_FAILED: /* device operation failure */
+ return std::string("MFX_ERR_DEVICE_FAILED");
+ case MFX_ERR_MORE_BITSTREAM: /* expect more bitstream buffers at output */
+ return std::string("MFX_ERR_MORE_BITSTREAM");
+ case MFX_ERR_INCOMPATIBLE_AUDIO_PARAM: /* incompatible audio parameters */
+ return std::string("MFX_ERR_INCOMPATIBLE_AUDIO_PARAM");
+ case MFX_ERR_INVALID_AUDIO_PARAM: /* invalid audio parameters */
+ return std::string("MFX_ERR_INVALID_AUDIO_PARAM");
+ case MFX_ERR_GPU_HANG: /* device operation failure caused by GPU hang */
+ return std::string("MFX_ERR_GPU_HANG");
+ case MFX_ERR_REALLOC_SURFACE: /* bigger output surface required */
+ return std::string("MFX_ERR_REALLOC_SURFACE");
+
+ /* warnings >0 */
+ case MFX_WRN_IN_EXECUTION: /* the previous asynchronous operation is in execution */
+ return std::string("MFX_WRN_IN_EXECUTION");
+ case MFX_WRN_DEVICE_BUSY: /* the HW acceleration device is busy */
+ return std::string("MFX_WRN_DEVICE_BUSY");
+ case MFX_WRN_VIDEO_PARAM_CHANGED: /* the video parameters are changed during decoding */
+ return std::string("MFX_WRN_VIDEO_PARAM_CHANGED");
+ case MFX_WRN_PARTIAL_ACCELERATION: /* SW is used */
+ return std::string("MFX_WRN_PARTIAL_ACCELERATION");
+ case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM: /* incompatible video parameters */
+ return std::string("MFX_WRN_INCOMPATIBLE_VIDEO_PARAM");
+ case MFX_WRN_VALUE_NOT_CHANGED: /* the value is saturated based on its valid range */
+ return std::string("MFX_WRN_VALUE_NOT_CHANGED");
+ case MFX_WRN_OUT_OF_RANGE: /* the value is out of valid range */
+ return std::string("MFX_WRN_OUT_OF_RANGE");
+ case MFX_WRN_FILTER_SKIPPED: /* one of requested filters has been skipped */
+ return std::string("MFX_WRN_FILTER_SKIPPED");
+ case MFX_WRN_INCOMPATIBLE_AUDIO_PARAM: /* incompatible audio parameters */
+ return std::string("MFX_WRN_INCOMPATIBLE_AUDIO_PARAM");
+
+ /* threading statuses */
+ //case MFX_TASK_DONE: == ERR_NONE /* task has been completed */
+ case MFX_TASK_WORKING: /* there is some more work to do */
+ return std::string("MFX_TASK_WORKING");
+ case MFX_TASK_BUSY: /* task is waiting for resources */
+ return std::string("MFX_TASK_BUSY");
+
+ /* plug-in statuses */
+ case MFX_ERR_MORE_DATA_SUBMIT_TASK: /* return MFX_ERR_MORE_DATA but submit internal asynchronous task */
+ return std::string("MFX_ERR_MORE_DATA_SUBMIT_TASK");
+
+ case MFX_ERR_UNKNOWN: /* unknown error. */
+ default:
+ return std::string("MFX_ERR_UNKNOWN");
+ }
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/verifier.cpp b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/verifier.cpp
new file mode 100644
index 0000000..604c1f3
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/asg-hevc/src/verifier.cpp
@@ -0,0 +1,1055 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#include "mfxvideo.h"
+
+#if MFX_VERSION >= MFX_VERSION_NEXT
+
+#include "verifier.h"
+
+// Processor for verification mode
+void Verifier::Init()
+{
+ try
+ { // Add buffers to bufferReader
+ if (m_InputParams.m_TestType & (GENERATE_INTER | GENERATE_INTRA))
+ {
+ m_BufferReader.AddBuffer(MFX_EXTBUFF_HEVCFEI_PAK_CTU_REC, m_InputParams.m_PakCtuBufferFileName);
+ m_BufferReader.AddBuffer(MFX_EXTBUFF_HEVCFEI_PAK_CU_REC, m_InputParams.m_PakCuBufferFileName);
+ }
+ }
+ catch (std::string& e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: Couldn't initialize Verifier");
+ }
+}
+
+// Get surface
+ExtendedSurface* Verifier::PrepareSurface()
+{
+ ExtendedSurface* surf = GetFreeSurf();
+ if (!surf)
+ {
+ throw std::string("ERROR: Verifier::PrepareSurface: Undefined reference to surface");
+ }
+ ++surf->Data.Locked;
+ return surf;
+}
+
+// Save all data
+void Verifier::DropFrames()
+{
+ // Sort data by frame order and drop in DisplayOrder
+
+ // TODO / FIXME: Add EncodedOrder processing, it might be required for HEVC FEI PAK
+ m_Surfaces.sort([](ExtendedSurface& left, ExtendedSurface& right) { return left.Data.FrameOrder < right.Data.FrameOrder; });
+
+ for (ExtendedSurface& surf : m_Surfaces)
+ {
+ // If Locked surface met - stop dumping
+ if (surf.Data.Locked) break;
+
+ // If the surface has already been output, move on to the next one in frame order
+ if (surf.isWritten) continue;
+
+ surf.isWritten = true;
+ }
+}
+
+void Verifier::SavePSData()
+{
+ if (fpPicStruct.is_open())
+ {
+ // sort by coding order
+ std::sort(m_RefControl.RefLogInfo.begin(), m_RefControl.RefLogInfo.end(), IsInCodingOrder);
+
+ //vector RefLogInfo;
+
+ while (!fpPicStruct.eof()) {
+ RefState stateLd;
+ if (!stateLd.Load(fpPicStruct))
+ break;
+ stateLd.picture.codingOrder = m_Counters.m_totalPics; // i.e. line number
+ auto istate = m_RefControl.RefLogInfo.cbegin() + m_Counters.m_totalPics;
+ m_Counters.m_totalPics++;
+ m_Counters.m_correctRecords += (stateLd == *istate);
+
+ //RefLogInfo.emplace_back(stateLd);
+ }
+ }
+}
+
+void Verifier::VerifyDesc(FrameChangeDescriptor & frameDescr)
+{
+ try
+ {
+ if (m_InputParams.m_TestType & (GENERATE_INTER | GENERATE_INTRA))
+ {
+ // Width/Height alignment should set as CTU size, because now we are working with bs_parser output data w/o HW requirements
+ mfxU32 alignedWidth = MSDK_ALIGN(m_InputParams.m_width, m_InputParams.m_CTUStr.CTUSize);
+ mfxU32 alignedHeight = MSDK_ALIGN(m_InputParams.m_height, m_InputParams.m_CTUStr.CTUSize);
+
+ mfxU32 heightInCTU = alignedHeight / m_InputParams.m_CTUStr.CTUSize;
+ mfxU32 widthInCTU = alignedWidth / m_InputParams.m_CTUStr.CTUSize;
+
+ // For FEI compatibility
+ mfxU32 maxNumCuInCtu = m_InputParams.m_CTUStr.GetMaxNumCuInCtu();
+
+ // Buffers creations
+ ExtendedBuffer tmpCtuBuff(MFX_EXTBUFF_HEVCFEI_PAK_CTU_REC, widthInCTU, heightInCTU);
+
+ // This one has to be (maxNumCuInCtu) times larger than the CTU record buffer. For the time
+ // being, implemented this via pitch adjustment
+ ExtendedBuffer tmpCuBuff(MFX_EXTBUFF_HEVCFEI_PAK_CU_REC, widthInCTU*maxNumCuInCtu, heightInCTU);
+
+ // Reading statistics from data storage
+ m_BufferReader.ReadBuffer(&tmpCtuBuff.m_pakCtuRecord.Header);
+ m_BufferReader.ReadBuffer(&tmpCuBuff.m_pakCuRecord.Header);
+ // Structure will be in encoded order
+ if (frameDescr.m_changeType == MOD)
+ {
+ for (auto& asgCTUDescr : frameDescr.m_vCTUdescr)
+ {
+ m_Counters.m_testCTUs++;
+ mfxU32 idxYInCTU = asgCTUDescr.m_AdrYInCTU;
+ mfxU32 idxXInCTU = asgCTUDescr.m_AdrXInCTU;
+
+ mfxFeiHevcPakCtuRecordV0 ctuPakFromFEI = tmpCtuBuff.m_pakCtuRecord.Data[idxYInCTU * widthInCTU + idxXInCTU];
+
+ mfxU32 startCuOffset = maxNumCuInCtu * (idxYInCTU * widthInCTU + idxXInCTU);
+
+ // Prerare CTU descriptor from FEI output
+ CTUDescriptor feiCTUDescr = ConvertFeiOutInLocalStr(ctuPakFromFEI, tmpCuBuff, startCuOffset);
+
+ asgLog << std::endl << "Frame " << frameDescr.m_frameNumber << std::endl;
+ asgLog << "ASG " << asgCTUDescr << std::endl << "FEI " << feiCTUDescr << std::endl;
+
+ CompareSplits(asgCTUDescr, feiCTUDescr);
+ CompareMVs(asgCTUDescr, feiCTUDescr);
+ CountExactMatches(asgCTUDescr, feiCTUDescr);
+ }
+ }
+ }
+ }
+ catch (std::string& e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: Verifier::VerifyDesc");
+ }
+}
+
+void Verifier::ExtractMVs(const CTUDescriptor& ctuDescr, std::vector& mvCmpBlocks)
+{
+ mfxU32 diffMaxBaseBlockLuma = m_InputParams.m_CTUStr.log2CTUSize - LOG2_MV_COMPARE_BASE_BLOCK_SIZE;
+ mfxU32 widthInCompareBlocks = 1 << diffMaxBaseBlockLuma;
+ constexpr mfxU32 baseBlockSize = 1 << LOG2_MV_COMPARE_BASE_BLOCK_SIZE;
+
+ for (auto& CU : ctuDescr.m_CUVec)
+ {
+ switch (CU.m_PredType)
+ {
+ case INTER_PRED:
+ for (auto& PU : CU.m_PUVec)
+ {
+ mfxU32 firstYBlock = (PU.m_AdrY - ctuDescr.m_AdrY) / baseBlockSize;
+ mfxU32 firstXBlock = (PU.m_AdrX - ctuDescr.m_AdrX) / baseBlockSize;
+ mfxU32 lastYBlock = firstYBlock + (PU.m_BHeight / baseBlockSize);
+ mfxU32 lastXBlock = firstXBlock + (PU.m_BWidth / baseBlockSize);
+
+ for (mfxU32 idxMVCBY = firstYBlock; idxMVCBY < lastYBlock; ++idxMVCBY)
+ {
+ for (mfxU32 idxMVCBX = firstXBlock; idxMVCBX < lastXBlock; ++idxMVCBX)
+ {
+ MVCompareBlock& block = mvCmpBlocks.at(idxMVCBY * widthInCompareBlocks + idxMVCBX);
+ block.m_AdrX = ctuDescr.m_AdrX + baseBlockSize * idxMVCBX;
+ block.m_AdrY = ctuDescr.m_AdrY + baseBlockSize * idxMVCBY;
+ block.m_BHeight = block.m_BWidth = baseBlockSize;
+
+ block.MV = PU.m_MV;
+ block.usedMVPPoolNo = PU.usedMVPPoolNo;
+ block.usedMVPIndex = PU.usedMVPIndex;
+
+ block.bIsIntra = false;
+
+ block.predFlagL0 = PU.predFlagL0;
+ block.predFlagL1 = PU.predFlagL1;
+ }
+ }
+ }
+ break;
+ case INTRA_PRED:
+ {
+ mfxU32 firstYBlock = (CU.m_AdrY - ctuDescr.m_AdrY) / baseBlockSize;
+ mfxU32 firstXBlock = (CU.m_AdrX - ctuDescr.m_AdrX) / baseBlockSize;
+ mfxU32 lastYBlock = firstYBlock + (CU.m_BHeight / baseBlockSize);
+ mfxU32 lastXBlock = firstXBlock + (CU.m_BWidth / baseBlockSize);
+
+ for (mfxU32 idxMVCBY = firstYBlock; idxMVCBY < lastYBlock; ++idxMVCBY)
+ {
+ for (mfxU32 idxMVCBX = firstXBlock; idxMVCBX < lastXBlock; ++idxMVCBX)
+ {
+ MVCompareBlock& block = mvCmpBlocks.at(idxMVCBY * widthInCompareBlocks + idxMVCBX);
+ block.m_AdrX = ctuDescr.m_AdrX + baseBlockSize * idxMVCBX;
+ block.m_AdrY = ctuDescr.m_AdrY + baseBlockSize * idxMVCBY;
+ block.m_BHeight = block.m_BWidth = baseBlockSize;
+
+ block.bIsIntra = true;
+ }
+ }
+ break;
+ }
+ default:
+ throw std::string("ERROR: ExtractMVs: unknown CU prediction type\n");
+ }
+ }
+}
+
+void Verifier::CompareSplits(const CTUDescriptor& ctuDescrASG, const CTUDescriptor& ctuDescrFEI)
+{
+ //First, count total number of split partitions (PUs and CUs) by their size
+ for (const auto& CU : ctuDescrASG.m_CUVec)
+ {
+ m_Counters.m_testCUSizeMapASG.AddBlockTotal(CU.m_BWidth, CU.m_BHeight);
+ for (const auto& PU : CU.m_PUVec)
+ {
+ m_Counters.m_testPUSizeMapASG.AddBlockTotal(PU.m_BWidth, PU.m_BHeight);
+ }
+ }
+
+ for (const auto& CU : ctuDescrFEI.m_CUVec)
+ {
+ m_Counters.m_testCUSizeMapFEI.AddBlockTotal(CU.m_BWidth, CU.m_BHeight);
+ for (const auto& PU : CU.m_PUVec)
+ {
+ m_Counters.m_testPUSizeMapFEI.AddBlockTotal(PU.m_BWidth, PU.m_BHeight);
+ }
+ }
+
+ asgLog << std::endl << "Comparing splits:" << std::endl;
+ asgLog << "FEI CUs: " << ctuDescrFEI.m_CUVec.size() << ", ASG CUs: " << ctuDescrASG.m_CUVec.size() << std::endl;
+ for (const auto& asgCU : ctuDescrASG.m_CUVec)
+ {
+ // Verificator finds equal CU
+ asgLog << "Searching for CU " << asgCU;
+ const auto itFeiCU = std::find_if(ctuDescrFEI.m_CUVec.begin(), ctuDescrFEI.m_CUVec.end(),
+ [&asgCU](const CUBlock& cu) { return (cu.m_AdrX == asgCU.m_AdrX && cu.m_AdrY == asgCU.m_AdrY &&
+ cu.m_BWidth == asgCU.m_BWidth && cu.m_BHeight == asgCU.m_BHeight); });
+ if (itFeiCU != ctuDescrFEI.m_CUVec.end())
+ {
+ asgLog << " -- FOUND, FEI PUs: " << asgCU.m_PUVec.size()
+ << ", ASG PUs: " << itFeiCU->m_PUVec.size() << std::endl;
+ m_Counters.m_testCUSizeMapASG.AddBlockCorrect(itFeiCU->m_BWidth, itFeiCU->m_BHeight);
+ for (auto& asgPU : asgCU.m_PUVec)
+ {
+ //Verificator finds equal PUs and calculates their number, while incrementing the correct count
+ //for the respective PU size in the block size map
+ m_Counters.m_correctPUs += (mfxU32)std::count_if(itFeiCU->m_PUVec.begin(), itFeiCU->m_PUVec.end(),
+ [&asgPU, this](const PUBlock& pu) {
+ if (pu.m_AdrX == asgPU.m_AdrX && pu.m_AdrY == asgPU.m_AdrY
+ && pu.m_BHeight == asgPU.m_BHeight && pu.m_BWidth == asgPU.m_BWidth)
+ {
+ asgLog << "\t Found matching PU: " << asgPU << std::endl;
+ m_Counters.m_testPUSizeMapASG.AddBlockCorrect(pu.m_BWidth, pu.m_BHeight);
+ return true;
+ }
+ else
+ {
+ asgLog << "\t PU mismatch -- FEI " << asgPU << ", ASG " << pu << std::endl;
+ return false;
+ }
+ });
+ }
+ }
+ else
+ {
+ asgLog << " -- NOT FOUND" << std::endl;
+ }
+ }
+}
+
+void Verifier::CompareMVs(const CTUDescriptor& asgCTUDescr, const CTUDescriptor& feiCTUDescr)
+{
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ mfxU32 poolNo = 0;
+ asgLog << "\nGenerated MVP pools:\n";
+ for (const auto& genMVPPool : asgCTUDescr.m_MVPGenPools)
+ {
+ asgLog << "MVP pool no. : "<< poolNo++ << "\n";
+ for (mfxU32 mvpIndex = 0; mvpIndex < MVP_PER_16x16_BLOCK; ++mvpIndex)
+ {
+ asgLog << mvpIndex << ": " << "L0:";
+ std::stringstream sstreamL0;
+ sstreamL0 << " (" << genMVPPool[mvpIndex].MV[0].x << "; " <<
+ genMVPPool[mvpIndex].MV[0].y << ")";
+ asgLog << std::setw(14) << sstreamL0.str();
+
+ asgLog << ", L1:";
+ std::stringstream sstreamL1;
+ sstreamL1 << " (" << genMVPPool[mvpIndex].MV[1].x << "; " <<
+ genMVPPool[mvpIndex].MV[1].y << ")";
+ asgLog << std::setw(14) << sstreamL1.str();
+ asgLog << "\n";
+ }
+ }
+ }
+ asgLog << "\nComparing MVs:\n";
+
+ // Tool mapping MVs on 4x4 compare blocks for checking [numCompareBlocksInCtu][List]
+ mfxU32 diffMaxBaseBlockLuma = m_InputParams.m_CTUStr.log2CTUSize - LOG2_MV_COMPARE_BASE_BLOCK_SIZE;
+ mfxU32 numCompareBlocksInCtu = (1 << (2 * diffMaxBaseBlockLuma));
+
+ std::vector MVCmpBlocksASG(numCompareBlocksInCtu);
+ std::vector MVCmpBlocksFEI(numCompareBlocksInCtu);
+
+ // Extract information from FEI output
+ ExtractMVs(feiCTUDescr, MVCmpBlocksFEI);
+
+ // Extract information from ASG tree structure
+ ExtractMVs(asgCTUDescr, MVCmpBlocksASG);
+
+ for (mfxU32 idxMVCmpBlock = 0; idxMVCmpBlock < numCompareBlocksInCtu; ++idxMVCmpBlock)
+ {
+ const MVCompareBlock& asgMVBlock = MVCmpBlocksASG[idxMVCmpBlock];
+ const MVCompareBlock& feiMVBlock = MVCmpBlocksFEI[idxMVCmpBlock];
+
+ asgLog << std::endl << "Block " << idxMVCmpBlock + 1 << "/" << numCompareBlocksInCtu << "; "
+ << BaseBlock(asgMVBlock) << std::endl;
+
+ CompareMVBlocks(asgMVBlock, feiMVBlock);
+ }
+
+ CalculateTotalMVCmpBlocksInCTU(MVCmpBlocksASG);
+}
+
+void Verifier::CompareMVBlocks(const MVCompareBlock& asgMVCmpBlock, const MVCompareBlock& feiMVCmpBlock)
+{
+ const auto feiMVL0 = feiMVCmpBlock.MV.GetL0MVTuple();
+ const auto feiMVL1 = feiMVCmpBlock.MV.GetL1MVTuple();
+
+ const auto asgMVL0 = asgMVCmpBlock.MV.GetL0MVTuple();
+ const auto asgMVL1 = asgMVCmpBlock.MV.GetL1MVTuple();
+
+ if (!asgMVCmpBlock.bIsIntra)
+ {
+ if ((m_InputParams.m_TestType & GENERATE_PREDICTION) && asgMVCmpBlock.usedMVPIndex < 0)
+ {
+ throw std::string("Verifier::CompareMVs: Some PU has invalid used MVP index");
+ }
+
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ asgLog << "MVP index used in ASG: " << asgMVCmpBlock.usedMVPIndex << " ";
+ }
+
+ if (asgMVCmpBlock.predFlagL0 && !asgMVCmpBlock.predFlagL1)
+ {
+ asgLog << "Uni-predicted MV compare block\n";
+ asgLog << "L0 MV: " << "FEI " << std::setw(14) << feiMVL0 << ", ASG " << std::setw(14) << asgMVL0
+ << ", MVP pool no. : " << asgMVCmpBlock.usedMVPPoolNo << ", MVP index : " << asgMVCmpBlock.usedMVPIndex;
+
+ if (feiMVL0 == asgMVL0)
+ {
+ m_Counters.m_correctMVCmpBlocksL0++;
+
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ m_Counters.m_correctMVCmpBlocksL0PerMVPIndex[asgMVCmpBlock.usedMVPIndex]++;
+ }
+
+ asgLog << " -- OK\n";
+ }
+ else
+ {
+ asgLog << " -- MISMATCH\n";
+ }
+ }
+ else if (!asgMVCmpBlock.predFlagL0 && asgMVCmpBlock.predFlagL1)
+ {
+ asgLog << "Uni-predicted MV compare block\n";
+ asgLog << "L1 MV: " << "FEI " << std::setw(14) << feiMVL1 << ", ASG " << std::setw(14) << asgMVL1
+ << ", MVP pool no. : " << asgMVCmpBlock.usedMVPPoolNo << ", MVP index : " << asgMVCmpBlock.usedMVPIndex;
+
+ if (feiMVL1 == asgMVL1)
+ {
+ m_Counters.m_correctMVCmpBlocksL1++;
+
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ m_Counters.m_correctMVCmpBlocksL1PerMVPIndex[asgMVCmpBlock.usedMVPIndex]++;
+ }
+
+ asgLog << " -- OK\n";
+ }
+ else
+ {
+ asgLog << " -- MISMATCH\n";
+ }
+ }
+ else if (asgMVCmpBlock.predFlagL0 && asgMVCmpBlock.predFlagL1)
+ {
+ asgLog << "Bi-predicted MV compare block\n";
+ asgLog << "L0 MV: " << "FEI " << std::setw(14) << feiMVL0 << ", ASG "
+ << std::setw(14) << asgMVL0 << "\n";
+ asgLog << "L1 MV: " << "FEI " << std::setw(14) << feiMVL1 << ", ASG "
+ << std::setw(14) << asgMVL1 << ", MVP pool no. : " << asgMVCmpBlock.usedMVPPoolNo
+ << ", MVP index : " << asgMVCmpBlock.usedMVPIndex;
+
+ if ((feiMVL0 == asgMVL0) && (feiMVL1 == asgMVL1))
+ {
+ m_Counters.m_correctMVCmpBlocksBi++;
+
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ m_Counters.m_correctMVCmpBlocksBiPerMVPIndex[asgMVCmpBlock.usedMVPIndex]++;
+ }
+
+ asgLog << " -- OK\n";
+ }
+ else
+ {
+ asgLog << " -- MISMATCH\n";
+ }
+
+ // Won't affect test result
+ if ((feiMVL0 == asgMVL0) && (feiMVL1 != asgMVL1))
+ {
+ m_Counters.m_correctMVsL0FromBiMVCmpBlocks++;
+ }
+ else if ((feiMVL0 != asgMVL0) && (feiMVL1 == asgMVL1))
+ {
+ m_Counters.m_correctMVsL1FromBiMVCmpBlocks++;
+ }
+ }
+ }
+ else
+ {
+ asgLog << " -- skipped due to being intra in ASG" << std::endl;
+ }
+}
+
+void Verifier::CalculateTotalMVCmpBlocksInCTU(std::vector& mvCmpBlocks)
+{
+ mfxU32 testMVCmpBlocksCountL0 = (mfxU32)std::count_if(mvCmpBlocks.begin(), mvCmpBlocks.end(),
+ [](const MVCompareBlock& block) { return !block.bIsIntra && block.predFlagL0 && !block.predFlagL1; });
+
+ mfxU32 testMVCmpBlocksCountL1 = (mfxU32)std::count_if(mvCmpBlocks.begin(), mvCmpBlocks.end(),
+ [](const MVCompareBlock& block) { return !block.bIsIntra && !block.predFlagL0 && block.predFlagL1; });
+
+ mfxU32 testMVCmpBlocksCountBi = (mfxU32)std::count_if(mvCmpBlocks.begin(), mvCmpBlocks.end(),
+ [](const MVCompareBlock& block) { return !block.bIsIntra && block.predFlagL0 && block.predFlagL1; });
+
+ m_Counters.m_totalMVCmpBlocksL0 += testMVCmpBlocksCountL0;
+ m_Counters.m_totalMVCmpBlocksL1 += testMVCmpBlocksCountL1;
+ m_Counters.m_totalMVCmpBlocksBi += testMVCmpBlocksCountBi;
+
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ for (mfxI32 mvpIndex = 0; mvpIndex < MVP_PER_16x16_BLOCK; mvpIndex++)
+ {
+ mfxU32 testMVCmpBlocksCountL0 = (mfxU32)std::count_if(mvCmpBlocks.begin(), mvCmpBlocks.end(),
+ [mvpIndex](const MVCompareBlock& block) { return !block.bIsIntra && block.predFlagL0
+ && !block.predFlagL1 && block.usedMVPIndex == mvpIndex; });
+
+ mfxU32 testMVCmpBlocksCountL1 = (mfxU32)std::count_if(mvCmpBlocks.begin(), mvCmpBlocks.end(),
+ [mvpIndex](const MVCompareBlock& block) { return !block.bIsIntra && !block.predFlagL0
+ && block.predFlagL1 && block.usedMVPIndex == mvpIndex; });
+
+ mfxU32 testMVCmpBlocksCountBi = (mfxU32)std::count_if(mvCmpBlocks.begin(), mvCmpBlocks.end(),
+ [mvpIndex](const MVCompareBlock& block) { return !block.bIsIntra && block.predFlagL0
+ && block.predFlagL1 && block.usedMVPIndex == mvpIndex; });
+
+ m_Counters.m_totalMVCmpBlocksL0PerMVPIndex[mvpIndex] += testMVCmpBlocksCountL0;
+ m_Counters.m_totalMVCmpBlocksL1PerMVPIndex[mvpIndex] += testMVCmpBlocksCountL1;
+ m_Counters.m_totalMVCmpBlocksBiPerMVPIndex[mvpIndex] += testMVCmpBlocksCountBi;
+ }
+ }
+}
+
+void Verifier::CountExactMatches(const CTUDescriptor& asgCTUDescr, const CTUDescriptor& feiCTUDescr)
+{
+ std::vector asgPUBlocksOfCTU = asgCTUDescr.GetTotalPUsVec();
+ std::vector feiPUBlocksOfCTU = feiCTUDescr.GetTotalPUsVec();
+
+ mfxU32 exactPUMatches = 0;
+
+ for (const auto& asgPU : asgPUBlocksOfCTU)
+ {
+ exactPUMatches += (mfxU32)std::count(feiPUBlocksOfCTU.begin(), feiPUBlocksOfCTU.end(), asgPU);
+ }
+
+ mfxU32 exactCUMatches = 0;
+ //TODO: optimize so that PUs don't get compared twice
+ for (const auto& asgCU : asgCTUDescr.m_CUVec)
+ {
+ exactCUMatches += (mfxU32)std::count(feiCTUDescr.m_CUVec.begin(), feiCTUDescr.m_CUVec.end(), asgCU);
+ }
+
+ if (exactCUMatches == asgCTUDescr.m_CUVec.size() && exactCUMatches == feiCTUDescr.m_CUVec.size() &&
+ exactPUMatches == asgPUBlocksOfCTU.size() &&
+ exactPUMatches == feiPUBlocksOfCTU.size())
+ {
+ asgLog << std::endl << "CTUs are exactly matching" << std::endl;
+ m_Counters.m_exactCTUs++;
+ }
+ else
+ {
+ asgLog << std::endl << "CTUs are not exactly matching" << std::endl;
+ asgLog << "CUs (exact/ASG total): " << exactCUMatches << '/' << asgPUBlocksOfCTU.size() << std::endl;
+ asgLog << "PUs (exact/ASG total): " << exactPUMatches << '/' << asgPUBlocksOfCTU.size() << std::endl;
+ }
+ m_Counters.m_exactCUs += exactCUMatches;
+ m_Counters.m_exactPUs += exactPUMatches;
+}
+
+CTUDescriptor Verifier::ConvertFeiOutInLocalStr(const mfxFeiHevcPakCtuRecordV0& ctuPakFromFEI, const ExtendedBuffer& tmpCuBuff, const mfxU32 startCuOffset)
+{
+ try
+ {
+ CTUDescriptor tmpDescr(ctuPakFromFEI.CtuAddrX, ctuPakFromFEI.CtuAddrY,
+ ctuPakFromFEI.CtuAddrX * m_InputParams.m_CTUStr.CTUSize, ctuPakFromFEI.CtuAddrY * m_InputParams.m_CTUStr.CTUSize,
+ m_InputParams.m_CTUStr.CTUSize, m_InputParams.m_CTUStr.CTUSize);
+
+ mfxU32 bitMask = 0;
+ mfxU32 baseSplitLevel2Shift = 4;
+ bitMask |= ctuPakFromFEI.SplitLevel0;
+ bitMask |= ctuPakFromFEI.SplitLevel1 << 1;
+ bitMask |= ctuPakFromFEI.SplitLevel2Part0 << (baseSplitLevel2Shift + 1);
+ bitMask |= ctuPakFromFEI.SplitLevel2Part1 << (2 * baseSplitLevel2Shift + 1);
+ bitMask |= ctuPakFromFEI.SplitLevel2Part2 << (3 * baseSplitLevel2Shift + 1);
+ bitMask |= ctuPakFromFEI.SplitLevel2Part3 << (4 * baseSplitLevel2Shift + 1);
+
+ m_FrameProcessor.GenQuadTreeInCTUWithBitMask(tmpDescr, bitMask);
+ std::vector tmpVec;
+ tmpDescr.m_CUQuadTree.GetQuadTreeBlocksRecur(tmpDescr.m_CUQuadTree.root, tmpDescr.m_AdrX, tmpDescr.m_AdrY, tmpDescr.m_BHeight, tmpVec);
+
+ if (tmpVec.size() != mfxU32(ctuPakFromFEI.CuCountMinus1 + 1))
+ throw std::string("ERROR: Verifier::ConvertFeiOutInLocalStr. Incorrect number of the CUs into tree");
+
+ mfxU32 idxCUInCTU = 0;
+ for (const auto& block : tmpVec)
+ {
+ CUBlock cu_block(block);
+ mfxFeiHevcPakCuRecordV0 cuPakFromFEI = tmpCuBuff.m_pakCuRecord.Data[startCuOffset + idxCUInCTU];
+
+ if (cuPakFromFEI.PredMode)
+ {
+ cu_block.m_PredType = INTER_PRED;
+ cu_block.BuildPUsVector((INTER_PART_MODE)cuPakFromFEI.PartMode);
+
+ mfxU32 idxPUInCU = 0;
+ for (auto& PU : cu_block.m_PUVec)
+ {
+ mfxU8 interpredIdcPU = (cuPakFromFEI.InterpredIdc >> (2 * idxPUInCU)) & 0x03;
+
+ switch (interpredIdcPU)
+ {
+ case 0:
+ PU.predFlagL0 = true;
+ PU.predFlagL1 = false;
+ break;
+ case 1:
+ PU.predFlagL0 = false;
+ PU.predFlagL1 = true;
+ break;
+ case 2:
+ PU.predFlagL0 = true;
+ PU.predFlagL1 = true;
+ break;
+ case 3:
+ throw std::string("ERROR: Verifier::ConvertFeiOutInLocalStr: incorrect value for InterpredIdc");
+ }
+
+ for (mfxU32 idxList = 0; idxList < 2; ++idxList)
+ {
+ PU.m_MV.MV[idxList].x = cuPakFromFEI.MVs[idxList].x[idxPUInCU];
+ PU.m_MV.MV[idxList].y = cuPakFromFEI.MVs[idxList].y[idxPUInCU];
+ }
+
+ switch (idxPUInCU)
+ {
+ case 0:
+ PU.m_MV.RefIdx.RefL0 = cuPakFromFEI.RefIdx[0].Ref0;
+ PU.m_MV.RefIdx.RefL1 = cuPakFromFEI.RefIdx[1].Ref0;
+ break;
+ case 1:
+ PU.m_MV.RefIdx.RefL0 = cuPakFromFEI.RefIdx[0].Ref1;
+ PU.m_MV.RefIdx.RefL1 = cuPakFromFEI.RefIdx[1].Ref1;
+ break;
+ case 2:
+ PU.m_MV.RefIdx.RefL0 = cuPakFromFEI.RefIdx[0].Ref2;
+ PU.m_MV.RefIdx.RefL1 = cuPakFromFEI.RefIdx[1].Ref2;
+ break;
+ case 3:
+ PU.m_MV.RefIdx.RefL0 = cuPakFromFEI.RefIdx[0].Ref3;
+ PU.m_MV.RefIdx.RefL1 = cuPakFromFEI.RefIdx[1].Ref3;
+ break;
+ }
+
+ ++idxPUInCU;
+ }
+ }
+ else
+ {
+ cu_block.m_PredType = INTRA_PRED;
+ }
+
+ tmpDescr.m_CUVec.push_back(cu_block);
+ ++idxCUInCTU;
+ }
+
+ return tmpDescr;
+ }
+
+ catch (std::string& e) {
+ std::cout << e << std::endl;
+ throw std::string("ERROR: Verifier::ConvertFeiOutInLocalStr");
+ }
+}
+
+void Verifier::CheckStatistics(Thresholds thres)
+{
+ m_Counters.m_totalCUsASG = m_Counters.m_testCUSizeMapASG.GetTotalCount();
+ m_Counters.m_totalPUsASG = m_Counters.m_testPUSizeMapASG.GetTotalCount();
+
+ m_Counters.m_totalCUsFEI = m_Counters.m_testCUSizeMapFEI.GetTotalCount();
+ m_Counters.m_totalPUsFEI = m_Counters.m_testPUSizeMapFEI.GetTotalCount();
+
+ m_Counters.m_correctCUs = m_Counters.m_testCUSizeMapASG.GetCorrectCount();
+ m_Counters.m_correctPUs = m_Counters.m_testPUSizeMapASG.GetCorrectCount();
+
+ std::cout << "Total CTUs tested: " << m_Counters.m_testCTUs << std::endl;
+ std::cout << "Exact matches: CTUs " << m_Counters.m_exactCTUs << '/' << m_Counters.m_testCTUs << '(';
+ CheckLowerThreshold(m_Counters.m_exactCTUs, m_Counters.m_testCTUs);
+ std::cout << "), CUs " << m_Counters.m_exactCUs << '/' << m_Counters.m_totalCUsASG << '(';
+ CheckLowerThreshold(m_Counters.m_exactCUs, m_Counters.m_totalCUsASG);
+ std::cout << "), PUs " << m_Counters.m_exactPUs << '/' << m_Counters.m_totalPUsASG << '(';
+ CheckLowerThreshold(m_Counters.m_exactPUs, m_Counters.m_totalPUsASG);
+ std::cout << ")" << std::endl;
+
+ if (m_InputParams.m_TestType & GENERATE_INTER)
+ {
+ CheckMVs(thres);
+ }
+
+ if (m_InputParams.m_TestType & (GENERATE_INTER | GENERATE_INTRA))
+ {
+ CheckSplits(thres);
+ }
+
+ if (m_InputParams.m_TestType == GENERATE_PICSTRUCT)
+ {
+ CheckPicStruct();
+ }
+
+ if (!m_errorMsgList.empty())
+ {
+ std::cout << std::endl <<"TEST FAILED" << std::endl;
+
+ //Output errors in order of occurence as the last lines of output
+ //so that the test system recognizes test failure
+ for (auto& message : m_errorMsgList)
+ {
+ std::cout << message << std::endl;
+ }
+
+ throw ASG_HEVC_ERR_LOW_PASS_RATE;
+ }
+}
+
+bool Verifier::CheckLowerThreshold(mfxU32 numerator, mfxU32 denominator, mfxU32 threshold)
+{
+ if (denominator > 0)
+ {
+ std::cout.precision(1);
+ std::cout.setf(std::ios::fixed);
+ std::cout << 100 * ((mfxF32)numerator / denominator) << "%";
+ return (100 * ((mfxF32)numerator / denominator) >= (mfxF32)threshold);
+ }
+ else
+ {
+ std::cout << "n/a";
+ return true;
+ }
+}
+
+void Verifier::PrintPercentRatio(mfxU32 numerator, mfxU32 denominator)
+{
+ if (denominator > 0)
+ {
+ std::cout.precision(1);
+ std::cout.setf(std::ios::fixed);
+ std::cout << 100 * ((mfxF32)numerator / denominator) << "%";
+ }
+ else
+ {
+ std::cout << "n/a";
+ }
+}
+
+void Verifier::CheckMVs(Thresholds threshold)
+{
+ std::cout << std::endl << "MOTION VECTOR TESTING:\n";
+
+ CheckL0MVs(threshold);
+
+ CheckL1MVs(threshold);
+
+ CheckBiMVs(threshold);
+}
+
+void Verifier::CheckL0MVs(Thresholds threshold)
+{
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ CheckL0MVsPerMVPIndex(threshold);
+ }
+ else
+ {
+ std::cout << "Correct uni-predicted (L0) MV " << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks: "
+ << m_Counters.m_correctMVCmpBlocksL0 << '/' << m_Counters.m_totalMVCmpBlocksL0 << " (";
+
+ bool isOverallCheckPassed = CheckLowerThreshold(m_Counters.m_correctMVCmpBlocksL0,
+ m_Counters.m_totalMVCmpBlocksL0, threshold.mvThres);
+
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (isOverallCheckPassed)
+ {
+ std::cout << "MVs[Uni, L0] test passed" << std::endl;
+ }
+ else
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for uni-predicted L0 blocks");
+ }
+ }
+}
+
+void Verifier::CheckL0MVsPerMVPIndex(Thresholds threshold)
+{
+ bool isIncorrectPredCheckPassed = true;
+ bool isCorrectPredCheckPassed = true;
+
+ mfxU32 expectedCorrectTotal = 0;
+ mfxU32 expectedCorrectCount = 0;
+ mfxU32 expectedIncorrectTotal = 0;
+ mfxU32 expectedIncorrectCount = 0;
+
+ for (mfxU32 mvpIndex = 0; mvpIndex < MVP_PER_16x16_BLOCK; mvpIndex++)
+ {
+ std::cout << "MVP index: " << mvpIndex << " Correct uni-predicted (L0) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks: "
+ << m_Counters.m_correctMVCmpBlocksL0PerMVPIndex[mvpIndex] << '/'
+ << m_Counters.m_totalMVCmpBlocksL0PerMVPIndex[mvpIndex] << " (";
+ PrintPercentRatio(m_Counters.m_correctMVCmpBlocksL0PerMVPIndex[mvpIndex],
+ m_Counters.m_totalMVCmpBlocksL0PerMVPIndex[mvpIndex]);
+ std::cout << ")" << std::endl;
+
+ // Calculating incorrectly predicted blocks per disabled MVP indexes
+ if (mvpIndex / m_InputParams.m_NumMVPredictors)
+ {
+ expectedIncorrectTotal += m_Counters.m_totalMVCmpBlocksL0PerMVPIndex[mvpIndex];
+ expectedIncorrectCount += (m_Counters.m_totalMVCmpBlocksL0PerMVPIndex[mvpIndex]
+ - m_Counters.m_correctMVCmpBlocksL0PerMVPIndex[mvpIndex]);
+ }
+ else // Calculating correctly predicted blocks per enabled MVP indexes
+ {
+ expectedCorrectTotal += m_Counters.m_totalMVCmpBlocksL0PerMVPIndex[mvpIndex];
+ expectedCorrectCount += m_Counters.m_correctMVCmpBlocksL0PerMVPIndex[mvpIndex];
+ }
+ }
+
+ std::cout << "Correctly uni-predicted (L0) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks on enabled EMVP: "
+ << expectedCorrectCount << "/" << expectedCorrectTotal << " (";
+ isCorrectPredCheckPassed = CheckLowerThreshold(expectedCorrectCount, expectedCorrectTotal,
+ threshold.mvThres);
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (!isCorrectPredCheckPassed)
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for correctly uni-predicted L0 blocks");
+ }
+
+ std::cout << "Incorrectly uni-predicted (L0) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks on disabled EMVP: "
+ << expectedIncorrectCount << "/" << expectedIncorrectTotal << " (";
+ isIncorrectPredCheckPassed = CheckLowerThreshold(expectedIncorrectCount, expectedIncorrectTotal,
+ threshold.mvThres);
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (!isIncorrectPredCheckPassed)
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for incorrectly uni-predicted L0 blocks");
+ }
+
+ if (isCorrectPredCheckPassed && isIncorrectPredCheckPassed)
+ {
+ std::cout << "MVs[Uni, L0] test passed" << std::endl;
+ }
+}
+
+void Verifier::CheckL1MVs(Thresholds threshold)
+{
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ CheckL1MVsPerMVPIndex(threshold);
+ }
+ else
+ {
+ std::cout << "Correct uni-predicted (L1) MV " << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE
+ << " compare blocks: " << m_Counters.m_correctMVCmpBlocksL1 << '/'
+ << m_Counters.m_totalMVCmpBlocksL1 << " (";
+
+ bool isOverallPassed = CheckLowerThreshold(m_Counters.m_correctMVCmpBlocksL1,
+ m_Counters.m_totalMVCmpBlocksL1, threshold.mvThres);
+
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (isOverallPassed)
+ {
+ std::cout << "MVs[Uni, L1] test passed" << std::endl;
+ }
+ else
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for uni-predicted L1 blocks");
+ }
+ }
+}
+
+void Verifier::CheckL1MVsPerMVPIndex(Thresholds threshold)
+{
+ bool isIncorrectPredCheckPassed = true;
+ bool isCorrectPredCheckPassed = true;
+
+ mfxU32 expectedCorrectTotal = 0;
+ mfxU32 expectedCorrectCount = 0;
+ mfxU32 expectedIncorrectTotal = 0;
+ mfxU32 expectedIncorrectCount = 0;
+
+ std::cout << std::endl;
+
+ for (mfxU32 mvpIndex = 0; mvpIndex < MVP_PER_16x16_BLOCK; mvpIndex++)
+ {
+ std::cout << "MVP index: " << mvpIndex << " Correct uni-predicted (L1) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks: "
+ << m_Counters.m_correctMVCmpBlocksL1PerMVPIndex[mvpIndex] << '/'
+ << m_Counters.m_totalMVCmpBlocksL1PerMVPIndex[mvpIndex] << " (";
+ PrintPercentRatio(m_Counters.m_correctMVCmpBlocksL1PerMVPIndex[mvpIndex],
+ m_Counters.m_totalMVCmpBlocksL1PerMVPIndex[mvpIndex]);
+ std::cout << ")" << std::endl;
+
+ // Calculating incorrectly predicted blocks per disabled MVP indexes
+ if (mvpIndex / m_InputParams.m_NumMVPredictors)
+ {
+ expectedIncorrectTotal += m_Counters.m_totalMVCmpBlocksL1PerMVPIndex[mvpIndex];
+ expectedIncorrectCount += (m_Counters.m_totalMVCmpBlocksL1PerMVPIndex[mvpIndex]
+ - m_Counters.m_correctMVCmpBlocksL1PerMVPIndex[mvpIndex]);
+ }
+ else // Calculating correctly predicted blocks per enabled MVP indexes
+ {
+ expectedCorrectTotal += m_Counters.m_totalMVCmpBlocksL1PerMVPIndex[mvpIndex];
+ expectedCorrectCount += m_Counters.m_correctMVCmpBlocksL1PerMVPIndex[mvpIndex];
+ }
+ }
+
+ std::cout << "Correctly uni-predicted (L1) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks on enabled EMVP: "
+ << expectedCorrectCount << "/" << expectedCorrectTotal << " (";
+ isCorrectPredCheckPassed = CheckLowerThreshold(expectedCorrectCount,
+ expectedCorrectTotal, threshold.mvThres);
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (!isCorrectPredCheckPassed)
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for correctly uni-predicted L1 blocks");
+ }
+
+ std::cout << "Incorrectly uni-predicted (L1) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks on disabled EMVP: "
+ << expectedIncorrectCount << "/" << expectedIncorrectTotal << " (";
+ isIncorrectPredCheckPassed = CheckLowerThreshold(expectedIncorrectCount,
+ expectedIncorrectTotal, threshold.mvThres);
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (!isIncorrectPredCheckPassed)
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for incorrectly uni-predicted L1 blocks");
+ }
+
+ if (isCorrectPredCheckPassed && isIncorrectPredCheckPassed)
+ {
+ std::cout << "MVs[Uni, L1] test passed" << std::endl;
+ }
+}
+
+void Verifier::CheckBiMVs(Thresholds threshold)
+{
+ if (m_InputParams.m_TestType & GENERATE_PREDICTION)
+ {
+ CheckBiMVsPerMVPIndex(threshold);
+ }
+ else
+ {
+ std::cout << "Correct bi-predicted (Bi) MVs " << MV_CMP_BLOCK_SIZE << "x"
+ << MV_CMP_BLOCK_SIZE << " compare blocks: "
+ << m_Counters.m_correctMVCmpBlocksBi << '/' << m_Counters.m_totalMVCmpBlocksBi << " (";
+
+ bool isOverallPassed = CheckLowerThreshold(m_Counters.m_correctMVCmpBlocksBi,
+ m_Counters.m_totalMVCmpBlocksBi, threshold.mvThres);
+
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (isOverallPassed)
+ {
+ std::cout << "MVs[Bi] test passed" << std::endl;
+ }
+ else
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for bi-predicted blocks");
+ }
+ }
+
+ // Won't affect test result
+ std::cout << std::endl << "Bi MVs with correct L0 and incorrect L1: "
+ << m_Counters.m_correctMVsL0FromBiMVCmpBlocks << std::endl;
+ std::cout << "Bi MVs with correct L1 and incorrect L0: "
+ << m_Counters.m_correctMVsL1FromBiMVCmpBlocks << std::endl;
+}
+
+void Verifier::CheckBiMVsPerMVPIndex(Thresholds threshold)
+{
+ bool isIncorrectPredCheckPassed = true;
+ bool isCorrectPredCheckPassed = true;
+
+ mfxU32 expectedCorrectTotal = 0;
+ mfxU32 expectedCorrectCount = 0;
+ mfxU32 expectedIncorrectTotal = 0;
+ mfxU32 expectedIncorrectCount = 0;
+
+ std::cout << std::endl;
+
+ for (mfxU32 mvpIndex = 0; mvpIndex < MVP_PER_16x16_BLOCK; mvpIndex++)
+ {
+ std::cout << "MVP index: " << mvpIndex << " Correct bi-predicted (Bi) MVs "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks: "
+ << m_Counters.m_correctMVCmpBlocksBiPerMVPIndex[mvpIndex] << '/'
+ << m_Counters.m_totalMVCmpBlocksBiPerMVPIndex[mvpIndex] << " (";
+ PrintPercentRatio(m_Counters.m_correctMVCmpBlocksBiPerMVPIndex[mvpIndex],
+ m_Counters.m_totalMVCmpBlocksBiPerMVPIndex[mvpIndex]);
+ std::cout << ")" << std::endl;
+
+ if (mvpIndex / m_InputParams.m_NumMVPredictors)
+ {
+ expectedIncorrectTotal += m_Counters.m_totalMVCmpBlocksBiPerMVPIndex[mvpIndex];
+ expectedIncorrectCount += (m_Counters.m_totalMVCmpBlocksBiPerMVPIndex[mvpIndex]
+ - m_Counters.m_correctMVCmpBlocksBiPerMVPIndex[mvpIndex]);
+ }
+ else
+ {
+ expectedCorrectTotal += m_Counters.m_totalMVCmpBlocksBiPerMVPIndex[mvpIndex];
+ expectedCorrectCount += m_Counters.m_correctMVCmpBlocksBiPerMVPIndex[mvpIndex];
+ }
+ }
+
+ std::cout << "Correctly bi-predicted (Bi) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks on enabled EMVP: "
+ << expectedCorrectCount << "/" << expectedCorrectTotal << " (";
+ isCorrectPredCheckPassed = CheckLowerThreshold(expectedCorrectCount,
+ expectedCorrectTotal, threshold.mvThres);
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (!isCorrectPredCheckPassed)
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for correctly bi-predicted blocks");
+ }
+
+ std::cout << "Incorrectly bi-predicted (Bi) MV "
+ << MV_CMP_BLOCK_SIZE << "x" << MV_CMP_BLOCK_SIZE << " compare blocks on disabled EMVP: "
+ << expectedIncorrectCount << "/" << expectedIncorrectTotal << " (";
+ isIncorrectPredCheckPassed = CheckLowerThreshold(expectedIncorrectCount,
+ expectedIncorrectTotal, threshold.mvThres);
+ std::cout << "); threshold: " << threshold.mvThres << '%' << std::endl;
+
+ if (!isIncorrectPredCheckPassed)
+ {
+ m_errorMsgList.emplace_back("ERROR: Low MV pass-rate for incorrect bi-predicted blocks");
+ }
+
+ if (isCorrectPredCheckPassed && isIncorrectPredCheckPassed)
+ {
+ std::cout << "MVs[Bi] test passed" << std::endl;
+ }
+}
+
+void Verifier::CheckSplits(Thresholds threshold)
+{
+ bool isStagePassed = true;
+
+ std::cout << std::endl << "SPLIT TESTING (PU-based):";
+
+ std::cout << std::endl << "Total FEI CU partitions by size (for test CTUs):\n";
+ m_Counters.m_testCUSizeMapFEI.PrintTable();
+ std::cout << "Total FEI PU partitions by size (for test CTUs):\n";
+ m_Counters.m_testPUSizeMapFEI.PrintTable();
+
+ std::cout << "Correct FEI CU partitions by size (actual/maximum):\n";
+ m_Counters.m_testCUSizeMapASG.PrintTable();
+ std::cout << "Correct FEI PU partitions by size (actual/maximum):\n";
+ m_Counters.m_testPUSizeMapASG.PrintTable();
+
+ std::cout << "\nTotal partition counts: FEI CUs -- " << m_Counters.m_totalCUsFEI
+ << ", FEI PUs -- " << m_Counters.m_totalPUsFEI << ", ASG CUs -- " << m_Counters.m_totalCUsASG
+ << ", ASG PUs -- " << m_Counters.m_totalPUsASG << std::endl;
+
+ std::cout << "Correct partition counts: CUs -- " << m_Counters.m_correctCUs
+ << '/' << m_Counters.m_totalCUsASG << "(";
+
+ CheckLowerThreshold(m_Counters.m_correctCUs, m_Counters.m_totalCUsASG);
+
+ std::cout << "), PUs -- " << m_Counters.m_correctPUs << '/' << m_Counters.m_totalPUsASG
+ << "(";
+
+ isStagePassed = CheckLowerThreshold(m_Counters.m_correctPUs, m_Counters.m_totalPUsASG, threshold.splitThres);
+
+ std::cout << "); PU threshold: " << threshold.splitThres << '%' << std::endl;
+
+ if (isStagePassed)
+ {
+ std::cout << "Split test passed" << std::endl;
+ }
+ else
+ {
+ m_errorMsgList.emplace_back("ERROR: Low pass-rate for splits");
+ }
+}
+
+void Verifier::CheckPicStruct()
+{
+ if (m_Counters.m_totalPics == m_Counters.m_correctRecords)
+ {
+ std::cout << "Picture Structure test passed" << std::endl;
+ }
+ else
+ {
+ m_errorMsgList.emplace_back("ERROR: Picture Structure test failed");
+ }
+}
+
+#endif // MFX_VERSION
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/CMakeLists.txt b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/CMakeLists.txt
new file mode 100644
index 0000000..e082b94
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories (
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+)
+
+file( GLOB_RECURSE sources "${CMAKE_CURRENT_SOURCE_DIR}/src/*.c" "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp" )
+
+set( defs " -DMFX_VERSION_USE_LATEST " )
+
+make_library( bs_parser_hevc_static none static )
+set( defs "" )
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.def b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.def
new file mode 100644
index 0000000..270a163
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.def
@@ -0,0 +1,13 @@
+LIBRARY "bs_parser_hevc"
+EXPORTS
+ BS_HEVC2_Init
+ BS_HEVC2_OpenFile
+ BS_HEVC2_SetBuffer
+ BS_HEVC2_ParseNextAU
+ BS_HEVC2_Close
+ BS_HEVC2_SetTraceLevel
+ BS_HEVC2_Lock
+ BS_HEVC2_Unlock
+ BS_HEVC2_GetOffset
+ BS_HEVC2_Sync
+ BS_HEVC2_GetAsyncDepth
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.vcxproj b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.vcxproj
new file mode 100644
index 0000000..0a13c8d
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.vcxproj
@@ -0,0 +1,207 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 15.0
+ {6A44B0B8-2D21-4D64-9F0A-D73A2BBB3103}
+ Win32Proj
+ 10.0.17134.0
+
+
+
+ DynamicLibrary
+ true
+ v141
+
+
+ DynamicLibrary
+ false
+ v141
+
+
+ DynamicLibrary
+ true
+ v141
+
+
+ DynamicLibrary
+ false
+ v141
+ Unicode
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(Configuration)\$(ProjectName)\
+
+
+ true
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(Configuration)\$(ProjectName)\
+
+
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(Configuration)\$(ProjectName)\
+ .dll
+ false
+ false
+
+
+ $(ProjectDir)..\..\..\build\win_$(Platform)\$(Configuration)\bin\
+ $(OutDir)..\objs\$(Configuration)\$(ProjectName)\
+ .dll
+
+
+
+ WIN32;_DEBUG;_WINDOWS;_USRDLL;BS_PARSER_HEVC_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDebugDLL
+ Level3
+ ProgramDatabase
+ Disabled
+ ./include;%(AdditionalIncludeDirectories)
+ false
+ Guard
+ true
+
+
+ MachineX86
+ true
+ Windows
+ bs_parser_hevc.def
+ $(OutDir)../lib/$(ProjectName).lib
+
+
+
+
+ _WIN32;WIN632;NDEBUG;_WINDOWS;_USRDLL;BS_PARSER_EXPORTS;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Level3
+ ProgramDatabase
+ ./include;%(AdditionalIncludeDirectories)
+ Speed
+ true
+ true
+ Cdecl
+
+
+ MachineX86
+ true
+ Windows
+ true
+ true
+ bs_parser_hevc.def
+ $(OutDir)../lib/$(ProjectName).lib
+
+
+
+
+ ./include;%(AdditionalIncludeDirectories)
+
+
+
+
+ Level3
+ true
+ Speed
+ _WIN64;WIN64;NDEBUG;_WINDOWS;_USRDLL;BS_PARSER_EXPORTS;%(PreprocessorDefinitions)
+ StdCall
+
+
+ Windows
+ true
+ true
+ UseFastLinkTimeCodeGeneration
+ $(OutDir)../lib/$(ProjectName).lib
+ bs_parser_hevc.def
+
+
+
+
+ ./include;%(AdditionalIncludeDirectories)
+
+
+
+
+ Level3
+ ProgramDatabase
+ false
+ _WIN64;WIN64;_DEBUG;_WINDOWS;_USRDLL;BS_PARSER_EXPORTS;%(PreprocessorDefinitions)
+ true
+ Guard
+
+
+ bs_parser_hevc.def
+ $(OutDir)../lib/$(ProjectName).lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.vcxproj.filters b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.vcxproj.filters
new file mode 100644
index 0000000..ecd86ea
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/bs_parser_hevc.vcxproj.filters
@@ -0,0 +1,102 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav
+
+
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_def.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_def.h
new file mode 100644
index 0000000..50e8d28
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_def.h
@@ -0,0 +1,73 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __BS_DEF_H
+#define __BS_DEF_H
+
+//#undef __BS_TRACE__
+//#define __BS_TRACE__
+
+typedef unsigned char byte;
+typedef unsigned char Bs8u;
+typedef unsigned short Bs16u;
+typedef unsigned int Bs32u;
+
+typedef signed char Bs8s;
+typedef signed short Bs16s;
+typedef signed int Bs32s;
+
+#ifdef __GNUC__
+ typedef unsigned long long Bs64u;
+ typedef signed long long Bs64s;
+#else
+ typedef unsigned __int64 Bs64u;
+ typedef signed __int64 Bs64s;
+#endif
+
+ #if defined( _WIN32 ) || defined ( _WIN64 )
+ #define __STDCALL __stdcall
+ #define __CDECL __cdecl
+ #define __INT64 __int64
+ #define __UINT64 unsigned __int64
+#else
+ #define __STDCALL
+ #define __CDECL
+ #define __INT64 long long
+ #define __UINT64 unsigned long long
+#endif
+
+typedef enum {
+ BS_ERR_NONE = 0,
+ BS_ERR_UNKNOWN = -1,
+ BS_ERR_WRONG_UNITS_ORDER = -2,
+ BS_ERR_MORE_DATA = -3,
+ BS_ERR_INVALID_PARAMS = -4,
+ BS_ERR_MEM_ALLOC = -5,
+ BS_ERR_NOT_IMPLEMENTED = -6,
+ BS_ERR_NOT_ENOUGH_BUFFER = -7,
+ BS_ERR_BAD_HANDLE = -8,
+ BS_ERR_INCOMPLETE_DATA = -9
+} BSErr;
+
+#define BS_MIN(x, y) ( ((x) < (y)) ? (x) : (y) )
+#define BS_MAX(x, y) ( ((x) > (y)) ? (x) : (y) )
+#define BS_ABS(x) ( ((x) > 0) ? (x) : (-(x)) )
+
+#endif //__BS_DEF_H
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_mem+.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_mem+.h
new file mode 100644
index 0000000..470096a
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_mem+.h
@@ -0,0 +1,300 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#pragma once
+#include
+#include
+#include
+#include
+#include
+
+//#define BS_MEM_TRACE
+
+#ifdef BS_MEM_TRACE
+#include
+#endif
+
+namespace BS_MEM
+{
+
+class MemBase
+{
+public:
+ virtual void* Get() = 0;
+ virtual ~MemBase(){}
+};
+
+template class MemObj : public MemBase
+{
+public:
+ T* m_obj;
+ bool m_del;
+
+ MemObj(unsigned int count, bool zero)
+ {
+ if (zero)
+ m_obj = new T[count]{}; // array value-initialization
+ else
+ m_obj = new T[count];
+ m_del = true;
+ }
+
+ MemObj(T* obj)
+ : m_obj(obj)
+ , m_del(false)
+ {}
+
+ MemObj(const MemObj&) = delete;
+ MemObj& operator=(const MemObj&) = delete;
+
+ virtual ~MemObj()
+ {
+ if (m_del)
+ delete[] m_obj;
+ }
+
+ void* Get() { return m_obj; }
+};
+
+class MemD
+{
+public:
+ MemD()
+ : locked(0)
+ , to_delete(false)
+ , mem(nullptr)
+ {
+ }
+
+ ~MemD()
+ {
+ if (mem)
+ delete mem;
+ }
+
+ unsigned int locked;
+ bool to_delete;
+ std::set base;
+ std::set dep;
+ MemBase* mem;
+};
+
+class Allocator
+{
+private:
+ std::map m_mem;
+ std::recursive_mutex m_mtx;
+ bool m_zero;
+
+ inline bool Touch(void* p) { return !!m_mem.count(p); }
+ inline void __notrace(const char*, ...) {}
+
+#ifdef BS_MEM_TRACE
+#define BS_MEM_TRACE_F printf
+#else
+#define BS_MEM_TRACE_F __notrace
+#endif
+
+public:
+
+ Allocator()
+ : m_zero(false)
+ {
+ }
+
+ ~Allocator()
+ {
+ }
+
+ void SetZero(bool zero)
+ {
+ std::unique_lock _lock(m_mtx);
+ m_zero = zero;
+ }
+
+ bool touch(void* p)
+ {
+ std::unique_lock _lock(m_mtx);
+ BS_MEM_TRACE_F("BS_MEM::touch(%p)\n", p);
+ return Touch(p);
+ }
+
+ void bound(void* dep, void* base)
+ {
+ std::unique_lock _lock(m_mtx);
+ BS_MEM_TRACE_F("BS_MEM::bound(%p, %p)\n", dep, base);
+
+ if (!Touch(base) || !Touch(dep))
+ throw std::bad_alloc();
+
+ m_mem[base].dep.insert(dep);
+ m_mem[dep].base.insert(base);
+ }
+
+ template T* alloc(void* base = nullptr, unsigned int count = 1)
+ {
+ if (count == 0)
+ return nullptr;
+
+ std::unique_lock _lock(m_mtx);
+
+ MemBase* pObj = new MemObj(count, m_zero);
+ T* p = (T*)pObj->Get();
+
+ m_mem[p].mem = pObj;
+
+ BS_MEM_TRACE_F("BS_MEM::alloc(%p, %d) = %p\n", base, count, p);
+ if (base)
+ bound(p, base);
+
+ return p;
+ }
+
+ template T* alloc_nozero(void* base = nullptr, unsigned int count = 1)
+ {
+ if (count == 0)
+ return nullptr;
+
+ std::unique_lock _lock(m_mtx);
+
+ MemBase* pObj = new MemObj(count, false);
+ T* p = (T*)pObj->Get();
+
+ m_mem[p].mem = pObj;
+
+ BS_MEM_TRACE_F("BS_MEM::alloc_nozero(%p, %d) = %p\n", base, count, p);
+ if (base)
+ bound(p, base);
+
+ return p;
+ }
+
+ void free(void* p)
+ {
+ std::unique_lock _lock(m_mtx);
+ BS_MEM_TRACE_F("BS_MEM::free(%p)", p);
+
+ if (!Touch(p))
+ throw std::bad_alloc();
+
+ auto& d = m_mem[p];
+
+ if (d.locked)
+ {
+ BS_MEM_TRACE_F(" - delayed\n", p);
+ d.to_delete = true;
+ return;
+ }
+
+ if (!d.base.empty())
+ {
+ BS_MEM_TRACE_F(" - delayed\n", p);
+ return;
+ }
+
+ BS_MEM_TRACE_F(" - done\n", p);
+
+ for (auto& pdep : d.dep)
+ {
+ auto& ddep = m_mem[pdep];
+
+ ddep.base.erase(p);
+
+ if (ddep.base.empty())
+ free(pdep);
+ }
+
+ m_mem.erase(p);
+ }
+
+ void lock(void* p)
+ {
+ std::unique_lock _lock(m_mtx);
+ BS_MEM_TRACE_F("BS_MEM::lock(%p)\n", p);
+
+ if (!Touch(p))
+ throw std::bad_alloc();
+
+ m_mem[p].locked++;
+ }
+
+ void unlock(void* p)
+ {
+ BS_MEM_TRACE_F("BS_MEM::unlock(%p)\n", p);
+
+ if (!p)
+ return;
+
+ std::unique_lock _lock(m_mtx);
+
+ if (!Touch(p))
+ throw std::bad_alloc();
+
+ auto& d = m_mem[p];
+
+ if (!m_mem[p].locked)
+ throw std::bad_alloc();
+
+ d.locked--;
+
+ if (d.to_delete)
+ free(p);
+ }
+#undef BS_MEM_TRACE_F
+};
+
+class AutoLock
+{
+public:
+ Allocator* m_pAllocator;
+ std::list m_ptr;
+
+ AutoLock(Allocator* pAllocator, void* ptr = 0)
+ : m_pAllocator(pAllocator)
+ {
+ if (m_pAllocator && ptr)
+ {
+ m_pAllocator->lock(ptr);
+ m_ptr.push_back(ptr);
+ }
+ }
+
+ ~AutoLock()
+ {
+ if (m_pAllocator)
+ {
+ for (auto p : m_ptr)
+ m_pAllocator->unlock(p);
+ }
+ }
+
+ void Add(void* p)
+ {
+ if (m_pAllocator)
+ {
+ m_pAllocator->lock(p);
+ m_ptr.push_back(p);
+ }
+ else
+ throw std::bad_alloc();
+ }
+};
+
+};
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_parser++.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_parser++.h
new file mode 100644
index 0000000..825cf57
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_parser++.h
@@ -0,0 +1,90 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __BS_PARSER_PP_H
+#define __BS_PARSER_PP_H
+
+#include
+#include
+
+class BS_parser{
+public:
+ BS_parser(){};
+ virtual BSErr open(const char* file) = 0;
+ virtual BSErr set_buffer(byte* buf, Bs32u buf_size) = 0;
+ virtual BSErr parse_next_unit() = 0;
+ virtual BSErr reset() = 0;
+ virtual BSErr lock (void* p) = 0;
+ virtual BSErr unlock(void* p) = 0;
+ virtual void* get_header() = 0;
+ virtual void* get_handle() = 0;
+ virtual Bs64u get_offset() = 0;
+ virtual void set_trace_level(Bs32u level) = 0;
+ virtual BSErr sync(void* p) { (void) p; return BS_ERR_NONE; };
+ virtual Bs16u async_depth() { return 0; }
+ virtual ~BS_parser(){};
+};
+
+class BS_HEVC2_parser : public BS_parser{
+public:
+ typedef BS_HEVC2::NALU UnitType;
+
+ BS_HEVC2_parser(Bs32u mode = 0)
+ {
+ BS_HEVC2_Init(hdl, mode);
+ hdr = 0;
+ };
+
+ BS_HEVC2_parser(BS_HEVC2_parser const&) = delete;
+ BS_HEVC2_parser& operator=(BS_HEVC2_parser const&) = delete;
+
+ ~BS_HEVC2_parser() { BS_HEVC2_Close(hdl); };
+
+ BSErr parse_next_au(UnitType*& pAU) { return BS_HEVC2_ParseNextAU(hdl, pAU); };
+ BSErr parse_next_unit() { return BS_HEVC2_ParseNextAU(hdl, hdr); };
+ BSErr open(const char* file) { return BS_HEVC2_OpenFile(hdl, file); };
+ BSErr set_buffer(byte* buf, Bs32u buf_size) { return BS_HEVC2_SetBuffer(hdl, buf, buf_size); };
+ BSErr lock(void* p) { return BS_HEVC2_Lock(hdl, p); };
+ BSErr unlock(void* p) { return BS_HEVC2_Unlock(hdl, p); };
+ BSErr sync(void* p) { return BS_HEVC2_Sync(hdl, (BS_HEVC2::NALU*)p); };
+ Bs16u async_depth() { return BS_HEVC2_GetAsyncDepth(hdl); }
+
+ void set_trace_level(Bs32u level) { BS_HEVC2_SetTraceLevel(hdl, level); };
+ void* get_header() { return hdr; };
+ void* get_handle() { return hdl; };
+ Bs64u get_offset() {
+ Bs64u offset = -1;
+ BS_HEVC2_GetOffset(hdl, offset);
+ return offset;
+ };
+
+ BSErr reset()
+ {
+ BS_HEVC2_Close(hdl);
+ hdr = 0;
+ return BS_HEVC2_Init(hdl, 0);
+ };
+private:
+ BS_HEVC2::HDL hdl;
+ UnitType* hdr;
+};
+
+
+#endif //__BS_PARSER_PP_H
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_parser.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_parser.h
new file mode 100644
index 0000000..a03f599
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_parser.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __BS_PARSER_H
+#define __BS_PARSER_H
+
+#include
+
+extern "C"{
+
+ BSErr __STDCALL BS_HEVC2_Init (BS_HEVC2::HDL& hdl, Bs32u mode);
+ BSErr __STDCALL BS_HEVC2_OpenFile (BS_HEVC2::HDL hdl, const char* file);
+ BSErr __STDCALL BS_HEVC2_SetBuffer (BS_HEVC2::HDL hdl, byte* buf, Bs32u buf_size);
+ BSErr __STDCALL BS_HEVC2_ParseNextAU (BS_HEVC2::HDL hdl, BS_HEVC2::NALU*& pAU);
+ BSErr __STDCALL BS_HEVC2_Close (BS_HEVC2::HDL hdl);
+ BSErr __STDCALL BS_HEVC2_SetTraceLevel (BS_HEVC2::HDL hdl, Bs32u level);
+ BSErr __STDCALL BS_HEVC2_Lock (BS_HEVC2::HDL hdl, void* p);
+ BSErr __STDCALL BS_HEVC2_Unlock (BS_HEVC2::HDL hdl, void* p);
+ BSErr __STDCALL BS_HEVC2_GetOffset (BS_HEVC2::HDL hdl, Bs64u& offset);
+ BSErr __STDCALL BS_HEVC2_Sync (BS_HEVC2::HDL hdl, BS_HEVC2::NALU* slice);
+ Bs16u __STDCALL BS_HEVC2_GetAsyncDepth (BS_HEVC2::HDL hdl);
+
+}
+
+
+#endif //__BS_PARSER_H
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_reader.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_reader.h
new file mode 100644
index 0000000..0054d5e
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_reader.h
@@ -0,0 +1,247 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#ifndef __BS_READER_H
+#define __BS_READER_H
+
+#include
+#include
+#include
+#include
+#include
+
+#define BS_BUF_SIZE 2048
+#if defined(__APPLE__) || defined(LINUX32) || defined(LINUX64) || defined(ANDROID)
+ #define BS_FILE_MODE 0 /* no fteelo64 on OSX */
+#else
+ #define BS_FILE_MODE 1
+#endif
+
+#if (BS_FILE_MODE == 1)
+ #define BS_FADDR_TYPE Bs64u
+ #define BS_FOFFSET_TYPE Bs64s
+ #define BS_TRACE_FORMAT "0x%016I64X[%i]: %s = %i\n"
+ #define BS_TRACE_OFFSET_FORMAT "0x%016I64X[%i]: "
+ #ifdef __GNUC__
+ #define _FILE_OFFSET_BITS 64
+ #define BS_FTELL(fh) ftello64(fh)
+ #define BS_FSEEK(fh,offset,origin) fseeko64( fh, offset, origin )
+ #else
+ #include
+ #include
+ #include
+ #define BS_FH_TYPE int
+ #define BS_FOPEN(file, fh) { int tmp_fh = 0; if(!_sopen_s(&tmp_fh, file_name, _O_BINARY|_O_RDONLY, _SH_DENYNO, 0))fh = tmp_fh;}
+ #define BS_FCLOSE(fh) _close(fh)
+ #define BS_FTELL(fh) _telli64(fh)
+ #define BS_FEOF(fh) _eof(fh)
+ #define BS_FREAD(fh,dst,size) _read(fh, dst, size)
+ #define BS_FSEEK(fh,offset,origin) _lseeki64( fh, offset, origin )
+ #endif
+#endif
+#if (BS_FILE_MODE == 0) || defined(__GNUC__)
+ #if (BS_FILE_MODE == 0)
+ #define BS_FADDR_TYPE Bs32u
+ #define BS_FOFFSET_TYPE Bs32s
+ #define BS_TRACE_FORMAT "0x%08X[%i]: %s = %i\n"
+ #define BS_TRACE_OFFSET_FORMAT "0x%08X[%i]: "
+ #define BS_FTELL(fh) ftell(fh)
+ #define BS_FSEEK(fh,offset,origin) fseek( fh, offset, origin )
+ #endif
+ #define BS_FH_TYPE FILE*
+ #define BS_FOPEN(file, fh) {fh = fopen( file_name, "rb" );}
+ #define BS_FCLOSE(fh) fclose(fh)
+ #define BS_FEOF(fh) feof(fh)
+ #define BS_FREAD(fh,dst,size) fread( dst, 1, size, fh )
+#endif
+
+#ifdef __BS_TRACE__
+ #define BS_TRACE( val, comment ) { \
+ if(trace_flag) {printf( BS_TRACE_FORMAT, file_pos+offset, bit, #comment, (int)(val) ); fflush(stdout);}\
+ else (val); \
+ if(last_err) return last_err; \
+ }
+ #define BS_SET( val, var ) { \
+ if(trace_flag){ printf( BS_TRACE_FORMAT, file_pos+offset, bit, #var, (int)((var) = (val)) ); fflush(stdout);} \
+ else (var) = (val); \
+ if(last_err) return last_err; \
+ }
+ #define BS_GET_BITS( n, var ) { \
+ (var) = (tmp_buf)>>(32-(n)); tmp_buf <<= (n);\
+ if(trace_flag) printf( BS_TRACE_FORMAT, file_pos+offset, bit, #var, (var) ); \
+ }
+ #define BS_TRACE_BITS( n, var ) { \
+ if(trace_flag) printf( BS_TRACE_FORMAT, file_pos+offset, bit, #var, ((tmp_buf)>>(32-(n))) ); \
+ tmp_buf <<= n;\
+ }
+ #define BS_TROX( x, b ) if(trace_flag) printf(BS_TRACE_OFFSET_FORMAT, (unsigned int)(x), (b));
+ #define BS_TRO if(trace_flag) printf(BS_TRACE_OFFSET_FORMAT,file_pos+offset, bit);
+ #define BS_SETM( val, var, map ) {\
+ if(trace_flag) {BS_TRO; (var) = (val); printf("%s = %s (%d)\n", #var, map[var], var);}\
+ else (var) = (val);\
+ if(last_err) return last_err; \
+ }
+ #define BS_TRACE_ARR(name, el, sz) \
+ if(trace_flag){\
+ printf("%s = { ", #name);\
+ for(Bs32u _idx = 0; _idx < (Bs32u)(sz); _idx++ ) {\
+ printf("%d ", (el));\
+ }\
+ printf("}\n");\
+ } else for(Bs32u _idx = 0; _idx < (Bs32u)(sz); _idx++ ) { (el); }
+ #define BS_TRACE_NO_OFFSET( val, comment ) { \
+ if(trace_flag) printf( "%s = %d\n", #comment, (val) ); \
+ else (val); \
+ if(last_err) return last_err; \
+ }
+ #define BS_TRACE_STR( str ) { if(trace_flag) printf( "%s\n", str ); }
+#else
+ #define BS_TRACE( val, comment ) { (val); if(last_err) return last_err; }
+ #define BS_SET( val, var ) { (var) = (val); if(last_err) return last_err; }
+ #define BS_GET_BITS( n, var ) { (var) = (tmp_buf)>>(32-(n)); tmp_buf <<= (n);}
+ #define BS_TRACE_BITS( n, var ) { tmp_buf <<= (n); }
+ #define BS_TROX( x, b ) { (x); (b); };
+ #define BS_TRO {}
+ #define BS_SETM( val, var, map ) BS_SET( val, var )
+ #define BS_TRACE_ARR(name, el, sz)for(Bs32u _idx = 0; _idx < (Bs32u)(sz); _idx++ ) { (el); }
+ #define BS_TRACE_NO_OFFSET( val, comment ) BS_TRACE( val, comment )
+ #define BS_TRACE_STR( str ) {}
+#endif
+
+#define BS_STRUCT_ALLOC( type, var ){ \
+ var = (type*)malloc( sizeof(type) ); \
+ if(var){ \
+ memset( var, 0, sizeof(type) ); \
+ }else{ \
+ return last_err = BS_ERR_MEM_ALLOC; \
+ }; \
+ /*printf("BS_STRUCT_ALLOC:\t0x%p ( %i ) \t %s : %i\n", var, sizeof(type), __FILE__, __LINE__ );*/\
+}
+#define BS_CALLOC( type, size, var ){ \
+ var = (type*)calloc( (size), sizeof(type) ); \
+ if(!var) return last_err = BS_ERR_MEM_ALLOC; \
+ /*printf("BS_CALLOC:\t\t0x%p ( %i * %i ) \t %s : %i\n", var, sizeof(type), (size), __FILE__, __LINE__ );*/\
+}
+#define BS_FREE(p) {if(p){ free(p); p = NULL;}}
+#define BSCE if(last_err) return last_err;
+
+class BS_Reader{
+public:
+ BS_Reader(){
+ last_err = BS_ERR_NONE;
+ bs = NULL;
+ buf_size = 0;
+ file_pos = 0;
+ offset = 0;
+ bit = 0;
+ buf = NULL;
+ ignore_bytes = (BS_FADDR_TYPE*)malloc(sizeof(BS_FADDR_TYPE));
+ ignore_bytes_cnt = 0;
+ next_ignored_byte = NULL;
+ tmp_buf = 0;
+ trace_flag = true;
+ trace_level = 0xFFFFFFFF;
+ }
+
+ BS_Reader(BS_Reader const&) = delete;
+ BS_Reader& operator=(BS_Reader const&) = delete;
+
+ virtual ~BS_Reader(){
+ if( bs && buf ) free( buf );
+ close();
+ if( ignore_bytes ) free(ignore_bytes);
+ }
+
+ BSErr open( const char* file_name );
+ void set_buffer( byte* buf, Bs32u buf_size );
+
+ inline BSErr get_last_err(){ return last_err; };
+ inline BS_FADDR_TYPE get_cur_pos() { return file_pos+offset; };
+ inline BSErr close(){
+ last_err = (bs) ? ( BS_FCLOSE(bs) ? BS_ERR_UNKNOWN : BS_ERR_NONE ) : BS_ERR_NONE;
+ if(!last_err) bs = 0;
+ return last_err;
+ };
+ inline void set_trace_level(Bs32u level) {trace_level = level;};
+
+protected:
+ Bs32u buf_size;
+ Bs32u offset;
+ byte bit;
+ BS_FADDR_TYPE file_pos;
+ BSErr last_err;
+
+ Bs32u tmp_buf;
+ bool trace_flag;
+ Bs32u trace_level;
+
+ inline void trace_on(Bs32u level) {trace_flag = !!(trace_level & level);};
+ inline void trace_off() {trace_flag = (trace_level == 0xFFFFFFFF);};
+
+ Bs32u ue_v();
+ Bs32s se_v();
+ Bs32u read_bits( Bs32u nBits /*1..32*/ );
+ Bs32u next_bits( Bs32u nBits /*1..32*/ ); // keep current position
+ Bs32u next_bytes( byte nBytes /*1..4*/ );
+ byte read_1_bit();
+ byte read_1_byte();
+ BSErr read_arr(byte* arr, Bs32u size);
+
+ void skip_bytes( Bs32u nBytes );
+ void ignore_next_byte();
+ BSErr shift(long nBytes);
+ BSErr shift_forward( Bs32u nBytes );
+ BSErr shift_back( Bs32u nBytes );
+
+ inline BSErr shift_forward64(Bs64u nBytes){
+ while(nBytes){
+ Bs32u n = (Bs32u)BS_MIN(nBytes,0xFFFFFFFF);
+ shift_forward(n);BSCE;
+ nBytes -= n;
+ }
+ return last_err;
+ };
+
+ inline bool byte_aligned() { return bit ? false : true; };
+ inline void skip_byte() { shift_forward(1); };
+ inline void set_first_ignored_byte() { next_ignored_byte = &ignore_bytes[0]; };
+ inline void wipe_ignore_bytes() { ignore_bytes_cnt = 0; next_ignored_byte = NULL; };
+ Bs32u get_num_ignored_bytes(BS_FADDR_TYPE end){
+ Bs32u n = 0;
+ BS_FADDR_TYPE* b = next_ignored_byte;
+ Bs32u c = 0;
+
+ while(c < ignore_bytes_cnt && b[c++] < end++)
+ n++;
+
+ return n;
+ }
+
+private:
+ BS_FH_TYPE bs; //file handle
+ byte* buf;
+ BS_FADDR_TYPE* ignore_bytes;
+ BS_FADDR_TYPE* next_ignored_byte;
+ Bs32u ignore_bytes_cnt;
+
+ BSErr read_more_data();
+
+};
+#endif //__BS_READER_H
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_reader2.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_reader2.h
new file mode 100644
index 0000000..05f16bf
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_reader2.h
@@ -0,0 +1,418 @@
+// Copyright (c) 2018-2020 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#pragma once
+
+#include "bs_def.h"
+#include
+#include
+#include
+#include
+
+namespace BsReader2
+{
+
+class Exception : public std::exception
+{
+private:
+ BSErr m_sts;
+public:
+ Exception(BSErr sts)
+ : std::exception()
+ , m_sts(sts)
+ { /*assert(!"Error in bs_parser!");*/ }
+ inline BSErr Err() { return m_sts; }
+};
+
+class EndOfBuffer : public Exception
+{
+public:
+ EndOfBuffer() : Exception(BS_ERR_MORE_DATA) {}
+};
+
+class InvalidSyntax : public Exception
+{
+public:
+ InvalidSyntax() : Exception(BS_ERR_UNKNOWN) { /*assert(!"invalid syntax!");*/ }
+};
+
+class BufferUpdater
+{
+public:
+ virtual bool UpdateBuffer(Bs8u*& start, Bs8u*& cur, Bs8u*& end, Bs32u keepBytes) = 0;
+ virtual ~BufferUpdater() {};
+};
+
+class File : public BufferUpdater
+{
+private:
+ FILE* m_f;
+ std::vector m_b;
+ static const Bs32u DEFAULT_BUFF_SIZE = 2048;
+public:
+ File();
+ ~File();
+
+ bool Open(const char* file, Bs32u buffSize = DEFAULT_BUFF_SIZE);
+ void Close();
+ bool UpdateBuffer(Bs8u*& start, Bs8u*& cur, Bs8u*& end, Bs32u keepBytes);
+};
+
+#ifdef __BS_TRACE__
+
+#define BS2_TRO { if (TraceOffset()) fprintf(GetLog(), "0x%016llX[%i]: ", GetByteOffset(), GetBitOffset()); }
+
+#define BS2_SET(val, var) \
+{ \
+ if (Trace()) { \
+ BS2_TRO; \
+ var = (val); \
+ fprintf(GetLog(), std::is_same::value ? "%s = %lli\n" : "%s = %i\n", #var, var);\
+ fflush(GetLog()); \
+ } else { var = (val); } \
+}
+
+#define BS2_SETM(val, var, map) \
+{ \
+ if (Trace()) { \
+ BS2_TRO; \
+ var = (val); \
+ fprintf(GetLog(), "%s = %s(%d)\n", #var, map[var], var); \
+ fflush(GetLog()); \
+ } else { var = (val); } \
+}
+
+#define BS2_TRACE(val, var) \
+{ \
+ if (Trace()) { \
+ BS2_TRO; \
+ fprintf(GetLog(), std::is_same::value ? "%s = %lli\n" : "%s = %i\n", #var, (val));\
+ fflush(GetLog()); } \
+ else { (val); } \
+}
+
+#define BS2_TRACE_STR(str)\
+ { if (Trace()) { BS2_TRO; fprintf(GetLog(), "%s\n", (str)); fflush(GetLog());} }
+
+#define BS2_SET_ARR_F(val, var, sz, split, format) \
+{ \
+ if (Trace()){ \
+ BS2_TRO; \
+ fprintf(GetLog(), "%s = { ", #var); \
+ for (Bs32u _i = 0; _i < Bs32u(sz); _i++){ \
+ if ((split) != 0 && _i % (split) == 0) \
+ fprintf(GetLog(), "\n"); \
+ (var)[_i] = (val); \
+ fprintf(GetLog(), format, (var)[_i]); \
+ } \
+ fprintf(GetLog(), "}\n"); fflush(GetLog()); \
+ } else { for (Bs32u _i = 0; _i < (sz); _i++) (var)[_i] = (val); } \
+}
+
+#define BS2_SET_ARR_M(val, var, sz, split, format, map) \
+{ \
+ if (Trace()){ \
+ BS2_TRO; \
+ fprintf(GetLog(), "%s = { ", #var); \
+ for (Bs32u _i = 0; _i < Bs32u(sz); _i++) { \
+ if ((split) != 0 && _i % (split) == 0) \
+ fprintf(GetLog(), "\n"); \
+ (var)[_i] = (val); \
+ fprintf(GetLog(), format, map[(var)[_i]], (var)[_i]);\
+ } \
+ fprintf(GetLog(), "}\n"); fflush(GetLog()); \
+ } \
+ else { for (Bs32u _i = 0; _i < (sz); _i++) (var)[_i] = (val); } \
+}
+
+#define BS2_TRACE_ARR_VF(val, var, sz, split, format) \
+{ \
+ if (Trace()){ \
+ BS2_TRO; \
+ fprintf(GetLog(), "%s = { ", #var); \
+ for (Bs32u _i = 0; _i < Bs32u(sz); _i++) { \
+ if ((split) != 0&& _i % (split) == 0) \
+ fprintf(GetLog(), "\n"); \
+ fprintf(GetLog(), format, (val)); \
+ } \
+ fprintf(GetLog(), "}\n"); fflush(GetLog());\
+ } \
+ else { for (Bs32u _i = 0; _i < (sz); _i++) (val); }\
+}
+
+#define BS2_TRACE_MDARR(type, arr, dim, split, split2, format)\
+{ \
+ if (Trace()){ \
+ BS2_TRO; \
+ fprintf(GetLog(), "%s = \n", #arr); \
+ traceMDArr\
+ (arr, dim, split, format, split2); \
+ fflush(GetLog()); \
+ } \
+}
+
+#define BS2_TRACE_BIN(pval, off, sz, var) \
+{ \
+ if (Trace()) { \
+ BS2_TRO; \
+ fprintf(GetLog(), "%s = ", #var);\
+ traceBin(pval, off, sz); \
+ fprintf(GetLog(), "\n"); \
+ fflush(GetLog()); \
+ } \
+ else { (pval); } \
+}
+
+#else
+
+#define BS2_TRO
+#define BS2_SET(val, var) { var = (val); }
+#define BS2_TRACE(val, var) {(void)(val);}
+#define BS2_TRACE_STR(str) {(void)(str);}
+#define BS2_SET_ARR_F(val, var, sz, split, format) \
+ { for (Bs32u _i = 0; _i < (Bs32u)(sz); _i++) (var)[_i] = (val); }
+#define BS2_TRACE_ARR_VF(val, var, sz, split, format) \
+ { for (Bs32u _i = 0; _i < (Bs32u)(sz); _i++) (void)(val); }
+#define BS2_TRACE_MDARR(type, arr, dim, split, split2, format) { (void)(arr);}
+#define BS2_SET_ARR_M(val, var, sz, split, format, map) BS2_SET_ARR_F(val, var, sz, split, format)
+#define BS2_SETM(val, var, map) BS2_SET(val, var)
+#define BS2_TRACE_BIN(pval, off, sz, var) { (void)(pval); }
+
+#endif
+
+#define BS2_SET_ARR(val, var, sz, split) BS2_SET_ARR_F(val, var, sz, split, "%i ")
+#define BS2_TRACE_ARR_F(var, sz, split, format) BS2_TRACE_ARR_VF(var[_i], var, sz, split, format)
+#define BS2_TRACE_ARR(var, sz, split) BS2_TRACE_ARR_F(var, sz, split, "%i ")
+
+struct State
+{
+ BufferUpdater* m_updater;
+ Bs8u* m_bsStart;
+ Bs8u* m_bsEnd;
+ Bs8u* m_bs;
+ Bs8u m_bitStart;
+ Bs8u m_bitOffset;
+ bool m_emulation;
+ Bs32u m_emuBytes;
+ Bs64u m_startOffset;
+ bool m_trace;
+ bool m_traceOffset;
+ Bs32u m_traceLevel;
+ FILE* m_log;
+};
+
+class Reader : private State
+{
+public:
+ Reader();
+ ~Reader();
+
+ Bs32u GetBit();
+ Bs32u GetBits(Bs32u n);
+ void GetBits(void* b, Bs32u o, Bs32u n);
+ Bs32u GetUE();
+ Bs32s GetSE();
+ Bs32u GetByte(); // ignore bit offset
+ Bs32u GetBytes(Bs32u n, bool nothrow = false); // ignore bit offset
+
+ void ReturnByte();
+ void ReturnBits(Bs32u n);
+
+ bool NextStartCode(bool stopBefore);
+
+ bool TrailingBits(bool stopBefore = false);
+ bool NextBytes(Bs8u* b, Bs32u n);
+
+ inline Bs32u NextBits(Bs32u n)
+ {
+ Bs32u b = GetBits(n);
+ ReturnBits(n);
+ return b;
+ }
+
+ Bs32u ExtractRBSP(Bs8u* buf, Bs32u size);
+ Bs32u ExtractData(Bs8u* buf, Bs32u size);
+
+ inline Bs64u GetByteOffset() { return m_startOffset + (m_bs - m_bsStart); }
+ inline Bs16u GetBitOffset() { return m_bitOffset; }
+
+ inline void SetEmulation(bool f) { m_emulation = f; };
+ inline bool GetEmulation() { return m_emulation; };
+
+ inline void SetEmuBytes(Bs32u f) { m_emuBytes = f; };
+ inline Bs32u GetEmuBytes() { return m_emuBytes; };
+
+ void Reset(Bs8u* bs = 0, Bs32u size = 0, Bs8u bitOffset = 0);
+ void Reset(BufferUpdater* reader) { m_updater = reader; m_bsEnd = 0; m_startOffset = 0; }
+
+ void SaveState(State& st){ st = *this; };
+ void LoadState(State& st){ *(State*)this = st; };
+
+#ifdef __BS_TRACE__
+ inline bool Trace() { return m_trace; }
+ inline bool TraceOffset() { return m_traceOffset; }
+ inline void TLStart(Bs32u level) { m_trace = !!(m_traceLevel & level); m_tln++; m_tla |= (Bs64u(m_trace) << m_tln); };
+ inline void TLEnd() { m_tla &= ~(Bs64u(1) << m_tln); m_tln--; m_trace = !!(1 & (m_tla >> m_tln)); };
+ inline bool TLTest(Bs32u tl) { return !!(m_traceLevel & tl); }
+ inline void SetTraceLevel(Bs32u level) { m_traceLevel = level; m_traceOffset = !!(level & 0x80000000); };
+#else
+ inline bool Trace() { return false; }
+ inline bool TraceOffset() { return false; }
+ inline void TLStart(Bs32u /*level*/) { };
+ inline void TLEnd() {};
+ inline bool TLTest(Bs32u /*tl*/) { return false; }
+ inline void SetTraceLevel(Bs32u /*level*/) { };
+#endif
+
+ inline FILE* GetLog() { return m_log; }
+ inline void SetLog(FILE* log) { m_log = log; }
+
+ template void traceMDArr(
+ const void* arr,
+ const Bs16u* sz,
+ Bs16u split,
+ const char* format,
+ Bs16u split2 = 0)
+ {
+ Bs16u off[depth];
+ for (Bs32u i = 0; i < depth; i++)
+ {
+ off[i] = 1;
+ for (Bs32u j = i + 1; j < depth; j++)
+ off[i] *= sz[j];
+ }
+ for (Bs32u i = 0, j = 0; i < Bs32u(off[0] * sz[0]); i++)
+ {
+ while (i % off[j] == 0)
+ {
+ fprintf(GetLog(), "{ ");
+
+ if (j < (split))
+ {
+ fprintf(GetLog(), "\n");
+ for (Bs32u c = 0; c <= j; c++)
+ fprintf(GetLog(), " ");
+ }
+ if (j == depth - 2)
+ break;
+ j++;
+ }
+ fprintf(GetLog(), format, ((const T*)arr)[i]);
+ if (split2 && (i + 1) % split2 == 0
+ && (i + 1) / split2 > 0
+ && (i + 1) % off[j] != 0)
+ {
+ fprintf(GetLog(), "\n");
+ for (Bs32u c = 0; c <= j; c++)
+ fprintf(GetLog(), " ");
+ }
+ while ((i + 1) % off[j] == 0)
+ {
+ bool f = j ? (i + 1) % off[--j] == 0 : !!j--;
+ fprintf(GetLog(), "} ");
+ if (j < (split))
+ {
+ fprintf(GetLog(), "\n");
+ for (Bs32u c = 0; c + f <= j; c++)
+ fprintf(GetLog(), " ");
+ }
+ if (!f)
+ {
+ j++;
+ break;
+ }
+ }
+ }
+ fprintf(GetLog(), "\n");
+ }
+
+ template void traceBin(T* p, Bs32u off, Bs32u sz)
+ {
+ Bs32u S0 = sizeof(T) * 8;
+ Bs32u O = off;
+ T* P0 = p;
+
+ if (off + sz > BS_MAX(S0, 32))
+ {
+ fprintf(GetLog(), "\n");
+
+ for (Bs32u i = 0; i < off; i++)
+ fprintf(GetLog(), " ");
+ }
+
+ while (sz)
+ {
+ Bs32u S = S0 - O;
+ Bs32u S1 = S0 - (O + BS_MIN(sz, S));
+
+ sz -= (S - S1);
+
+ while (S-- > S1)
+ fprintf(GetLog(), "%d", !!(*p & (1 << S)));
+
+ p++;
+ O = 0;
+
+ if (sz)
+ {
+ if ((p - P0) * S0 % 32 == 0)
+ fprintf(GetLog(), "\n");
+ else
+ fprintf(GetLog(), " ");
+ }
+ }
+ }
+
+private:
+ Bs64u m_tla;
+ Bs32u m_tln;
+
+ void MoreData(Bs32u keepBytes = 4);
+ bool MoreDataNoThrow(Bs32u keepBytes = 4);
+};
+
+class TLAuto
+{
+private:
+ Reader& m_r;
+public:
+ TLAuto(Reader& r, Bs32u tl) : m_r(r) { m_r.TLStart(tl); }
+ ~TLAuto() { m_r.TLEnd(); }
+};
+
+class StateSwitcher
+{
+private:
+ State m_st;
+ Reader& m_r;
+public:
+ StateSwitcher(Reader& r)
+ : m_r(r)
+ {
+ m_r.SaveState(m_st);
+ }
+
+ ~StateSwitcher()
+ {
+ m_r.LoadState(m_st);
+ }
+};
+
+}
\ No newline at end of file
diff --git a/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_thread.h b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_thread.h
new file mode 100644
index 0000000..de1cd75
--- /dev/null
+++ b/apk/v3.13/main/intel-media-sdk/src/MediaSDK-intel-mediasdk-21.1.3/tools/bs_parser_hevc/include/bs_thread.h
@@ -0,0 +1,115 @@
+// Copyright (c) 2018-2019 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+#pragma once
+#include
+#include
+#include
+#include
+#include