1 // Copyright (c) 2018-2020 Intel Corporation
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in all
11 // copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 #ifndef __MFX_H264_ENC_COMMON_HW_H__
22 #define __MFX_H264_ENC_COMMON_HW_H__
23 
24 #if defined(AS_H264LA_PLUGIN) && defined(MFX_ENABLE_ENCTOOLS)
25 #undef MFX_ENABLE_ENCTOOLS
26 #endif
27 
28 #include "mfx_common.h"
29 #include "mfxla.h"
30 
31 #if defined (MFX_ENABLE_H264_VIDEO_ENCODE_HW)
32 
33 #include <vector>
34 #include <assert.h>
35 #include <memory>
36 #include "mfx_ext_buffers.h"
37 #include "mfxfei.h"
38 #ifdef MFX_ENABLE_ENCTOOLS
39 #include "mfxenctools-int.h"
40 #else
41 #include "mfxbrc.h"
42 #endif
43 #include "mfx_h264_encode_struct_vaapi.h"
44 
45 #if defined(MFX_VA_LINUX)
46 #include <va/va.h>
47 #include <va/va_enc_h264.h>
48 #endif
49 #include "mfxmvc.h"
50 
51 #include "umc_defs.h"
52 
53 #define ENABLE_APQ_LQ
54 
55 
56 #define D3DFMT_NV12 (D3DFORMAT)(MFX_MAKEFOURCC('N', 'V', '1', '2'))
57 #define D3DDDIFMT_NV12 (D3DDDIFORMAT)(MFX_MAKEFOURCC('N', 'V', '1', '2'))
58 #define D3DDDIFMT_YU12 (D3DDDIFORMAT)(MFX_MAKEFOURCC('Y', 'U', '1', '2'))
59 
60 // this guid is used to identify that device creation is performed during Query or QueryIOSurf call
61 static const GUID MSDK_Private_Guid_Encode_AVC_Query =
62 { 0x32560c63, 0xe3dc, 0x43c9, { 0xa8, 0x16, 0xda, 0x73, 0x36, 0x45, 0x89, 0xe9 } };
63 // this guid is used to identify device creation for MVC BD/AVCHD dependent view
64 static const GUID MSDK_Private_Guid_Encode_MVC_Dependent_View =
65 { 0x68bebcda, 0xefff, 0x4858, { 0x8d, 0x65, 0x92, 0x28, 0xab, 0xc5, 0x8c, 0x4e } };
66 // this guid is used to identify that device creation is performed during for low power encoder
67 static const GUID MSDK_Private_Guid_Encode_AVC_LowPower_Query =
68 { 0x6815aa23, 0xc93e, 0x4a71, { 0xae, 0x66, 0xb, 0x60, 0x5d, 0x3b, 0xc4, 0xd7 } };
69 
70 namespace MfxHwH264Encode
71 {
72     class  DdiTask;
73     class  InputBitstream;
74     class  OutputBitstream;
75     struct mfxExtSpsHeader;
76     struct mfxExtPpsHeader;
77 
78     const mfxU16 CROP_UNIT_X[] = { 1, 2, 2, 1 };
79     const mfxU16 CROP_UNIT_Y[] = { 1, 2, 1, 1 };
80 
81     static const mfxU16 MFX_PICSTRUCT_PART1 = MFX_PICSTRUCT_PROGRESSIVE | MFX_PICSTRUCT_FIELD_TFF | MFX_PICSTRUCT_FIELD_BFF;
82     static const mfxU16 MFX_PICSTRUCT_PART2 = MFX_PICSTRUCT_FIELD_REPEATED | MFX_PICSTRUCT_FRAME_DOUBLING | MFX_PICSTRUCT_FRAME_TRIPLING;
83 
84     static const mfxU16 MFX_PICSTRUCT_FRAME_FLAGS = MFX_PICSTRUCT_FRAME_DOUBLING | MFX_PICSTRUCT_FRAME_TRIPLING;
85     static const mfxU16 MFX_PICSTRUCT_FIELD_FLAGS = MFX_PICSTRUCT_FIELD_REPEATED;
86 
87     static const mfxU8 SEI_TYPE_BUFFERING_PERIOD               = 0;
88     static const mfxU8 SEI_TYPE_PIC_TIMING                     = 1;
89     static const mfxU8 SEI_TYPE_FILLER_PAYLOAD                 = 3;
90     static const mfxU8 SEI_TYPE_RECOVERY_POINT                 = 6;
91     static const mfxU8 SEI_TYPE_DEC_REF_PIC_MARKING_REPETITION = 7;
92     static const mfxU8 SEI_TYPE_SCALABILITY_INFO               = 24;
93 // MVC BD {
94     static const mfxU8 SEI_TYPE_MVC_SCALABLE_NESTING           = 37;
95 // MVC BD }
96 
97     static const mfxU16 MFX_RATECONTROL_WIDI_VBR = 100;
98 
99     // internally used buffers
100     static const mfxU32 MFX_EXTBUFF_SPS_HEADER     = MFX_MAKEFOURCC(0xff, 'S', 'P', 'S');
101     static const mfxU32 MFX_EXTBUFF_PPS_HEADER     = MFX_MAKEFOURCC(0xff, 'P', 'P', 'S');
102 
103     static const mfxU16 MFX_FRAMETYPE_IPB     = MFX_FRAMETYPE_I | MFX_FRAMETYPE_P | MFX_FRAMETYPE_B;
104     static const mfxU16 MFX_FRAMETYPE_PB      = MFX_FRAMETYPE_P | MFX_FRAMETYPE_B;
105     static const mfxU16 MFX_FRAMETYPE_PREF    = MFX_FRAMETYPE_P | MFX_FRAMETYPE_REF;
106     static const mfxU16 MFX_FRAMETYPE_IREF    = MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF;
107     static const mfxU16 MFX_FRAMETYPE_IREFIDR = MFX_FRAMETYPE_I | MFX_FRAMETYPE_REF | MFX_FRAMETYPE_IDR;
108     static const mfxU16 MFX_FRAMETYPE_xIPB    = MFX_FRAMETYPE_xI | MFX_FRAMETYPE_xP | MFX_FRAMETYPE_xB;
109     static const mfxU16 MFX_FRAMETYPE_xPREF   = MFX_FRAMETYPE_xP | MFX_FRAMETYPE_xREF;
110     static const mfxU16 MFX_FRAMETYPE_xIREF   = MFX_FRAMETYPE_xI | MFX_FRAMETYPE_xREF;
111     static const mfxU16 MFX_FRAMETYPE_KEYPIC  = 0x0020;
112 
113     static const mfxU16 MFX_IOPATTERN_IN_MASK_SYS_OR_D3D =
114         MFX_IOPATTERN_IN_SYSTEM_MEMORY | MFX_IOPATTERN_IN_VIDEO_MEMORY;
115 
116     static const mfxU16 MFX_IOPATTERN_IN_MASK =
117         MFX_IOPATTERN_IN_MASK_SYS_OR_D3D | MFX_IOPATTERN_IN_OPAQUE_MEMORY;
118 
119     // masks for VideoParam.mfx.CodecProfile
120     static const mfxU16 MASK_PROFILE_IDC          = (0xff);
121     static const mfxU16 MASK_CONSTRAINT_SET0_FLAG = (0x100 << 0);
122     static const mfxU16 MASK_CONSTRAINT_SET1_FLAG = (0x100 << 1);
123     static const mfxU16 MASK_CONSTRAINT_SET2_FLAG = (0x100 << 2);
124     static const mfxU16 MASK_CONSTRAINT_SET3_FLAG = (0x100 << 3);
125     static const mfxU16 MASK_CONSTRAINT_SET4_FLAG = (0x100 << 4);
126     static const mfxU16 MASK_CONSTRAINT_SET5_FLAG = (0x100 << 5);
127     static const mfxU16 MASK_CONSTRAINT_SET6_FLAG = (0x100 << 6);
128     static const mfxU16 MASK_CONSTRAINT_SET7_FLAG = (0x100 << 7);
129     static const mfxU16 MASK_CONSTRAINT_SET0123_FLAG =  MASK_CONSTRAINT_SET0_FLAG | MASK_CONSTRAINT_SET1_FLAG | MASK_CONSTRAINT_SET2_FLAG | MASK_CONSTRAINT_SET3_FLAG;
130 
SecondHalfOf(std::vector<T> & v)131     template<class T> inline T* SecondHalfOf(std::vector<T>& v) { return &v[v.size() / 2]; }
132 
Zero(T & obj)133     template<class T> inline void Zero(T & obj)                { memset(reinterpret_cast<void*>(&obj), 0, sizeof(obj)); }
Zero(std::vector<T> & vec)134     template<class T> inline void Zero(std::vector<T> & vec)   { if (vec.size() > 0) memset(&vec[0], 0, sizeof(T) * vec.size()); }
Zero(T * first,size_t cnt)135     template<class T> inline void Zero(T * first, size_t cnt)  { memset(first, 0, sizeof(T) * cnt); }
136 
Equal(T const & lhs,T const & rhs)137     template<class T> inline bool Equal(T const & lhs, T const & rhs) { return memcmp(&lhs, &rhs, sizeof(T)) == 0; }
138 
Copy(T & dst,U const & src)139     template<class T, class U> inline void Copy(T & dst, U const & src)
140     {
141         static_assert(sizeof(T) == sizeof(U), "copy_objects_of_different_size");
142         MFX_INTERNAL_CPY(&dst, &src, sizeof(dst));
143     }
144 
RemoveConst(T const & t)145     template<class T> inline T & RemoveConst(T const & t) { return const_cast<T &>(t); }
146 
RemoveConst(T const * t)147     template<class T> inline T * RemoveConst(T const * t) { return const_cast<T *>(t); }
148 
Begin(T (& t)[N])149     template<class T, size_t N> inline T * Begin(T(& t)[N]) { return t; }
150 
End(T (& t)[N])151     template<class T, size_t N> inline T * End(T(& t)[N]) { return t + N; }
152 
SizeOf(T (&)[N])153     template<class T, size_t N> inline size_t SizeOf(T(&)[N]) { return N; }
154 
Begin(std::vector<T> const & t)155     template<class T> inline T const * Begin(std::vector<T> const & t) { return &*t.begin(); }
156 
End(std::vector<T> const & t)157     template<class T> inline T const * End(std::vector<T> const & t) { return &*t.begin() + t.size(); }
158 
Begin(std::vector<T> & t)159     template<class T> inline T * Begin(std::vector<T> & t) { return &*t.begin(); }
160 
End(std::vector<T> & t)161     template<class T> inline T * End(std::vector<T> & t) { return &*t.begin() + t.size(); }
162 
163     template<class T> struct ExtBufTypeToId {};
164 
165 #define BIND_EXTBUF_TYPE_TO_ID(TYPE, ID) template<> struct ExtBufTypeToId<TYPE> { enum { id = ID }; }
166     BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOption,         MFX_EXTBUFF_CODING_OPTION            );
167     BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOptionSPSPPS,   MFX_EXTBUFF_CODING_OPTION_SPSPPS     );
168     BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOptionDDI,      MFX_EXTBUFF_DDI                      );
169     BIND_EXTBUF_TYPE_TO_ID (mfxExtVideoSignalInfo,      MFX_EXTBUFF_VIDEO_SIGNAL_INFO        );
170     BIND_EXTBUF_TYPE_TO_ID (mfxExtOpaqueSurfaceAlloc,   MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION);
171     BIND_EXTBUF_TYPE_TO_ID (mfxExtMVCSeqDesc,           MFX_EXTBUFF_MVC_SEQ_DESC             );
172     BIND_EXTBUF_TYPE_TO_ID (mfxExtMVCTargetViews,       MFX_EXTBUFF_MVC_TARGET_VIEWS         );
173     BIND_EXTBUF_TYPE_TO_ID (mfxExtPictureTimingSEI,     MFX_EXTBUFF_PICTURE_TIMING_SEI       );
174     BIND_EXTBUF_TYPE_TO_ID (mfxExtSpsHeader,            MFX_EXTBUFF_SPS_HEADER               );
175     BIND_EXTBUF_TYPE_TO_ID (mfxExtPpsHeader,            MFX_EXTBUFF_PPS_HEADER               );
176     BIND_EXTBUF_TYPE_TO_ID (mfxExtAVCRefListCtrl,       MFX_EXTBUFF_AVC_REFLIST_CTRL         );
177 #if defined MFX_ENABLE_H264_ROUNDING_OFFSET
178     BIND_EXTBUF_TYPE_TO_ID (mfxExtAVCRoundingOffset,    MFX_EXTBUFF_AVC_ROUNDING_OFFSET      );
179 #endif
180     BIND_EXTBUF_TYPE_TO_ID (mfxExtAvcTemporalLayers,    MFX_EXTBUFF_AVC_TEMPORAL_LAYERS      );
181     BIND_EXTBUF_TYPE_TO_ID (mfxExtVppAuxData,           MFX_EXTBUFF_VPP_AUXDATA              );
182     BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOption2,        MFX_EXTBUFF_CODING_OPTION2           );
183     BIND_EXTBUF_TYPE_TO_ID (mfxExtAVCEncodedFrameInfo,  MFX_EXTBUFF_ENCODED_FRAME_INFO       );
184     BIND_EXTBUF_TYPE_TO_ID (mfxExtEncoderResetOption,   MFX_EXTBUFF_ENCODER_RESET_OPTION     );
185     BIND_EXTBUF_TYPE_TO_ID (mfxExtEncoderCapability,    MFX_EXTBUFF_ENCODER_CAPABILITY       );
186     BIND_EXTBUF_TYPE_TO_ID (mfxExtEncoderROI,           MFX_EXTBUFF_ENCODER_ROI              );
187     BIND_EXTBUF_TYPE_TO_ID (mfxExtLAFrameStatistics,    MFX_EXTBUFF_LOOKAHEAD_STAT           );
188     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiParam,             MFX_EXTBUFF_FEI_PARAM                );
189     BIND_EXTBUF_TYPE_TO_ID (mfxExtAVCRefLists,          MFX_EXTBUFF_AVC_REFLISTS             );
190     BIND_EXTBUF_TYPE_TO_ID (mfxExtCodingOption3,        MFX_EXTBUFF_CODING_OPTION3           );
191     BIND_EXTBUF_TYPE_TO_ID (mfxExtMBQP,                 MFX_EXTBUFF_MBQP                     );
192 #if MFX_VERSION >= 1023
193     BIND_EXTBUF_TYPE_TO_ID (mfxExtMBForceIntra,         MFX_EXTBUFF_MB_FORCE_INTRA           );
194 #endif
195     BIND_EXTBUF_TYPE_TO_ID (mfxExtChromaLocInfo,        MFX_EXTBUFF_CHROMA_LOC_INFO          );
196     BIND_EXTBUF_TYPE_TO_ID (mfxExtMBDisableSkipMap,     MFX_EXTBUFF_MB_DISABLE_SKIP_MAP      );
197     BIND_EXTBUF_TYPE_TO_ID (mfxExtPredWeightTable,      MFX_EXTBUFF_PRED_WEIGHT_TABLE        );
198     BIND_EXTBUF_TYPE_TO_ID (mfxExtDirtyRect,            MFX_EXTBUFF_DIRTY_RECTANGLES         );
199     BIND_EXTBUF_TYPE_TO_ID (mfxExtMoveRect,             MFX_EXTBUFF_MOVING_RECTANGLES        );
200     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiCodingOption,      MFX_EXTBUFF_FEI_CODING_OPTION        );
201     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiEncMV,             MFX_EXTBUFF_FEI_ENC_MV               );
202     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiEncMBStat,         MFX_EXTBUFF_FEI_ENC_MB_STAT          );
203     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiPakMBCtrl,         MFX_EXTBUFF_FEI_PAK_CTRL             );
204     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiEncFrameCtrl,      MFX_EXTBUFF_FEI_ENC_CTRL             );
205     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiEncMVPredictors,   MFX_EXTBUFF_FEI_ENC_MV_PRED          );
206     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiEncMBCtrl,         MFX_EXTBUFF_FEI_ENC_MB               );
207     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiEncQP,             MFX_EXTBUFF_FEI_ENC_QP               );
208     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiSPS,               MFX_EXTBUFF_FEI_SPS                  );
209     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiPPS,               MFX_EXTBUFF_FEI_PPS                  );
210     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiSliceHeader,       MFX_EXTBUFF_FEI_SLICE                );
211     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiPreEncMV,          MFX_EXTBUFF_FEI_PREENC_MV            );
212     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiPreEncMBStat,      MFX_EXTBUFF_FEI_PREENC_MB            );
213     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiPreEncCtrl,        MFX_EXTBUFF_FEI_PREENC_CTRL          );
214     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiPreEncMVPredictors,MFX_EXTBUFF_FEI_PREENC_MV_PRED       );
215     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiRepackCtrl,        MFX_EXTBUFF_FEI_REPACK_CTRL          );
216 #if (MFX_VERSION >= 1025)
217     BIND_EXTBUF_TYPE_TO_ID (mfxExtFeiRepackStat,        MFX_EXTBUFF_FEI_REPACK_STAT          );
218 #endif
219 #if defined (__MFXBRC_H__)
220     BIND_EXTBUF_TYPE_TO_ID (mfxExtBRC,        MFX_EXTBUFF_BRC          );
221 #endif
222 
223 #ifdef MFX_ENABLE_MFE
224     BIND_EXTBUF_TYPE_TO_ID (mfxExtMultiFrameControl,     MFX_EXTBUFF_MULTI_FRAME_CONTROL     );
225     BIND_EXTBUF_TYPE_TO_ID (mfxExtMultiFrameParam,       MFX_EXTBUFF_MULTI_FRAME_PARAM       );
226 #endif
227 #if defined (MFX_ENABLE_ENCTOOLS)
228     BIND_EXTBUF_TYPE_TO_ID(mfxEncTools, MFX_EXTBUFF_ENCTOOLS);
229     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsBRCFrameParams, MFX_EXTBUFF_ENCTOOLS_BRC_FRAME_PARAM);
230     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsBRCQuantControl, MFX_EXTBUFF_ENCTOOLS_BRC_QUANT_CONTROL);
231     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsBRCHRDPos, MFX_EXTBUFF_ENCTOOLS_BRC_HRD_POS);
232     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsBRCEncodeResult, MFX_EXTBUFF_ENCTOOLS_BRC_ENCODE_RESULT);
233     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsBRCStatus, MFX_EXTBUFF_ENCTOOLS_BRC_STATUS);
234     BIND_EXTBUF_TYPE_TO_ID(mfxExtEncToolsConfig, MFX_EXTBUFF_ENCTOOLS_CONFIG);
235     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsCtrlExtDevice, MFX_EXTBUFF_ENCTOOLS_DEVICE);
236     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsCtrlExtAllocator, MFX_EXTBUFF_ENCTOOLS_ALLOCATOR);
237     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsFrameToAnalyze, MFX_EXTBUFF_ENCTOOLS_FRAME_TO_ANALYZE);
238     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsHintPreEncodeSceneChange, MFX_EXTBUFF_ENCTOOLS_HINT_SCENE_CHANGE);
239     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsHintPreEncodeGOP, MFX_EXTBUFF_ENCTOOLS_HINT_GOP);
240     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsHintPreEncodeARefFrames, MFX_EXTBUFF_ENCTOOLS_HINT_AREF);
241     BIND_EXTBUF_TYPE_TO_ID(mfxEncToolsBRCBufferHint, MFX_EXTBUFF_ENCTOOLS_BRC_BUFFER_HINT);
242 
243 #endif
244 
245 #undef BIND_EXTBUF_TYPE_TO_ID
246 
InitExtBufHeader(T & extBuf)247     template <class T> inline void InitExtBufHeader(T & extBuf)
248     {
249         Zero(extBuf);
250         extBuf.Header.BufferId = ExtBufTypeToId<T>::id;
251         extBuf.Header.BufferSz = sizeof(T);
252     }
253 
254     template <> inline void InitExtBufHeader<mfxExtVideoSignalInfo>(mfxExtVideoSignalInfo & extBuf)
255     {
256         Zero(extBuf);
257         extBuf.Header.BufferId = ExtBufTypeToId<mfxExtVideoSignalInfo>::id;
258         extBuf.Header.BufferSz = sizeof(mfxExtVideoSignalInfo);
259 
260         // set default values
261         extBuf.VideoFormat              = 5; // unspecified video format
262         extBuf.VideoFullRange           = 0;
263         extBuf.ColourDescriptionPresent = 0;
264         extBuf.ColourPrimaries          = 2; // unspecified
265         extBuf.TransferCharacteristics  = 2; // unspecified
266         extBuf.MatrixCoefficients       = 2; // unspecified
267     }
268 
269     template <> inline void InitExtBufHeader<mfxExtAVCRefListCtrl>(mfxExtAVCRefListCtrl & extBuf)
270     {
271         Zero(extBuf);
272         extBuf.Header.BufferId = ExtBufTypeToId<mfxExtAVCRefListCtrl>::id;
273         extBuf.Header.BufferSz = sizeof(mfxExtAVCRefListCtrl);
274 
275         for (mfxU32 i = 0; i < 32; i++)
276             extBuf.PreferredRefList[i].FrameOrder = mfxU32(MFX_FRAMEORDER_UNKNOWN);
277         for (mfxU32 i = 0; i < 16; i++)
278             extBuf.RejectedRefList[i].FrameOrder = mfxU32(MFX_FRAMEORDER_UNKNOWN);
279         for (mfxU32 i = 0; i < 16; i++)
280             extBuf.LongTermRefList[i].FrameOrder = mfxU32(MFX_FRAMEORDER_UNKNOWN);
281     }
282 #if defined(MFX_ENABLE_ENCTOOLS)
283     template <> inline void InitExtBufHeader<mfxExtEncToolsConfig>(mfxExtEncToolsConfig & extBuf)
284     {
285         Zero(extBuf);
286         extBuf.Header.BufferId = ExtBufTypeToId<mfxExtEncToolsConfig>::id;
287         extBuf.Header.BufferSz = sizeof(mfxExtEncToolsConfig);
288 
289         extBuf.AdaptiveI =
290             extBuf.AdaptiveB =
291             extBuf.AdaptiveRefP =
292             extBuf.AdaptiveRefB =
293             extBuf.SceneChange =
294             extBuf.AdaptiveLTR =
295             extBuf.AdaptivePyramidQuantP =
296             extBuf.AdaptivePyramidQuantB =
297             extBuf.AdaptiveQuantMatrices =
298             extBuf.BRCBufferHints =
299             extBuf.BRC = MFX_CODINGOPTION_OFF;
300     }
301 #endif
302     template <class T> struct GetPointedType {};
303     template <class T> struct GetPointedType<T *> { typedef T Type; };
304     template <class T> struct GetPointedType<T const *> { typedef T Type; };
305 
306     struct HrdParameters
307     {
308         mfxU8   cpbCntMinus1;
309         mfxU8   bitRateScale;
310         mfxU8   cpbSizeScale;
311         mfxU32  bitRateValueMinus1[32];
312         mfxU32  cpbSizeValueMinus1[32];
313         mfxU8   cbrFlag[32];
314         mfxU8   initialCpbRemovalDelayLengthMinus1;
315         mfxU8   cpbRemovalDelayLengthMinus1;
316         mfxU8   dpbOutputDelayLengthMinus1;
317         mfxU8   timeOffsetLength;
318     };
319 
320     struct VuiParameters
321     {
322         struct
323         {
324             mfxU16  aspectRatioInfoPresent         : 1;
325             mfxU16  overscanInfoPresent            : 1;
326             mfxU16  overscanAppropriate            : 1;
327             mfxU16  videoSignalTypePresent         : 1;
328             mfxU16  videoFullRange                 : 1;
329             mfxU16  colourDescriptionPresent       : 1;
330             mfxU16  chromaLocInfoPresent           : 1;
331             mfxU16  timingInfoPresent              : 1;
332             mfxU16  fixedFrameRate                 : 1;
333             mfxU16  nalHrdParametersPresent        : 1;
334             mfxU16  vclHrdParametersPresent        : 1;
335             mfxU16  lowDelayHrd                    : 1;
336             mfxU16  picStructPresent               : 1;
337             mfxU16  bitstreamRestriction           : 1;
338             mfxU16  motionVectorsOverPicBoundaries : 1;
339             mfxU16  reserved                       : 1;
340         } flags;
341 
342         mfxU8   aspectRatioIdc;
343         mfxU16  sarWidth;
344         mfxU16  sarHeight;
345         mfxU8   videoFormat;
346         mfxU8   colourPrimaries;
347         mfxU8   transferCharacteristics;
348         mfxU8   matrixCoefficients;
349         mfxU8   chromaSampleLocTypeTopField;
350         mfxU8   chromaSampleLocTypeBottomField;
351         mfxU32  numUnitsInTick;
352         mfxU32  timeScale;
353 
354         HrdParameters nalHrdParameters;
355         HrdParameters vclHrdParameters;
356 
357         mfxU8   maxBytesPerPicDenom;
358         mfxU8   maxBitsPerMbDenom;
359         mfxU8   log2MaxMvLengthHorizontal;
360         mfxU8   log2MaxMvLengthVertical;
361         mfxU8   numReorderFrames;
362         mfxU8   maxDecFrameBuffering;
363     };
364 
365     struct mfxExtSpsHeader
366     {
367         mfxExtBuffer Header;
368 
369         mfxU8   nalRefIdc;
370         mfxU8   nalUnitType;
371         mfxU8   profileIdc;
372 
373         struct
374         {
375             mfxU8   set0 : 1;
376             mfxU8   set1 : 1;
377             mfxU8   set2 : 1;
378             mfxU8   set3 : 1;
379             mfxU8   set4 : 1;
380             mfxU8   set5 : 1;
381             mfxU8   set6 : 2;
382             mfxU8   set7 : 2;
383         } constraints;
384 
385         mfxU8   levelIdc;
386         mfxU8   seqParameterSetId;
387         mfxU8   chromaFormatIdc;
388         mfxU8   separateColourPlaneFlag;
389         mfxU8   bitDepthLumaMinus8;
390         mfxU8   bitDepthChromaMinus8;
391         mfxU8   qpprimeYZeroTransformBypassFlag;
392         mfxU8   seqScalingMatrixPresentFlag;
393         mfxU8   seqScalingListPresentFlag[12];
394         mfxU8   scalingList4x4[6][16];
395         mfxU8   scalingList8x8[6][64];
396 
397         mfxU8   log2MaxFrameNumMinus4;
398         mfxU8   picOrderCntType;
399         mfxU8   log2MaxPicOrderCntLsbMinus4;
400         mfxU8   deltaPicOrderAlwaysZeroFlag;
401         mfxI32  offsetForNonRefPic;
402         mfxI32  offsetForTopToBottomField;
403         mfxU8   numRefFramesInPicOrderCntCycle;
404         mfxI32  offsetForRefFrame[256];
405 
406         mfxU8   maxNumRefFrames;
407         mfxU8   gapsInFrameNumValueAllowedFlag;
408         mfxU16  picWidthInMbsMinus1;
409         mfxU16  picHeightInMapUnitsMinus1;
410         mfxU8   frameMbsOnlyFlag;
411         mfxU8   mbAdaptiveFrameFieldFlag;
412         mfxU8   direct8x8InferenceFlag;
413         mfxU8   frameCroppingFlag;
414         mfxU32  frameCropLeftOffset;
415         mfxU32  frameCropRightOffset;
416         mfxU32  frameCropTopOffset;
417         mfxU32  frameCropBottomOffset;
418         mfxU8   vuiParametersPresentFlag;
419 
420         VuiParameters vui;
421     };
422 
423     bool operator ==(mfxExtSpsHeader const & lhs, mfxExtSpsHeader const & rhs);
424 
425     template <> inline bool Equal<mfxExtSpsHeader>(mfxExtSpsHeader const & lhs, mfxExtSpsHeader const & rhs)
426     {
427         return lhs == rhs;
428     }
429 
430     struct mfxExtSpsSvcHeader
431     {
432         mfxExtBuffer Header;
433 
434         mfxU8   interLayerDeblockingFilterControlPresentFlag;
435         mfxU8   extendedSpatialScalabilityIdc;
436         mfxU8   chromaPhaseXPlus1Flag;
437         mfxU8   chromaPhaseYPlus1;
438         mfxU8   seqRefLayerChromaPhaseXPlus1Flag;
439         mfxU8   seqRefLayerChromaPhaseYPlus1;
440         mfxI16  seqScaledRefLayerLeftOffset;
441         mfxI16  seqScaledRefLayerTopOffset;
442         mfxI16  seqScaledRefLayerRightOffset;
443         mfxI16  seqScaledRefLayerBottomOffset;
444         mfxU8   seqTcoeffLevelPredictionFlag;
445         mfxU8   adaptiveTcoeffLevelPredictionFlag;
446         mfxU8   sliceHeaderRestrictionFlag;
447     };
448 
449 
450     union SliceGroupInfo
451     {
452         struct
453         {
454             mfxU32 runLengthMinus1[8];
455         } t0;
456 
457         struct
458         {
459             mfxU32 topLeft[7];
460             mfxU32 bottomRight[7];
461         } t2;
462 
463         struct
464         {
465             mfxU8  sliceGroupChangeDirectionFlag;
466             mfxU32 sliceGroupChangeRate;
467         } t3;
468 
469         struct
470         {
471             mfxU32 picSizeInMapUnitsMinus1;
472         } t6;
473     };
474 
475     template <> inline void InitExtBufHeader<mfxExtSpsHeader>(mfxExtSpsHeader & extBuf)
476     {
477         Zero(extBuf);
478         extBuf.Header.BufferId = ExtBufTypeToId<mfxExtSpsHeader>::id;
479         extBuf.Header.BufferSz = sizeof (mfxExtSpsHeader);
480 
481         // set default non-zero values
482         extBuf.chromaFormatIdc                   = 1;
483         extBuf.vuiParametersPresentFlag          = 1;
484         extBuf.vui.flags.nalHrdParametersPresent = 1;
485         extBuf.vui.flags.timingInfoPresent       = 1;
486         extBuf.vui.flags.fixedFrameRate          = 1;
487     }
488 
489     struct mfxExtPpsHeader
490     {
491         mfxExtBuffer Header;
492 
493         mfxU8   nalRefIdc;
494         mfxU8   picParameterSetId;
495         mfxU8   seqParameterSetId;
496         mfxU8   entropyCodingModeFlag;
497         mfxU8   bottomFieldPicOrderInframePresentFlag;
498         mfxU8   numSliceGroupsMinus1;
499         mfxU8   sliceGroupMapType;
500 
501         SliceGroupInfo sliceGroupInfo;
502 
503         mfxU8   numRefIdxL0DefaultActiveMinus1;
504         mfxU8   numRefIdxL1DefaultActiveMinus1;
505         mfxU8   weightedPredFlag;
506         mfxU8   weightedBipredIdc;
507         mfxI8   picInitQpMinus26;
508         mfxI8   picInitQsMinus26;
509         mfxI8   chromaQpIndexOffset;
510         mfxU8   deblockingFilterControlPresentFlag;
511         mfxU8   constrainedIntraPredFlag;
512         mfxU8   redundantPicCntPresentFlag;
513         mfxU8   transform8x8ModeFlag;
514         mfxU8   picScalingMatrixPresentFlag;
515         mfxI8   secondChromaQpIndexOffset;
516         bool    moreRbspData;
517 
518         mfxU8   scalingList4x4[6][16];
519         mfxU8   scalingList8x8[6][64];
520         bool    picScalingListPresentFlag[12];
521     };
522 
523     struct mfxRoiDesc{
524         mfxU32  Left;
525         mfxU32  Top;
526         mfxU32  Right;
527         mfxU32  Bottom;
528 
529         mfxI16  ROIValue;
530     };
531 
532     struct mfxRectDesc{
533         mfxU32  Left;
534         mfxU32  Top;
535         mfxU32  Right;
536         mfxU32  Bottom;
537     };
538 
539     struct mfxMovingRectDesc{
540         mfxU32  DestLeft;
541         mfxU32  DestTop;
542         mfxU32  DestRight;
543         mfxU32  DestBottom;
544 
545         mfxU32  SourceLeft;
546         mfxU32  SourceTop;
547     };
548 
549     class MfxVideoParam : public mfxVideoParam
550     {
551     public:
552         MfxVideoParam();
553         MfxVideoParam(MfxVideoParam const &);
554         MfxVideoParam(mfxVideoParam const &);
555 
556         MfxVideoParam & operator = (MfxVideoParam const &);
557         MfxVideoParam & operator = (mfxVideoParam const &);
558 
559         void SyncVideoToCalculableParam();
560 
561         void SyncCalculableToVideoParam();
562 
563         void AlignCalcWithBRCParamMultiplier();
564 
565         void ApplyDefaultsToMvcSeqDesc();
566 
567 
568     protected:
569         void Construct(mfxVideoParam const & par);
570 
571         void ConstructMvcSeqDesc(mfxExtMVCSeqDesc const & desc);
572 
573     private:
574 #if defined(MFX_ENABLE_ENCTOOLS)
575         mfxExtBuffer *              m_extParam[40];
576 #else
577         mfxExtBuffer *              m_extParam[32];
578 #endif
579         // external, documented
580         mfxExtCodingOption          m_extOpt;
581         mfxExtCodingOption2         m_extOpt2;
582         mfxExtCodingOption3         m_extOpt3;
583         mfxExtCodingOptionSPSPPS    m_extOptSpsPps;
584         mfxExtVideoSignalInfo       m_extVideoSignal;
585         mfxExtOpaqueSurfaceAlloc    m_extOpaque;
586         mfxExtMVCSeqDesc            m_extMvcSeqDescr;
587         mfxExtPictureTimingSEI      m_extPicTiming;
588         mfxExtAvcTemporalLayers     m_extTempLayers;
589         mfxExtEncoderResetOption    m_extEncResetOpt;
590         mfxExtEncoderROI            m_extEncRoi;
591         mfxExtFeiParam              m_extFeiParam;
592         mfxExtChromaLocInfo         m_extChromaLoc;
593         mfxExtPredWeightTable       m_extPwt;
594         mfxExtDirtyRect             m_extDirtyRect;
595         mfxExtMoveRect              m_extMoveRect;
596 
597         mfxExtCodingOptionDDI       m_extOptDdi;
598         mfxExtSpsHeader             m_extSps;
599         mfxExtPpsHeader             m_extPps;
600 
601         mfxExtFeiCodingOption       m_extFeiOpt;
602         mfxExtFeiSliceHeader        m_extFeiSlice[2];
603         mfxExtFeiSPS                m_extFeiSPS;
604         mfxExtFeiPPS                m_extFeiPPS;
605 
606 #if defined(__MFXBRC_H__)
607         mfxExtBRC                   m_extBRC;
608 #endif
609 #if defined(MFX_ENABLE_ENCTOOLS)
610         mfxEncTools                     m_encTools;
611         mfxExtEncToolsConfig            m_encToolsConfig;
612         mfxEncToolsCtrlExtDevice        m_extDevice;
613         mfxEncToolsCtrlExtAllocator     m_extAllocator;
614 #endif
615 #if defined (MFX_ENABLE_MFE)
616         mfxExtMultiFrameParam    m_MfeParam;
617         mfxExtMultiFrameControl  m_MfeControl;
618 #endif
619         std::vector<mfxMVCViewDependency> m_storageView;
620         std::vector<mfxMVCOperationPoint> m_storageOp;
621         std::vector<mfxU16>               m_storageViewId;
622 
623     public:
624         struct CalculableParam
625         {
626             mfxU32 bufferSizeInKB;
627             mfxU32 initialDelayInKB;
628             mfxU32 targetKbps;
629             mfxU32 maxKbps;
630             mfxU32 WinBRCMaxAvgKbps;
631 
632             mfxU32 numTemporalLayer;
633             mfxU32 tid[8];
634             mfxU32 scale[8];
635 
636 // MVC BD {
637             struct
638             {
639                 mfxU32 bufferSizeInKB;
640                 mfxU32 initialDelayInKB;
641                 mfxU32 targetKbps;
642                 mfxU32 maxKbps;
643                 mfxU16 codecLevel;
644             } mvcPerViewPar;
645 // MVC BD }
646             mfxU32 numDependencyLayer;
647             mfxU32 did[8];
648             mfxU32 numLayersTotal;
649             mfxU32 numLayerOffset[8];
650             mfxU32 dqId1Exists;
651             mfxU32 tempScalabilityMode;
652             mfxU32 cqpHrdMode; // special CQP mode in which HRD information is written into bitstreams: 0 - disabled, 1 -CBR, 2 - VBR
653             struct
654             {
655                 mfxU32 bufferSizeInKB;
656                 mfxU32 initialDelayInKB;
657                 mfxU32 targetKbps;
658                 mfxU32 maxKbps;
659             } decorativeHrdParam; // decorative HRD parameters for cqpHrdMode
660 
661             mfxU16 widthLa;
662             mfxU16 heightLa;
663             mfxU32 TCBRCTargetFrameSize;
664             mfxU32 PPyrInterval;
665         } calcParam;
666     };
667 
668     bool   isSWBRC (MfxVideoParam const & par);
669     bool   isAdaptiveQP(MfxVideoParam const & par);
670     mfxU16 GetMaxNumSlices(MfxVideoParam const & par);
671 
672     mfxU16 GetNumSurfInput(MfxVideoParam const & video);
673 
674     mfxU8 GetNumReorderFrames(MfxVideoParam const & video);
675 
676     mfxU32 CalcNumSurfRaw(MfxVideoParam const & video);
677 
678     mfxU32 CalcNumSurfRecon(MfxVideoParam const & video);
679 
680     mfxU32 CalcNumSurfBitstream(MfxVideoParam const & video);
681 
682     mfxU32 CalcNumTasks(MfxVideoParam const & video);
683 
684     mfxI64 CalcDTSFromPTS(
685         mfxFrameInfo const & info,
686         mfxU16               dpbOutputDelay,
687         mfxU64               timeStamp);
688 
689 #define SCALE_FROM_DRIVER 4 // driver hardcodes scale 4. Need to use this value in MSDK. Otherwise BRC and MSDK HRD calculations will diverge.
690 
691     mfxU32 GetMaxBitrateValue(
692         mfxU32 kbps,
693         mfxU32 scale = SCALE_FROM_DRIVER);
694 
695     mfxU8 GetCabacInitIdc(mfxU32 targetUsage);
696 
697     bool IsLookAheadSupported(
698         MfxVideoParam const & video,
699         eMFXHWType            platform);
700     bool IsMctfSupported(
701         MfxVideoParam const & video);
702 
703     mfxU32 GetPPyrSize(
704         MfxVideoParam const & video,
705         mfxU32 miniGopSize,
706         bool   bEncToolsLA);
707 
708     bool IsExtBrcSceneChangeSupported(
709         MfxVideoParam const & video);
710 
711     bool IsCmNeededForSCD(
712         MfxVideoParam const & video);
713 
714     bool IsAdaptiveLtrOn(
715         MfxVideoParam const & video);
716 
717     mfxU8 DetermineQueryMode(mfxVideoParam * in);
718 
719     mfxStatus SetLowPowerDefault(
720         MfxVideoParam& par,
721         const eMFXHWType& platform);
722 
723     mfxStatus QueryHwCaps(
724         VideoCORE *       core,
725         MFX_ENCODE_CAPS & hwCaps,
726         mfxVideoParam *   par);
727 
728     mfxStatus QueryMbProcRate(
729         VideoCORE* core,
730         mfxVideoParam const & out,
731         mfxU32 (&mbPerSec)[16],
732         const mfxVideoParam * in);
733 
734     mfxStatus QueryGuid(
735         VideoCORE* core,
736         GUID guid);
737 
738     mfxStatus ReadSpsPpsHeaders(MfxVideoParam & par);
739 
740     mfxU16 GetFrameWidth(MfxVideoParam & par);
741 
742     mfxU16 GetFrameHeight(MfxVideoParam & par);
743 
744     mfxStatus CorrectCropping(
745         MfxVideoParam & par);
746 
747     bool IsRunTimeOnlyExtBuffer(
748         mfxU32 id);
749 
750     bool IsRunTimeExtBufferIdSupported(
751         MfxVideoParam const & video, mfxU32 id);
752 
753     bool IsRuntimeOutputExtBufferIdSupported(
754         MfxVideoParam const & video, mfxU32 id);
755 
756     bool IsRunTimeExtBufferPairAllowed(
757         MfxVideoParam const & video, mfxU32 id);
758 
759     bool IsRunTimeExtBufferPairRequired(
760         MfxVideoParam const & video, mfxU32 id);
761 
762     bool IsVideoParamExtBufferIdSupported(
763         mfxU32 id);
764 
765     mfxStatus CheckExtBufferId(
766         mfxVideoParam const & par);
767 
768 
769     mfxStatus CheckWidthAndHeight(
770         MfxVideoParam const & par);
771 
772     mfxStatus CopySpsPpsToVideoParam(
773         MfxVideoParam & par);
774 
775     mfxStatus CheckForAllowedH264SpecViolations(
776         MfxVideoParam const & par);
777 
778     mfxStatus CheckAndFixRectQueryLike(
779         MfxVideoParam const & par,
780         mfxRectDesc *         rect);
781 
782     mfxStatus CheckAndFixOpenRectQueryLike(
783         MfxVideoParam const & par,
784         mfxRectDesc *         rect);
785 
786     mfxStatus CheckAndFixRoiQueryLike(
787         MfxVideoParam const & par,
788         mfxRoiDesc *          roi,
789         mfxU16                roiMode);
790 
791     mfxStatus CheckAndFixMovingRectQueryLike(
792         MfxVideoParam const & par,
793         mfxMovingRectDesc *   rect);
794 
795 
796     mfxStatus CheckVideoParam(
797         MfxVideoParam &         par,
798         MFX_ENCODE_CAPS const & hwCaps,
799         bool                    setExtAlloc,
800         eMFXHWType              platform = MFX_HW_UNKNOWN,
801         eMFXVAType              vaType = MFX_HW_NO,
802         eMFXGTConfig            config = MFX_GT_UNKNOWN,
803         bool                    bInit = false);
804 
805     mfxStatus CheckVideoParamFEI(
806         MfxVideoParam &     par);
807 
808     mfxStatus CheckVideoParamQueryLike(
809         MfxVideoParam &         par,
810         MFX_ENCODE_CAPS const & hwCaps,
811         eMFXHWType              platform = MFX_HW_UNKNOWN,
812         eMFXVAType              vaType = MFX_HW_NO,
813         eMFXGTConfig            config = MFX_GT_UNKNOWN);
814 
815     mfxStatus CheckVideoParamMvcQueryLike(MfxVideoParam &     par);
816 
817     mfxStatus CheckMVCSeqDescQueryLike(mfxExtMVCSeqDesc * mvcSeqDesc);
818 
819     mfxStatus CheckAndFixMVCSeqDesc(mfxExtMVCSeqDesc * mvcSeqDesc, bool isViewOutput);
820 
821     void SetDefaults(
822         MfxVideoParam &         par,
823         MFX_ENCODE_CAPS const & hwCaps,
824         bool                    setExtAlloc,
825         eMFXHWType              platform = MFX_HW_UNKNOWN,
826         eMFXVAType              vaType = MFX_HW_NO,
827         eMFXGTConfig            config = MFX_GT_UNKNOWN);
828 
829     void InheritDefaultValues(
830         MfxVideoParam const & parInit,
831         MfxVideoParam &       parReset,
832         MFX_ENCODE_CAPS const & hwCaps,
833         mfxVideoParam const * parResetIn = 0);
834 
835     mfxStatus CheckPayloads(
836         mfxPayload const * const * payload,
837         mfxU16                     numPayload);
838 
839     mfxStatus CheckRunTimeExtBuffers(
840         MfxVideoParam const & video,
841         mfxEncodeCtrl *       ctrl,
842         mfxFrameSurface1 *    surface,
843         mfxBitstream *        bs,
844         MFX_ENCODE_CAPS const &   caps,
845         eMFXHWType            platform = MFX_HW_UNKNOWN);
846 
847     mfxStatus CheckFEIRunTimeExtBuffersContent(
848         MfxVideoParam const & video,
849         mfxEncodeCtrl *       ctrl,
850         mfxFrameSurface1 *    surface,
851         mfxBitstream *        bs);
852 
853     mfxStatus CheckRunTimePicStruct(
854         mfxU16 runtPicStruct,
855         mfxU16 initPicStruct);
856 
857     bool IsRecoveryPointSeiMessagePresent(
858         mfxPayload const * const * payload,
859         mfxU16                     numPayload,
860         mfxU32                     payloadLayout);
861 
862     mfxStatus CopyFrameDataBothFields(
863         VideoCORE *          core,
864         mfxFrameData const & dst,
865         mfxFrameData const & src,
866         mfxFrameInfo const & info);
867 
868     mfxExtBuffer * GetExtBuffer(
869         mfxExtBuffer ** extBuf,
870         mfxU32          numExtBuf,
871         mfxU32          id,
872         mfxU32          offset = 0);
873     struct mfxExtBufferProxy;
874     struct mfxExtBufferRefProxy;
875     template <typename T> mfxExtBufferProxy GetExtBuffer(const T & par, mfxU32 fieldId = 0);
876     template <typename T> mfxExtBufferProxy GetExtBufferFEI(const T & bs, mfxU32 fieldId = 0);
877     template <typename T> mfxExtBufferRefProxy GetExtBufferRef(const T & par, mfxU32 fieldId = 0);
878 
879     struct mfxExtBufferProxy
880     {
881     public:
882         template <typename T> operator T()
883         {
884             mfxExtBuffer * p = MfxHwH264Encode::GetExtBuffer(
885                 m_extParam,
886                 m_numExtParam,
887                 ExtBufTypeToId<typename GetPointedType<T>::Type>::id,
888                 m_fieldId);
889             return reinterpret_cast<T>(p);
890         }
891 
892         template <typename T> friend mfxExtBufferProxy GetExtBuffer(const T & par, mfxU32 fieldId)
893         {
894             return mfxExtBufferProxy(par.ExtParam, par.NumExtParam, fieldId);
895         }
896         template <typename T> friend mfxExtBufferProxy GetExtBufferFEI(const T & bs, mfxU32 fieldId)
897         {
898             return mfxExtBufferProxy(bs->ExtParam, bs->NumExtParam, fieldId);
899         }
900 
901     protected:
902         mfxExtBufferProxy(mfxExtBuffer ** extParam, mfxU32 numExtParam,  mfxU32 fieldId = 0)
903             : m_extParam(extParam)
904             , m_numExtParam(numExtParam)
905             , m_fieldId(fieldId)
906         {
907         }
908 
909     private:
910         mfxExtBuffer ** m_extParam;
911         mfxU32          m_numExtParam;
912         mfxU32          m_fieldId;
913     };
914 
915     // version with assert, special for extract extBuffer from wrapper MfxVideoParam
916     struct mfxExtBufferRefProxy{
917     public:
918         template <typename T> operator T&()
919         {
920             mfxExtBuffer * p = MfxHwH264Encode::GetExtBuffer(
921                 m_extParam,
922                 m_numExtParam,
923                 ExtBufTypeToId<typename GetPointedType<T*>::Type>::id,
924                 m_fieldId);
925             assert(p);
926             return *(reinterpret_cast<T*>(p));
927         }
928 
929         // Intention of GetExtBufferRef is to get ext buffers
930         // from MfxVideoParam structure which always has full set
931         // of extension buffers ("MfxHwH264Encode::GetExtBuffer" can't return zero).
932         //
933         // So, for MfxVideoParam it's better to use function GetExtBufferRef()
934         // instead GetExtBuffer(), we can wrap issues from static code analyze
935         // to one place (body of function GetExtBufferRef()) instead several
936         // places (every calling GetExtBuffer())
937         template <typename T> friend mfxExtBufferRefProxy GetExtBufferRef(const T & par, mfxU32 fieldId)
938         {
939             return mfxExtBufferRefProxy(par.ExtParam, par.NumExtParam, fieldId);
940         }
941 
942     protected:
943         mfxExtBufferRefProxy(mfxExtBuffer ** extParam, mfxU32 numExtParam,  mfxU32 fieldId = 0)
944             : m_extParam(extParam)
945             , m_numExtParam(numExtParam)
946             , m_fieldId(fieldId)
947         {
948         }
949 
950     private:
951         mfxExtBuffer ** m_extParam;
952         mfxU32          m_numExtParam;
953         mfxU32          m_fieldId;
954     };
955 
956     inline bool IsFieldCodingPossible(MfxVideoParam const & par)
957     {
958         return (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0;
959     }
960 
961     inline void ResetNumSliceIPB(mfxVideoParam &par)
962     {
963         mfxExtCodingOption3 * extOpt3 = GetExtBuffer(par);
964         if(extOpt3 != nullptr && (extOpt3->NumSliceI == 0 || extOpt3->NumSliceP == 0 || extOpt3->NumSliceB == 0)){
965             extOpt3->NumSliceI = extOpt3->NumSliceP = extOpt3->NumSliceB = par.mfx.NumSlice;
966         }
967     }
968 
969     inline mfxU32 GetAvgFrameSizeInBytes(const MfxVideoParam &  par, bool bMaxKbps)
970     {
971         return mfxU32(1000.0 / 8.0*((par.mfx.MaxKbps && bMaxKbps) ? par.mfx.MaxKbps : par.mfx.TargetKbps) * std::max<mfxU32>(par.mfx.BRCParamMultiplier,1) /
972             (mfxF64(par.mfx.FrameInfo.FrameRateExtN) / par.mfx.FrameInfo.FrameRateExtD) );
973     }
974     inline bool IsTCBRC(const MfxVideoParam &  par, MFX_ENCODE_CAPS const & hwCaps)
975     {
976         mfxExtCodingOption3 &extOpt3 = GetExtBufferRef(par);
977         mfxExtCodingOption  &extOpt = GetExtBufferRef(par);
978         return (IsOn(extOpt3.LowDelayBRC) && (hwCaps.ddi_caps.TCBRCSupport) && IsOff(extOpt.NalHrdConformance) &&
979                (par.mfx.RateControlMethod  ==  MFX_RATECONTROL_VBR  ||
980                 par.mfx.RateControlMethod  ==  MFX_RATECONTROL_QVBR ||
981                 par.mfx.RateControlMethod  ==  MFX_RATECONTROL_VCM ));
982     }
983 
984     inline mfxU8 GetPayloadLayout(mfxU32 fieldPicFlag, mfxU32 secondFieldPicFlag)
985     {
986         return fieldPicFlag == 0
987             ? 0 /* MFX_PAYLOAD_LAYOUT_ALL */
988             : secondFieldPicFlag == 0
989                 ? 1 /* MFX_PAYLOAD_LAYOUT_EVEN */
990                 : 2 /* MFX_PAYLOAD_LAYOUT_ODD */;
991     }
992 
993     inline mfxU8 GetPayloadLayout(const mfxFrameParam& fp)
994     {
995         return GetPayloadLayout(fp.AVC.FieldPicFlag, fp.AVC.SecondFieldPicFlag);
996     }
997 
998     inline bool IsDriverSliceSizeControlEnabled(const MfxVideoParam & par, MFX_ENCODE_CAPS const & hwCaps)
999     {
1000         return IsOn(par.mfx.LowPower) && hwCaps.ddi_caps.SliceLevelRateCtrl;
1001     }
1002 
1003     mfxU8 ConvertFrameTypeMfx2Ddi(mfxU32 type);
1004 
1005     mfxU8 ConvertMfxFrameType2SliceType(mfxU8 type);
1006 
1007     ENCODE_FRAME_SIZE_TOLERANCE ConvertLowDelayBRCMfx2Ddi(mfxU16 type, bool bTCBRC);
1008 
1009     enum class SliceDividerType
1010     {
1011         ONESLICE            = 0, // Once slice for the whole frame
1012         ROW2ROW             = 1, // Slices are power of 2 number of rows, all slices the same
1013         ROWSLICE            = 2, // Slices are any number of rows, all slices the same
1014         ARBITRARY_ROW_SLICE = 3, // Slices are any number of rows, slices can be different
1015         ARBITRARY_MB_SLICE  = 4, // Slices are any number of MBs, slices can be different
1016     };
1017 
1018     struct MfxMemId
1019     {
1020     public:
1021         MfxMemId()
1022             : mid(0)
1023             , external(false)
1024         {}
1025 
1026         MfxMemId(mfxMemId mid_, bool external_)
1027             : mid(mid_)
1028             , external(external_)
1029         {}
1030 
1031         mfxMemId mid;
1032         bool     external;
1033     };
1034 
1035     inline mfxU32 CeilLog2(mfxU32 val)
1036     {
1037         mfxU32 res = 0;
1038 
1039         while (val)
1040         {
1041             val >>= 1;
1042             res++;
1043         }
1044 
1045         return res;
1046     }
1047 
1048     inline mfxU32 ExpGolombCodeLength(mfxU32 val)
1049     {
1050         return
1051             CeilLog2(val + 1) * 2 - 1;
1052     }
1053 
1054     // auto-lock for frames
1055     struct FrameLocker
1056     {
1057         FrameLocker(VideoCORE * core, mfxFrameData & data, bool external = false)
1058             : m_core(core)
1059             , m_data(data)
1060             , m_memId(data.MemId)
1061             , m_status(Lock(external))
1062         {
1063         }
1064 
1065         FrameLocker(VideoCORE * core, mfxFrameData & data, mfxMemId memId, bool external = false)
1066             : m_core(core)
1067             , m_data(data)
1068             , m_memId(memId)
1069             , m_status(Lock(external))
1070         {
1071         }
1072 
1073         ~FrameLocker() { Unlock(); }
1074 
1075         mfxStatus Unlock()
1076         {
1077             mfxStatus mfxSts = MFX_ERR_NONE;
1078 
1079             if (m_status == LOCK_INT)
1080                 mfxSts = m_core->UnlockFrame(m_memId, &m_data);
1081             else if (m_status == LOCK_EXT)
1082                 mfxSts = m_core->UnlockExternalFrame(m_memId, &m_data);
1083 
1084             m_status = LOCK_NO;
1085             return mfxSts;
1086         }
1087 
1088 
1089         enum { LOCK_NO, LOCK_INT, LOCK_EXT };
1090 
1091         mfxU32 Lock(bool external)
1092         {
1093             mfxU32 status = LOCK_NO;
1094 
1095             if (m_data.Y == 0)
1096             {
1097                 status = external
1098                     ? (m_core->LockExternalFrame(m_memId, &m_data) == MFX_ERR_NONE ? LOCK_EXT : LOCK_NO)
1099                     : (m_core->LockFrame(m_memId, &m_data) == MFX_ERR_NONE ? LOCK_INT : LOCK_NO);
1100             }
1101 
1102             return status;
1103         }
1104 
1105     private:
1106         FrameLocker(FrameLocker const &);
1107         FrameLocker & operator =(FrameLocker const &);
1108 
1109         VideoCORE *    m_core;
1110         mfxFrameData & m_data;
1111         mfxMemId       m_memId;
1112         mfxU32         m_status;
1113     };
1114 
1115     class FileHandle
1116     {
1117     public:
1118         FileHandle(FILE * file = 0)
1119             : m_file(file)
1120         {
1121         }
1122 
1123         ~FileHandle()
1124         {
1125             Close();
1126         }
1127 
1128         void Close()
1129         {
1130             if (m_file != 0)
1131             {
1132                 fclose(m_file);
1133             }
1134         }
1135 
1136         FileHandle & operator =(FILE* file)
1137         {
1138             Close();
1139             m_file = file;
1140             return *this;
1141         }
1142 
1143         operator FILE *()
1144         {
1145             return m_file;
1146         }
1147 
1148     private:
1149         FileHandle(FileHandle const &); // no impl
1150         FileHandle & operator =(FileHandle const &); // no impl
1151         FILE* m_file;
1152     };
1153 
1154     template <class T>
1155     class ScopedArray
1156     {
1157     public:
1158         ScopedArray(T * arr = 0)
1159             : m_arr(arr)
1160         {
1161         }
1162 
1163         ~ScopedArray()
1164         {
1165             reset(0);
1166         }
1167 
1168         T * reset(T * arr)
1169         {
1170             T * tmp(m_arr);
1171             delete [] m_arr;
1172             m_arr = arr;
1173             return tmp;
1174         }
1175 
1176         T * cptr()
1177         {
1178             return m_arr;
1179         }
1180 
1181         T const * cptr() const
1182         {
1183             return m_arr;
1184         }
1185 
1186         T & operator [](size_t idx)
1187         {
1188             assert(m_arr);
1189             return m_arr[idx];
1190         }
1191 
1192         T const & operator [](size_t idx) const
1193         {
1194             assert(m_arr);
1195             return m_arr[idx];
1196         }
1197 
1198     private:
1199         ScopedArray(ScopedArray const &);
1200         ScopedArray & operator =(ScopedArray const &);
1201 
1202         T * m_arr;
1203     };
1204 
1205     struct SliceDividerState
1206     {
1207         mfxU32 m_numSlice;
1208         mfxU32 m_numMbInRow;
1209         mfxU32 m_numMbRow;
1210         mfxU32 m_leftSlice;
1211         mfxU32 m_leftMbRow;
1212         mfxU32 m_currSliceFirstMbRow;
1213         mfxU32 m_currSliceNumMbRow;
1214     };
1215 
1216     struct SliceDivider : protected SliceDividerState
1217     {
1218         SliceDivider() : m_pfNext(0) {}
1219 
1220         // 'False' means no more slices, object needs to be recreated
1221         bool Next() { return m_pfNext(*this); }
1222 
1223         mfxU32 GetFirstMbInSlice() const;
1224 
1225         mfxU32 GetNumMbInSlice() const;
1226 
1227         mfxU32 GetNumSlice() const;
1228 
1229     protected:
1230         bool (*m_pfNext)(SliceDividerState & state);
1231     };
1232 
1233 
1234     struct SliceDividerOneSlice : SliceDivider
1235     {
1236         SliceDividerOneSlice(
1237             mfxU32 numSlice,
1238             mfxU32 widthInMbs,
1239             mfxU32 heightInMbs);
1240 
1241         static bool Next(SliceDividerState & state);
1242     };
1243 
1244 
1245     struct SliceDividerArbitraryRowSlice : SliceDivider
1246     {
1247         SliceDividerArbitraryRowSlice(
1248             mfxU32 numSlice,
1249             mfxU32 widthInMbs,
1250             mfxU32 heightInMbs);
1251 
1252         static bool Next(SliceDividerState & state);
1253     };
1254 
1255 
1256     struct SliceDividerRow2Row : SliceDivider
1257     {
1258         SliceDividerRow2Row(
1259             mfxU32 numSlice,
1260             mfxU32 widthInMbs,
1261             mfxU32 heightInMbs);
1262 
1263         static bool Next(SliceDividerState & state);
1264 
1265         static void Test();
1266     };
1267 
1268 
1269     struct SliceDividerRowSlice : SliceDivider
1270     {
1271         SliceDividerRowSlice(
1272             mfxU32 numSlice,
1273             mfxU32 widthInMbs,
1274             mfxU32 heightInMbs);
1275 
1276         static bool Next(SliceDividerState & state);
1277     };
1278 
1279     struct SliceDividerTemporalScalability : SliceDivider
1280     {
1281         SliceDividerTemporalScalability(
1282             mfxU32 sliceSizeInMbs,
1283             mfxU32 widthInMbs,
1284             mfxU32 heightInMbs);
1285 
1286         static bool Next(SliceDividerState & state);
1287     };
1288     struct SliceDividerLowPower : SliceDivider
1289     {
1290         SliceDividerLowPower(
1291             mfxU32 numSlice,
1292             mfxU32 widthInMbs,
1293             mfxU32 heightInMbs);
1294 
1295         static bool Next(SliceDividerState & state);
1296     };
1297     struct SliceDividerLowPowerTemporalScalability : SliceDivider
1298     {
1299         SliceDividerLowPowerTemporalScalability(
1300             mfxU32 sliceSizeInMbs,
1301             mfxU32 widthInMbs,
1302             mfxU32 heightInMbs);
1303 
1304         static bool Next(SliceDividerState & state);
1305     };
1306     SliceDivider MakeSliceDivider(
1307         SliceDividerType sliceHwCaps,
1308         mfxU32  sliceSizeInMbs,
1309         mfxU32  numSlice,
1310         mfxU32  widthInMbs,
1311         mfxU32  heightInMbs,
1312         bool isLowPower = false);
1313 
1314 
1315     class AspectRatioConverter
1316     {
1317     public:
1318         AspectRatioConverter(mfxU16 sarw, mfxU16 sarh);
1319         AspectRatioConverter(mfxU8 sarIdc, mfxU16 sarw, mfxU16 sarh);
1320         mfxU8  GetSarIdc()    const { return m_sarIdc; }
1321         mfxU16 GetSarWidth()  const { return m_sarWidth; }
1322         mfxU16 GetSarHeight() const { return m_sarHeight; }
1323 
1324     private:
1325         mfxU8  m_sarIdc;
1326         mfxU16 m_sarWidth;
1327         mfxU16 m_sarHeight;
1328     };
1329 
1330     class EndOfBuffer : public std::exception
1331     {
1332     public:
1333         EndOfBuffer() : std::exception() {}
1334     };
1335 
1336     class InvalidBitstream : public std::exception
1337     {
1338     public:
1339         InvalidBitstream() : std::exception() {}
1340     };
1341 
1342     void ReadSpsHeader(
1343         InputBitstream &  reader,
1344         mfxExtSpsHeader & sps);
1345 
1346     mfxU8 ReadSpsIdOfPpsHeader(
1347         InputBitstream reader);
1348 
1349     void ReadPpsHeader(
1350         InputBitstream &        reader,
1351         mfxExtSpsHeader const & sps,
1352         mfxExtPpsHeader &       pps);
1353 
1354     mfxU32 WriteSpsHeader(
1355         OutputBitstream &       writer,
1356         mfxExtSpsHeader const & sps);
1357 
1358     mfxU32 WriteSpsHeader(
1359         OutputBitstream &        writer,
1360         mfxExtSpsHeader const &  sps,
1361         mfxExtBuffer const &     spsExt);
1362 
1363     mfxU32 WritePpsHeader(
1364         OutputBitstream &       writer,
1365         mfxExtPpsHeader const & pps);
1366 
1367     void WriteScalingList(
1368         OutputBitstream &       writer,
1369         const mfxU8* scalingList,
1370         mfxI32 sizeOfScalingList);
1371 
1372     mfxU32 WriteAud(
1373         OutputBitstream & writer,
1374         mfxU32            frameType);
1375 
1376     struct RefListMod;
1377     struct WeightTab;
1378     template<class T, mfxU32 N> struct FixedArray;
1379     typedef FixedArray<RefListMod, 32> ArrayRefListMod;
1380     typedef FixedArray<WeightTab, 32> ArrayWeightTab;
1381 
1382     void WriteRefPicListModification(
1383         OutputBitstream &       writer,
1384         ArrayRefListMod const & refListMod);
1385 
1386     struct DecRefPicMarkingInfo;
1387 
1388     void WriteDecRefPicMarking(
1389         OutputBitstream &            writer,
1390         DecRefPicMarkingInfo const & marking,
1391         mfxU32                       idrPicFlag);
1392 
1393     bool IsAvcProfile(mfxU32 profile);
1394 
1395     bool IsAvcBaseProfile(mfxU32 profile);
1396 
1397     bool IsAvcHighProfile(mfxU32 profile);
1398 
1399     bool IsMvcProfile(mfxU32 profile);
1400 
1401 
1402     inline mfxStatus Error(mfxStatus sts)
1403     {
1404         return sts;
1405     }
1406 
1407     inline mfxStatus Warning(mfxStatus sts)
1408     {
1409         //__asm { int 3 }
1410         return sts;
1411     }
1412 
1413     mfxU8 * PackPrefixNalUnitSvc(
1414         mfxU8 *         begin,
1415         mfxU8 *         end,
1416         bool            emulationControl,
1417         DdiTask const & task,
1418         mfxU32          fieldId,
1419         mfxU32          nalUnitType = 0xe);
1420 
1421     class HeaderPacker
1422     {
1423     public:
1424         void Init(
1425             MfxVideoParam const &     par,
1426             MFX_ENCODE_CAPS const &   hwCaps,
1427             bool                      emulPrev = true); // insert emualtion prevention bytes when possible (sps/pps/sei/aud)
1428 
1429         std::vector<ENCODE_PACKEDHEADER_DATA> const & PackSlices(
1430             DdiTask const & task,
1431             mfxU32          fieldId);
1432 
1433 
1434 
1435         ENCODE_PACKEDHEADER_DATA const & PackSkippedSlice(
1436             DdiTask const & task,
1437             mfxU32          fieldId);
1438 
1439         ENCODE_PACKEDHEADER_DATA const & PackAud(
1440             DdiTask const & task,
1441             mfxU32          fieldId);
1442 
1443 
1444         ENCODE_PACKEDHEADER_DATA const & GetAud() const { return m_packedAud; }
1445 
1446         std::vector<ENCODE_PACKEDHEADER_DATA> const & GetSps() const { return m_packedSps; }
1447 
1448         std::vector<ENCODE_PACKEDHEADER_DATA> const & GetPps() const { return m_packedPps; }
1449 
1450         std::vector<ENCODE_PACKEDHEADER_DATA> const & GetSlices() const { return m_packedSlices; }
1451 
1452         bool isMVC() const { return m_isMVC; }
1453         bool isSvcPrefixUsed() const { return m_needPrefixNalUnit; }
1454 
1455         void ResizeSlices(mfxU32 num);
1456 
1457 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
1458         void GetHeadersInfo(std::vector<mfxEncodedUnitInfo> &HeadersMap, DdiTask const& task, mfxU32 fid);
1459 #endif
1460 
1461     private:
1462 
1463         mfxU32 WriteSlice(
1464             OutputBitstream & obs,
1465             DdiTask const &   task,
1466             mfxU32            fieldId,
1467             mfxU32            sliceId);
1468 
1469         mfxU32 WriteSlice(
1470             OutputBitstream & obs,
1471             DdiTask const &   task,
1472             mfxU32            fieldId,
1473             mfxU32            firstMbInSlice,
1474             mfxU32            numMbInSlice);
1475 
1476         // for header packing
1477         std::vector<mfxExtSpsHeader>    m_sps;
1478         std::vector<mfxExtPpsHeader>    m_pps;
1479         MFX_ENCODE_CAPS                 m_hwCaps;
1480         mfxU8                           m_spsIdx[8][16];            // for lookup by did & qid
1481         mfxU8                           m_ppsIdx[8][16];            // for lookup by did & qid
1482         mfxU8                           m_refDqId[8];               // for lookup by did
1483         mfxU8                           m_simulcast[8];             // for lookup by did
1484         mfxU16                          m_cabacInitIdc;             // same for all layers and slices
1485         mfxU16                          m_directSpatialMvPredFlag;  // same for all layers and slices
1486         mfxU16                          m_numMbPerSlice;
1487         bool                            m_needPrefixNalUnit;
1488         bool                            m_emulPrev;                 // insert emualtion prevention bytes when possible (sps/pps/sei/aud)
1489         bool                            m_isMVC;
1490         bool                            m_longStartCodes;
1491         bool                            m_isLowPower;
1492 
1493         ENCODE_PACKEDHEADER_DATA                m_packedAud;
1494         std::vector<ENCODE_PACKEDHEADER_DATA>   m_packedSps;
1495         std::vector<ENCODE_PACKEDHEADER_DATA>   m_packedPps;
1496         std::vector<ENCODE_PACKEDHEADER_DATA>   m_packedSlices;
1497         std::vector<mfxU8>                      m_headerBuffer;
1498         std::vector<mfxU8>                      m_sliceBuffer;
1499 
1500         static const mfxU32 SPSPPS_BUFFER_SIZE = 1024;
1501         static const mfxU32 SLICE_BUFFER_SIZE  = 2048;
1502     };
1503 
1504     inline mfxU16 LaDSenumToFactor(const mfxU16& LookAheadDS)
1505     {
1506         switch (LookAheadDS)
1507         {
1508         case MFX_LOOKAHEAD_DS_UNKNOWN:
1509             return 0;
1510         case MFX_LOOKAHEAD_DS_OFF:
1511             return 1;
1512         case MFX_LOOKAHEAD_DS_2x :
1513             return 2;
1514         case MFX_LOOKAHEAD_DS_4x :
1515             return 4;
1516         default:
1517             assert(0);
1518             return LookAheadDS;
1519         }
1520     }
1521 };
1522 
1523 #endif // MFX_ENABLE_H264_VIDEO_..._HW
1524 #endif // __MFX_H264_ENC_COMMON_HW_H__
1525