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 #include "mfx_common.h"
22 
23 #if defined (MFX_ENABLE_H264_VIDEO_ENCODE_HW)
24 
25 #include <limits>
26 #include <limits.h>
27 
28 #if defined (MFX_VA_LINUX)
29 #include <va/va.h>
30 #endif
31 #include "libmfx_core_interface.h"
32 #include "libmfx_core_factory.h"
33 
34 #include "mfx_h264_encode_hw_utils.h"
35 
36 #include "mfx_brc_common.h"
37 #include "umc_h264_brc.h"
38 #include "mfx_enc_common.h"
39 #include "umc_h264_common.h"
40 #ifdef MFX_ENABLE_H264_VIDEO_FEI_ENCPAK
41 #include "mfxfei.h"
42 #endif
43 
44 
45 using namespace MfxHwH264Encode;
46 
47 const mfxU32 DEFAULT_CPB_IN_SECONDS = 2000;          //  BufferSizeInBits = DEFAULT_CPB_IN_SECONDS * MaxKbps
48 const mfxU32 MAX_BITRATE_RATIO = mfxU32(1.5 * 1000); //  MaxBps = MAX_BITRATE_RATIO * TargetKbps;
49 
50 const mfxU32 DEFAULT_ASYNC_DEPTH_TO_WA_D3D9_128_SURFACE_LIMIT = 10; //  Use this value in case of d3d9 and when par.AsyncDepth parameter is set to a very big value
51 
52 namespace
53 {
54     static const mfxU8 EXTENDED_SAR = 0xff;
55 
56     static const mfxU32 MAX_H_MV = 2048;
57 
58     static const struct { mfxU16 w, h; } TABLE_E1[] =
59     {
60         {   0,   0 }, {   1,   1 }, {  12,  11 }, {  10,  11 }, {  16,  11 },
61         {  40,  33 }, {  24,  11 }, {  20,  11 }, {  32,  11 }, {  80,  33 },
62         {  18,  11 }, {  15,  11 }, {  64,  33 }, { 160,  99 }, {   4,   3 },
63         {   3,   2 }, {   2,   1 }
64     };
65 
66     const mfxU16 AVBR_ACCURACY_MIN = 1;
67     const mfxU16 AVBR_ACCURACY_MAX = 65535;
68 
69     const mfxU16 AVBR_CONVERGENCE_MIN = 1;
70     const mfxU16 AVBR_CONVERGENCE_MAX = 65535;
71 
CheckTriStateOption(mfxU16 & opt)72     bool CheckTriStateOption(mfxU16 & opt)
73     {
74         if (opt != MFX_CODINGOPTION_UNKNOWN &&
75             opt != MFX_CODINGOPTION_ON &&
76             opt != MFX_CODINGOPTION_OFF)
77         {
78             opt = MFX_CODINGOPTION_UNKNOWN;
79             return false;
80         }
81 
82         return true;
83     }
84 #ifdef MFX_ENABLE_H264_REPARTITION_CHECK
CheckTriStateOptionWithAdaptive(mfxU16 & opt)85     bool CheckTriStateOptionWithAdaptive(mfxU16 & opt)
86     {
87         if (opt != MFX_CODINGOPTION_UNKNOWN &&
88             opt != MFX_CODINGOPTION_ON &&
89             opt != MFX_CODINGOPTION_OFF &&
90             opt != MFX_CODINGOPTION_ADAPTIVE)
91         {
92             opt = MFX_CODINGOPTION_UNKNOWN;
93             return false;
94         }
95 
96         return true;
97     }
98 #endif
99 
CheckTriStateOptionForOff(mfxU16 & opt)100     bool CheckTriStateOptionForOff(mfxU16 & opt)
101     {
102         if (opt !=  MFX_CODINGOPTION_OFF)
103         {
104             opt = MFX_CODINGOPTION_OFF;
105             return false;
106         }
107 
108         return true;
109     }
110 
SetDefaultOn(mfxU16 & opt)111     inline void SetDefaultOn(mfxU16 & opt)
112     {
113         if (opt ==  MFX_CODINGOPTION_UNKNOWN)
114         {
115             opt = MFX_CODINGOPTION_ON;
116         }
117     }
118 
SetDefaultOff(mfxU16 & opt)119     inline void SetDefaultOff(mfxU16 & opt)
120     {
121         if (opt ==  MFX_CODINGOPTION_UNKNOWN)
122         {
123             opt = MFX_CODINGOPTION_OFF;
124         }
125     }
126 
127     template <class T, class U>
CheckFlag(T & opt,U deflt)128     bool CheckFlag(T & opt, U deflt)
129     {
130         if (opt > 1)
131         {
132             opt = static_cast<T>(deflt);
133             return false;
134         }
135 
136         return true;
137     }
138 
139     template <class T, class U>
CheckRange(T & opt,U min,U max)140     bool CheckRange(T & opt, U min, U max)
141     {
142         if (opt < min)
143         {
144             opt = static_cast<T>(min);
145             return false;
146         }
147 
148         if (opt > max)
149         {
150             opt = static_cast<T>(max);
151             return false;
152         }
153 
154         return true;
155     }
156 
157     template <class T, class U>
CheckRangeDflt(T & opt,U min,U max,U deflt)158     bool CheckRangeDflt(T & opt, U min, U max, U deflt)
159     {
160         if (opt < static_cast<T>(min) || opt > static_cast<T>(max))
161         {
162             opt = static_cast<T>(deflt);
163             return false;
164         }
165 
166         return true;
167     }
168 
169     struct FunctionQuery {};
170     struct FunctionInit {};
171 
172     template <class T, class U>
CheckAgreement(FunctionQuery,T & lowerPriorityValue,U higherPriorityValue)173     mfxU32 CheckAgreement(FunctionQuery, T & lowerPriorityValue, U higherPriorityValue)
174     {
175         if (lowerPriorityValue != 0 &&
176             lowerPriorityValue != higherPriorityValue)
177             return lowerPriorityValue = higherPriorityValue, 1;
178         else
179             return 0;
180     }
181 
182     template <class T, class U>
CheckAgreement(FunctionInit,T & lowerPriorityValue,U higherPriorityValue)183     mfxU32 CheckAgreement(FunctionInit, T & lowerPriorityValue, U higherPriorityValue)
184     {
185         if (lowerPriorityValue == 0)
186             return lowerPriorityValue = higherPriorityValue, 0; // assignment, not a correction
187         else if (lowerPriorityValue != higherPriorityValue)
188             return lowerPriorityValue = higherPriorityValue, 1; // correction
189         else
190             return 0; // already equal
191     }
192 
CheckMbAlignment(mfxU32 & opt)193     bool CheckMbAlignment(mfxU32 & opt)
194     {
195         if (opt & 0x0f)
196         {
197             opt = opt & 0xfffffff0;
198             return false;
199         }
200 
201         return true;
202     }
203 
CheckMbAlignmentAndUp(mfxU32 & opt)204     bool CheckMbAlignmentAndUp(mfxU32 & opt)
205     {
206         if (opt & 0x0f)
207         {
208             opt = (opt & 0xfffffff0) + 0x10;
209             return false;
210         }
211 
212         return true;
213     }
214 
IsValidCodingLevel(mfxU16 level)215     bool IsValidCodingLevel(mfxU16 level)
216     {
217         return
218             level == MFX_LEVEL_AVC_1  ||
219             level == MFX_LEVEL_AVC_11 ||
220             level == MFX_LEVEL_AVC_12 ||
221             level == MFX_LEVEL_AVC_13 ||
222             level == MFX_LEVEL_AVC_1b ||
223             level == MFX_LEVEL_AVC_2  ||
224             level == MFX_LEVEL_AVC_21 ||
225             level == MFX_LEVEL_AVC_22 ||
226             level == MFX_LEVEL_AVC_3  ||
227             level == MFX_LEVEL_AVC_31 ||
228             level == MFX_LEVEL_AVC_32 ||
229             level == MFX_LEVEL_AVC_4  ||
230             level == MFX_LEVEL_AVC_41 ||
231             level == MFX_LEVEL_AVC_42 ||
232             level == MFX_LEVEL_AVC_5  ||
233             level == MFX_LEVEL_AVC_51 ||
234             level == MFX_LEVEL_AVC_52;
235     }
236 
IsValidCodingProfile(mfxU16 profile)237     bool IsValidCodingProfile(mfxU16 profile)
238     {
239         return
240             IsAvcBaseProfile(profile)       ||
241             IsAvcHighProfile(profile)       ||
242             (IsMvcProfile(profile) && (profile != MFX_PROFILE_AVC_MULTIVIEW_HIGH)) || // Multiview high isn't supported by MSDK
243             profile == MFX_PROFILE_AVC_MAIN
244             ;
245     }
246 
GetMaxSupportedLevel()247     inline mfxU16 GetMaxSupportedLevel()
248     {
249         return MFX_LEVEL_AVC_52;
250     }
251 
GetNextProfile(mfxU16 profile)252     mfxU16 GetNextProfile(mfxU16 profile)
253     {
254         switch (profile)
255         {
256         case MFX_PROFILE_AVC_BASELINE:    return MFX_PROFILE_AVC_MAIN;
257         case MFX_PROFILE_AVC_MAIN:        return MFX_PROFILE_AVC_HIGH;
258         case MFX_PROFILE_AVC_HIGH:        return MFX_PROFILE_UNKNOWN;
259         case MFX_PROFILE_AVC_STEREO_HIGH: return MFX_PROFILE_UNKNOWN;
260         default: assert(!"bad profile");
261             return MFX_PROFILE_UNKNOWN;
262         }
263     }
264 
GetLevelLimitByDpbSize(mfxVideoParam const & par)265     mfxU16 GetLevelLimitByDpbSize(mfxVideoParam const & par)
266     {
267         mfxU32 dpbSize = par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height * 3 / 2;
268 
269         dpbSize *= par.mfx.NumRefFrame;
270         assert(dpbSize > 0);
271 
272         if (dpbSize <=   152064) return MFX_LEVEL_AVC_1;
273         if (dpbSize <=   345600) return MFX_LEVEL_AVC_11;
274         if (dpbSize <=   912384) return MFX_LEVEL_AVC_12;
275         if (dpbSize <=  1824768) return MFX_LEVEL_AVC_21;
276         if (dpbSize <=  3110400) return MFX_LEVEL_AVC_22;
277         if (dpbSize <=  6912000) return MFX_LEVEL_AVC_31;
278         if (dpbSize <=  7864320) return MFX_LEVEL_AVC_32;
279         if (dpbSize <= 12582912) return MFX_LEVEL_AVC_4;
280         if (dpbSize <= 13369344) return MFX_LEVEL_AVC_42;
281         if (dpbSize <= 42393600) return MFX_LEVEL_AVC_5;
282         if (dpbSize <= 70778880) return MFX_LEVEL_AVC_51;
283 
284         return MFX_LEVEL_UNKNOWN;
285     }
286 
GetLevelLimitByFrameSize(mfxVideoParam const & par)287     mfxU16 GetLevelLimitByFrameSize(mfxVideoParam const & par)
288     {
289         mfxU32 numMb = par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256;
290 
291         if (numMb <=    99) return MFX_LEVEL_AVC_1;
292         if (numMb <=   396) return MFX_LEVEL_AVC_11;
293         if (numMb <=   792) return MFX_LEVEL_AVC_21;
294         if (numMb <=  1620) return MFX_LEVEL_AVC_22;
295         if (numMb <=  3600) return MFX_LEVEL_AVC_31;
296         if (numMb <=  5120) return MFX_LEVEL_AVC_32;
297         if (numMb <=  8192) return MFX_LEVEL_AVC_4;
298         if (numMb <=  8704) return MFX_LEVEL_AVC_42;
299         if (numMb <= 22080) return MFX_LEVEL_AVC_5;
300         if (numMb <= 36864) return MFX_LEVEL_AVC_51;
301 
302         return MFX_LEVEL_UNKNOWN;
303     }
304 
GetLevelLimitByMbps(mfxVideoParam const & par)305     mfxU16 GetLevelLimitByMbps(mfxVideoParam const & par)
306     {
307         mfxU32 numMb = par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256;
308         mfxF64 fR = mfxF64(par.mfx.FrameInfo.FrameRateExtN) / par.mfx.FrameInfo.FrameRateExtD;
309         mfxF64 mbps = numMb * fR;
310 
311         if (mbps <=   1485)  return MFX_LEVEL_AVC_1;
312         if (mbps <=   3000)  return MFX_LEVEL_AVC_11;
313         if (mbps <=   6000)  return MFX_LEVEL_AVC_12;
314         if (mbps <=  11880)  return MFX_LEVEL_AVC_13;
315         if (mbps <=  19800)  return MFX_LEVEL_AVC_21;
316         if (mbps <=  20250)  return MFX_LEVEL_AVC_22;
317         if (mbps <=  40500)  return MFX_LEVEL_AVC_3;
318         if (mbps <= 108000)  return MFX_LEVEL_AVC_31;
319         if (mbps <= 216000)  return MFX_LEVEL_AVC_32;
320         if (mbps <= 245760)  return MFX_LEVEL_AVC_4;
321         if (mbps <= 522240)  return MFX_LEVEL_AVC_42;
322         if (mbps <= 589824)  return MFX_LEVEL_AVC_5;
323         if (mbps <= 983040)  return MFX_LEVEL_AVC_51;
324         if (mbps <= 2073600) return MFX_LEVEL_AVC_52;
325 
326         return MFX_LEVEL_UNKNOWN;
327     }
328 
GetLevelLimitByMaxBitrate(mfxU16 profile,mfxU32 kbps)329     mfxU16 GetLevelLimitByMaxBitrate(mfxU16 profile, mfxU32 kbps)
330     {
331         mfxU32 brFactor = IsAvcHighProfile(profile) ? 1500 : 1200;
332         mfxU32 br = 1000 * kbps;
333 
334         if (br <=     64 * brFactor) return MFX_LEVEL_AVC_1;
335         if (br <=    128 * brFactor) return MFX_LEVEL_AVC_1b;
336         if (br <=    192 * brFactor) return MFX_LEVEL_AVC_11;
337         if (br <=    384 * brFactor) return MFX_LEVEL_AVC_12;
338         if (br <=    768 * brFactor) return MFX_LEVEL_AVC_13;
339         if (br <=   2000 * brFactor) return MFX_LEVEL_AVC_2;
340         if (br <=   4000 * brFactor) return MFX_LEVEL_AVC_21;
341         if (br <=  10000 * brFactor) return MFX_LEVEL_AVC_3;
342         if (br <=  14000 * brFactor) return MFX_LEVEL_AVC_31;
343         if (br <=  20000 * brFactor) return MFX_LEVEL_AVC_32;
344         if (br <=  50000 * brFactor) return MFX_LEVEL_AVC_41;
345         if (br <= 135000 * brFactor) return MFX_LEVEL_AVC_5;
346         if (br <= 240000 * brFactor) return MFX_LEVEL_AVC_51;
347 
348         return MFX_LEVEL_UNKNOWN;
349     }
350 
GetLevelLimitByBufferSize(mfxU16 profile,mfxU32 bufferSizeInKb)351     mfxU16 GetLevelLimitByBufferSize(mfxU16 profile, mfxU32 bufferSizeInKb)
352     {
353         mfxU32 brFactor = IsAvcHighProfile(profile) ? 1500 : 1200;
354         mfxU32 bufSize = 8000 * bufferSizeInKb;
355 
356         if (bufSize <=    175 * brFactor) return MFX_LEVEL_AVC_1;
357         if (bufSize <=    350 * brFactor) return MFX_LEVEL_AVC_1b;
358         if (bufSize <=    500 * brFactor) return MFX_LEVEL_AVC_11;
359         if (bufSize <=   1000 * brFactor) return MFX_LEVEL_AVC_12;
360         if (bufSize <=   2000 * brFactor) return MFX_LEVEL_AVC_13;
361         if (bufSize <=   4000 * brFactor) return MFX_LEVEL_AVC_21;
362         if (bufSize <=  10000 * brFactor) return MFX_LEVEL_AVC_3;
363         if (bufSize <=  14000 * brFactor) return MFX_LEVEL_AVC_31;
364         if (bufSize <=  20000 * brFactor) return MFX_LEVEL_AVC_32;
365         if (bufSize <=  25000 * brFactor) return MFX_LEVEL_AVC_4;
366         if (bufSize <=  62500 * brFactor) return MFX_LEVEL_AVC_41;
367         if (bufSize <= 135000 * brFactor) return MFX_LEVEL_AVC_5;
368         if (bufSize <= 240000 * brFactor) return MFX_LEVEL_AVC_51;
369 
370         return MFX_LEVEL_UNKNOWN;
371     }
372 
373     // calculate possible minimum level for encoding of input stream
GetMinLevelForAllParameters(MfxVideoParam const & par)374     mfxU16 GetMinLevelForAllParameters(MfxVideoParam const & par)
375     {
376         mfxExtSpsHeader const & extSps = GetExtBufferRef(par);
377 
378         if (par.mfx.FrameInfo.Width  == 0 ||
379             par.mfx.FrameInfo.Height == 0)
380         {
381             // input information isn't enough to determine required level
382             return 0;
383         }
384 
385         mfxU16 maxSupportedLevel = GetMaxSupportedLevel();
386         mfxU16 level = GetLevelLimitByFrameSize(par);
387 
388         if (level == 0 || level == maxSupportedLevel)
389         {
390             // level is already maximum possible, return it
391             return maxSupportedLevel;
392         }
393 
394         if (extSps.vui.flags.timingInfoPresent == 0 ||
395             par.mfx.FrameInfo.FrameRateExtN    == 0 ||
396             par.mfx.FrameInfo.FrameRateExtD    == 0)
397         {
398             // no information about frame rate
399             return level;
400         }
401 
402         mfxU16 levelMbps = GetLevelLimitByMbps(par);
403 
404         if (levelMbps == 0 || levelMbps == maxSupportedLevel)
405         {
406             // level is already maximum possible, return it
407             return maxSupportedLevel;
408         }
409 
410         if (levelMbps > level)
411             level = levelMbps;
412 
413         if (par.mfx.NumRefFrame      != 0 &&
414             par.mfx.FrameInfo.Width  != 0 &&
415             par.mfx.FrameInfo.Height != 0)
416         {
417             mfxU16 levelDpbs = GetLevelLimitByDpbSize(par);
418 
419             if (levelDpbs == 0 || levelDpbs == maxSupportedLevel)
420             {
421                 // level is already maximum possible, return it
422                 return maxSupportedLevel;
423             }
424 
425 
426             if (levelDpbs > level)
427                 level = levelDpbs;
428         }
429 
430         mfxU16 profile = par.mfx.CodecProfile;
431         mfxU32 kbps = par.calcParam.targetKbps;
432         if (
433             par.mfx.RateControlMethod == MFX_RATECONTROL_VCM ||
434             par.mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
435             par.mfx.RateControlMethod == MFX_RATECONTROL_WIDI_VBR ||
436             par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR ||
437             par.mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD)
438         {
439             if (par.calcParam.maxKbps >= kbps)
440                 kbps = par.calcParam.maxKbps;
441             else
442                 kbps = par.calcParam.targetKbps * MAX_BITRATE_RATIO / 1000;
443         }
444         mfxU16 levelBr = GetLevelLimitByMaxBitrate(profile, kbps);
445 
446         if (levelBr == 0 || levelBr == maxSupportedLevel)
447         {
448             // level is already maximum possible, return it
449             return maxSupportedLevel;
450         }
451 
452         if (levelBr > level)
453             level = levelBr;
454 
455         profile = par.mfx.CodecProfile;
456         mfxU32 cpb = par.calcParam.bufferSizeInKB;
457         mfxU16 levelCPM = GetLevelLimitByBufferSize(profile, cpb);
458         if (levelCPM == 0 || levelCPM == maxSupportedLevel)
459         {
460             // level is already maximum possible, return it
461             return maxSupportedLevel;
462         }
463 
464         if (levelCPM > level)
465             level = levelCPM;
466 
467         return level;
468     }
469     // calculate minimum level required for encoding of input stream (with given resolution and frame rate)
470     // input stream can't be encoded with lower level regardless of any encoding parameters
GetMinLevelForResolutionAndFramerate(MfxVideoParam const & par)471     mfxU16 GetMinLevelForResolutionAndFramerate(MfxVideoParam const & par)
472     {
473         mfxExtSpsHeader const & extSps = GetExtBufferRef(par);
474 
475         if (par.mfx.FrameInfo.Width         == 0 ||
476             par.mfx.FrameInfo.Height        == 0)
477         {
478             // input information isn't enough to determine required level
479             return 0;
480         }
481 
482         mfxU16 maxSupportedLevel = GetMaxSupportedLevel();
483         mfxU16 level = GetLevelLimitByFrameSize(par);
484 
485         if (level == 0 || level == maxSupportedLevel)
486         {
487             // level is already maximum possible, return it
488             return maxSupportedLevel;
489         }
490 
491         if (extSps.vui.flags.timingInfoPresent == 0 ||
492             par.mfx.FrameInfo.FrameRateExtN    == 0 ||
493             par.mfx.FrameInfo.FrameRateExtD    == 0)
494         {
495             // no information about frame rate
496             return level;
497         }
498 
499         mfxU16 levelMbps = GetLevelLimitByMbps(par);
500 
501         if (levelMbps == 0 || levelMbps == maxSupportedLevel)
502         {
503             // level is already maximum possible, return it
504             return maxSupportedLevel;
505         }
506 
507         if (levelMbps > level)
508             level = levelMbps;
509 
510         return level;
511     }
512 
GetMaxNumRefFrame(mfxU16 level,mfxU16 width,mfxU16 height)513     mfxU16 GetMaxNumRefFrame(mfxU16 level, mfxU16 width, mfxU16 height)
514     {
515         mfxU32 maxDpbSize = 0;
516         if (level == MFX_LEVEL_UNKNOWN)
517             level = MFX_LEVEL_AVC_52;
518 
519         switch (level)
520         {
521         case MFX_LEVEL_AVC_1 : maxDpbSize =   152064; break;
522         case MFX_LEVEL_AVC_1b: maxDpbSize =   152064; break;
523         case MFX_LEVEL_AVC_11: maxDpbSize =   345600; break;
524         case MFX_LEVEL_AVC_12: maxDpbSize =   912384; break;
525         case MFX_LEVEL_AVC_13: maxDpbSize =   912384; break;
526         case MFX_LEVEL_AVC_2 : maxDpbSize =   912384; break;
527         case MFX_LEVEL_AVC_21: maxDpbSize =  1824768; break;
528         case MFX_LEVEL_AVC_22: maxDpbSize =  3110400; break;
529         case MFX_LEVEL_AVC_3 : maxDpbSize =  3110400; break;
530         case MFX_LEVEL_AVC_31: maxDpbSize =  6912000; break;
531         case MFX_LEVEL_AVC_32: maxDpbSize =  7864320; break;
532         case MFX_LEVEL_AVC_4 : maxDpbSize = 12582912; break;
533         case MFX_LEVEL_AVC_41: maxDpbSize = 12582912; break;
534         case MFX_LEVEL_AVC_42: maxDpbSize = 13369344; break;
535         case MFX_LEVEL_AVC_5 : maxDpbSize = 42393600; break;
536         case MFX_LEVEL_AVC_51: maxDpbSize = 70778880; break;
537         case MFX_LEVEL_AVC_52: maxDpbSize = 70778880; break;
538         default: assert(!"bad CodecLevel");
539         }
540 
541         mfxU32 frameSize = width * height * 3 / 2;
542         return mfx::clamp<mfxU16>(maxDpbSize / frameSize, 1, 16);
543     }
544 
GetMaxNumRefFrame(mfxVideoParam const & par)545     mfxU16 GetMaxNumRefFrame(mfxVideoParam const & par)
546     {
547         return GetMaxNumRefFrame(par.mfx.CodecLevel, par.mfx.FrameInfo.Width, par.mfx.FrameInfo.Height);
548     }
549 
GetMinNumRefFrameForPyramid(mfxU16 GopRefDist)550     mfxU16 GetMinNumRefFrameForPyramid(mfxU16 GopRefDist)
551     {
552         mfxU16 refIP = (GopRefDist > 1 ? 2 : 1);
553         mfxU16 refB  = GopRefDist ? (GopRefDist - 1) / 2 : 0;
554 
555         for (mfxU16 x = refB; x > 2;)
556         {
557             x     = (x - 1) / 2;
558             refB -= x;
559         }
560 
561         return refIP + refB;
562     }
563 
GetMinNumRefFrameForPyramid(mfxVideoParam const & par)564     mfxU16 GetMinNumRefFrameForPyramid(mfxVideoParam const & par)
565     {
566         return GetMinNumRefFrameForPyramid(par.mfx.GopRefDist);
567     }
568 
GetMaxBitrate(mfxVideoParam const & par)569     mfxU32 GetMaxBitrate(mfxVideoParam const & par)
570     {
571         mfxU32 brFactor = IsAvcHighProfile(par.mfx.CodecProfile) ? 1500 : 1200;
572 
573         mfxU16 level = par.mfx.CodecLevel;
574         if (level == MFX_LEVEL_UNKNOWN)
575             level = MFX_LEVEL_AVC_52;
576 
577         switch (level)
578         {
579         case MFX_LEVEL_AVC_1 : return     64 * brFactor;
580         case MFX_LEVEL_AVC_1b: return    128 * brFactor;
581         case MFX_LEVEL_AVC_11: return    192 * brFactor;
582         case MFX_LEVEL_AVC_12: return    384 * brFactor;
583         case MFX_LEVEL_AVC_13: return    768 * brFactor;
584         case MFX_LEVEL_AVC_2 : return   2000 * brFactor;
585         case MFX_LEVEL_AVC_21: return   4000 * brFactor;
586         case MFX_LEVEL_AVC_22: return   4000 * brFactor;
587         case MFX_LEVEL_AVC_3 : return  10000 * brFactor;
588         case MFX_LEVEL_AVC_31: return  14000 * brFactor;
589         case MFX_LEVEL_AVC_32: return  20000 * brFactor;
590         case MFX_LEVEL_AVC_4 : return  20000 * brFactor;
591         case MFX_LEVEL_AVC_41: return  50000 * brFactor;
592         case MFX_LEVEL_AVC_42: return  50000 * brFactor;
593         case MFX_LEVEL_AVC_5 : return 135000 * brFactor;
594         case MFX_LEVEL_AVC_51: return 240000 * brFactor;
595         case MFX_LEVEL_AVC_52: return 240000 * brFactor;
596         default: assert(!"bad CodecLevel"); return 0;
597         }
598     }
599 
GetMaxPerViewBitrate(MfxVideoParam const & par)600     mfxU32 GetMaxPerViewBitrate(MfxVideoParam const & par)
601     {
602         mfxU32 brFactor = IsMvcProfile(par.mfx.CodecProfile) ? 1500 :
603             IsAvcHighProfile(par.mfx.CodecProfile) ? 1500 : 1200;
604 
605         mfxU16 level = IsMvcProfile(par.mfx.CodecProfile) ? par.calcParam.mvcPerViewPar.codecLevel : par.mfx.CodecLevel;
606         if (level == MFX_LEVEL_UNKNOWN)
607             level = MFX_LEVEL_AVC_52;
608 
609         switch (level)
610         {
611         case MFX_LEVEL_AVC_1 : return     64 * brFactor;
612         case MFX_LEVEL_AVC_1b: return    128 * brFactor;
613         case MFX_LEVEL_AVC_11: return    192 * brFactor;
614         case MFX_LEVEL_AVC_12: return    384 * brFactor;
615         case MFX_LEVEL_AVC_13: return    768 * brFactor;
616         case MFX_LEVEL_AVC_2 : return   2000 * brFactor;
617         case MFX_LEVEL_AVC_21: return   4000 * brFactor;
618         case MFX_LEVEL_AVC_22: return   4000 * brFactor;
619         case MFX_LEVEL_AVC_3 : return  10000 * brFactor;
620         case MFX_LEVEL_AVC_31: return  14000 * brFactor;
621         case MFX_LEVEL_AVC_32: return  20000 * brFactor;
622         case MFX_LEVEL_AVC_4 : return  20000 * brFactor;
623         case MFX_LEVEL_AVC_41: return  50000 * brFactor;
624         case MFX_LEVEL_AVC_42: return  50000 * brFactor;
625         case MFX_LEVEL_AVC_5 : return 135000 * brFactor;
626         case MFX_LEVEL_AVC_51: return 240000 * brFactor;
627         case MFX_LEVEL_AVC_52: return 240000 * brFactor;
628         default: assert(!"bad CodecLevel"); return 0;
629         }
630     }
631 
GetMaxBufferSize(mfxVideoParam const & par)632     mfxU32 GetMaxBufferSize(mfxVideoParam const & par)
633     {
634         mfxU32 brFactor = IsAvcHighProfile(par.mfx.CodecProfile) ? 1500 : 1200;
635 
636         mfxU16 level = par.mfx.CodecLevel;
637         if (level == MFX_LEVEL_UNKNOWN)
638             level = MFX_LEVEL_AVC_52;
639 
640         switch (level)
641         {
642         case MFX_LEVEL_AVC_1 : return    175 * brFactor;
643         case MFX_LEVEL_AVC_1b: return    350 * brFactor;
644         case MFX_LEVEL_AVC_11: return    500 * brFactor;
645         case MFX_LEVEL_AVC_12: return   1000 * brFactor;
646         case MFX_LEVEL_AVC_13: return   2000 * brFactor;
647         case MFX_LEVEL_AVC_2 : return   2000 * brFactor;
648         case MFX_LEVEL_AVC_21: return   4000 * brFactor;
649         case MFX_LEVEL_AVC_22: return   4000 * brFactor;
650         case MFX_LEVEL_AVC_3 : return  10000 * brFactor;
651         case MFX_LEVEL_AVC_31: return  14000 * brFactor;
652         case MFX_LEVEL_AVC_32: return  20000 * brFactor;
653         case MFX_LEVEL_AVC_4 : return  25000 * brFactor;
654         case MFX_LEVEL_AVC_41: return  62500 * brFactor;
655         case MFX_LEVEL_AVC_42: return  62500 * brFactor;
656         case MFX_LEVEL_AVC_5 : return 135000 * brFactor;
657         case MFX_LEVEL_AVC_51: return 240000 * brFactor;
658         case MFX_LEVEL_AVC_52: return 240000 * brFactor;
659         default: assert(!"bad CodecLevel"); return 0;
660         }
661     }
662 
GetMaxPerViewBufferSize(MfxVideoParam const & par)663     mfxU32 GetMaxPerViewBufferSize(MfxVideoParam const & par)
664     {
665         mfxU32 brFactor = IsMvcProfile(par.mfx.CodecProfile) ? 1500 :
666             IsAvcHighProfile(par.mfx.CodecProfile) ? 1500 : 1200;
667 
668         mfxU16 level = IsMvcProfile(par.mfx.CodecProfile) ? par.calcParam.mvcPerViewPar.codecLevel : par.mfx.CodecLevel;
669         if (level == MFX_LEVEL_UNKNOWN)
670             level = MFX_LEVEL_AVC_52;
671 
672         switch (level)
673         {
674         case MFX_LEVEL_AVC_1 : return    175 * brFactor;
675         case MFX_LEVEL_AVC_1b: return    350 * brFactor;
676         case MFX_LEVEL_AVC_11: return    500 * brFactor;
677         case MFX_LEVEL_AVC_12: return   1000 * brFactor;
678         case MFX_LEVEL_AVC_13: return   2000 * brFactor;
679         case MFX_LEVEL_AVC_2 : return   2000 * brFactor;
680         case MFX_LEVEL_AVC_21: return   4000 * brFactor;
681         case MFX_LEVEL_AVC_22: return   4000 * brFactor;
682         case MFX_LEVEL_AVC_3 : return  10000 * brFactor;
683         case MFX_LEVEL_AVC_31: return  14000 * brFactor;
684         case MFX_LEVEL_AVC_32: return  20000 * brFactor;
685         case MFX_LEVEL_AVC_4 : return  25000 * brFactor;
686         case MFX_LEVEL_AVC_41: return  62500 * brFactor;
687         case MFX_LEVEL_AVC_42: return  62500 * brFactor;
688         case MFX_LEVEL_AVC_5 : return 135000 * brFactor;
689         case MFX_LEVEL_AVC_51: return 240000 * brFactor;
690         case MFX_LEVEL_AVC_52: return 240000 * brFactor;
691         default: assert(!"bad CodecLevel"); return 0;
692         }
693     }
694 
695 
GetMaxMbps(mfxVideoParam const & par)696     mfxU32 GetMaxMbps(mfxVideoParam const & par)
697     {
698         switch (par.mfx.CodecLevel)
699         {
700         case MFX_LEVEL_AVC_1 :
701         case MFX_LEVEL_AVC_1b: return   1485;
702         case MFX_LEVEL_AVC_11: return   3000;
703         case MFX_LEVEL_AVC_12: return   6000;
704         case MFX_LEVEL_AVC_13:
705         case MFX_LEVEL_AVC_2 : return  11800;
706         case MFX_LEVEL_AVC_21: return  19800;
707         case MFX_LEVEL_AVC_22: return  20250;
708         case MFX_LEVEL_AVC_3 : return  40500;
709         case MFX_LEVEL_AVC_31: return 108000;
710         case MFX_LEVEL_AVC_32: return 216000;
711         case MFX_LEVEL_AVC_4 :
712         case MFX_LEVEL_AVC_41: return 245760;
713         case MFX_LEVEL_AVC_42: return 522240;
714         case MFX_LEVEL_AVC_5 : return 589824;
715         case MFX_LEVEL_AVC_51: return 983040;
716         case MFX_LEVEL_AVC_52: return 2073600;
717         default: assert(!"bad CodecLevel"); return 0;
718         }
719     }
720 
GetMinCr(mfxU32 level)721     mfxU32 GetMinCr(mfxU32 level)
722     {
723         return level >= MFX_LEVEL_AVC_31 && level <= MFX_LEVEL_AVC_42 ? 4 : 2; // AVCHD spec requires MinCR = 4 for levels  4.1, 4.2
724     }
725 
GetFirstMaxFrameSize(mfxVideoParam const & par)726     mfxU32 GetFirstMaxFrameSize(mfxVideoParam const & par)
727     {
728         mfxU32 picSizeInMbs = par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256;
729         return 384 * std::max<mfxU32>(picSizeInMbs, GetMaxMbps(par) / 172) / GetMinCr(par.mfx.CodecLevel);
730     }
731 
GetMaxFrameSize(mfxVideoParam const & par)732     mfxU32 GetMaxFrameSize(mfxVideoParam const & par)
733     {
734         mfxF64 frameRate = mfxF64(par.mfx.FrameInfo.FrameRateExtN) / par.mfx.FrameInfo.FrameRateExtD;
735         return mfxU32(384 * GetMaxMbps(par) / frameRate / GetMinCr(par.mfx.CodecLevel));
736     }
737 
CheckMaxFrameSize(MfxVideoParam & par,MFX_ENCODE_CAPS const & hwCaps)738     mfxStatus CheckMaxFrameSize(MfxVideoParam & par, MFX_ENCODE_CAPS const & hwCaps)
739     {
740         mfxExtCodingOption2 & extOpt2 = GetExtBufferRef(par);
741         mfxExtCodingOption3 & extOpt3 = GetExtBufferRef(par);
742         bool changed = false;
743         bool unsupported = false;
744 
745         if (extOpt2.MaxFrameSize == 0 && extOpt3.MaxFrameSizeI == 0 && extOpt3.MaxFrameSizeP == 0)
746             return MFX_ERR_NONE;
747 
748         bool IsEnabledSwBrc = isSWBRC(par);
749         if ((par.mfx.RateControlMethod == MFX_RATECONTROL_CBR || par.mfx.RateControlMethod == MFX_RATECONTROL_CQP) || // max frame size supported only for VBR based methods
750             (hwCaps.ddi_caps.UserMaxFrameSizeSupport == 0 && !IsEnabledSwBrc))
751         {
752             if (extOpt2.MaxFrameSize != 0 || extOpt3.MaxFrameSizeI != 0 || extOpt3.MaxFrameSizeP != 0)
753                 changed = true;
754             extOpt2.MaxFrameSize = 0;
755             extOpt3.MaxFrameSizeI = 0;
756             extOpt3.MaxFrameSizeP = 0;
757         }
758         else
759         {
760             if (par.calcParam.cqpHrdMode == 0 && par.calcParam.targetKbps != 0 &&
761                 par.mfx.FrameInfo.FrameRateExtN != 0 && par.mfx.FrameInfo.FrameRateExtD != 0)
762             {
763                 mfxF64 frameRate = mfxF64(par.mfx.FrameInfo.FrameRateExtN) / par.mfx.FrameInfo.FrameRateExtD;
764                 mfxU32 avgFrameSizeInBytes = par.calcParam.TCBRCTargetFrameSize ?
765                     par.calcParam.TCBRCTargetFrameSize :
766                     mfxU32(par.calcParam.targetKbps * 1000 / frameRate / 8);
767 
768                 if ((extOpt2.MaxFrameSize < avgFrameSizeInBytes) && (extOpt2.MaxFrameSize != 0))
769                 {
770                     changed = true;
771                     extOpt2.MaxFrameSize = 0;
772                 }
773                 if ((extOpt3.MaxFrameSizeI < avgFrameSizeInBytes) && (extOpt3.MaxFrameSizeI != 0))
774                 {
775                     changed = true;
776                     extOpt3.MaxFrameSizeI = 0;
777                     extOpt3.MaxFrameSizeP = 0;
778                 }
779             }
780             if ((extOpt2.MaxFrameSize != 0 && extOpt3.MaxFrameSizeI != 0) &&
781                 extOpt3.MaxFrameSizeI != extOpt2.MaxFrameSize)
782             {
783                 extOpt2.MaxFrameSize = 0;
784                 changed = true;
785             }
786             if (extOpt3.MaxFrameSizeI == 0 && extOpt3.MaxFrameSizeP != 0)
787             {
788                 extOpt3.MaxFrameSizeP = 0;
789                 unsupported = true;
790             }
791         }
792 
793 #if MFX_VERSION >= 1023
794         if (!CheckTriStateOption(extOpt3.AdaptiveMaxFrameSize)) changed = true;
795 
796         if(!hwCaps.AdaptiveMaxFrameSizeSupport && IsOn(extOpt3.AdaptiveMaxFrameSize))
797         {
798             extOpt3.AdaptiveMaxFrameSize = MFX_CODINGOPTION_UNKNOWN;
799             unsupported = true;
800         }
801 
802         if (hwCaps.ddi_caps.UserMaxFrameSizeSupport == 0 && !IsEnabledSwBrc && IsOn(extOpt3.AdaptiveMaxFrameSize))
803         {
804             extOpt3.AdaptiveMaxFrameSize = MFX_CODINGOPTION_UNKNOWN;
805             unsupported = true;
806         }
807 
808         if (hwCaps.ddi_caps.UserMaxFrameSizeSupport == 1 && !IsEnabledSwBrc &&
809             (extOpt3.MaxFrameSizeP == 0 || IsOn(par.mfx.LowPower)) &&
810             IsOn(extOpt3.AdaptiveMaxFrameSize))
811         {
812             extOpt3.AdaptiveMaxFrameSize = MFX_CODINGOPTION_UNKNOWN;
813             changed = true;
814         }
815 #endif
816         return unsupported ? MFX_ERR_UNSUPPORTED : (changed ? MFX_WRN_INCOMPATIBLE_VIDEO_PARAM : MFX_ERR_NONE);
817     }
818 
GetMaxVmv(mfxU32 level)819     mfxU32 GetMaxVmv(mfxU32 level)
820     {
821         switch (level)
822         {
823         case MFX_LEVEL_AVC_1 :
824         case MFX_LEVEL_AVC_1b: return  64;
825         case MFX_LEVEL_AVC_11:
826         case MFX_LEVEL_AVC_12:
827         case MFX_LEVEL_AVC_13:
828         case MFX_LEVEL_AVC_2 : return 128;
829         case MFX_LEVEL_AVC_21:
830         case MFX_LEVEL_AVC_22:
831         case MFX_LEVEL_AVC_3 : return 256;
832         case MFX_LEVEL_AVC_31:
833         case MFX_LEVEL_AVC_32:
834         case MFX_LEVEL_AVC_4 :
835         case MFX_LEVEL_AVC_41:
836         case MFX_LEVEL_AVC_42:
837         case MFX_LEVEL_AVC_5 :
838         case MFX_LEVEL_AVC_51:
839         case MFX_LEVEL_AVC_52: return 512;
840         default: assert(!"bad CodecLevel"); return 0;
841         }
842     }
843 
GetDefaultAsyncDepth(MfxVideoParam const & par)844     mfxU16 GetDefaultAsyncDepth(MfxVideoParam const & par)
845     {
846 //        mfxExtCodingOption2 const * extOpt2 = GetExtBuffer(par);
847 
848         if (par.mfx.EncodedOrder)
849             return 1;
850 
851         //if (IsOn(extOpt2->ExtBRC))
852         //    return 1;
853 
854         mfxU32 picSize = par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height;
855         if (picSize < 200000)
856             return 6; // CIF
857         else if (picSize < 500000)
858             return 5; // SD
859         else if (picSize < 900000)
860             return 4; // between SD and HD
861         else
862             return 3; // HD
863     }
864 
GetDefaultPicOrderCount(MfxVideoParam const & par)865     mfxU8 GetDefaultPicOrderCount(MfxVideoParam const & par)
866     {
867         if (par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
868             return 0;
869         if (par.mfx.GopRefDist > 1)
870             return 0;
871 
872         if (par.calcParam.numTemporalLayer > 1)
873         {
874             if (par.mfx.NumRefFrame < par.calcParam.scale[par.calcParam.numTemporalLayer - 2])
875                 return 0; // more than 1 consecutive non-reference frames
876 
877             if (par.calcParam.scale[par.calcParam.numTemporalLayer - 1] /
878                 par.calcParam.scale[par.calcParam.numTemporalLayer - 2] > 2)
879                 return 0; // more than 1 consecutive non-reference frames
880         }
881 
882         return 2;
883     }
884 
GetDefaultLog2MaxPicOrdCntMinus4(MfxVideoParam const & par)885     mfxU8 GetDefaultLog2MaxPicOrdCntMinus4(MfxVideoParam const & par)
886     {
887         mfxU32 numReorderFrames = GetNumReorderFrames(par);
888         mfxU32 maxPocDiff = (numReorderFrames * par.mfx.GopRefDist + 1) * 2;
889 
890         if (par.calcParam.numTemporalLayer > 0 || par.calcParam.tempScalabilityMode)
891         {
892             mfxU32 maxScale = par.calcParam.scale[par.calcParam.numTemporalLayer - 1];
893             // for tempScalabilityMode number of temporal layers should be changed dynamically w/o IDR insertion
894             // to assure this first SPS in bitstream should contain maximum possible log2_max_frame_num_minus4
895             if (par.calcParam.tempScalabilityMode)
896                 maxScale = 8; // 8 is maximum scale for 4 temporal layers
897 
898             maxPocDiff = std::max(maxPocDiff, 2 * maxScale);
899         }
900 
901         mfxU32 log2MaxPoc = CeilLog2(2 * maxPocDiff - 1);
902         return mfxU8(std::max(log2MaxPoc, 4u) - 4);
903     }
904 
GetDefaultGopRefDist(mfxU32 targetUsage,eMFXHWType platform)905     mfxU16 GetDefaultGopRefDist(mfxU32 targetUsage, eMFXHWType platform)
906     {
907         if(platform == MFX_HW_VLV){
908             const mfxU16 DEFAUILT_GOP_REF_DIST[8] = { 3, 3, 2, 2, 1, 1, 1 };
909             assert(targetUsage > 0 && targetUsage < 8);
910             return DEFAUILT_GOP_REF_DIST[targetUsage - 1];
911         }else{
912             return 3;
913         }
914         /*
915 
916         */
917     }
918 
GetDefaultNumRefFrames(mfxU32 targetUsage)919     mfxU16 GetDefaultNumRefFrames(mfxU32 targetUsage)
920     {
921         mfxU16 const DEFAULT_BY_TU[] = { 0, 3, 3, 3, 2, 1, 1, 1 };
922         return DEFAULT_BY_TU[targetUsage];
923     }
924 #if defined(MFX_ENABLE_MFE)
GetDefaultNumMfeFrames(mfxU32 targetUsage,const mfxFrameInfo & info,eMFXHWType platform,mfxFeiFunction func,int slices,bool extSurfUsed,eMFXGTConfig config,mfxU16 brcMethod)925     mfxU16 GetDefaultNumMfeFrames(mfxU32 targetUsage, const mfxFrameInfo& info,
926         eMFXHWType platform, mfxFeiFunction func, int slices, bool extSurfUsed,
927         eMFXGTConfig config, mfxU16 brcMethod)
928     {
929         std::ignore = targetUsage;//no specific check for TU now, can be added later
930         if (platform <= MFX_HW_BDW)//no MFE support prior to SKL.
931             return 1;
932         // ICQ is unsupported for MFE now, QVBR and VCM are low latency usage rate controls, MFE is not suitable for low latency usages
933         if(brcMethod == MFX_RATECONTROL_ICQ || brcMethod == MFX_RATECONTROL_QVBR || brcMethod == MFX_RATECONTROL_VCM)
934             return 1;
935         else if (platform == MFX_HW_SCL && config >= MFX_GT3)
936         {
937             if ((info.CropH > 1088 && info.CropW > 1920) || slices > 1)
938             {
939                 return 1;
940             }
941             else if ( extSurfUsed || func == MFX_FEI_FUNCTION_ENCODE)
942             {
943                 return 2;
944             }
945             //other functions either already rejected(PAK, ENC/PreEnc absense of support) or can run bigger amount of frames(for PreEnc).
946             //extSurfUsed - mean we are using  running into kernel limitation for max number of surfaces used in kernel
947             else if (func)
948             {
949                 return 1;
950             }
951             else
952             {
953                 return 3;
954             }
955         }
956         else if (platform == MFX_HW_SCL && config == MFX_GT2)
957         {
958             if ((info.CropH > 1088 && info.CropW > 1920) || slices > 1)
959             {
960                 return 1;
961             }
962             else if (extSurfUsed || func == MFX_FEI_FUNCTION_ENCODE)
963             {
964                 return 2;
965             }
966             //other functions either already rejected(PAK, ENC/PreEnc absense of support) or can run bigger amount of frames(for PreEnc).
967             //extSurfUsed - mean we are using running into kernel limitation for max number of surfaces used in kernel
968             else if (func)
969             {
970                 return 1;
971             }
972             else if (info.CropH > 720 && info.CropW > 1280)
973             {
974                 return 2;
975             }
976             else
977             {
978                 return 3;
979             }
980         }
981         else
982             return 1;//to be adjusted based on performance measurements on other platforms
983     }
984 
calculateMfeTimeout(const mfxFrameInfo & info)985     mfxU32 calculateMfeTimeout(const mfxFrameInfo& info)
986     {
987         //Just calculate based on latency expectation from framerate in microsecond now, can be changed in future
988         return mfxU32((mfxU64)info.FrameRateExtD * 1000000 / info.FrameRateExtN);
989     }
990 #endif
991 
GetMaxNumRefActivePL0(mfxU32 targetUsage,eMFXHWType platform,bool isLowPower,const mfxFrameInfo & info)992     mfxU16 GetMaxNumRefActivePL0(mfxU32 targetUsage,
993                                         eMFXHWType platform,
994                                         bool isLowPower,
995                                         const mfxFrameInfo& info)
996     {
997         if (platform <= MFX_HW_IVB || platform == MFX_HW_VLV)
998         {
999             return 1;
1000         }
1001 
1002         constexpr mfxU16 DEFAULT_BY_TU[][8] = {
1003             { 0, 8, 6, 4, 3, 2, 1, 1 }, // VME progressive < 4k or interlaced (platform <= MFX_HW_HSW_ULT)
1004             { 0, 8, 6, 3, 3, 3, 1, 1 }, // VME progressive < 4k or interlaced (platform > MFX_HW_HSW_ULT)
1005             { 0, 4, 4, 4, 3, 2, 1, 1 }, // VME progressive >= 4k (platform <= MFX_HW_HSW_ULT)
1006             { 0, 4, 4, 3, 3, 3, 1, 1 }, // VME progressive >= 4k (platform > MFX_HW_HSW_ULT)
1007             { 0, 3, 3, 2, 2, 2, 1, 1 }  // VDEnc
1008         };
1009 
1010         if (!isLowPower)
1011         {
1012             if ((info.Width < 3840 && info.Height < 2160) ||
1013                 (info.PicStruct != MFX_PICSTRUCT_PROGRESSIVE))
1014             {
1015                 return DEFAULT_BY_TU[platform > MFX_HW_HSW_ULT ? 1 : 0][targetUsage];
1016             }
1017             else //progressive >= 4K
1018             {
1019                 return DEFAULT_BY_TU[platform > MFX_HW_HSW_ULT ? 3 : 2][targetUsage];
1020             }
1021         }
1022         else
1023         {
1024             return DEFAULT_BY_TU[4][targetUsage];
1025         }
1026     }
1027 
GetDefaultNumRefActivePL0(const mfxInfoMFX & mfx,eMFXHWType platform)1028     mfxU16 GetDefaultNumRefActivePL0(const mfxInfoMFX& mfx, eMFXHWType platform)
1029     {
1030         return GetMaxNumRefActivePL0(mfx.TargetUsage, platform, IsOn(mfx.LowPower), mfx.FrameInfo);
1031     }
1032 
GetMaxNumRefActiveBL0(mfxU32 targetUsage,eMFXHWType platform,bool isLowPower)1033     mfxU16 GetMaxNumRefActiveBL0(mfxU32 targetUsage,
1034                                         eMFXHWType platform,
1035                                         bool isLowPower)
1036     {
1037         if ((platform >= MFX_HW_HSW && platform != MFX_HW_VLV) && !isLowPower)
1038         {
1039             constexpr mfxU16 DEFAULT_BY_TU[][8] = {
1040                 { 0, 4, 4, 3, 2, 2, 1, 1 }, // platform <= MFX_HW_HSW_ULT
1041                 { 0, 4, 4, 2, 2, 2, 1, 1 }
1042             };
1043             return DEFAULT_BY_TU[platform > MFX_HW_HSW_ULT ? 1 : 0][targetUsage];
1044         }
1045         else
1046         {
1047             return 1;
1048         }
1049     }
1050 
GetDefaultNumRefActiveBL0(const mfxInfoMFX & mfx,eMFXHWType platform)1051     mfxU16 GetDefaultNumRefActiveBL0(const mfxInfoMFX& mfx, eMFXHWType platform)
1052     {
1053         return GetMaxNumRefActiveBL0(mfx.TargetUsage, platform, IsOn(mfx.LowPower));
1054     }
1055 
GetMaxNumRefActiveBL1(mfxU32 targetUsage,eMFXHWType platform,mfxU16 picStruct,bool isLowPower)1056     mfxU16 GetMaxNumRefActiveBL1(mfxU32 targetUsage,
1057                                      eMFXHWType platform,
1058                                      mfxU16 picStruct,
1059                                      bool isLowPower)
1060     {
1061         if ((platform >= MFX_HW_HSW && platform != MFX_HW_VLV) &&
1062             picStruct != MFX_PICSTRUCT_PROGRESSIVE && !isLowPower)
1063         {
1064             constexpr mfxU16 DEFAULT_BY_TU[] = { 0, 2, 2, 2, 2, 2, 1, 1 };
1065             return DEFAULT_BY_TU[targetUsage];
1066         }
1067         else
1068         {
1069             return 1;
1070         }
1071     }
1072 
GetDefaultNumRefActiveBL1(const mfxInfoMFX & mfx,eMFXHWType platform)1073     mfxU16 GetDefaultNumRefActiveBL1(const mfxInfoMFX& mfx, eMFXHWType platform)
1074     {
1075         return GetMaxNumRefActiveBL0(mfx.TargetUsage, platform, IsOn(mfx.LowPower));
1076     }
1077 
GetDefaultIntraPredBlockSize(MfxVideoParam const & par,eMFXHWType platform)1078     mfxU16 GetDefaultIntraPredBlockSize(
1079         MfxVideoParam const & par,
1080         eMFXHWType            platform)
1081     {
1082         mfxU8 minTUForTransform8x8 = (platform <= MFX_HW_IVB || platform == MFX_HW_VLV) ? 4 : 7;
1083         return (IsAvcBaseProfile(par.mfx.CodecProfile)       ||
1084             par.mfx.CodecProfile == MFX_PROFILE_AVC_MAIN ||
1085             par.mfx.TargetUsage > minTUForTransform8x8)
1086                 ? mfxU16(MFX_BLOCKSIZE_MIN_16X16)
1087                 : mfxU16(MFX_BLOCKSIZE_MIN_4X4);
1088     }
1089 
GetCpbSizeValue(mfxU32 kbyte,mfxU32 scale)1090     mfxU32 GetCpbSizeValue(mfxU32 kbyte, mfxU32 scale)
1091     {
1092         return (8000 * kbyte) >> (4 + scale);
1093     }
1094 
GetMaxCodedFrameSizeInKB(MfxVideoParam const & par)1095     mfxU32 GetMaxCodedFrameSizeInKB(MfxVideoParam const & par)
1096     {
1097         mfxU64 mvcMultiplier = 1;
1098         const mfxU32 maxMBBytes = 3200 / 8;
1099 
1100         if (IsMvcProfile(par.mfx.CodecProfile))
1101         {
1102             mfxExtMVCSeqDesc const & extMvc = GetExtBufferRef(par);
1103             mfxExtCodingOption const & extOpt = GetExtBufferRef(par);
1104             if (extOpt.ViewOutput != MFX_CODINGOPTION_ON) // in case of ViewOutput bitstream should contain one view (not all views)
1105                 mvcMultiplier = extMvc.NumView ? extMvc.NumView : 1;
1106         }
1107 
1108         return mfxU32(std::min<size_t>(UINT_MAX, size_t(par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height * mvcMultiplier / (16u * 16u) * maxMBBytes + 999u) / 1000u));
1109     }
1110 
CheckAgreementOfFrameRate(FunctionQuery,mfxU32 & frameRateExtN,mfxU32 & frameRateExtD,mfxU32 timeScale,mfxU32 numUnitsInTick)1111     mfxU32 CheckAgreementOfFrameRate(
1112         FunctionQuery,
1113         mfxU32 & frameRateExtN,
1114         mfxU32 & frameRateExtD,
1115         mfxU32   timeScale,
1116         mfxU32   numUnitsInTick)
1117     {
1118         if (frameRateExtN != 0 &&
1119             frameRateExtD != 0 &&
1120             mfxU64(frameRateExtN) * numUnitsInTick * 2 != mfxU64(frameRateExtD) * timeScale)
1121         {
1122             frameRateExtN = timeScale;
1123             frameRateExtD = numUnitsInTick * 2;
1124             return 1;
1125         }
1126 
1127         return 0;
1128     }
1129 
CheckAgreementOfFrameRate(FunctionInit,mfxU32 & frameRateExtN,mfxU32 & frameRateExtD,mfxU32 timeScale,mfxU32 numUnitsInTick)1130     mfxU32 CheckAgreementOfFrameRate(
1131         FunctionInit,
1132         mfxU32 & frameRateExtN,
1133         mfxU32 & frameRateExtD,
1134         mfxU32   timeScale,
1135         mfxU32   numUnitsInTick)
1136     {
1137         if (frameRateExtN == 0 || frameRateExtD == 0)
1138         {
1139             frameRateExtN = timeScale;
1140             frameRateExtD = numUnitsInTick * 2;
1141             return 0; // initialized, no error
1142         }
1143         else if (mfxU64(frameRateExtN) * numUnitsInTick * 2 != mfxU64(frameRateExtD) * timeScale)
1144         {
1145             frameRateExtN = timeScale;
1146             frameRateExtD = numUnitsInTick * 2;
1147             return 1; // modified
1148         }
1149         else
1150         {
1151             return 0; // equal, no error
1152         }
1153     }
1154 
FlagToTriState(mfxU16 flag)1155     inline mfxU16 FlagToTriState(mfxU16 flag)
1156     {
1157         return flag ? mfxU16(MFX_CODINGOPTION_ON)
1158             : mfxU16(MFX_CODINGOPTION_OFF);
1159     }
1160 
1161     template <class TFunc>
CheckAgreementOfSequenceLevelParameters(MfxVideoParam & par,mfxExtSpsHeader const & sps)1162     bool CheckAgreementOfSequenceLevelParameters(MfxVideoParam & par, mfxExtSpsHeader const & sps)
1163     {
1164         mfxU32 changed = 0;
1165 
1166         mfxFrameInfo & fi = par.mfx.FrameInfo;
1167         mfxExtCodingOption  & extOpt  = GetExtBufferRef(par);
1168         mfxExtCodingOption2 & extOpt2 = GetExtBufferRef(par);
1169         mfxExtCodingOption3 & extOpt3 = GetExtBufferRef(par);
1170 
1171 
1172         TFunc f;
1173 
1174         changed |= CheckAgreement(f, par.mfx.CodecProfile, sps.profileIdc);
1175         changed |= CheckAgreement(f, par.mfx.CodecLevel,   sps.levelIdc);
1176         changed |= CheckAgreement(f, par.mfx.NumRefFrame,  sps.maxNumRefFrames);
1177         changed |= CheckAgreement(f, fi.ChromaFormat,      sps.chromaFormatIdc);
1178 
1179         mfxU16 const cropUnitX = CROP_UNIT_X[fi.ChromaFormat];
1180         mfxU16 const cropUnitY = CROP_UNIT_Y[fi.ChromaFormat] * (2 - sps.frameMbsOnlyFlag);
1181 
1182         changed |= CheckAgreement(f, fi.Width,     mfxU16(16 * (sps.picWidthInMbsMinus1 + 1)));
1183         changed |= CheckAgreement(f, fi.Height,    mfxU16(16 * (sps.picHeightInMapUnitsMinus1 + 1) * (2 - sps.frameMbsOnlyFlag)));
1184         changed |= CheckAgreement(f, fi.PicStruct, mfxU16(sps.frameMbsOnlyFlag ? mfxU16(MFX_PICSTRUCT_PROGRESSIVE) : fi.PicStruct));
1185         changed |= CheckAgreement(f, fi.CropX,     mfxU16(sps.frameCropLeftOffset * cropUnitX));
1186         changed |= CheckAgreement(f, fi.CropY,     mfxU16(sps.frameCropTopOffset * cropUnitY));
1187         changed |= CheckAgreement(f, fi.CropW,     mfxU16(fi.Width  - (sps.frameCropLeftOffset + sps.frameCropRightOffset) * cropUnitX));
1188         changed |= CheckAgreement(f, fi.CropH,     mfxU16(fi.Height - (sps.frameCropTopOffset  + sps.frameCropBottomOffset) * cropUnitY));
1189 
1190         mfxU16 disableVui = FlagToTriState(!sps.vuiParametersPresentFlag);
1191         changed |= CheckAgreement(f, extOpt2.DisableVUI, disableVui);
1192 
1193         mfxU16 aspectRatioPresent   = FlagToTriState(sps.vui.flags.aspectRatioInfoPresent);
1194         mfxU16 timingInfoPresent    = FlagToTriState(sps.vui.flags.timingInfoPresent);
1195         mfxU16 overscanInfoPresent  = FlagToTriState(sps.vui.flags.overscanInfoPresent);
1196         mfxU16 bitstreamRestriction = FlagToTriState(sps.vui.flags.bitstreamRestriction);
1197 
1198         changed |= CheckAgreement(f, extOpt3.AspectRatioInfoPresent, aspectRatioPresent);
1199         changed |= CheckAgreement(f, extOpt3.TimingInfoPresent,      timingInfoPresent);
1200         changed |= CheckAgreement(f, extOpt3.OverscanInfoPresent,    overscanInfoPresent);
1201         changed |= CheckAgreement(f, extOpt3.BitstreamRestriction,   bitstreamRestriction);
1202 
1203         if (sps.vuiParametersPresentFlag)
1204         {
1205             if (sps.vui.flags.timingInfoPresent)
1206             {
1207                 mfxU16 fixedFrameRate = FlagToTriState(sps.vui.flags.fixedFrameRate);
1208                 changed |= CheckAgreement(f, extOpt2.FixedFrameRate, fixedFrameRate);
1209                 changed |= CheckAgreementOfFrameRate(f, fi.FrameRateExtN, fi.FrameRateExtD, sps.vui.timeScale, sps.vui.numUnitsInTick);
1210             }
1211 
1212             if (sps.vui.flags.aspectRatioInfoPresent)
1213             {
1214                 AspectRatioConverter arConv(sps.vui.aspectRatioIdc, sps.vui.sarWidth, sps.vui.sarHeight);
1215                 changed |= CheckAgreement(f, fi.AspectRatioW, arConv.GetSarWidth());
1216                 changed |= CheckAgreement(f, fi.AspectRatioH, arConv.GetSarHeight());
1217             }
1218 
1219             if (sps.vui.flags.nalHrdParametersPresent)
1220             {
1221                 mfxU16 rcmethod   = sps.vui.nalHrdParameters.cbrFlag[0] ? mfxU16(MFX_RATECONTROL_CBR) : mfxU16(MFX_RATECONTROL_VBR);
1222                 mfxU16 maxkbps    = mfxU16(((
1223                     (sps.vui.nalHrdParameters.bitRateValueMinus1[0] + 1) <<
1224                     (6 + sps.vui.nalHrdParameters.bitRateScale)) + 999) / 1000);
1225                 mfxU16 buffersize = mfxU16((((sps.vui.nalHrdParameters.cpbSizeValueMinus1[0] + 1) <<
1226                     (4 + sps.vui.nalHrdParameters.cpbSizeScale)) + 7999) / 8000);
1227                 mfxU16 lowDelayHrd = FlagToTriState(sps.vui.flags.lowDelayHrd);
1228 
1229                 changed |= CheckAgreement(f, par.mfx.RateControlMethod,    rcmethod);
1230                 changed |= CheckAgreement(f, par.calcParam.maxKbps,        maxkbps);
1231                 changed |= CheckAgreement(f, par.calcParam.bufferSizeInKB, buffersize);
1232                 changed |= CheckAgreement(f, extOpt3.LowDelayHrd,          lowDelayHrd);
1233 
1234             }
1235         }
1236 
1237         mfxU16 picTimingSei = sps.vui.flags.picStructPresent
1238             ? mfxU16(MFX_CODINGOPTION_ON)
1239             : mfxU16(MFX_CODINGOPTION_OFF);
1240         mfxU16 vuiNalHrdParameters = sps.vui.flags.nalHrdParametersPresent
1241             ? mfxU16(MFX_CODINGOPTION_ON)
1242             : mfxU16(MFX_CODINGOPTION_OFF);
1243         mfxU16 vuiVclHrdParameters = sps.vui.flags.vclHrdParametersPresent
1244             ? mfxU16(MFX_CODINGOPTION_ON)
1245             : mfxU16(MFX_CODINGOPTION_OFF);
1246 
1247         if (sps.vui.flags.bitstreamRestriction)
1248             changed |= CheckAgreement(f, extOpt.MaxDecFrameBuffering, sps.vui.maxDecFrameBuffering);
1249 
1250         changed |= CheckAgreement(f, extOpt.PicTimingSEI,         picTimingSei);
1251         changed |= CheckAgreement(f, extOpt.VuiNalHrdParameters,  vuiNalHrdParameters);
1252         changed |= CheckAgreement(f, extOpt.VuiVclHrdParameters,  vuiVclHrdParameters);
1253 
1254         return changed == 0;
1255     }
1256 
1257     template <class TFunc>
CheckAgreementOfPictureLevelParameters(mfxVideoParam & par,mfxExtPpsHeader const & pps)1258     bool CheckAgreementOfPictureLevelParameters(mfxVideoParam & par, mfxExtPpsHeader const & pps)
1259     {
1260         mfxU32 changed = 0;
1261 
1262         mfxExtCodingOption * extOpt = GetExtBuffer(par);
1263 
1264         mfxU16 intraPredBlockSize = pps.transform8x8ModeFlag
1265             ? mfxU16(MFX_BLOCKSIZE_MIN_8X8)
1266             : mfxU16(MFX_BLOCKSIZE_MIN_16X16);
1267         mfxU16 cavlc = pps.entropyCodingModeFlag
1268             ? mfxU16(MFX_CODINGOPTION_OFF)
1269             : mfxU16(MFX_CODINGOPTION_ON);
1270 
1271         TFunc f;
1272 
1273         changed |= CheckAgreement(f, extOpt->IntraPredBlockSize, intraPredBlockSize);
1274         changed |= CheckAgreement(f, extOpt->CAVLC,              cavlc);
1275 
1276         return changed == 0;
1277     }
1278 
1279     template <class T>
InheritOption(T optInit,T & optReset)1280     void InheritOption(T optInit, T & optReset)
1281     {
1282         if (optReset == 0)
1283             optReset = optInit;
1284     }
1285 }
1286 
CalcNumSurfRaw(MfxVideoParam const & video)1287 mfxU32 MfxHwH264Encode::CalcNumSurfRaw(MfxVideoParam const & video)
1288 {
1289     mfxExtCodingOption2 const & extOpt2 = GetExtBufferRef(video);
1290     mfxExtCodingOption3 const & extOpt3 = GetExtBufferRef(video);
1291 
1292     if (video.IOPattern == MFX_IOPATTERN_IN_SYSTEM_MEMORY)
1293         return video.AsyncDepth + video.mfx.GopRefDist - 1 +
1294             std::max(1u, mfxU32(extOpt2.LookAheadDepth)) + (video.AsyncDepth - 1) +
1295             (IsOn(extOpt2.UseRawRef) ? video.mfx.NumRefFrame : 0) + ((extOpt2.MaxSliceSize != 0 || IsOn(extOpt3.FadeDetection)) ? 1 : 0);
1296     else
1297         return 0;
1298 }
1299 
CalcNumSurfRecon(MfxVideoParam const & video)1300 mfxU32 MfxHwH264Encode::CalcNumSurfRecon(MfxVideoParam const & video)
1301 {
1302     mfxExtCodingOption2 const & extOpt2 = GetExtBufferRef(video);
1303 
1304     if (IsOn(extOpt2.UseRawRef))
1305         return video.mfx.NumRefFrame + (video.AsyncDepth - 1) +
1306             (video.IOPattern == MFX_IOPATTERN_IN_VIDEO_MEMORY ? video.mfx.GopRefDist : 1);
1307     else
1308         return video.mfx.NumRefFrame + video.AsyncDepth;
1309 }
1310 
CalcNumSurfBitstream(MfxVideoParam const & video)1311 mfxU32 MfxHwH264Encode::CalcNumSurfBitstream(MfxVideoParam const & video)
1312 {
1313     return (IsFieldCodingPossible(video) ? video.AsyncDepth * 2 : video.AsyncDepth);
1314 }
1315 
GetMaxNumSlices(MfxVideoParam const & par)1316 mfxU16 MfxHwH264Encode::GetMaxNumSlices(MfxVideoParam const & par)
1317 {
1318     mfxExtCodingOption3 & extOpt3 = GetExtBufferRef(par);
1319     return std::max({extOpt3.NumSliceI, extOpt3.NumSliceP, extOpt3.NumSliceB});
1320 }
1321 
GetNumReorderFrames(MfxVideoParam const & video)1322 mfxU8 MfxHwH264Encode::GetNumReorderFrames(MfxVideoParam const & video)
1323 {
1324     mfxExtCodingOption2 & extOpt2 = GetExtBufferRef(video);
1325     mfxU8 numReorderFrames = video.mfx.GopRefDist > 1 ? 1 : 0;
1326 
1327     if (video.mfx.GopRefDist > 2 && extOpt2.BRefType == MFX_B_REF_PYRAMID)
1328     {
1329         numReorderFrames = (mfxU8)std::max(CeilLog2(video.mfx.GopRefDist - 1), 1u);
1330     }
1331 
1332     return numReorderFrames;
1333 }
1334 
CalcNumTasks(MfxVideoParam const & video)1335 mfxU32 MfxHwH264Encode::CalcNumTasks(MfxVideoParam const & video)
1336 {
1337     assert(video.mfx.GopRefDist > 0);
1338     assert(video.AsyncDepth > 0);
1339     mfxExtCodingOption2 const & extOpt2 = GetExtBufferRef(video);
1340 
1341     return video.mfx.GopRefDist + (video.AsyncDepth - 1) + std::max(1u, mfxU32(extOpt2.LookAheadDepth)) +
1342         (IsOn(extOpt2.UseRawRef) ? video.mfx.NumRefFrame : 0);
1343 }
1344 
CalcDTSFromPTS(mfxFrameInfo const & info,mfxU16 dpbOutputDelay,mfxU64 timeStamp)1345 mfxI64 MfxHwH264Encode::CalcDTSFromPTS(
1346     mfxFrameInfo const & info,
1347     mfxU16               dpbOutputDelay,
1348     mfxU64               timeStamp)
1349 {
1350     if (timeStamp != static_cast<mfxU64>(MFX_TIMESTAMP_UNKNOWN))
1351     {
1352         mfxF64 tcDuration90KHz = (mfxF64)info.FrameRateExtD / (info.FrameRateExtN * 2) * 90000; // calculate tick duration
1353         return mfxI64(timeStamp - tcDuration90KHz * dpbOutputDelay); // calculate DTS from PTS
1354     }
1355 
1356     return MFX_TIMESTAMP_UNKNOWN;
1357 }
1358 
GetMaxBitrateValue(mfxU32 kbps,mfxU32 scale)1359 mfxU32 MfxHwH264Encode::GetMaxBitrateValue(mfxU32 kbps, mfxU32 scale)
1360 {
1361     return (1000 * kbps) >> (6 + scale);
1362 }
1363 
GetCabacInitIdc(mfxU32 targetUsage)1364 mfxU8 MfxHwH264Encode::GetCabacInitIdc(mfxU32 targetUsage)
1365 {
1366     assert(targetUsage >= 1);
1367     assert(targetUsage <= 7);
1368     (void)targetUsage;
1369     //const mfxU8 CABAC_INIT_IDC_TABLE[] = { 0, 2, 2, 1, 0, 0, 0, 0 };
1370     return 0;
1371     //return CABAC_INIT_IDC_TABLE[targetUsage];
1372 }
1373 
IsLookAheadSupported(MfxVideoParam const &,eMFXHWType platform)1374 bool MfxHwH264Encode::IsLookAheadSupported(
1375     MfxVideoParam const & /*video*/,
1376     eMFXHWType            platform)
1377 {
1378     return ((platform >= MFX_HW_HSW) && (platform != MFX_HW_VLV));
1379 }
GetPPyrSize(MfxVideoParam const & video,mfxU32 miniGopSize,bool bEncToolsLA)1380 mfxU32 MfxHwH264Encode::GetPPyrSize(MfxVideoParam const & video, mfxU32 miniGopSize, bool bEncToolsLA)
1381 {
1382     mfxExtCodingOption3 const & extOpt3 = GetExtBufferRef(video);
1383     mfxExtCodingOptionDDI const & extDdi = GetExtBufferRef(video);
1384 
1385     mfxU32 pyrSize = 1;
1386 
1387     if (video.mfx.GopRefDist == 1 &&
1388         extOpt3.PRefType == MFX_P_REF_PYRAMID &&
1389         !IsOn(extOpt3.ExtBrcAdaptiveLTR) &&
1390         extDdi.NumActiveRefP != 1)
1391     {
1392         if (bEncToolsLA)
1393             pyrSize = (miniGopSize <= 1) ? 1 : 4;
1394         else
1395             pyrSize =  DEFAULT_PPYR_INTERVAL;
1396     }
1397 
1398     return pyrSize;
1399 
1400 }
IsExtBrcSceneChangeSupported(MfxVideoParam const & video)1401 bool MfxHwH264Encode::IsExtBrcSceneChangeSupported(
1402     MfxVideoParam const & video)
1403 {
1404     bool extbrcsc = false;
1405 #if (MFX_VERSION >= 1026)
1406     // extbrc API change dependency
1407     mfxExtCodingOption2 const & extOpt2 = GetExtBufferRef(video);
1408     extbrcsc = (IsOn(extOpt2.ExtBRC) &&
1409         (video.mfx.RateControlMethod == MFX_RATECONTROL_CBR || video.mfx.RateControlMethod == MFX_RATECONTROL_VBR)
1410         && (video.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) && !video.mfx.EncodedOrder);
1411 #endif
1412     return extbrcsc;
1413 }
1414 
IsCmNeededForSCD(MfxVideoParam const & video)1415 bool MfxHwH264Encode::IsCmNeededForSCD(
1416     MfxVideoParam const & video)
1417 {
1418     bool useCm = false;
1419 #if (MFX_VERSION >= 1026)
1420     // If frame in Sys memory then Cm is not needed
1421     mfxExtOpaqueSurfaceAlloc & extOpaq = GetExtBufferRef(video);
1422     useCm = !(video.IOPattern == MFX_IOPATTERN_IN_SYSTEM_MEMORY ||
1423         (video.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY && (extOpaq.In.Type & MFX_MEMTYPE_SYSTEM_MEMORY)));
1424 #endif
1425     return useCm;
1426 }
1427 
IsMctfSupported(MfxVideoParam const & video)1428 bool MfxHwH264Encode::IsMctfSupported(
1429     MfxVideoParam const & video)
1430 {
1431     (void)video;
1432     bool
1433         isSupported = false;
1434 #if defined(MFX_ENABLE_MCTF_IN_AVC)
1435     mfxExtCodingOption2 const & extOpt2 = GetExtBufferRef(video);
1436     isSupported = (IsOn(extOpt2.ExtBRC) &&
1437         IsExtBrcSceneChangeSupported(video) &&
1438         (video.mfx.FrameInfo.Width <= 3840 && video.vpp.In.Height <= 2160) &&
1439         (video.mfx.RateControlMethod == MFX_RATECONTROL_CBR || video.mfx.RateControlMethod == MFX_RATECONTROL_VBR) &&
1440         (video.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) &&
1441         ((video.mfx.FrameInfo.FourCC == MFX_FOURCC_NV12) || (video.mfx.FrameInfo.FourCC == MFX_FOURCC_YV12)) &&
1442         (video.mfx.FrameInfo.ChromaFormat == MFX_CHROMAFORMAT_YUV420) &&
1443         (video.mfx.FrameInfo.BitDepthLuma == 0 || video.mfx.FrameInfo.BitDepthLuma == 8) &&
1444         (video.mfx.GopRefDist == 8) &&
1445         !video.mfx.EncodedOrder);
1446 #endif
1447     return isSupported;
1448 }
1449 
IsAdaptiveLtrOn(MfxVideoParam const & video)1450 bool MfxHwH264Encode::IsAdaptiveLtrOn(
1451     MfxVideoParam const & video)
1452 {
1453     bool altr = false;
1454 #if (MFX_VERSION >= 1026)
1455     mfxExtCodingOption3 const & extOpt3 = GetExtBufferRef(video);
1456     altr = IsOn(extOpt3.ExtBrcAdaptiveLTR);
1457 #endif
1458     return altr;
1459 }
1460 
1461 // determine and return mode of Query operation (valid modes are 1, 2, 3, 4 - see MSDK spec for details)
DetermineQueryMode(mfxVideoParam * in)1462 mfxU8 MfxHwH264Encode::DetermineQueryMode(mfxVideoParam * in)
1463 {
1464     if (in == 0)
1465         return 1;
1466     else
1467     {
1468         mfxExtEncoderCapability * caps = GetExtBuffer(*in);
1469         mfxExtEncoderResetOption * resetOpt = GetExtBuffer(*in);
1470         if (caps)
1471         {
1472             if (resetOpt)
1473             {
1474                 // attached mfxExtEncoderCapability indicates mode 4. In this mode mfxExtEncoderResetOption shouldn't be attached
1475                 return 0;
1476             }
1477             // specific mode to notify encoder to check guid only
1478             if (0x667 == caps->reserved[0])
1479             {
1480                 return 5;
1481             }
1482 
1483             return 4;
1484         }else if (resetOpt)
1485             return 3;
1486         else
1487             return 2;
1488     }
1489 }
1490 
1491 /*
1492 Setting default value for LowPower option.
1493 By default LowPower is OFF (using DualPipe)
1494 For platforms that hasn't VME: use LowPower by default i.e. if LowPower is Unknown then LowPower is ON
1495 
1496 Return value:
1497 MFX_WRN_INCOMPATIBLE_VIDEO_PARAM - if initial value of par.mfx.LowPower is not equal to MFX_CODINGOPTION_ON, MFX_CODINGOPTION_OFF or MFX_CODINGOPTION_UNKNOWN
1498 MFX_ERR_NONE - if no errors
1499 */
SetLowPowerDefault(MfxVideoParam & par,const eMFXHWType & platform)1500 mfxStatus MfxHwH264Encode::SetLowPowerDefault(MfxVideoParam& par, const eMFXHWType& platform)
1501 {
1502     mfxStatus sts = CheckTriStateOption(par.mfx.LowPower) ? MFX_ERR_NONE : MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
1503 
1504     if (!hasSupportVME(platform))
1505     {   // DualPipe (aka VME) is not available
1506         par.mfx.LowPower = MFX_CODINGOPTION_ON;
1507         return sts;
1508     }
1509 
1510     // By default, platforms with 2 encoders (VDEnc & VME) will use VME
1511     // Therefore, garbage & UNKNOWN values will be overridden to OFF
1512     SetDefaultOff(par.mfx.LowPower);
1513     return sts;
1514 }
1515 
1516 /*
1517 Return cached caps if they are.
1518 Select GUID depends on LowPower option.
1519 creates AuxilliaryDevice
1520 request and cache EncodercCaps
1521 
1522 Return value:
1523 MFX_ERR_UNDEFINED_BEHAVIOR -  failed to get EncodeHWCaps iterface from Core
1524 MFX_ERR_DEVICE_FAILED  failed to create DDIEncoder/AuxilliaryDevice of
1525     requestcaps call fails
1526 MFX_ERR_NONE - if no errors
1527 */
QueryHwCaps(VideoCORE * core,MFX_ENCODE_CAPS & hwCaps,mfxVideoParam * par)1528 mfxStatus MfxHwH264Encode::QueryHwCaps(VideoCORE* core, MFX_ENCODE_CAPS & hwCaps, mfxVideoParam * par)
1529 {
1530     GUID guid = MSDK_Private_Guid_Encode_AVC_Query;
1531     if(IsOn(par->mfx.LowPower))
1532     {
1533         guid = MSDK_Private_Guid_Encode_AVC_LowPower_Query;
1534     }
1535 
1536     mfxU32 width  = par->mfx.FrameInfo.Width == 0 ? 1920: par->mfx.FrameInfo.Width;
1537     mfxU32 height = par->mfx.FrameInfo.Height == 0 ? 1088: par->mfx.FrameInfo.Height;
1538 
1539     EncodeHWCaps* pEncodeCaps = QueryCoreInterface<EncodeHWCaps>(core);
1540     if (!pEncodeCaps)
1541         return MFX_ERR_UNDEFINED_BEHAVIOR;
1542     else
1543     {
1544         if (pEncodeCaps->GetHWCaps<MFX_ENCODE_CAPS>(guid, &hwCaps) == MFX_ERR_NONE)
1545             return MFX_ERR_NONE;
1546     }
1547     std::unique_ptr<DriverEncoder> ddi;
1548 
1549     ddi.reset(CreatePlatformH264Encoder(core));
1550     if (ddi.get() == 0)
1551         return Error(MFX_ERR_DEVICE_FAILED);
1552 
1553 
1554     mfxStatus sts = ddi->CreateAuxilliaryDevice(core, guid, width, height, true);
1555     MFX_CHECK_STS(sts);
1556 
1557     sts = ddi->QueryEncodeCaps(hwCaps);
1558     MFX_CHECK_STS(sts);
1559 
1560     return pEncodeCaps->SetHWCaps<MFX_ENCODE_CAPS>(guid, &hwCaps);
1561 }
1562 
QueryMbProcRate(VideoCORE * core,mfxVideoParam const & par,mfxU32 (& mbPerSec)[16],const mfxVideoParam * in)1563 mfxStatus MfxHwH264Encode::QueryMbProcRate(VideoCORE* core, mfxVideoParam const & par, mfxU32 (&mbPerSec)[16], const mfxVideoParam * in)
1564 {
1565     mfxU32 width  = in->mfx.FrameInfo.Width == 0 ? 1920: in->mfx.FrameInfo.Width;
1566     mfxU32 height = in->mfx.FrameInfo.Height == 0 ? 1088: in->mfx.FrameInfo.Height;
1567 
1568     GUID guid = MSDK_Private_Guid_Encode_AVC_Query;
1569     if(IsOn(in->mfx.LowPower))
1570         guid = MSDK_Private_Guid_Encode_AVC_LowPower_Query;
1571 
1572     EncodeHWCaps* pEncodeCaps = QueryCoreInterface<EncodeHWCaps>(core, MFXIHWMBPROCRATE_GUID);
1573     if (!pEncodeCaps)
1574         return MFX_ERR_UNDEFINED_BEHAVIOR;
1575     else
1576     {
1577         if (pEncodeCaps->GetHWCaps<mfxU32>(guid, mbPerSec, 16) == MFX_ERR_NONE &&
1578             mbPerSec[(par.mfx.TargetUsage?par.mfx.TargetUsage:4) - 1] != 0) //check if MbPerSec for particular TU was already queried or need to save
1579             return MFX_ERR_NONE;
1580     }
1581 
1582     std::unique_ptr<DriverEncoder> ddi;
1583 
1584     ddi.reset(CreatePlatformH264Encoder(core));
1585     if (ddi.get() == 0)
1586         return Error(MFX_ERR_DEVICE_FAILED);
1587 
1588 
1589     mfxStatus sts = ddi->CreateAuxilliaryDevice(core, guid, width, height, true);
1590     MFX_CHECK_STS(sts);
1591 
1592     mfxU32 tempMbPerSec[16] = {0, };
1593     sts = ddi->QueryMbPerSec(par, tempMbPerSec);
1594 
1595     MFX_CHECK_STS(sts);
1596     mbPerSec[(par.mfx.TargetUsage?par.mfx.TargetUsage:4) - 1] = tempMbPerSec[0];
1597 
1598     return pEncodeCaps->SetHWCaps<mfxU32>(guid, mbPerSec, 16);
1599 }
1600 
QueryGuid(VideoCORE * core,GUID guid)1601 mfxStatus MfxHwH264Encode::QueryGuid(VideoCORE* core, GUID guid)
1602 {
1603     std::unique_ptr<DriverEncoder> ddi;
1604 
1605     ddi.reset(CreatePlatformH264Encoder(core));
1606     if (ddi.get() == 0)
1607         return Error(MFX_ERR_DEVICE_FAILED);
1608 
1609     return ddi->QueryHWGUID(core, guid, true);
1610 }
1611 
ReadSpsPpsHeaders(MfxVideoParam & par)1612 mfxStatus MfxHwH264Encode::ReadSpsPpsHeaders(MfxVideoParam & par)
1613 {
1614     mfxExtCodingOptionSPSPPS & extBits = GetExtBufferRef(par);
1615 
1616     try
1617     {
1618         if (extBits.SPSBuffer)
1619         {
1620             InputBitstream reader(extBits.SPSBuffer, extBits.SPSBufSize);
1621             mfxExtSpsHeader & extSps = GetExtBufferRef(par);
1622             ReadSpsHeader(reader, extSps);
1623 
1624             if (extBits.PPSBuffer)
1625             {
1626                 InputBitstream pps_reader(extBits.PPSBuffer, extBits.PPSBufSize);
1627                 mfxExtPpsHeader & extPps = GetExtBufferRef(par);
1628                 ReadPpsHeader(pps_reader, extSps, extPps);
1629             }
1630         }
1631     }
1632     catch (std::exception &)
1633     {
1634         return MFX_ERR_INVALID_VIDEO_PARAM;
1635     }
1636 
1637     return MFX_ERR_NONE;
1638 }
1639 
GetFrameWidth(MfxVideoParam & par)1640 mfxU16 MfxHwH264Encode::GetFrameWidth(MfxVideoParam & par)
1641 {
1642     mfxExtCodingOptionSPSPPS & extBits = GetExtBufferRef(par);
1643     if (extBits.SPSBuffer)
1644     {
1645         mfxExtSpsHeader & extSps = GetExtBufferRef(par);
1646         return mfxU16(16 * (extSps.picWidthInMbsMinus1 + 1));
1647     }
1648     else
1649     {
1650         return par.mfx.FrameInfo.Width;
1651     }
1652 }
1653 
GetFrameHeight(MfxVideoParam & par)1654 mfxU16 MfxHwH264Encode::GetFrameHeight(MfxVideoParam & par)
1655 {
1656     mfxExtCodingOptionSPSPPS & extBits = GetExtBufferRef(par);
1657     if (extBits.SPSBuffer)
1658     {
1659         mfxExtSpsHeader & extSps = GetExtBufferRef(par);
1660         return mfxU16(16 * (extSps.picHeightInMapUnitsMinus1 + 1) * (2 - extSps.frameMbsOnlyFlag));
1661     }
1662     else
1663     {
1664         return par.mfx.FrameInfo.Height;
1665     }
1666 }
1667 
1668 
CorrectCropping(MfxVideoParam & par)1669 mfxStatus MfxHwH264Encode::CorrectCropping(MfxVideoParam& par)
1670 {
1671     mfxStatus sts = MFX_ERR_NONE;
1672 
1673     mfxU16 horzCropUnit = CROP_UNIT_X[par.mfx.FrameInfo.ChromaFormat];
1674     mfxU16 vertCropUnit = CROP_UNIT_Y[par.mfx.FrameInfo.ChromaFormat];
1675     vertCropUnit *= IsFieldCodingPossible(par) ? 2 : 1;
1676 
1677     mfxU16 misalignment = par.mfx.FrameInfo.CropX & (horzCropUnit - 1);
1678     if (misalignment > 0)
1679     {
1680         par.mfx.FrameInfo.CropX += horzCropUnit - misalignment;
1681         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
1682 
1683         if (par.mfx.FrameInfo.CropW >= horzCropUnit - misalignment)
1684             par.mfx.FrameInfo.CropW -= horzCropUnit - misalignment;
1685         else
1686             par.mfx.FrameInfo.CropW = 0;
1687     }
1688 
1689     misalignment = par.mfx.FrameInfo.CropW & (horzCropUnit - 1);
1690     if (misalignment > 0)
1691     {
1692         par.mfx.FrameInfo.CropW = par.mfx.FrameInfo.CropW - misalignment;
1693         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
1694     }
1695 
1696     misalignment = par.mfx.FrameInfo.CropY & (vertCropUnit - 1);
1697     if (misalignment > 0)
1698     {
1699         par.mfx.FrameInfo.CropY += vertCropUnit - misalignment;
1700         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
1701 
1702         if (par.mfx.FrameInfo.CropH >= vertCropUnit - misalignment)
1703             par.mfx.FrameInfo.CropH -= vertCropUnit - misalignment;
1704         else
1705             par.mfx.FrameInfo.CropH = 0;
1706     }
1707 
1708     misalignment = par.mfx.FrameInfo.CropH & (vertCropUnit - 1);
1709     if (misalignment > 0)
1710     {
1711         par.mfx.FrameInfo.CropH = par.mfx.FrameInfo.CropH - misalignment;
1712         sts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
1713     }
1714 
1715     return sts;
1716 }
1717 
IsRunTimeOnlyExtBuffer(mfxU32 id)1718 bool MfxHwH264Encode::IsRunTimeOnlyExtBuffer(mfxU32 id)
1719 {
1720     return
1721            id == MFX_EXTBUFF_AVC_REFLIST_CTRL
1722 #if defined (MFX_ENABLE_H264_ROUNDING_OFFSET)
1723         || id == MFX_EXTBUFF_AVC_ROUNDING_OFFSET
1724 #endif
1725         || id == MFX_EXTBUFF_ENCODED_FRAME_INFO
1726         || id == MFX_EXTBUFF_MBQP
1727 #if MFX_VERSION >= 1023
1728         || id == MFX_EXTBUFF_MB_FORCE_INTRA
1729 #endif
1730         || id == MFX_EXTBUFF_MB_DISABLE_SKIP_MAP
1731 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
1732         || id == MFX_EXTBUFF_ENCODED_UNITS_INFO
1733 #endif
1734         ;
1735 }
1736 
IsRunTimeExtBufferIdSupported(MfxVideoParam const & video,mfxU32 id)1737 bool MfxHwH264Encode::IsRunTimeExtBufferIdSupported(MfxVideoParam const & video, mfxU32 id)
1738 {
1739 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1740     mfxExtFeiParam const & feiParam = GetExtBufferRef(video);
1741     bool isFeiENCPAK = feiParam.Func == MFX_FEI_FUNCTION_ENCODE;
1742 #else
1743     (void)video;
1744 #endif
1745 
1746     return
1747           (id == MFX_EXTBUFF_AVC_REFLIST_CTRL
1748         || id == MFX_EXTBUFF_AVC_REFLISTS
1749 #if defined (MFX_ENABLE_H264_ROUNDING_OFFSET)
1750         || id == MFX_EXTBUFF_AVC_ROUNDING_OFFSET
1751 #endif
1752         || id == MFX_EXTBUFF_ENCODED_FRAME_INFO
1753         || id == MFX_EXTBUFF_PICTURE_TIMING_SEI
1754         || id == MFX_EXTBUFF_CODING_OPTION2
1755         || id == MFX_EXTBUFF_CODING_OPTION3
1756         || id == MFX_EXTBUFF_ENCODER_ROI
1757         || id == MFX_EXTBUFF_MBQP
1758         || id == MFX_EXTBUFF_MOVING_RECTANGLES
1759         || id == MFX_EXTBUFF_DIRTY_RECTANGLES
1760 #if MFX_VERSION >= 1023
1761         || id == MFX_EXTBUFF_MB_FORCE_INTRA
1762 #endif
1763         || id == MFX_EXTBUFF_MB_DISABLE_SKIP_MAP
1764         || id == MFX_EXTBUFF_PRED_WEIGHT_TABLE
1765 #if defined (MFX_ENABLE_MFE)
1766         || id == MFX_EXTBUFF_MULTI_FRAME_CONTROL
1767 #endif
1768 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1769         || (isFeiENCPAK &&
1770              (  id == MFX_EXTBUFF_FEI_SLICE
1771              || id == MFX_EXTBUFF_FEI_ENC_CTRL
1772              || id == MFX_EXTBUFF_FEI_ENC_MV_PRED
1773              || id == MFX_EXTBUFF_FEI_REPACK_CTRL
1774              || id == MFX_EXTBUFF_FEI_ENC_MB
1775              || id == MFX_EXTBUFF_FEI_ENC_QP
1776              || id == MFX_EXTBUFF_FEI_ENC_MB_STAT
1777              || id == MFX_EXTBUFF_FEI_ENC_MV
1778              || id == MFX_EXTBUFF_FEI_PAK_CTRL
1779              || id == MFX_EXTBUFF_PRED_WEIGHT_TABLE
1780            ))
1781 #endif
1782         );
1783 }
1784 
IsRuntimeOutputExtBufferIdSupported(MfxVideoParam const & video,mfxU32 id)1785 bool MfxHwH264Encode::IsRuntimeOutputExtBufferIdSupported(MfxVideoParam const & video, mfxU32 id)
1786 {
1787 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1788     mfxExtFeiParam const & feiParam = GetExtBufferRef(video);
1789     bool isFeiENCPAK = feiParam.Func == MFX_FEI_FUNCTION_ENCODE;
1790 #else
1791     (void)video;
1792 #endif
1793 
1794     return
1795             id == MFX_EXTBUFF_ENCODED_FRAME_INFO
1796 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
1797             || id == MFX_EXTBUFF_ENCODED_UNITS_INFO
1798 #endif
1799 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1800             || (isFeiENCPAK && (
1801                id == MFX_EXTBUFF_FEI_ENC_MV
1802             || id == MFX_EXTBUFF_FEI_ENC_MB_STAT
1803             || id == MFX_EXTBUFF_FEI_PAK_CTRL))
1804 #endif
1805             ;
1806 }
1807 
IsRunTimeExtBufferPairAllowed(MfxVideoParam const & video,mfxU32 id)1808 bool MfxHwH264Encode::IsRunTimeExtBufferPairAllowed(MfxVideoParam const & video, mfxU32 id)
1809 {
1810 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1811     mfxExtFeiParam const & feiParam = GetExtBufferRef(video);
1812     bool isFeiENCPAK = feiParam.Func == MFX_FEI_FUNCTION_ENCODE;
1813 #else
1814     (void)video;
1815 #endif
1816 
1817     return (id == MFX_EXTBUFF_AVC_REFLISTS
1818 #if defined (MFX_ENABLE_H264_ROUNDING_OFFSET)
1819             || id == MFX_EXTBUFF_AVC_ROUNDING_OFFSET
1820 #endif
1821            )
1822 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1823            || (isFeiENCPAK &&
1824                 (  id == MFX_EXTBUFF_FEI_SLICE
1825                 || id == MFX_EXTBUFF_FEI_ENC_CTRL
1826                 || id == MFX_EXTBUFF_FEI_ENC_MV_PRED
1827                 || id == MFX_EXTBUFF_FEI_REPACK_CTRL
1828                 || id == MFX_EXTBUFF_FEI_ENC_MB
1829                 || id == MFX_EXTBUFF_FEI_ENC_QP
1830                 || id == MFX_EXTBUFF_FEI_ENC_MB_STAT
1831                 || id == MFX_EXTBUFF_FEI_ENC_MV
1832                 || id == MFX_EXTBUFF_FEI_PAK_CTRL
1833                 || id == MFX_EXTBUFF_PRED_WEIGHT_TABLE
1834            ))
1835 #endif
1836            ;
1837 }
1838 
IsRunTimeExtBufferPairRequired(MfxVideoParam const & video,mfxU32 id)1839 bool MfxHwH264Encode::IsRunTimeExtBufferPairRequired(MfxVideoParam const & video, mfxU32 id)
1840 {
1841 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1842     mfxExtFeiParam const & feiParam = GetExtBufferRef(video);
1843     bool isFeiENCPAK = feiParam.Func == MFX_FEI_FUNCTION_ENCODE;
1844 
1845     return (isFeiENCPAK &&
1846             (  id == MFX_EXTBUFF_FEI_SLICE
1847             || id == MFX_EXTBUFF_FEI_ENC_CTRL
1848             || id == MFX_EXTBUFF_FEI_ENC_MV_PRED
1849             || id == MFX_EXTBUFF_FEI_REPACK_CTRL
1850             || id == MFX_EXTBUFF_FEI_ENC_MB
1851             || id == MFX_EXTBUFF_FEI_ENC_QP
1852             || id == MFX_EXTBUFF_FEI_ENC_MB_STAT
1853             || id == MFX_EXTBUFF_FEI_ENC_MV
1854             || id == MFX_EXTBUFF_FEI_PAK_CTRL
1855             || id == MFX_EXTBUFF_PRED_WEIGHT_TABLE
1856            ));
1857 #else
1858     (void)id;
1859     (void)video;
1860 #endif
1861     return false;
1862 }
1863 
IsVideoParamExtBufferIdSupported(mfxU32 id)1864 bool MfxHwH264Encode::IsVideoParamExtBufferIdSupported(mfxU32 id)
1865 {
1866     return
1867            (id == MFX_EXTBUFF_CODING_OPTION
1868         || id == MFX_EXTBUFF_CODING_OPTION_SPSPPS
1869 #if defined(__MFXBRC_H__)
1870         || id == MFX_EXTBUFF_BRC
1871 #endif
1872 #if defined(MFX_ENABLE_ENCTOOLS)
1873         || id == MFX_EXTBUFF_ENCTOOLS
1874         || id == MFX_EXTBUFF_ENCTOOLS_CONFIG
1875         || id == MFX_EXTBUFF_ENCTOOLS_DEVICE
1876         || id == MFX_EXTBUFF_ENCTOOLS_ALLOCATOR
1877 #endif
1878 
1879         || id == MFX_EXTBUFF_MVC_SEQ_DESC
1880         || id == MFX_EXTBUFF_VIDEO_SIGNAL_INFO
1881         || id == MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION
1882         || id == MFX_EXTBUFF_PICTURE_TIMING_SEI
1883         || id == MFX_EXTBUFF_AVC_TEMPORAL_LAYERS
1884         || id == MFX_EXTBUFF_CODING_OPTION2
1885         || id == MFX_EXTBUFF_ENCODER_RESET_OPTION
1886         || id == MFX_EXTBUFF_ENCODER_CAPABILITY
1887         || id == MFX_EXTBUFF_ENCODER_ROI
1888         || id == MFX_EXTBUFF_CODING_OPTION3
1889         || id == MFX_EXTBUFF_CHROMA_LOC_INFO
1890         || id == MFX_EXTBUFF_PRED_WEIGHT_TABLE
1891         || id == MFX_EXTBUFF_DIRTY_RECTANGLES
1892         || id == MFX_EXTBUFF_MOVING_RECTANGLES
1893         || id == MFX_EXTBUFF_FEI_CODING_OPTION
1894 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1895         || id == MFX_EXTBUFF_FEI_PARAM
1896         || id == MFX_EXTBUFF_FEI_SLICE
1897         || id == MFX_EXTBUFF_FEI_SPS
1898         || id == MFX_EXTBUFF_FEI_PPS
1899 #endif
1900 
1901 #if defined (MFX_ENABLE_MFE)
1902         || id == MFX_EXTBUFF_MULTI_FRAME_PARAM
1903         || id == MFX_EXTBUFF_MULTI_FRAME_CONTROL
1904 #endif
1905         );
1906 }
1907 
CheckExtBufferId(mfxVideoParam const & par)1908 mfxStatus MfxHwH264Encode::CheckExtBufferId(mfxVideoParam const & par)
1909 {
1910     for (mfxU32 i = 0; i < par.NumExtParam; i++)
1911     {
1912         if (par.ExtParam[i] == 0)
1913             return MFX_ERR_INVALID_VIDEO_PARAM;
1914 
1915         if (!IsVideoParamExtBufferIdSupported(par.ExtParam[i]->BufferId))
1916             return MFX_ERR_INVALID_VIDEO_PARAM;
1917 
1918         // check if buffer presents twice in video param
1919 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1920         if (par.ExtParam[i]->BufferId != MFX_EXTBUFF_FEI_SLICE)
1921 #endif
1922         {
1923             if (MfxHwH264Encode::GetExtBuffer(
1924                 par.ExtParam + i + 1,
1925                 par.NumExtParam - i - 1,
1926                 par.ExtParam[i]->BufferId) != 0)
1927             {
1928                 return MFX_ERR_INVALID_VIDEO_PARAM;
1929             }
1930         }
1931     }
1932 
1933 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
1934     // FEI SPS / PPS buffers on Init stage supported only by FEI ENC / PAK
1935     if (MfxHwH264Encode::GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_FEI_SPS) ||
1936         MfxHwH264Encode::GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_FEI_PPS))
1937     {
1938         mfxExtFeiParam* fei_func = reinterpret_cast<mfxExtFeiParam*>(MfxHwH264Encode::GetExtBuffer(par.ExtParam, par.NumExtParam, MFX_EXTBUFF_FEI_PARAM));
1939         if (!fei_func || (fei_func->Func != MFX_FEI_FUNCTION_ENC && fei_func->Func != MFX_FEI_FUNCTION_PAK))
1940             return MFX_ERR_INVALID_VIDEO_PARAM;
1941     }
1942 #endif
1943 
1944     return MFX_ERR_NONE;
1945 }
1946 
1947 namespace
1948 {
CheckWidthAndHeight(mfxU32 width,mfxU32 height,mfxU32 picStruct)1949     mfxStatus CheckWidthAndHeight(mfxU32 width, mfxU32 height, mfxU32 picStruct)
1950     {
1951         MFX_CHECK(width  > 0, MFX_ERR_INVALID_VIDEO_PARAM);
1952         MFX_CHECK(height > 0, MFX_ERR_INVALID_VIDEO_PARAM);
1953 
1954         MFX_CHECK((width  & 15) == 0, MFX_ERR_INVALID_VIDEO_PARAM);
1955         MFX_CHECK((height & 15) == 0, MFX_ERR_INVALID_VIDEO_PARAM);
1956 
1957         // repeat flags are for EncodeFrameAsync
1958         if (picStruct & MFX_PICSTRUCT_PART2)
1959             picStruct = MFX_PICSTRUCT_UNKNOWN;
1960 
1961         // more then one flag was set
1962         if (mfxU32 picStructPart1 = picStruct & MFX_PICSTRUCT_PART1)
1963             if (picStructPart1 & (picStructPart1 - 1))
1964                 picStruct = MFX_PICSTRUCT_UNKNOWN;
1965 
1966         if ((picStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0)
1967             MFX_CHECK((height & 31) == 0, MFX_ERR_INVALID_VIDEO_PARAM);
1968 
1969         return MFX_ERR_NONE;
1970     }
1971 };
1972 
1973 
CheckWidthAndHeight(MfxVideoParam const & par)1974 mfxStatus MfxHwH264Encode::CheckWidthAndHeight(MfxVideoParam const & par)
1975 {
1976     mfxExtCodingOptionSPSPPS const & extBits = GetExtBufferRef(par);
1977 
1978     if (extBits.SPSBuffer)
1979         // width/height/picStruct are always valid
1980         // when they come from SPSPPS buffer
1981         // no need to check them
1982         return MFX_ERR_NONE;
1983 
1984     mfxU16 width     = par.mfx.FrameInfo.Width;
1985     mfxU16 height    = par.mfx.FrameInfo.Height;
1986     mfxU16 picStruct = par.mfx.FrameInfo.PicStruct;
1987 
1988 
1989     return ::CheckWidthAndHeight(width, height, picStruct);
1990 }
1991 
CopySpsPpsToVideoParam(MfxVideoParam & par)1992 mfxStatus MfxHwH264Encode::CopySpsPpsToVideoParam(
1993     MfxVideoParam & par)
1994 {
1995     MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "MfxHwH264Encode::CopySpsPpsToVideoParam");
1996     mfxExtCodingOptionSPSPPS & extBits = GetExtBufferRef(par);
1997 
1998     bool changed = false;
1999 
2000     if (extBits.SPSBuffer)
2001     {
2002         mfxExtSpsHeader const * extSps = GetExtBuffer(par);
2003         MFX_CHECK_NULL_PTR1(extSps);
2004         if (!CheckAgreementOfSequenceLevelParameters<FunctionInit>(par, *extSps))
2005             changed = true;
2006     }
2007 
2008 
2009     if (extBits.PPSBuffer)
2010     {
2011         mfxExtPpsHeader const * extPps = GetExtBuffer(par);
2012         MFX_CHECK_NULL_PTR1(extPps);
2013         if (!CheckAgreementOfPictureLevelParameters<FunctionInit>(par, *extPps))
2014             changed = true;
2015     }
2016 
2017     return changed ? MFX_WRN_INCOMPATIBLE_VIDEO_PARAM : MFX_ERR_NONE;
2018 }
2019 
2020 // check encoding configuration for number of H264 spec violations allowed by MSDK
2021 // it's required to report correct status to application
CheckForAllowedH264SpecViolations(MfxVideoParam const & par)2022 mfxStatus MfxHwH264Encode::CheckForAllowedH264SpecViolations(
2023     MfxVideoParam const & par)
2024 {
2025     if (par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE
2026         && par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_UNKNOWN
2027         && par.mfx.CodecLevel > MFX_LEVEL_AVC_41)
2028     {
2029         return MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
2030     }
2031 
2032     return MFX_ERR_NONE;
2033 }
2034 
CheckVideoParam(MfxVideoParam & par,MFX_ENCODE_CAPS const & hwCaps,bool setExtAlloc,eMFXHWType platform,eMFXVAType vaType,eMFXGTConfig config,bool bInit)2035 mfxStatus MfxHwH264Encode::CheckVideoParam(
2036     MfxVideoParam &         par,
2037     MFX_ENCODE_CAPS const & hwCaps,
2038     bool                    setExtAlloc,
2039     eMFXHWType              platform,
2040     eMFXVAType              vaType,
2041     eMFXGTConfig            config,
2042     bool                    bInit)
2043 {
2044     MFX_AUTO_LTRACE(MFX_TRACE_LEVEL_HOTSPOTS, "MfxHwH264Encode::CheckVideoParam");
2045     mfxStatus checkSts = MFX_ERR_NONE;
2046 
2047     mfxExtCodingOptionSPSPPS & extBits = GetExtBufferRef(par);
2048     mfxExtSpsHeader          & extSps  = GetExtBufferRef(par);
2049     mfxExtCodingOption3      & extOpt3 = GetExtBufferRef(par);
2050 
2051     // first check mandatory parameters
2052     MFX_CHECK(
2053         extBits.SPSBuffer != 0 ||
2054         (par.mfx.FrameInfo.Width > 0 && par.mfx.FrameInfo.Height > 0), MFX_ERR_INVALID_VIDEO_PARAM);
2055 
2056     MFX_CHECK(
2057         (extSps.vui.timeScale            > 0 && extSps.vui.numUnitsInTick       > 0) ||
2058         (par.mfx.FrameInfo.FrameRateExtN > 0 && par.mfx.FrameInfo.FrameRateExtD > 0),
2059         MFX_ERR_INVALID_VIDEO_PARAM);
2060 
2061     MFX_CHECK(par.mfx.TargetUsage            <= 7, MFX_ERR_INVALID_VIDEO_PARAM);
2062     MFX_CHECK(par.mfx.FrameInfo.ChromaFormat != 0, MFX_ERR_INVALID_VIDEO_PARAM);
2063     MFX_CHECK(par.IOPattern                  != 0, MFX_ERR_INVALID_VIDEO_PARAM);
2064 
2065 
2066     if (bInit)
2067     {
2068         mfxExtBRC           & extBRC  = GetExtBufferRef(par);
2069         mfxExtCodingOption2 & extOpt2 = GetExtBufferRef(par);
2070         if ((extBRC.pthis || extBRC.Init || extBRC.Close || extBRC.GetFrameCtrl || extBRC.Update || extBRC.Reset) &&
2071             (!extBRC.pthis || !extBRC.Init || !extBRC.Close || !extBRC.GetFrameCtrl || !extBRC.Update || !extBRC.Reset))
2072         {
2073             extOpt2.ExtBRC      = 0;
2074             extBRC.pthis        = 0;
2075             extBRC.Init         = 0;
2076             extBRC.Close        = 0;
2077             extBRC.GetFrameCtrl = 0;
2078             extBRC.Update       = 0;
2079             extBRC.Reset        = 0;
2080             return MFX_ERR_INVALID_VIDEO_PARAM;
2081         }
2082     }
2083 
2084     mfxStatus sts = MFX_ERR_NONE;
2085 
2086     if (IsMvcProfile(par.mfx.CodecProfile))
2087     {
2088         mfxExtCodingOption & extOpt = GetExtBufferRef(par);
2089         mfxExtMVCSeqDesc * extMvc   = GetExtBuffer(par);
2090         sts = CheckAndFixMVCSeqDesc(extMvc, extOpt.ViewOutput == MFX_CODINGOPTION_ON);
2091         if (MFX_WRN_INCOMPATIBLE_VIDEO_PARAM == sts)
2092         {
2093             checkSts = sts;
2094         }
2095         else if (sts < MFX_ERR_NONE)
2096         {
2097             return MFX_ERR_INVALID_VIDEO_PARAM;
2098         }
2099         sts = CheckVideoParamMvcQueryLike(par); // check and correct mvc per-view bitstream, buffer, level
2100         switch (sts)
2101         {
2102         case MFX_ERR_UNSUPPORTED:
2103             return MFX_ERR_INVALID_VIDEO_PARAM;
2104         case MFX_ERR_INVALID_VIDEO_PARAM:
2105         case MFX_WRN_PARTIAL_ACCELERATION:
2106         case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
2107             return sts;
2108         case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM:
2109             checkSts = sts;
2110             break;
2111         default:
2112             break;
2113         }
2114     }
2115 
2116     sts = CheckVideoParamQueryLike(par, hwCaps, platform, vaType, config);
2117     switch (sts)
2118     {
2119     case MFX_ERR_UNSUPPORTED:
2120         return MFX_ERR_INVALID_VIDEO_PARAM;
2121     case MFX_ERR_INVALID_VIDEO_PARAM:
2122     case MFX_WRN_PARTIAL_ACCELERATION:
2123     case MFX_ERR_INCOMPATIBLE_VIDEO_PARAM:
2124         return sts;
2125     case MFX_WRN_INCOMPATIBLE_VIDEO_PARAM:
2126         checkSts = sts;
2127         break;
2128     default:
2129         break;
2130     }
2131 
2132     if (par.IOPattern == MFX_IOPATTERN_IN_VIDEO_MEMORY)
2133     {
2134         MFX_CHECK(setExtAlloc, MFX_ERR_INVALID_VIDEO_PARAM);
2135     }
2136 
2137     MFX_CHECK(
2138         ((par.IOPattern == MFX_IOPATTERN_IN_VIDEO_MEMORY) || (par.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY) ||(par.Protected == 0)),
2139         MFX_ERR_INVALID_VIDEO_PARAM);
2140 
2141     if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP &&
2142         par.mfx.RateControlMethod != MFX_RATECONTROL_ICQ &&
2143         par.mfx.RateControlMethod != MFX_RATECONTROL_LA_ICQ
2144         )
2145         MFX_CHECK(par.calcParam.targetKbps > 0, MFX_ERR_INVALID_VIDEO_PARAM);
2146 
2147     if (extOpt3.NumSliceI || extOpt3.NumSliceP || extOpt3.NumSliceB)
2148     {
2149         // application should set number of slices for all 3 slice types at once
2150         MFX_CHECK(extOpt3.NumSliceI > 0, MFX_ERR_INVALID_VIDEO_PARAM);
2151         MFX_CHECK(extOpt3.NumSliceP > 0, MFX_ERR_INVALID_VIDEO_PARAM);
2152         MFX_CHECK(extOpt3.NumSliceB > 0, MFX_ERR_INVALID_VIDEO_PARAM);
2153     }
2154 
2155     SetDefaults(par, hwCaps, setExtAlloc, platform, vaType, config);
2156 
2157     sts = CheckForAllowedH264SpecViolations(par);
2158     if (sts == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM)
2159         checkSts = sts;
2160 
2161     if (par.IOPattern == MFX_IOPATTERN_IN_OPAQUE_MEMORY)
2162     {
2163         mfxExtOpaqueSurfaceAlloc & extOpaq = GetExtBufferRef(par);
2164 
2165         mfxU32 numFrameMin = CalcNumFrameMin(par, hwCaps);
2166 
2167         MFX_CHECK(extOpaq.In.NumSurface >= numFrameMin, MFX_ERR_INVALID_VIDEO_PARAM);
2168     }
2169 
2170     sts = CheckVideoParamFEI(par);
2171     MFX_CHECK(sts >= MFX_ERR_NONE, sts);
2172 
2173 
2174     return checkSts;
2175 }
2176 
CheckVideoParamFEI(MfxVideoParam & par)2177 mfxStatus MfxHwH264Encode::CheckVideoParamFEI(
2178     MfxVideoParam &     par)
2179 {
2180     mfxStatus checkSts = MFX_ERR_NONE;
2181 
2182     mfxExtFeiParam & feiParam = GetExtBufferRef(par);
2183 
2184     if (!feiParam.Func)
2185     {
2186         // It is not FEI, but regular encoder
2187         return MFX_ERR_NONE;
2188     }
2189 
2190     bool isPAK      = feiParam.Func == MFX_FEI_FUNCTION_PAK;
2191     bool isENCorPAK = feiParam.Func == MFX_FEI_FUNCTION_ENC || isPAK;
2192 
2193     switch (feiParam.Func)
2194     {
2195     case MFX_FEI_FUNCTION_PREENC:
2196     case MFX_FEI_FUNCTION_ENCODE:
2197     case MFX_FEI_FUNCTION_ENC:
2198     case MFX_FEI_FUNCTION_PAK:
2199     case MFX_FEI_FUNCTION_DEC:
2200         break;
2201     default:
2202         return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
2203     }
2204 
2205     mfxExtCodingOption3 & extCodingOpt3 = GetExtBufferRef(par);
2206     MFX_CHECK(!IsOn(extCodingOpt3.EnableMBQP), MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2207 
2208     /* FEI works with CQP only */
2209     MFX_CHECK(MFX_RATECONTROL_CQP == par.mfx.RateControlMethod, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2210 
2211     if (isENCorPAK)
2212     {
2213         MFX_CHECK(par.mfx.EncodedOrder ==                             1, MFX_ERR_INVALID_VIDEO_PARAM);
2214         MFX_CHECK(par.AsyncDepth       ==                             1, MFX_ERR_INVALID_VIDEO_PARAM);
2215         MFX_CHECK(par.IOPattern        == MFX_IOPATTERN_IN_VIDEO_MEMORY, MFX_ERR_INVALID_VIDEO_PARAM);
2216 
2217         /*FEI PAK SEI option should be OFF*/
2218         mfxExtCodingOption & extCodingOpt = GetExtBufferRef(par);
2219         if (!CheckTriStateOptionForOff(extCodingOpt.PicTimingSEI)     ||
2220             !CheckTriStateOptionForOff(extCodingOpt.RecoveryPointSEI) ||
2221             !CheckTriStateOptionForOff(extCodingOpt.RefPicMarkRep))
2222         {
2223             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
2224         }
2225         mfxExtCodingOption2 & extCodingOpt2 = GetExtBufferRef(par);
2226         if (extCodingOpt2.BufferingPeriodSEI == MFX_BPSEI_IFRAME)
2227         {
2228             extCodingOpt2.BufferingPeriodSEI = MFX_BPSEI_DEFAULT;
2229             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
2230         }
2231     }
2232 
2233    // Possible options on Init stage:
2234    //   one slice buffer      - propagate value to all slices
2235    //   buffer for each slice - set value for each slice independently
2236    mfxU32 fieldCount = par.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE ? 1 : 2;
2237    for (mfxU32 i = 0; i < fieldCount; i++)
2238    {
2239        mfxExtFeiSliceHeader *pDataSliceHeader = GetExtBuffer(par, i);
2240        if (pDataSliceHeader && pDataSliceHeader->Slice)
2241        {
2242            // If buffer attached, it should be properly filled
2243            MFX_CHECK(pDataSliceHeader->NumSlice, MFX_ERR_INVALID_VIDEO_PARAM);
2244 
2245            if (pDataSliceHeader->NumSlice != 1)
2246            {
2247                MFX_CHECK(GetMaxNumSlices(par) == pDataSliceHeader->NumSlice, MFX_ERR_INVALID_VIDEO_PARAM);
2248            }
2249 
2250            for (mfxU32 slice = 0; slice < pDataSliceHeader->NumSlice; ++slice)
2251            {
2252                MFX_CHECK(pDataSliceHeader->Slice[slice].DisableDeblockingFilterIdc <=  2, MFX_ERR_INVALID_VIDEO_PARAM);
2253                MFX_CHECK(pDataSliceHeader->Slice[slice].SliceAlphaC0OffsetDiv2     <=  6, MFX_ERR_INVALID_VIDEO_PARAM);
2254                MFX_CHECK(pDataSliceHeader->Slice[slice].SliceAlphaC0OffsetDiv2     >= -6, MFX_ERR_INVALID_VIDEO_PARAM);
2255                MFX_CHECK(pDataSliceHeader->Slice[slice].SliceBetaOffsetDiv2        <=  6, MFX_ERR_INVALID_VIDEO_PARAM);
2256                MFX_CHECK(pDataSliceHeader->Slice[slice].SliceBetaOffsetDiv2        >= -6, MFX_ERR_INVALID_VIDEO_PARAM);
2257            }
2258        }
2259    }
2260 
2261     return checkSts;
2262 }
2263 /*
2264  * utils for debug purposes
2265  */
2266 struct Bool
2267 {
BoolBool2268     explicit Bool(bool val) : m_val(val) {}
BoolBool2269     Bool(Bool const & rhs) : m_val(rhs.m_val) {}
operator =Bool2270     Bool & operator =(Bool const & rhs) { m_val = rhs.m_val; return *this; }
operator boolBool2271     operator bool() { return m_val; }
2272 
operator =Bool2273     Bool & operator =(bool val)
2274     {
2275         //__asm { int 3 }
2276         m_val = val;
2277         return *this;
2278     }
2279 
2280 private:
2281     bool m_val;
2282 };
2283 
CheckAndFixRectQueryLike(MfxVideoParam const & par,mfxRectDesc * rect)2284 mfxStatus MfxHwH264Encode::CheckAndFixRectQueryLike(
2285     MfxVideoParam const & par,
2286     mfxRectDesc *         rect)
2287 {
2288     mfxStatus checkSts = MFX_ERR_NONE;
2289 
2290     if (rect->Left == 0 && rect->Right == 0 && rect->Top == 0 && rect->Bottom == 0)
2291         return checkSts;
2292 
2293     checkSts = CheckAndFixOpenRectQueryLike(par, rect);
2294 
2295     return checkSts;
2296 }
2297 
2298 /*
2299 The function does following
2300 align down Left Top corner to Mb  i.e. 15->0
2301 align up Right and Bottom corner to Mb  i.e. 15->16
2302 
2303 checks that aligned rect is 'open '  i.e. Left < Right and Top < Bottom
2304 check that Right and Bottom fits in Frame
2305 i.e. Right(aligned up) <= par.mfx.FrameInfo.Width( must be aligned)
2306 
2307 returns:
2308 MFX_WRN_INCOMPATIBLE_VIDEO_PARAM - if any has been aligned
2309 MFX_ERR_UNSUPPORTED - if Left < Right and Top < Bottom
2310 MFX_ERR_UNSUPPORTED - if Right or Bottom
2311 */
CheckAndFixOpenRectQueryLike(MfxVideoParam const & par,mfxRectDesc * rect)2312 mfxStatus MfxHwH264Encode::CheckAndFixOpenRectQueryLike(
2313     MfxVideoParam const & par,
2314     mfxRectDesc *         rect)
2315 {
2316     mfxStatus checkSts = MFX_ERR_NONE;
2317 
2318     // check that rectangle is aligned to MB, correct it if not
2319     if (!CheckMbAlignment(rect->Left))          checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
2320     if (!CheckMbAlignment(rect->Top))           checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
2321     if (!CheckMbAlignmentAndUp(rect->Right))    checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
2322     if (!CheckMbAlignmentAndUp(rect->Bottom))   checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
2323 
2324     // check that rectangle dimensions don't conflict with each other and don't exceed frame size
2325     if (par.mfx.FrameInfo.Width)
2326     {
2327         if (!CheckRangeDflt(rect->Left, mfxU32(0), mfxU32(par.mfx.FrameInfo.Width - 16), mfxU32(0))) checkSts = MFX_ERR_UNSUPPORTED;
2328         if (!CheckRangeDflt(rect->Right, mfxU32(rect->Left + 16), mfxU32(par.mfx.FrameInfo.Width), mfxU32(0))) checkSts = MFX_ERR_UNSUPPORTED;
2329     }
2330 
2331     if (rect->Right && rect->Right < rect->Left)
2332     {
2333         checkSts = MFX_ERR_UNSUPPORTED;
2334         rect->Right = 0;
2335     }
2336 
2337     if (par.mfx.FrameInfo.Height)
2338     {
2339         if (!CheckRangeDflt(rect->Top, mfxU32(0), mfxU32(par.mfx.FrameInfo.Height - 16), mfxU32(0))) checkSts = MFX_ERR_UNSUPPORTED;
2340         if (!CheckRangeDflt(rect->Bottom, mfxU32(rect->Top + 16), mfxU32(par.mfx.FrameInfo.Height), mfxU32(0))) checkSts = MFX_ERR_UNSUPPORTED;
2341     }
2342 
2343     if (rect->Bottom && rect->Bottom <= rect->Top)
2344     {
2345         checkSts = MFX_ERR_UNSUPPORTED;
2346         rect->Bottom = 0;
2347     }
2348 
2349     return checkSts;
2350 }
2351 
CheckAndFixRoiQueryLike(MfxVideoParam const & par,mfxRoiDesc * roi,mfxU16 roiMode)2352 mfxStatus MfxHwH264Encode::CheckAndFixRoiQueryLike(
2353     MfxVideoParam const & par,
2354     mfxRoiDesc *          roi,
2355     mfxU16                roiMode)
2356 {
2357     mfxStatus checkSts = CheckAndFixOpenRectQueryLike(par, (mfxRectDesc*)roi);
2358 
2359     // check QP
2360     if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP)
2361     {
2362         if (!CheckRangeDflt(roi->ROIValue, -51, 51, 0))
2363             checkSts = MFX_ERR_UNSUPPORTED;
2364     }
2365     else
2366     {
2367         if (roiMode == MFX_ROI_MODE_QP_DELTA && !CheckRangeDflt(roi->ROIValue, -51, 51, 0))
2368             checkSts = MFX_ERR_UNSUPPORTED;
2369 
2370         else if (roiMode == MFX_ROI_MODE_PRIORITY && !CheckRangeDflt(roi->ROIValue, -3, 3, 0))
2371             checkSts = MFX_ERR_UNSUPPORTED;
2372     }
2373 
2374     return checkSts;
2375 }
2376 
CheckAndFixMovingRectQueryLike(MfxVideoParam const & par,mfxMovingRectDesc * rect)2377 mfxStatus MfxHwH264Encode::CheckAndFixMovingRectQueryLike(
2378     MfxVideoParam const & par,
2379     mfxMovingRectDesc *   rect)
2380 {
2381     mfxStatus checkSts = CheckAndFixRectQueryLike(par, (mfxRectDesc*)rect);
2382 
2383     if (par.mfx.FrameInfo.Width)
2384         if(!CheckRangeDflt(rect->SourceLeft, mfxU32(0), mfxU32(par.mfx.FrameInfo.Width - 1), mfxU32(0))) checkSts = MFX_ERR_UNSUPPORTED;
2385 
2386     if (par.mfx.FrameInfo.Height)
2387         if(!CheckRangeDflt(rect->SourceTop, mfxU32(0), mfxU32(par.mfx.FrameInfo.Height - 1), mfxU32(0))) checkSts = MFX_ERR_UNSUPPORTED;
2388 
2389     return checkSts;
2390 }
2391 
2392 //typedef bool Bool;
2393 
CheckVideoParamQueryLike(MfxVideoParam & par,MFX_ENCODE_CAPS const & hwCaps,eMFXHWType platform,eMFXVAType vaType,eMFXGTConfig config)2394 mfxStatus MfxHwH264Encode::CheckVideoParamQueryLike(
2395     MfxVideoParam &         par,
2396     MFX_ENCODE_CAPS const & hwCaps,
2397     eMFXHWType              platform,
2398     eMFXVAType              vaType,
2399     eMFXGTConfig            config)
2400 {
2401     Bool unsupported(false);
2402     Bool changed(false);
2403     Bool warning(false);
2404 
2405     mfxExtCodingOption *       extOpt       = GetExtBuffer(par);
2406     mfxExtCodingOptionDDI *    extDdi       = GetExtBuffer(par);
2407     mfxExtVideoSignalInfo *    extVsi       = GetExtBuffer(par);
2408     mfxExtCodingOptionSPSPPS * extBits      = GetExtBuffer(par);
2409     mfxExtPictureTimingSEI *   extPt        = GetExtBuffer(par);
2410     mfxExtSpsHeader *          extSps       = GetExtBuffer(par);
2411     mfxExtPpsHeader *          extPps       = GetExtBuffer(par);
2412     mfxExtMVCSeqDesc *         extMvc       = GetExtBuffer(par);
2413     mfxExtAvcTemporalLayers *  extTemp      = GetExtBuffer(par);
2414     mfxExtCodingOption2 *      extOpt2      = GetExtBuffer(par);
2415     mfxExtEncoderROI *         extRoi       = GetExtBuffer(par);
2416     mfxExtCodingOption3 *      extOpt3      = GetExtBuffer(par);
2417     mfxExtChromaLocInfo *      extCli       = GetExtBuffer(par);
2418     mfxExtDirtyRect  *         extDirtyRect = GetExtBuffer(par);
2419     mfxExtMoveRect *           extMoveRect  = GetExtBuffer(par);
2420     mfxExtPredWeightTable *    extPwt       = GetExtBuffer(par);
2421     mfxExtFeiParam *           feiParam     = GetExtBuffer(par);
2422 #if defined(MFX_ENABLE_ENCTOOLS)
2423     mfxExtEncToolsConfig *     extConfig    = GetExtBuffer(par);
2424 #endif
2425     mfxExtBRC *                extBRC       = GetExtBuffer(par);
2426 
2427 
2428     bool isENCPAK = (feiParam->Func == MFX_FEI_FUNCTION_ENCODE) ||
2429                     (feiParam->Func == MFX_FEI_FUNCTION_ENC)    ||
2430                     (feiParam->Func == MFX_FEI_FUNCTION_PAK);
2431     bool sliceRowAlligned = true;
2432 
2433     // check HW capabilities
2434     if (par.mfx.FrameInfo.Width  > hwCaps.ddi_caps.MaxPicWidth ||
2435         par.mfx.FrameInfo.Height > hwCaps.ddi_caps.MaxPicHeight)
2436         return Error(MFX_WRN_PARTIAL_ACCELERATION);
2437 
2438     if ((par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PART1 )!= MFX_PICSTRUCT_PROGRESSIVE && hwCaps.ddi_caps.NoInterlacedField){
2439         if(par.mfx.LowPower == MFX_CODINGOPTION_ON)
2440         {
2441             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2442             changed = true;
2443         }
2444         else
2445             return Error(MFX_WRN_PARTIAL_ACCELERATION);
2446     }
2447 
2448     if (hwCaps.ddi_caps.MaxNum_TemporalLayer != 0 &&
2449         hwCaps.ddi_caps.MaxNum_TemporalLayer < par.calcParam.numTemporalLayer)
2450         return Error(MFX_WRN_PARTIAL_ACCELERATION);
2451 
2452     if (!CheckTriStateOption(par.mfx.LowPower)) changed = true;
2453 
2454     if (IsOn(par.mfx.LowPower))
2455     {
2456         if (par.mfx.GopRefDist > 1)
2457         {
2458             changed = true;
2459             par.mfx.GopRefDist = 1;
2460         }
2461 
2462         if (par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
2463         {
2464             changed = true;
2465             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2466         }
2467 
2468 
2469         if (par.mfx.RateControlMethod != 0 &&
2470             par.mfx.RateControlMethod != MFX_RATECONTROL_CBR &&
2471             par.mfx.RateControlMethod != MFX_RATECONTROL_VBR &&
2472             par.mfx.RateControlMethod != MFX_RATECONTROL_AVBR &&
2473             par.mfx.RateControlMethod != MFX_RATECONTROL_QVBR &&
2474             par.mfx.RateControlMethod != MFX_RATECONTROL_VCM &&
2475             par.mfx.RateControlMethod != MFX_RATECONTROL_CQP)
2476         {
2477             changed = true;
2478             par.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
2479         }
2480 
2481         if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP
2482             && par.calcParam.cqpHrdMode == 0)
2483         {
2484             if (!CheckRange(par.mfx.QPI, 10, 51)) changed = true;
2485             if (!CheckRange(par.mfx.QPP, 10, 51)) changed = true;
2486             if (!CheckRange(par.mfx.QPB, 10, 51)) changed = true;
2487         }
2488     }
2489 
2490     if (par.mfx.GopRefDist > 1 && hwCaps.ddi_caps.SliceIPOnly)
2491     {
2492         changed = true;
2493         par.mfx.GopRefDist = 1;
2494     }
2495 
2496     // sps/pps parameters if present overrides corresponding fields of VideoParam
2497     if (extBits->SPSBuffer)
2498     {
2499         if (!CheckAgreementOfSequenceLevelParameters<FunctionQuery>(par, *extSps))
2500             changed = true;
2501 
2502         if (extBits->PPSBuffer)
2503             if (!CheckAgreementOfPictureLevelParameters<FunctionQuery>(par, *extPps))
2504                 changed = true;
2505     }
2506 
2507     if (par.Protected != 0)
2508     {
2509         unsupported = true;
2510         par.Protected = 0;
2511     }
2512 
2513     if (par.IOPattern != 0)
2514     {
2515         if ((par.IOPattern & MFX_IOPATTERN_IN_MASK) != par.IOPattern)
2516         {
2517             changed = true;
2518             par.IOPattern &= MFX_IOPATTERN_IN_MASK;
2519         }
2520 
2521         if (par.IOPattern != MFX_IOPATTERN_IN_VIDEO_MEMORY  &&
2522             par.IOPattern != MFX_IOPATTERN_IN_SYSTEM_MEMORY &&
2523             par.IOPattern != MFX_IOPATTERN_IN_OPAQUE_MEMORY)
2524         {
2525             changed = true;
2526             par.IOPattern = MFX_IOPATTERN_IN_VIDEO_MEMORY;
2527         }
2528     }
2529 
2530 
2531     if (par.mfx.TargetUsage > 7)
2532     {
2533         changed = true;
2534         par.mfx.TargetUsage = 7;
2535     }
2536 
2537     if (par.mfx.GopPicSize > 0 &&
2538         par.mfx.GopRefDist > 0 &&
2539         par.mfx.GopRefDist > par.mfx.GopPicSize)
2540     {
2541         changed = true;
2542         par.mfx.GopRefDist = par.mfx.GopPicSize - 1;
2543     }
2544 
2545     if (par.mfx.GopRefDist > 1)
2546     {
2547         if (IsAvcBaseProfile(par.mfx.CodecProfile) ||
2548             par.mfx.CodecProfile == MFX_PROFILE_AVC_CONSTRAINED_HIGH)
2549         {
2550             changed = true;
2551             par.mfx.GopRefDist = 1;
2552         }
2553     }
2554 
2555     if (par.mfx.RateControlMethod != 0 &&
2556         par.mfx.RateControlMethod != MFX_RATECONTROL_CBR &&
2557         par.mfx.RateControlMethod != MFX_RATECONTROL_VBR &&
2558         par.mfx.RateControlMethod != MFX_RATECONTROL_CQP &&
2559         par.mfx.RateControlMethod != MFX_RATECONTROL_AVBR &&
2560         par.mfx.RateControlMethod != MFX_RATECONTROL_WIDI_VBR &&
2561         par.mfx.RateControlMethod != MFX_RATECONTROL_VCM &&
2562         par.mfx.RateControlMethod != MFX_RATECONTROL_ICQ &&
2563         par.mfx.RateControlMethod != MFX_RATECONTROL_QVBR &&
2564         !bRateControlLA(par.mfx.RateControlMethod))
2565     {
2566         changed = true;
2567         par.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
2568     }
2569     if ((isENCPAK) && (MFX_RATECONTROL_CQP != par.mfx.RateControlMethod))
2570         unsupported = true;
2571 
2572     if ((isENCPAK) && !CheckTriStateOption(feiParam->SingleFieldProcessing))
2573         unsupported = true;
2574 
2575     if(MFX_HW_VAAPI == vaType &&
2576        par.mfx.RateControlMethod != 0 &&
2577        par.mfx.RateControlMethod != MFX_RATECONTROL_CBR &&
2578        par.mfx.RateControlMethod != MFX_RATECONTROL_VBR &&
2579        par.mfx.RateControlMethod != MFX_RATECONTROL_VCM &&
2580        par.mfx.RateControlMethod != MFX_RATECONTROL_QVBR &&
2581        par.mfx.RateControlMethod != MFX_RATECONTROL_CQP &&
2582        par.mfx.RateControlMethod != MFX_RATECONTROL_AVBR &&
2583        par.mfx.RateControlMethod != MFX_RATECONTROL_ICQ &&
2584        !bRateControlLA(par.mfx.RateControlMethod))
2585     {
2586         unsupported = true;
2587         par.mfx.RateControlMethod = 0;
2588     }
2589 
2590     bool laEnabled = true;
2591     // LA and FD supports only with VME
2592     if (!hasSupportVME(platform))
2593     {
2594         laEnabled = false;
2595         if (bRateControlLA(par.mfx.RateControlMethod))
2596         {
2597             unsupported = true;
2598             par.mfx.RateControlMethod = 0;
2599         }
2600 
2601         if (IsOn(extOpt3->FadeDetection))
2602         {
2603             unsupported = true;
2604             extOpt3->FadeDetection = 0;
2605         }
2606     }
2607 
2608     if (extOpt2->MaxSliceSize &&
2609         !(IsDriverSliceSizeControlEnabled(par, hwCaps) ||  // driver slice control condition
2610           (hwCaps.ddi_caps.SliceStructure == 4 && laEnabled)))  // sw slice control condition
2611         {
2612             unsupported = true;
2613             extOpt2->MaxSliceSize = 0;
2614         }
2615 
2616 
2617     if (bRateControlLA(par.mfx.RateControlMethod) && IsOn(extOpt->CAVLC))
2618     {
2619         extOpt->CAVLC = MFX_CODINGOPTION_OFF;
2620         changed = true;
2621     }
2622 
2623     if (extOpt2->MaxSliceSize)
2624     {
2625         if (par.mfx.GopRefDist > 1)
2626         {
2627             changed = true;
2628             par.mfx.GopRefDist = 1;
2629         }
2630         if (par.mfx.RateControlMethod != MFX_RATECONTROL_LA &&
2631             !IsDriverSliceSizeControlEnabled(par, hwCaps))
2632         {
2633             par.mfx.RateControlMethod = MFX_RATECONTROL_LA;
2634             changed = true;
2635         }
2636         if (extOpt2->LookAheadDepth > 1)
2637         {
2638             extOpt2->LookAheadDepth = 1;
2639             changed = true;
2640         }
2641         if (IsOn(extOpt->FieldOutput))
2642         {
2643             unsupported = true;
2644             extOpt->FieldOutput = MFX_CODINGOPTION_UNKNOWN;
2645         }
2646         if ((par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0)
2647         {
2648             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
2649             changed = true;
2650         }
2651         if (extDdi->LookAheadDependency != 0)
2652         {
2653             extDdi->LookAheadDependency = 0;
2654             changed = true;
2655         }
2656         if (par.AsyncDepth > 1 && par.mfx.LowPower != MFX_CODINGOPTION_ON)
2657         {
2658             par.AsyncDepth  = 1;
2659             changed = true;
2660         }
2661         if (extOpt2->NumMbPerSlice)
2662         {
2663             extOpt2->NumMbPerSlice = 0;
2664             unsupported = true;
2665         }
2666     }
2667     else if (extOpt2->LookAheadDepth > 0)
2668     {
2669         if (!bRateControlLA(par.mfx.RateControlMethod))
2670         {
2671             changed = true;
2672             extOpt2->LookAheadDepth = 0;
2673         }
2674         else if (par.mfx.GopRefDist > 0 && extOpt2->LookAheadDepth < 2 * par.mfx.GopRefDist)
2675         {
2676             changed = true;
2677             extOpt2->LookAheadDepth = 2 * par.mfx.GopRefDist;
2678         }
2679 
2680         if(bRateControlLA(par.mfx.RateControlMethod) && extOpt2->LookAheadDepth < 2 * par.mfx.NumRefFrame)
2681         {
2682             changed = true;
2683             extOpt2->LookAheadDepth =  2 * par.mfx.NumRefFrame;
2684         }
2685     }
2686 
2687     /* max allowed combination */
2688     if (par.mfx.FrameInfo.PicStruct > (MFX_PICSTRUCT_PART1|MFX_PICSTRUCT_PART2))
2689     { /* */
2690         unsupported = true;
2691         par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN;
2692     }
2693 
2694     if (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PART2)
2695     { // repeat/double/triple flags are for EncodeFrameAsync
2696         changed = true;
2697         par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN;
2698     }
2699 
2700     mfxU16 picStructPart1 = par.mfx.FrameInfo.PicStruct;
2701     if (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PART1)
2702     {
2703         if (picStructPart1 & (picStructPart1 - 1))
2704         { // more then one flag set
2705             changed = true;
2706             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_UNKNOWN;
2707         }
2708     }
2709 
2710     if (par.mfx.FrameInfo.Width & 15)
2711     {
2712         unsupported = true;
2713         par.mfx.FrameInfo.Width = 0;
2714     }
2715 
2716     if (par.mfx.FrameInfo.Height & 15)
2717     {
2718         unsupported = true;
2719         par.mfx.FrameInfo.Height = 0;
2720     }
2721 
2722     if ((par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0 &&
2723         (par.mfx.FrameInfo.Height & 31) != 0)
2724     {
2725         unsupported = true;
2726         par.mfx.FrameInfo.PicStruct = 0;
2727         par.mfx.FrameInfo.Height = 0;
2728     }
2729 
2730     // driver doesn't support resolution 16xH
2731     if (par.mfx.FrameInfo.Width == 16)
2732     {
2733         unsupported = true;
2734         par.mfx.FrameInfo.Width = 0;
2735     }
2736 
2737     // driver doesn't support resolution Wx16
2738     if (par.mfx.FrameInfo.Height == 16)
2739     {
2740         unsupported = true;
2741         par.mfx.FrameInfo.Height = 0;
2742     }
2743 
2744     if (par.mfx.FrameInfo.Width > 0)
2745     {
2746         if (par.mfx.FrameInfo.CropX > par.mfx.FrameInfo.Width)
2747         {
2748             if (extBits->SPSBuffer)
2749                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2750 
2751             unsupported = true;
2752             par.mfx.FrameInfo.CropX = 0;
2753         }
2754 
2755         if (par.mfx.FrameInfo.CropX + par.mfx.FrameInfo.CropW > par.mfx.FrameInfo.Width)
2756         {
2757             if (extBits->SPSBuffer)
2758                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2759 
2760             unsupported = true;
2761             par.mfx.FrameInfo.CropW = par.mfx.FrameInfo.Width - par.mfx.FrameInfo.CropX;
2762         }
2763     }
2764 
2765     if (par.mfx.FrameInfo.Height > 0)
2766     {
2767         if (par.mfx.FrameInfo.CropY > par.mfx.FrameInfo.Height)
2768         {
2769             if (extBits->SPSBuffer)
2770                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2771 
2772             unsupported = true;
2773             par.mfx.FrameInfo.CropY = 0;
2774         }
2775 
2776         if (par.mfx.FrameInfo.CropY + par.mfx.FrameInfo.CropH > par.mfx.FrameInfo.Height)
2777         {
2778             if (extBits->SPSBuffer)
2779                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2780 
2781             unsupported = true;
2782             par.mfx.FrameInfo.CropH = par.mfx.FrameInfo.Height - par.mfx.FrameInfo.CropY;
2783         }
2784     }
2785 
2786     // WA for MVCe with d3d9. AsyncDepth parameter is checked here
2787     if (vaType == MFX_HW_D3D9 && par.AsyncDepth > 0 && IsMvcProfile(par.mfx.CodecProfile))
2788     {
2789         mfxU32 numEncs = (extOpt->ViewOutput == MFX_CODINGOPTION_ON) ? 2 : 1;
2790         mfxU32 numView = (extMvc->NumView == 0) ? 1 : extMvc->NumView;
2791         mfxU32 numSurfBitstream = mfxU32(CalcNumSurfBitstream(par) * (numEncs > 1 ? 1 : numView));
2792         mfxU32 numSurfRecon = mfxU32(CalcNumSurfRecon(par) * (numEncs > 1 ? 1 : numView));
2793         if (numSurfBitstream > 128 || numSurfRecon > 128)
2794         {
2795             changed = true;
2796             par.AsyncDepth = DEFAULT_ASYNC_DEPTH_TO_WA_D3D9_128_SURFACE_LIMIT;
2797         }
2798     }
2799 
2800     if (CorrectCropping(par) != MFX_ERR_NONE)
2801     { // cropping read from sps header always has correct alignment
2802         changed = true;
2803     }
2804 
2805 
2806     if (extOpt2->NumMbPerSlice != 0)
2807     {
2808         bool fieldCoding = (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0;
2809         mfxU16 widthInMbs  = par.mfx.FrameInfo.Width / 16;
2810         mfxU16 heightInMbs = par.mfx.FrameInfo.Height / 16 / (fieldCoding ? 2 : 1);
2811 
2812         if (   (hwCaps.ddi_caps.SliceStructure == 0)
2813             || (hwCaps.ddi_caps.SliceStructure  < 4 && (extOpt2->NumMbPerSlice % (par.mfx.FrameInfo.Width >> 4)))
2814             || (hwCaps.ddi_caps.SliceStructure == 1 && ((extOpt2->NumMbPerSlice / widthInMbs) & ((extOpt2->NumMbPerSlice / widthInMbs) - 1)))
2815             || (widthInMbs * heightInMbs) < extOpt2->NumMbPerSlice)
2816         {
2817             extOpt2->NumMbPerSlice = 0;
2818             unsupported = true;
2819         }
2820     }
2821 
2822     if (par.mfx.NumSlice !=0 &&
2823       (extOpt3->NumSliceI != 0 || extOpt3->NumSliceP != 0 || extOpt3->NumSliceB != 0))
2824     {
2825         if(par.mfx.NumSlice != extOpt3->NumSliceI &&
2826            par.mfx.NumSlice != extOpt3->NumSliceP &&
2827            par.mfx.NumSlice != extOpt3->NumSliceB)
2828         {
2829             changed = true;
2830             par.mfx.NumSlice = 0;
2831         }
2832     }
2833 
2834     if (extOpt3->LowDelayBRC == MFX_CODINGOPTION_ON) {
2835         if (par.mfx.RateControlMethod != MFX_RATECONTROL_VBR && par.mfx.RateControlMethod != MFX_RATECONTROL_QVBR &&
2836             par.mfx.RateControlMethod != MFX_RATECONTROL_VCM) {
2837             extOpt3->LowDelayBRC = MFX_CODINGOPTION_OFF;
2838             changed = true;
2839         }
2840         else {
2841             if (extOpt3->WinBRCMaxAvgKbps || extOpt3->WinBRCSize) {
2842                 extOpt3->WinBRCMaxAvgKbps = 0;
2843                 extOpt3->WinBRCSize = 0;
2844                 changed = true;
2845             }
2846             if (par.mfx.GopRefDist != 0 && par.mfx.GopRefDist != 1) {
2847                 par.mfx.GopRefDist = 1;
2848                 changed = true;
2849             }
2850         }
2851     }
2852 
2853     if (par.mfx.NumSlice         != 0 &&
2854         par.mfx.FrameInfo.Width  != 0 &&
2855         par.mfx.FrameInfo.Height != 0)
2856     {
2857         if (par.mfx.NumSlice > par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256)
2858         {
2859             unsupported = true;
2860             par.mfx.NumSlice = 0;
2861         }
2862 
2863         bool fieldCoding = (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0;
2864 
2865         SliceDivider divider = MakeSliceDivider(
2866             (hwCaps.ddi_caps.SliceLevelRateCtrl)? SliceDividerType::ARBITRARY_MB_SLICE : SliceDividerType(hwCaps.ddi_caps.SliceStructure),
2867             extOpt2->NumMbPerSlice,
2868             par.mfx.NumSlice,
2869             par.mfx.FrameInfo.Width / 16,
2870             par.mfx.FrameInfo.Height / 16 / (fieldCoding ? 2 : 1));
2871 
2872         if (par.mfx.NumSlice != divider.GetNumSlice())
2873         {
2874             changed = true;
2875             par.mfx.NumSlice = (mfxU16)divider.GetNumSlice();
2876         }
2877         if (extOpt3->NumSliceP == 0)
2878         {
2879             do
2880             {
2881                 if (divider.GetNumMbInSlice() % (par.mfx.FrameInfo.Width / 16) != 0)
2882                     sliceRowAlligned = false;
2883             } while (divider.Next());
2884         }
2885     }
2886 
2887     if (extOpt3->NumSliceI       != 0 &&
2888         par.mfx.FrameInfo.Width  != 0 &&
2889         par.mfx.FrameInfo.Height != 0)
2890     {
2891         if (extOpt3->NumSliceI > par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256)
2892         {
2893             unsupported = true;
2894             extOpt3->NumSliceI = 0;
2895         }
2896 
2897         bool fieldCoding = (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0;
2898 
2899         SliceDivider divider = MakeSliceDivider(
2900             (hwCaps.ddi_caps.SliceLevelRateCtrl)? SliceDividerType::ARBITRARY_MB_SLICE : SliceDividerType(hwCaps.ddi_caps.SliceStructure),
2901             extOpt2->NumMbPerSlice,
2902             extOpt3->NumSliceI,
2903             par.mfx.FrameInfo.Width / 16,
2904             par.mfx.FrameInfo.Height / 16 / (fieldCoding ? 2 : 1));
2905 
2906         if (extOpt3->NumSliceI != divider.GetNumSlice())
2907         {
2908             changed = true;
2909             extOpt3->NumSliceI = (mfxU16)divider.GetNumSlice();
2910         }
2911     }
2912 
2913     if (extOpt3->NumSliceP       != 0 &&
2914         par.mfx.FrameInfo.Width  != 0 &&
2915         par.mfx.FrameInfo.Height != 0)
2916     {
2917         if (extOpt3->NumSliceP > par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256)
2918         {
2919             unsupported = true;
2920             extOpt3->NumSliceP = 0;
2921         }
2922 
2923         bool fieldCoding = (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0;
2924 
2925         SliceDivider divider = MakeSliceDivider(
2926             (hwCaps.ddi_caps.SliceLevelRateCtrl)? SliceDividerType::ARBITRARY_MB_SLICE : SliceDividerType(hwCaps.ddi_caps.SliceStructure),
2927             extOpt2->NumMbPerSlice,
2928             extOpt3->NumSliceP,
2929             par.mfx.FrameInfo.Width / 16,
2930             par.mfx.FrameInfo.Height / 16 / (fieldCoding ? 2 : 1));
2931 
2932         if (extOpt3->NumSliceP != divider.GetNumSlice())
2933         {
2934             changed = true;
2935             extOpt3->NumSliceP = (mfxU16)divider.GetNumSlice();
2936         }
2937 
2938         do
2939         {
2940             if (divider.GetNumMbInSlice() % (par.mfx.FrameInfo.Width / 16) != 0)
2941                 sliceRowAlligned = false;
2942         } while (divider.Next());
2943     }
2944 
2945     if (extOpt3->NumSliceB       != 0 &&
2946         par.mfx.FrameInfo.Width  != 0 &&
2947         par.mfx.FrameInfo.Height != 0)
2948     {
2949         if (extOpt3->NumSliceB > par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height / 256)
2950         {
2951             unsupported = true;
2952             extOpt3->NumSliceB = 0;
2953         }
2954 
2955         bool fieldCoding = (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0;
2956 
2957         SliceDivider divider = MakeSliceDivider(
2958             (hwCaps.ddi_caps.SliceLevelRateCtrl)? SliceDividerType::ARBITRARY_MB_SLICE : SliceDividerType(hwCaps.ddi_caps.SliceStructure),
2959             extOpt2->NumMbPerSlice,
2960             extOpt3->NumSliceB,
2961             par.mfx.FrameInfo.Width / 16,
2962             par.mfx.FrameInfo.Height / 16 / (fieldCoding ? 2 : 1));
2963 
2964         if (extOpt3->NumSliceB != divider.GetNumSlice())
2965         {
2966             changed = true;
2967             extOpt3->NumSliceB = (mfxU16)divider.GetNumSlice();
2968         }
2969     }
2970 
2971     if (par.mfx.FrameInfo.ChromaFormat != 0 &&
2972         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV420 &&
2973         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV422 &&
2974         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV444)
2975     {
2976         if (extBits->SPSBuffer)
2977             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
2978 
2979         changed = true;
2980         par.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
2981     }
2982 
2983     if (par.mfx.FrameInfo.FourCC != 0 &&
2984         par.mfx.FrameInfo.FourCC != MFX_FOURCC_NV12 &&
2985         par.mfx.FrameInfo.FourCC != MFX_FOURCC_RGB4 &&
2986         par.mfx.FrameInfo.FourCC != MFX_FOURCC_BGR4 &&
2987         par.mfx.FrameInfo.FourCC != MFX_FOURCC_YUY2 &&
2988         par.mfx.FrameInfo.FourCC != MFX_FOURCC_AYUV)
2989     {
2990         unsupported = true;
2991         par.mfx.FrameInfo.FourCC = 0;
2992     }
2993 
2994     if (par.mfx.FrameInfo.FourCC == MFX_FOURCC_NV12 &&
2995         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV420 &&
2996         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_MONOCHROME)
2997     {
2998         if (extBits->SPSBuffer)
2999             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3000 
3001         changed = true;
3002         par.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
3003     }
3004 
3005     if (par.mfx.FrameInfo.FourCC == MFX_FOURCC_YUY2 &&
3006         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV422)
3007     {
3008         if (extBits->SPSBuffer)
3009             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3010 
3011         changed = true;
3012         par.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
3013     }
3014 
3015     if (par.mfx.FrameInfo.FourCC == MFX_FOURCC_AYUV &&
3016         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV444)
3017     {
3018         if (extBits->SPSBuffer)
3019             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3020 
3021         changed = true;
3022         par.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
3023     }
3024 
3025     if ((par.mfx.FrameInfo.FourCC == MFX_FOURCC_RGB4 || par.mfx.FrameInfo.FourCC == MFX_FOURCC_BGR4) &&
3026         par.mfx.FrameInfo.ChromaFormat != MFX_CHROMAFORMAT_YUV444)
3027     {
3028         if (extBits->SPSBuffer)
3029             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3030 
3031         changed = true;
3032         par.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
3033     }
3034 
3035     if (hwCaps.ddi_caps.Color420Only &&
3036         (par.mfx.FrameInfo.ChromaFormat == MFX_CHROMAFORMAT_YUV422 ||
3037          par.mfx.FrameInfo.ChromaFormat == MFX_CHROMAFORMAT_YUV444))
3038     {
3039         unsupported = true;
3040         par.mfx.FrameInfo.ChromaFormat = 0;
3041     }
3042 
3043     if (par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE &&
3044         (par.mfx.FrameInfo.ChromaFormat == MFX_CHROMAFORMAT_YUV422 ||
3045          par.mfx.FrameInfo.ChromaFormat == MFX_CHROMAFORMAT_YUV444))
3046     {
3047         changed = true;
3048         par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
3049     }
3050 
3051     if (!CheckTriStateOption(extOpt2->DisableVUI))         changed = true;
3052     if (!CheckTriStateOption(extOpt->VuiNalHrdParameters)) changed = true;
3053     if (!CheckTriStateOption(extOpt->VuiVclHrdParameters)) changed = true;
3054     if (!CheckTriStateOption(extOpt2->FixedFrameRate))     changed = true;
3055     if (!CheckTriStateOption(extOpt3->LowDelayHrd))        changed = true;
3056 
3057     if (IsOn(extOpt2->DisableVUI))
3058     {
3059         bool contradictoryVuiParam = false;
3060         if (!CheckTriStateOptionForOff(extOpt3->TimingInfoPresent))      contradictoryVuiParam = true;
3061         if (!CheckTriStateOptionForOff(extOpt3->OverscanInfoPresent))    contradictoryVuiParam = true;
3062         if (!CheckTriStateOptionForOff(extOpt3->AspectRatioInfoPresent)) contradictoryVuiParam = true;
3063         if (!CheckTriStateOptionForOff(extOpt3->BitstreamRestriction))   contradictoryVuiParam = true;
3064         if (!CheckTriStateOptionForOff(extOpt->VuiNalHrdParameters))     contradictoryVuiParam = true;
3065         if (!CheckTriStateOptionForOff(extOpt->VuiVclHrdParameters))     contradictoryVuiParam = true;
3066         if (!CheckTriStateOptionForOff(extOpt->PicTimingSEI))            contradictoryVuiParam = true;
3067 
3068         if (contradictoryVuiParam)
3069         {
3070             if (extBits->SPSBuffer)
3071                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3072 
3073             changed = true;
3074         }
3075     }
3076 
3077     if (IsOff(extOpt3->OverscanInfoPresent))
3078     {
3079         if (IsOn(extOpt3->OverscanAppropriate))
3080         {
3081             changed = true;
3082             extOpt3->OverscanAppropriate = MFX_CODINGOPTION_OFF;
3083         }
3084     }
3085     if (IsOff(extOpt3->BitstreamRestriction))
3086     {
3087         if (IsOn(extOpt3->MotionVectorsOverPicBoundaries))
3088         {
3089             changed = true;
3090             extOpt3->MotionVectorsOverPicBoundaries = MFX_CODINGOPTION_OFF;
3091         }
3092     }
3093     if (IsOff(extOpt3->TimingInfoPresent))
3094     {
3095         if (IsOn(extOpt2->FixedFrameRate))
3096         {
3097             changed = true;
3098             extOpt2->FixedFrameRate = MFX_CODINGOPTION_OFF;
3099         }
3100     }
3101 
3102     if ((par.mfx.FrameInfo.FrameRateExtN == 0) !=
3103         (par.mfx.FrameInfo.FrameRateExtD == 0))
3104     {
3105         if (extBits->SPSBuffer && !IsOff(extOpt3->TimingInfoPresent))
3106             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3107 
3108         unsupported = true;
3109         par.mfx.FrameInfo.FrameRateExtN = 0;
3110         par.mfx.FrameInfo.FrameRateExtD = 0;
3111     }
3112 
3113     if (!IsOff(extOpt3->TimingInfoPresent) &&
3114         par.mfx.FrameInfo.FrameRateExtN != 0 &&
3115         par.mfx.FrameInfo.FrameRateExtD != 0 &&
3116         par.mfx.FrameInfo.FrameRateExtN > mfxU64(172) * par.mfx.FrameInfo.FrameRateExtD)
3117     {
3118         if (extBits->SPSBuffer) // frame_rate read from sps
3119             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3120 
3121         unsupported = true;
3122         par.mfx.FrameInfo.FrameRateExtN = 0;
3123         par.mfx.FrameInfo.FrameRateExtD = 0;
3124     }
3125 
3126     if (IsOff(extOpt3->TimingInfoPresent) &&
3127         IsOn(extOpt2->FixedFrameRate))
3128     {
3129         // if timing_info_present_flag is 0, fixed_frame_rate_flag is inferred to be 0 (Annex E.2.1)
3130         if (extBits->SPSBuffer)
3131             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3132 
3133         changed = true;
3134         extOpt2->FixedFrameRate = MFX_CODINGOPTION_OFF;
3135     }
3136 
3137     if (!IsOff(extOpt3->TimingInfoPresent))
3138     {
3139         if (IsOn(extOpt2->FixedFrameRate) &&
3140             IsOn(extOpt3->LowDelayHrd))
3141         {
3142             if (extBits->SPSBuffer)
3143                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3144 
3145             changed = true;
3146             extOpt3->LowDelayHrd = MFX_CODINGOPTION_OFF;
3147         }
3148     }
3149 
3150     if (par.mfx.CodecProfile != MFX_PROFILE_UNKNOWN && !IsValidCodingProfile(par.mfx.CodecProfile))
3151     {
3152         if (extBits->SPSBuffer)
3153             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3154 
3155         if (par.mfx.CodecProfile == MFX_PROFILE_AVC_MULTIVIEW_HIGH)
3156             return Error(MFX_ERR_UNSUPPORTED);
3157 
3158         changed = true;
3159         par.mfx.CodecProfile = MFX_PROFILE_UNKNOWN;
3160     }
3161 
3162     if (par.mfx.CodecLevel != MFX_LEVEL_UNKNOWN && !IsValidCodingLevel(par.mfx.CodecLevel))
3163     {
3164         if (extBits->SPSBuffer)
3165             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3166 
3167         changed = true;
3168         par.mfx.CodecLevel = MFX_LEVEL_UNKNOWN;
3169     }
3170 
3171     if (par.mfx.NumRefFrame != 0)
3172     {
3173         if ((par.mfx.NumRefFrame & 1) &&
3174             (hwCaps.ddi_caps.HeaderInsertion) &&
3175             (par.Protected || !IsOff(extOpt->NalHrdConformance)))
3176         {
3177             // when driver writes headers it can write only even values of num_ref_frames
3178             if (extBits->SPSBuffer)
3179                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3180 
3181             changed = true;
3182             par.mfx.NumRefFrame++;
3183         }
3184     }
3185 
3186     if (par.mfx.FrameInfo.Width  != 0 &&
3187         par.mfx.FrameInfo.Height != 0)
3188     {
3189         mfxU16 minLevel = GetLevelLimitByFrameSize(par);
3190         if (minLevel == 0)
3191         {
3192             if (extBits->SPSBuffer)
3193                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3194             else if (par.mfx.CodecLevel != 0)
3195             {
3196                 changed = true; // warning should be returned if frame size exceeds maximum value supported by AVC standard
3197                 if (par.mfx.CodecLevel < GetMaxSupportedLevel())
3198                     par.mfx.CodecLevel = GetMaxSupportedLevel();
3199             }
3200         }
3201         else if (par.mfx.CodecLevel != 0 && par.mfx.CodecLevel < minLevel)
3202         {
3203             if (extBits->SPSBuffer)
3204                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3205 
3206             changed = true;
3207             par.mfx.CodecLevel = minLevel;
3208         }
3209     }
3210 
3211     if (!IsOff(extOpt3->TimingInfoPresent)  &&
3212         par.mfx.FrameInfo.Width         != 0 &&
3213         par.mfx.FrameInfo.Height        != 0 &&
3214         par.mfx.FrameInfo.FrameRateExtN != 0 &&
3215         par.mfx.FrameInfo.FrameRateExtD != 0)
3216     {
3217         mfxU16 minLevel = GetLevelLimitByMbps(par);
3218         if (minLevel == 0)
3219         {
3220             if (extBits->SPSBuffer)
3221             {
3222                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3223             }
3224             else if (par.mfx.CodecLevel != 0)
3225             {
3226                 changed = true; // warning should be returned if MB processing rate exceeds maximum value supported by AVC standard
3227                 if (par.mfx.CodecLevel < GetMaxSupportedLevel())
3228                     par.mfx.CodecLevel = GetMaxSupportedLevel();
3229             }
3230         }
3231         else if (par.mfx.CodecLevel != 0 && par.mfx.CodecLevel < minLevel)
3232         {
3233             if (extBits->SPSBuffer)
3234                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3235 
3236             changed = true;
3237             par.mfx.CodecLevel = minLevel;
3238         }
3239     }
3240 
3241     if (par.mfx.NumRefFrame      != 0 &&
3242         par.mfx.FrameInfo.Width  != 0 &&
3243         par.mfx.FrameInfo.Height != 0)
3244     {
3245         mfxU16 minLevel = GetLevelLimitByDpbSize(par);
3246         if (minLevel == 0)
3247         {
3248             if (extBits->SPSBuffer)
3249                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3250 
3251             changed = false;
3252             par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3253             par.mfx.NumRefFrame = GetMaxNumRefFrame(par);
3254         }
3255         else if (par.mfx.CodecLevel != 0 && par.mfx.CodecLevel < minLevel)
3256         {
3257             if (extBits->SPSBuffer)
3258                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3259 
3260             changed = false;
3261             par.mfx.CodecLevel = minLevel;
3262         }
3263     }
3264 
3265     if (IsAvcHighProfile(par.mfx.CodecProfile) && (par.mfx.CodecProfile & MASK_CONSTRAINT_SET0123_FLAG))
3266     {
3267         changed = true;
3268         par.mfx.CodecProfile = par.mfx.CodecProfile & ~MASK_CONSTRAINT_SET0123_FLAG;
3269     }
3270 
3271     if (!CheckTriStateOption(extOpt->RateDistortionOpt))        changed = true;
3272     if (!CheckTriStateOption(extOpt->EndOfSequence))            changed = true;
3273     if (!CheckTriStateOption(extOpt->FramePicture))             changed = true;
3274     if (!CheckTriStateOption(extOpt->CAVLC))                    changed = true;
3275     if (!CheckTriStateOption(extOpt->RefPicListReordering))     changed = true;
3276     if (!CheckTriStateOption(extOpt->ResetRefList))             changed = true;
3277     if (!CheckTriStateOption(extOpt->RefPicMarkRep))            changed = true;
3278     if (!CheckTriStateOption(extOpt->FieldOutput))              changed = true;
3279     if (!CheckTriStateOption(extOpt->AUDelimiter))              changed = true;
3280     if (!CheckTriStateOption(extOpt->EndOfStream))              changed = true;
3281     if (!CheckTriStateOption(extOpt->PicTimingSEI))             changed = true;
3282     if (!CheckTriStateOption(extOpt->SingleSeiNalUnit))         changed = true;
3283     if (!CheckTriStateOption(extOpt->NalHrdConformance))        changed = true;
3284     if (!CheckTriStateOption(extDdi->RefRaw))                   changed = true;
3285     if (!CheckTriStateOption(extDdi->DirectSpatialMvPredFlag))  changed = true;
3286     if (!CheckTriStateOption(extDdi->Hme))                      changed = true;
3287     if (!CheckTriStateOption(extOpt2->BitrateLimit))            changed = true;
3288     if (!CheckTriStateOption(extOpt2->MBBRC))                   changed = true;
3289     //if (!CheckTriStateOption(extOpt2->ExtBRC))                  changed = true;
3290     if (!CheckTriStateOption(extOpt2->RepeatPPS))               changed = true;
3291     if (!CheckTriStateOption(extOpt2->UseRawRef))               changed = true;
3292 
3293     if (!CheckTriStateOption(extOpt3->EnableQPOffset))              changed = true;
3294     if (!CheckTriStateOption(extOpt3->DirectBiasAdjustment))        changed = true;
3295     if (!CheckTriStateOption(extOpt3->GlobalMotionBiasAdjustment))  changed = true;
3296 
3297     if (   IsOn(extOpt3->EnableQPOffset)
3298         && (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP
3299             || (par.mfx.GopRefDist > 1 && extOpt2->BRefType == MFX_B_REF_OFF)
3300             || (par.mfx.GopRefDist == 1 && extOpt3->PRefType == MFX_P_REF_SIMPLE)))
3301     {
3302         extOpt3->EnableQPOffset = MFX_CODINGOPTION_OFF;
3303         changed = true;
3304     }
3305 
3306     if (IsOn(extOpt3->EnableQPOffset))
3307     {
3308         mfxU16 minQP = 1;
3309         mfxU16 maxQP = 51;
3310         mfxI16 QPX = (par.mfx.GopRefDist == 1) ? par.mfx.QPP : par.mfx.QPB;
3311 
3312         if (QPX)
3313         {
3314             for (mfxI16 i = 0; i < 8; i++)
3315                 if (!CheckRange(extOpt3->QPOffset[i], minQP - QPX, maxQP - QPX))
3316                     changed = true;
3317         }
3318     }
3319 
3320     if ((isENCPAK || vaType != MFX_HW_VAAPI)
3321         && (IsOn(extOpt3->DirectBiasAdjustment) || IsOn(extOpt3->GlobalMotionBiasAdjustment)))
3322     {
3323         changed = true;
3324         extOpt3->DirectBiasAdjustment       = MFX_CODINGOPTION_OFF;
3325         extOpt3->GlobalMotionBiasAdjustment = MFX_CODINGOPTION_OFF;
3326     }
3327 
3328     if (!CheckRangeDflt(extOpt3->MVCostScalingFactor, 0, 3, 0)) changed = true;
3329 
3330     if (extOpt3->MVCostScalingFactor && !IsOn(extOpt3->GlobalMotionBiasAdjustment))
3331     {
3332         changed = true;
3333         extOpt3->MVCostScalingFactor = 0;
3334     }
3335 
3336     if (extOpt2->BufferingPeriodSEI > MFX_BPSEI_IFRAME)
3337     {
3338         changed = true;
3339         extOpt2->BufferingPeriodSEI = 0;
3340     }
3341 
3342     if (IsMvcProfile(par.mfx.CodecProfile) && IsOn(extOpt->FieldOutput))
3343     {
3344         unsupported = true;
3345         extOpt->FieldOutput = MFX_CODINGOPTION_UNKNOWN;
3346     }
3347 
3348 
3349     if (par.mfx.RateControlMethod == MFX_RATECONTROL_VCM &&
3350         par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
3351     {
3352         changed = true;
3353         par.mfx.RateControlMethod = MFX_RATECONTROL_VBR;
3354     }
3355 
3356     if (hwCaps.ddi_caps.MBBRCSupport == 0 && hwCaps.ddi_caps.ICQBRCSupport == 0 && IsOn(extOpt2->MBBRC))
3357     {
3358         changed = true;
3359         extOpt2->MBBRC = MFX_CODINGOPTION_OFF;
3360     }
3361 
3362     if (extOpt2->BRefType > 2)
3363     {
3364         changed = true;
3365         extOpt2->BRefType = MFX_B_REF_UNKNOWN;
3366     }
3367 
3368     if (extOpt2->BRefType && extOpt2->BRefType != MFX_B_REF_OFF &&
3369         par.mfx.GopRefDist != 0 && par.mfx.GopRefDist < 3)
3370     {
3371         changed = true;
3372         extOpt2->BRefType = MFX_B_REF_OFF;
3373     }
3374 
3375     if (extOpt->IntraPredBlockSize != MFX_BLOCKSIZE_UNKNOWN &&
3376         extOpt->IntraPredBlockSize != MFX_BLOCKSIZE_MIN_16X16 &&
3377         extOpt->IntraPredBlockSize != MFX_BLOCKSIZE_MIN_8X8 &&
3378         extOpt->IntraPredBlockSize != MFX_BLOCKSIZE_MIN_4X4)
3379     {
3380         changed = true;
3381         extOpt->IntraPredBlockSize = MFX_BLOCKSIZE_UNKNOWN;
3382     }
3383 
3384     if (extOpt->InterPredBlockSize != MFX_BLOCKSIZE_UNKNOWN &&
3385         extOpt->InterPredBlockSize != MFX_BLOCKSIZE_MIN_16X16 &&
3386         extOpt->InterPredBlockSize != MFX_BLOCKSIZE_MIN_8X8 &&
3387         extOpt->InterPredBlockSize != MFX_BLOCKSIZE_MIN_4X4)
3388     {
3389         changed = true;
3390         extOpt->InterPredBlockSize = MFX_BLOCKSIZE_UNKNOWN;
3391     }
3392 
3393     if (extOpt->MVPrecision != MFX_MVPRECISION_UNKNOWN &&
3394         extOpt->MVPrecision != MFX_MVPRECISION_QUARTERPEL &&
3395         extOpt->MVPrecision != MFX_MVPRECISION_HALFPEL &&
3396         extOpt->MVPrecision != MFX_MVPRECISION_INTEGER)
3397     {
3398         changed = true;
3399         extOpt->MVPrecision = MFX_MVPRECISION_UNKNOWN;
3400     }
3401 
3402     if (extOpt->MaxDecFrameBuffering != 0)
3403     {
3404         if (par.mfx.CodecLevel       != 0 &&
3405             par.mfx.FrameInfo.Width  != 0 &&
3406             par.mfx.FrameInfo.Height != 0)
3407         {
3408             mfxU16 maxDpbSize = GetMaxNumRefFrame(par);
3409             if (extOpt->MaxDecFrameBuffering > maxDpbSize)
3410             {
3411                 if (extBits->SPSBuffer)
3412                     return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3413 
3414                 changed = true;
3415                 extOpt->MaxDecFrameBuffering = maxDpbSize;
3416             }
3417         }
3418 
3419         if (par.mfx.NumRefFrame != 0)
3420         {
3421             if (extOpt->MaxDecFrameBuffering < par.mfx.NumRefFrame)
3422             {
3423                 if (extBits->SPSBuffer)
3424                     return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3425 
3426                 changed = true;
3427                 extOpt->MaxDecFrameBuffering = par.mfx.NumRefFrame;
3428             }
3429         }
3430     }
3431 
3432     if ((IsOff(extOpt->CAVLC)) &&
3433         (IsAvcBaseProfile(par.mfx.CodecProfile) || hwCaps.ddi_caps.NoCabacSupport))
3434     {
3435         if (extBits->SPSBuffer)
3436             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3437 
3438         changed = true;
3439         extOpt->CAVLC = MFX_CODINGOPTION_ON;
3440     }
3441 
3442     if (extOpt->IntraPredBlockSize >= MFX_BLOCKSIZE_MIN_8X8)
3443     {
3444         if (IsAvcBaseProfile(par.mfx.CodecProfile) || par.mfx.CodecProfile == MFX_PROFILE_AVC_MAIN)
3445         {
3446             if (extBits->PPSBuffer && extPps->transform8x8ModeFlag)
3447                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3448 
3449             changed = true;
3450             extOpt->IntraPredBlockSize = MFX_BLOCKSIZE_MIN_16X16;
3451         }
3452     }
3453 
3454     if ((par.mfx.CodecProfile != MFX_PROFILE_UNKNOWN) && (par.mfx.CodecProfile != MFX_PROFILE_AVC_HIGH)
3455         && IsOn(extDdi->Transform8x8Mode))
3456     {
3457         unsupported = true;
3458         extDdi->Transform8x8Mode = MFX_CODINGOPTION_UNKNOWN;
3459     }
3460 
3461     if (par.calcParam.cqpHrdMode)
3462     {
3463         if (IsOn(extOpt->RecoveryPointSEI))
3464         {
3465             changed = true;
3466             extOpt->RecoveryPointSEI = MFX_CODINGOPTION_OFF;
3467         }
3468         if (IsOn(extOpt->PicTimingSEI))
3469         {
3470             changed = true;
3471             extOpt->PicTimingSEI = MFX_CODINGOPTION_OFF;
3472         }
3473         if (extOpt2->BufferingPeriodSEI != MFX_BPSEI_DEFAULT)
3474         {
3475             changed = true;
3476             extOpt2->BufferingPeriodSEI = MFX_BPSEI_DEFAULT;
3477         }
3478     }
3479 
3480     if ((IsOn(extOpt->VuiNalHrdParameters) ||IsOn(extOpt->NalHrdConformance)) &&
3481         par.mfx.RateControlMethod != 0 &&
3482         par.mfx.RateControlMethod != MFX_RATECONTROL_CBR &&
3483         par.mfx.RateControlMethod != MFX_RATECONTROL_VBR &&
3484         par.mfx.RateControlMethod != MFX_RATECONTROL_QVBR &&
3485         par.mfx.RateControlMethod != MFX_RATECONTROL_LA_HRD &&
3486         par.mfx.RateControlMethod != MFX_RATECONTROL_VCM &&
3487         par.calcParam.cqpHrdMode == 0)
3488     {
3489         changed = true;
3490         extOpt->NalHrdConformance = MFX_CODINGOPTION_OFF;
3491         extOpt->VuiNalHrdParameters = MFX_CODINGOPTION_OFF;
3492     }
3493 
3494     if (IsOn(extOpt->VuiNalHrdParameters)
3495         && IsOff(extOpt->NalHrdConformance)
3496         && par.calcParam.cqpHrdMode == 0)
3497     {
3498         changed = true;
3499         extOpt->VuiNalHrdParameters = MFX_CODINGOPTION_OFF;
3500     }
3501 
3502     if (IsOn(extOpt->VuiVclHrdParameters) &&
3503         IsOff(extOpt->NalHrdConformance))
3504     {
3505         changed = true;
3506         extOpt->VuiVclHrdParameters = MFX_CODINGOPTION_OFF;
3507     }
3508 
3509     if (IsOn(extOpt->VuiVclHrdParameters) &&
3510         par.mfx.RateControlMethod != 0 &&
3511         par.mfx.RateControlMethod != MFX_RATECONTROL_VBR &&
3512         par.mfx.RateControlMethod != MFX_RATECONTROL_QVBR)
3513     {
3514         changed = true;
3515         extOpt->VuiVclHrdParameters = MFX_CODINGOPTION_OFF;
3516     }
3517 
3518     if(IsOff(extOpt->VuiNalHrdParameters) &&
3519        IsOff(extOpt->VuiVclHrdParameters) &&
3520        IsOn(extOpt3->LowDelayHrd))
3521     {
3522         changed = true;
3523         extOpt3->LowDelayHrd = MFX_CODINGOPTION_OFF;
3524     }
3525 
3526     if (!IsOn(extOpt2->DisableVUI) &&
3527         IsOff(extOpt->VuiNalHrdParameters) &&
3528         IsOff(extOpt->VuiVclHrdParameters) &&
3529         extOpt2->FixedFrameRate != MFX_CODINGOPTION_UNKNOWN &&
3530         extOpt3->LowDelayHrd != MFX_CODINGOPTION_UNKNOWN &&
3531         IsOn(extOpt2->FixedFrameRate) != IsOff(extOpt3->LowDelayHrd))
3532     {
3533         // when low_delay_hrd_flag isn't present in bitstream, it's value should be inferred to be equal to 1 - fixed_frame_rate_flag (Annex E.2.1)
3534         changed = true;
3535         if (IsOn(extOpt2->FixedFrameRate))
3536             extOpt3->LowDelayHrd = MFX_CODINGOPTION_OFF;
3537     }
3538 
3539     if (extDdi->WeightedBiPredIdc > 2)
3540     {
3541         changed = true;
3542         extDdi->WeightedBiPredIdc = 0;
3543     }
3544 
3545     if (extDdi->CabacInitIdcPlus1 > 3)
3546     {
3547         changed = true;
3548         extDdi->CabacInitIdcPlus1 = 0;
3549     }
3550 
3551     if (bIntRateControlLA(par.mfx.RateControlMethod) &&
3552         !IsLookAheadSupported(par, platform))
3553     {
3554         unsupported = true;
3555         par.mfx.RateControlMethod = 0;
3556     }
3557 
3558     if (extOpt2->LookAheadDS > MFX_LOOKAHEAD_DS_4x)
3559     {
3560         extOpt2->LookAheadDS = MFX_LOOKAHEAD_DS_4x;
3561         changed = true;
3562     }
3563 
3564     if (extOpt2->LookAheadDS == MFX_LOOKAHEAD_DS_4x)
3565     {
3566         extOpt2->LookAheadDS = MFX_LOOKAHEAD_DS_2x;
3567         changed = true;
3568     }
3569 
3570     if (extOpt2->LookAheadDS > MFX_LOOKAHEAD_DS_OFF)
3571     {
3572         par.calcParam.widthLa  = mfx::align2_value((par.mfx.FrameInfo.Width  / LaDSenumToFactor(extOpt2->LookAheadDS)), 16);
3573         par.calcParam.heightLa = mfx::align2_value((par.mfx.FrameInfo.Height / LaDSenumToFactor(extOpt2->LookAheadDS)), 16);
3574     } else
3575     {
3576         par.calcParam.widthLa = par.mfx.FrameInfo.Width;
3577         par.calcParam.heightLa = par.mfx.FrameInfo.Height;
3578     }
3579 
3580     if (!CheckRangeDflt(extVsi->VideoFormat,             0,   8, 5)) changed = true;
3581     if (!CheckRangeDflt(extVsi->ColourPrimaries,         0, 255, 2)) changed = true;
3582     if (!CheckRangeDflt(extVsi->TransferCharacteristics, 0, 255, 2)) changed = true;
3583     if (!CheckRangeDflt(extVsi->MatrixCoefficients,      0, 255, 2)) changed = true;
3584     if (!CheckFlag(extVsi->VideoFullRange, 0))                       changed = true;
3585     if (!CheckFlag(extVsi->ColourDescriptionPresent, 0))             changed = true;
3586 
3587     if (!CheckRangeDflt(extCli->ChromaLocInfoPresentFlag,       0, 1, 0)) changed = true;
3588     if (!CheckRangeDflt(extCli->ChromaSampleLocTypeTopField,    0, 5, 0)) changed = true;
3589     if (!CheckRangeDflt(extCli->ChromaSampleLocTypeBottomField, 0, 5, 0)) changed = true;
3590 
3591     if (   (IsOn(extOpt2->DisableVUI) && extCli->ChromaLocInfoPresentFlag)
3592         || (!extCli->ChromaLocInfoPresentFlag && (extCli->ChromaSampleLocTypeTopField || extCli->ChromaSampleLocTypeBottomField)))
3593     {
3594         extCli->ChromaLocInfoPresentFlag       = 0;
3595         extCli->ChromaSampleLocTypeTopField    = 0;
3596         extCli->ChromaSampleLocTypeBottomField = 0;
3597         changed = true;
3598     }
3599 
3600     if (par.calcParam.cqpHrdMode == 0)
3601     {
3602         // regular check for compatibility of profile/level and BRC parameters
3603         if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP && par.calcParam.targetKbps != 0)
3604         {
3605             if (!IsOff(extOpt2->BitrateLimit)        &&
3606                 par.mfx.FrameInfo.Width         != 0 &&
3607                 par.mfx.FrameInfo.Height        != 0 &&
3608                 par.mfx.FrameInfo.FrameRateExtN != 0 &&
3609                 par.mfx.FrameInfo.FrameRateExtD != 0)
3610             {
3611                 mfxF64 rawDataBitrate = 12.0 * par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height *
3612                     par.mfx.FrameInfo.FrameRateExtN / par.mfx.FrameInfo.FrameRateExtD;
3613                 mfxU32 minTargetKbps = mfxU32(std::min<mfxF64>(0xffffffff, rawDataBitrate / 1000.0 / 700.0));
3614 
3615                 if (par.calcParam.targetKbps < minTargetKbps)
3616                 {
3617                     changed = true;
3618                     par.calcParam.targetKbps = minTargetKbps;
3619                 }
3620             }
3621 
3622             if ((!IsOff(extOpt->NalHrdConformance) && extBits->SPSBuffer == 0) || IsOn(extOpt->VuiNalHrdParameters) || IsOn(extOpt->VuiVclHrdParameters))
3623             {
3624                 mfxU16 profile = std::max<mfxU16>(MFX_PROFILE_AVC_BASELINE, par.mfx.CodecProfile & MASK_PROFILE_IDC);
3625                 for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
3626                 {
3627                     if (mfxU16 minLevel = GetLevelLimitByMaxBitrate(profile, par.calcParam.targetKbps))
3628                     {
3629                         if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0 && par.mfx.CodecLevel < minLevel)
3630                         {
3631                             if (extBits->SPSBuffer)
3632                                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3633 
3634                             changed = true;
3635                             par.mfx.CodecLevel   = minLevel;
3636                             par.mfx.CodecProfile = profile;
3637                         }
3638                         break;
3639                     }
3640                 }
3641 
3642                 if (profile == MFX_PROFILE_UNKNOWN)
3643                 {
3644                     if (extBits->SPSBuffer)
3645                         return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3646 
3647                     if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0)
3648                     {
3649                         par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
3650                         par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3651                     }
3652 
3653                     changed = true;
3654                     par.calcParam.targetKbps = GetMaxBitrate(par) / 1000;
3655                 }
3656             }
3657         }
3658 
3659         if (par.calcParam.targetKbps != 0 && par.calcParam.maxKbps != 0)
3660         {
3661             if (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR)
3662             {
3663                 if (par.calcParam.maxKbps != par.calcParam.targetKbps)
3664                 {
3665                     changed = true;
3666                     if (extBits->SPSBuffer && (
3667                         extSps->vui.flags.nalHrdParametersPresent ||
3668                         extSps->vui.flags.vclHrdParametersPresent))
3669                         par.calcParam.targetKbps = par.calcParam.maxKbps;
3670                     else
3671                         par.calcParam.maxKbps = par.calcParam.targetKbps;
3672                 }
3673             }
3674             else if (
3675                 par.mfx.RateControlMethod == MFX_RATECONTROL_VCM ||
3676                 par.mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
3677                 par.mfx.RateControlMethod == MFX_RATECONTROL_WIDI_VBR ||
3678                 par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR ||
3679                 par.mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD)
3680             {
3681                 if (par.calcParam.maxKbps < par.calcParam.targetKbps)
3682                 {
3683                     if (extBits->SPSBuffer && (
3684                         extSps->vui.flags.nalHrdParametersPresent ||
3685                         extSps->vui.flags.vclHrdParametersPresent))
3686                         return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3687 
3688                     changed = true;
3689                     par.calcParam.maxKbps = par.calcParam.targetKbps;
3690                 }
3691             }
3692         }
3693 
3694         if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP && par.calcParam.maxKbps != 0)
3695         {
3696             mfxU16 profile = std::max<mfxU16>(MFX_PROFILE_AVC_BASELINE, par.mfx.CodecProfile & MASK_PROFILE_IDC);
3697             for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
3698             {
3699                 if (mfxU16 minLevel = GetLevelLimitByMaxBitrate(profile, par.calcParam.maxKbps))
3700                 {
3701                     if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0 && par.mfx.CodecLevel < minLevel)
3702                     {
3703                         if (extBits->SPSBuffer)
3704                             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3705 
3706                         changed = true;
3707                         par.mfx.CodecLevel = minLevel;
3708                         par.mfx.CodecProfile = profile;
3709                     }
3710                     break;
3711                 }
3712             }
3713 
3714             if (profile == MFX_PROFILE_UNKNOWN)
3715             {
3716                 if (extBits->SPSBuffer)
3717                     return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3718 
3719                 if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0)
3720                 {
3721                     par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
3722                     par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3723                 }
3724 
3725                 changed = true;
3726                 par.calcParam.maxKbps = GetMaxBitrate(par) / 1000;
3727             }
3728         }
3729 
3730         if (par.calcParam.bufferSizeInKB != 0 && bRateControlLA(par.mfx.RateControlMethod) &&(par.mfx.RateControlMethod != MFX_RATECONTROL_LA_HRD))
3731         {
3732             mfxU32 uncompressedSizeInKb = GetMaxCodedFrameSizeInKB(par);
3733             if (par.calcParam.bufferSizeInKB < uncompressedSizeInKb)
3734             {
3735                 changed = true;
3736                 par.calcParam.bufferSizeInKB = uncompressedSizeInKb;
3737             }
3738         }
3739 
3740         if (par.calcParam.bufferSizeInKB != 0)
3741         {
3742             if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP)
3743             {
3744                 mfxU32 uncompressedSizeInKb = GetMaxCodedFrameSizeInKB(par);
3745                 if (par.calcParam.bufferSizeInKB < uncompressedSizeInKb)
3746                 {
3747                     changed = true;
3748                     par.calcParam.bufferSizeInKB = uncompressedSizeInKb;
3749                 }
3750             }
3751             else
3752             {
3753                 mfxF64 avgFrameSizeInKB = 0;
3754                 if (par.mfx.RateControlMethod       != MFX_RATECONTROL_AVBR &&
3755                     par.mfx.FrameInfo.FrameRateExtN != 0 &&
3756                     par.mfx.FrameInfo.FrameRateExtD != 0 &&
3757                     par.calcParam.targetKbps        != 0)
3758                 {
3759                     mfxF64 frameRate = mfxF64(par.mfx.FrameInfo.FrameRateExtN) / par.mfx.FrameInfo.FrameRateExtD;
3760                     avgFrameSizeInKB = par.calcParam.targetKbps / frameRate / 8;
3761 
3762                     if (par.calcParam.bufferSizeInKB < 2 * avgFrameSizeInKB)
3763                     {
3764                         if (extBits->SPSBuffer && (
3765                             extSps->vui.flags.nalHrdParametersPresent ||
3766                             extSps->vui.flags.vclHrdParametersPresent))
3767                             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3768 
3769                         changed = true;
3770                         par.calcParam.bufferSizeInKB = mfxU32(2 * avgFrameSizeInKB + 1);
3771                     }
3772                 }
3773 
3774                 mfxU16 profile = std::max<mfxU16>(MFX_PROFILE_AVC_BASELINE, par.mfx.CodecProfile & MASK_PROFILE_IDC);
3775                 for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
3776                 {
3777                     if (mfxU16 minLevel = GetLevelLimitByBufferSize(profile, par.calcParam.bufferSizeInKB))
3778                     {
3779                         if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0 && par.mfx.CodecLevel < minLevel)
3780                         {
3781                             if (extBits->SPSBuffer)
3782                                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3783 
3784                             changed = true;
3785                             par.mfx.CodecLevel = minLevel;
3786                         }
3787                         break;
3788                     }
3789                 }
3790 
3791                 if (profile == MFX_PROFILE_UNKNOWN)
3792                 {
3793                     if (extBits->SPSBuffer)
3794                         return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
3795 
3796                     if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0)
3797                     {
3798                         par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
3799                         par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3800                     }
3801 
3802                     changed = true;
3803                     par.calcParam.bufferSizeInKB = mfxU16(std::min<mfxU32>(GetMaxBufferSize(par) / 8000, USHRT_MAX));
3804                 }
3805 
3806                 if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP &&
3807                     par.mfx.RateControlMethod != MFX_RATECONTROL_AVBR &&
3808                     par.calcParam.initialDelayInKB != 0)
3809                 {
3810                     if (par.calcParam.initialDelayInKB >= par.calcParam.bufferSizeInKB)
3811                     {
3812                         changed = true;
3813                         par.calcParam.initialDelayInKB = par.calcParam.bufferSizeInKB / 2;
3814                     }
3815 
3816                     if (avgFrameSizeInKB > 0 && par.calcParam.initialDelayInKB < mfxU32(avgFrameSizeInKB))
3817                     {
3818                         changed = true;
3819                         par.calcParam.initialDelayInKB = std::min(par.calcParam.bufferSizeInKB, mfxU32(avgFrameSizeInKB));
3820                     }
3821                 }
3822             }
3823         }
3824     }
3825     else
3826     {
3827         // special check for compatibility of profile/level and BRC parameters for cqpHrdMode
3828         mfxU16 profile = std::max<mfxU16>(MFX_PROFILE_AVC_BASELINE, par.mfx.CodecProfile & MASK_PROFILE_IDC);
3829         for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
3830         {
3831             if (mfxU16 minLevel = GetLevelLimitByMaxBitrate(profile, par.calcParam.decorativeHrdParam.targetKbps))
3832             {
3833                 if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0 && par.mfx.CodecLevel < minLevel)
3834                 {
3835                     changed = true;
3836                     par.mfx.CodecLevel   = minLevel;
3837                     par.mfx.CodecProfile = profile;
3838                 }
3839                 break;
3840             }
3841 
3842             if (profile == MFX_PROFILE_UNKNOWN)
3843             {
3844                 if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0)
3845                 {
3846                     par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
3847                     par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3848                 }
3849             }
3850         }
3851 
3852         if (par.calcParam.decorativeHrdParam.maxKbps < par.calcParam.decorativeHrdParam.targetKbps)
3853         {
3854             changed = true;
3855             par.calcParam.decorativeHrdParam.maxKbps = par.calcParam.decorativeHrdParam.targetKbps;
3856         }
3857 
3858         profile = std::max<mfxU16>(MFX_PROFILE_AVC_BASELINE, par.mfx.CodecProfile & MASK_PROFILE_IDC);
3859         for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
3860         {
3861             if (mfxU16 minLevel = GetLevelLimitByMaxBitrate(profile, par.calcParam.decorativeHrdParam.maxKbps))
3862             {
3863                 if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0 && par.mfx.CodecLevel < minLevel)
3864                 {
3865                     changed = true;
3866                     par.mfx.CodecLevel = minLevel;
3867                     par.mfx.CodecProfile = profile;
3868                 }
3869                 break;
3870             }
3871         }
3872 
3873         if (profile == MFX_PROFILE_UNKNOWN)
3874         {
3875             if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0)
3876             {
3877                 par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
3878                 par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3879             }
3880         }
3881 
3882         profile = std::max<mfxU16>(MFX_PROFILE_AVC_BASELINE, par.mfx.CodecProfile & MASK_PROFILE_IDC);
3883         for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
3884         {
3885             if (mfxU16 minLevel = GetLevelLimitByBufferSize(profile, par.calcParam.decorativeHrdParam.bufferSizeInKB))
3886             {
3887                 if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0 && par.mfx.CodecLevel < minLevel)
3888                 {
3889                     changed = true;
3890                     par.mfx.CodecLevel = minLevel;
3891                 }
3892                 break;
3893             }
3894         }
3895 
3896         if (profile == MFX_PROFILE_UNKNOWN)
3897         {
3898             if (par.mfx.CodecLevel != 0 && par.mfx.CodecProfile != 0)
3899             {
3900                 par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
3901                 par.mfx.CodecLevel = MFX_LEVEL_AVC_52;
3902             }
3903             changed = true;
3904 
3905         }
3906 
3907         if (par.calcParam.decorativeHrdParam.initialDelayInKB > par.calcParam.decorativeHrdParam.bufferSizeInKB)
3908         {
3909             changed = true;
3910             par.calcParam.decorativeHrdParam.initialDelayInKB = par.calcParam.decorativeHrdParam.bufferSizeInKB / 2;
3911         }
3912     }
3913 
3914     mfxStatus sts = CheckMaxFrameSize(par, hwCaps);
3915     if (sts == MFX_ERR_UNSUPPORTED)
3916         unsupported = true;
3917     else if (sts == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM)
3918         changed = true;
3919 #if defined(MFX_ENABLE_ENCTOOLS)
3920     if (H264EncTools::isEncToolNeeded(par))
3921     {
3922         sts = H264EncTools::Query(par);
3923         if (sts == MFX_ERR_UNSUPPORTED)
3924             unsupported = true;
3925         else if (sts == MFX_WRN_INCOMPATIBLE_VIDEO_PARAM)
3926             changed = true;
3927     }
3928 #endif
3929     if (IsOn(extOpt2->ExtBRC) && par.mfx.RateControlMethod != 0 && par.mfx.RateControlMethod !=MFX_RATECONTROL_CBR && par.mfx.RateControlMethod !=MFX_RATECONTROL_VBR)
3930     {
3931         extOpt2->ExtBRC = MFX_CODINGOPTION_OFF;
3932         changed = true;
3933     }
3934 
3935     if ((!IsOn(extOpt2->ExtBRC)) && (extBRC->pthis || extBRC->Init || extBRC->Close || extBRC->GetFrameCtrl || extBRC->Update || extBRC->Reset) )
3936     {
3937         extBRC->pthis = 0;
3938         extBRC->Init = 0;
3939         extBRC->Close = 0;
3940         extBRC->GetFrameCtrl = 0;
3941         extBRC->Update = 0;
3942         extBRC->Reset = 0;
3943         changed = true;
3944     }
3945     if ((extBRC->pthis  || extBRC->Init || extBRC->Close   || extBRC->GetFrameCtrl  || extBRC->Update  || extBRC->Reset) &&
3946         (!extBRC->pthis || !extBRC->Init || !extBRC->Close || !extBRC->GetFrameCtrl || !extBRC->Update || !extBRC->Reset))
3947     {
3948         extOpt2->ExtBRC = 0;
3949         extBRC->pthis = 0;
3950         extBRC->Init = 0;
3951         extBRC->Close = 0;
3952         extBRC->GetFrameCtrl = 0;
3953         extBRC->Update = 0;
3954         extBRC->Reset = 0;
3955         changed = true;
3956     }
3957 
3958 
3959     if (par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
3960     {
3961         if (par.mfx.CodecLevel != 0 && par.mfx.CodecLevel < MFX_LEVEL_AVC_21)
3962         {
3963             if (extBits->SPSBuffer) // level came from sps header, override picstruct
3964                 par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
3965             else // level came from videoparam, override level
3966                 par.mfx.CodecLevel = MFX_LEVEL_AVC_21;
3967             changed = true;
3968         }
3969 
3970         mfxU16 levelToCheck = par.mfx.CodecLevel;
3971 
3972         if (levelToCheck == 0)
3973             levelToCheck = GetMinLevelForAllParameters(par);
3974 
3975         if (levelToCheck > MFX_LEVEL_AVC_41)
3976         {
3977             if (GetMinLevelForResolutionAndFramerate(par) <= MFX_LEVEL_AVC_41)
3978             {
3979                 // it's possible to encode stream with level lower than 4.2
3980                 // correct encoding parameters to satisfy H264 spec (table A-4, frame_mbs_only_flag)
3981                 changed = true;
3982                 par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
3983             }
3984             else
3985             {
3986                 // it's impossible to encode stream with level lower than 4.2
3987                 // allow H264 spec violation ((table A-4, frame_mbs_only_flag)) and return warning
3988                 warning = true;
3989             }
3990         }
3991     }
3992 
3993     if (par.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_PROGRESSIVE)
3994     {
3995         if (IsAvcBaseProfile(par.mfx.CodecProfile) ||
3996             par.mfx.CodecProfile == MFX_PROFILE_AVC_PROGRESSIVE_HIGH ||
3997             par.mfx.CodecProfile == MFX_PROFILE_AVC_CONSTRAINED_HIGH)
3998         {
3999             changed = true;
4000             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
4001         }
4002     }
4003 
4004     if ((par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0 && par.mfx.NumRefFrame == 1)
4005     {
4006         par.mfx.NumRefFrame ++; // HSW and IVB don't support 1 reference frame for interlaced encoding
4007         changed = true;
4008     }
4009 
4010     if (IsOn(extOpt->FieldOutput))
4011     {
4012         if (par.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE || IsOn(extOpt->FramePicture))
4013         {
4014             changed = true;
4015             extOpt->FieldOutput = MFX_CODINGOPTION_OFF;
4016         }
4017     }
4018 
4019     if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP
4020         && par.calcParam.cqpHrdMode == 0)
4021     {
4022         if (!CheckRange(par.mfx.QPI, 0, 51)) changed = true;
4023         if (!CheckRange(par.mfx.QPP, 0, 51)) changed = true;
4024         if (!CheckRange(par.mfx.QPB, 0, 51)) changed = true;
4025     }
4026 
4027     if (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR &&
4028         hwCaps.CBRSupport == 0)
4029     {
4030         par.mfx.RateControlMethod = 0;
4031         unsupported = true;
4032     }
4033 
4034     if (par.mfx.RateControlMethod == MFX_RATECONTROL_VBR &&
4035         hwCaps.VBRSupport == 0)
4036     {
4037         par.mfx.RateControlMethod = 0;
4038         unsupported = true;
4039     }
4040 
4041     if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP &&
4042         hwCaps.CQPSupport == 0)
4043     {
4044         par.mfx.RateControlMethod = 0;
4045         unsupported = true;
4046     }
4047 
4048     if (par.mfx.RateControlMethod == MFX_RATECONTROL_ICQ &&
4049         hwCaps.ddi_caps.ICQBRCSupport == 0)
4050     {
4051         par.mfx.RateControlMethod = 0;
4052         unsupported = true;
4053     }
4054 
4055     if (par.mfx.RateControlMethod == MFX_RATECONTROL_VCM &&
4056         hwCaps.ddi_caps.VCMBitrateControl == 0)
4057     {
4058         par.mfx.RateControlMethod = 0;
4059         unsupported = true;
4060     }
4061 
4062     if (par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR &&
4063         hwCaps.ddi_caps.QVBRBRCSupport == 0)
4064     {
4065         par.mfx.RateControlMethod = 0;
4066         unsupported = true;
4067     }
4068 
4069     if (par.mfx.RateControlMethod == MFX_RATECONTROL_AVBR &&
4070         hwCaps.AVBRSupport == 0)
4071     {
4072         par.mfx.RateControlMethod = 0;
4073         unsupported = true;
4074     }
4075 
4076     if ( ((par.mfx.RateControlMethod == MFX_RATECONTROL_ICQ) || (par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)) &&
4077          (extOpt2->MBBRC == MFX_CODINGOPTION_OFF) )
4078     {
4079         // for ICQ or QVBR BRC mode MBBRC is ignored by driver and always treated as ON
4080         // need to change extOpt2->MBBRC respectively to notify application about it
4081         extOpt2->MBBRC = MFX_CODINGOPTION_ON;
4082         changed = true;
4083     }
4084 
4085     if (par.mfx.RateControlMethod == MFX_RATECONTROL_ICQ ||
4086         par.mfx.RateControlMethod == MFX_RATECONTROL_LA_ICQ)
4087     {
4088         if (!CheckRange(par.mfx.ICQQuality, 0, 51)) changed = true;
4089     }
4090 
4091     if (par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
4092     {
4093         if (!CheckRange(extOpt3->QVBRQuality, 0, 51)) changed = true;
4094     }
4095 
4096     if (par.mfx.RateControlMethod == MFX_RATECONTROL_AVBR)
4097     {
4098         if (!CheckRange(par.mfx.Accuracy,    AVBR_ACCURACY_MIN,    AVBR_ACCURACY_MAX))    changed = true;
4099         if (!CheckRange(par.mfx.Convergence, AVBR_CONVERGENCE_MIN, AVBR_CONVERGENCE_MAX)) changed = true;
4100     }
4101 
4102     for (mfxU32 i = 0; i < 3; i++)
4103     {
4104         mfxU32 maxTimeOffset = (1 << 24) - 1;
4105 
4106         mfxU32 maxNFrames = (par.mfx.FrameInfo.FrameRateExtN > 0 && par.mfx.FrameInfo.FrameRateExtD > 0)
4107             ? (par.mfx.FrameInfo.FrameRateExtN - 1) / par.mfx.FrameInfo.FrameRateExtD
4108             : 255;
4109 
4110         if (extPt->TimeStamp[i].CtType != 0xffff)
4111         {
4112             if (!CheckRangeDflt(extPt->TimeStamp[i].CtType, 0, 3, 2))
4113                 changed = true;
4114         }
4115 
4116         if (!CheckRangeDflt(extPt->TimeStamp[i].CountingType, 0, 31, 0))    changed = true;
4117         if (!CheckRange(extPt->TimeStamp[i].NFrames, 0u, maxNFrames))       changed = true;
4118         if (!CheckRange(extPt->TimeStamp[i].SecondsValue, 0, 59))           changed = true;
4119         if (!CheckRange(extPt->TimeStamp[i].MinutesValue, 0, 59))           changed = true;
4120         if (!CheckRange(extPt->TimeStamp[i].HoursValue, 0, 23))             changed = true;
4121         if (!CheckRange(extPt->TimeStamp[i].TimeOffset, 0u, maxTimeOffset)) changed = true;
4122         if (!CheckFlag (extPt->TimeStamp[i].ClockTimestampFlag, 0))         changed = true;
4123         if (!CheckFlag (extPt->TimeStamp[i].NuitFieldBasedFlag, 1))         changed = true;
4124         if (!CheckFlag (extPt->TimeStamp[i].FullTimestampFlag, 1))          changed = true;
4125         if (!CheckFlag (extPt->TimeStamp[i].DiscontinuityFlag, 0))          changed = true;
4126         if (!CheckFlag (extPt->TimeStamp[i].CntDroppedFlag, 0))             changed = true;
4127         if (!CheckFlag (extPt->TimeStamp[i].SecondsFlag, 0))                changed = true;
4128         if (!CheckFlag (extPt->TimeStamp[i].MinutesFlag, 0))                changed = true;
4129         if (!CheckFlag (extPt->TimeStamp[i].HoursFlag, 0))                  changed = true;
4130     }
4131 
4132     if (!CheckRangeDflt(extBits->SPSId, 0,  31, 0)) changed = true;
4133     if (!CheckRangeDflt(extBits->PPSId, 0, 255, 0)) changed = true;
4134 
4135     if (extBits->SPSBuffer)
4136     {
4137         if (extSps->seqParameterSetId > 31                                  ||
4138             !IsValidCodingProfile(extSps->profileIdc)                       ||
4139             !IsValidCodingLevel(extSps->levelIdc)                           ||
4140             extSps->chromaFormatIdc != 1                                    ||
4141             extSps->bitDepthLumaMinus8 != 0                                 ||
4142             extSps->bitDepthChromaMinus8 != 0                               ||
4143             extSps->qpprimeYZeroTransformBypassFlag != 0                    ||
4144             extSps->seqScalingMatrixPresentFlag != 0                        ||
4145             extSps->picOrderCntType == 1                                    ||
4146             /*extSps->gapsInFrameNumValueAllowedFlag != 0                     ||*/
4147             extSps->mbAdaptiveFrameFieldFlag != 0                           ||
4148             extSps->vui.flags.vclHrdParametersPresent != 0                  ||
4149             extSps->vui.nalHrdParameters.cpbCntMinus1 > 0                   ||
4150             extSps->vui.numReorderFrames > extSps->vui.maxDecFrameBuffering)
4151             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
4152 
4153         // the following fields aren't supported by snb/ivb_win7 drivers directly and requires sps patching
4154         // patching is not possible whe protection is on
4155         if (par.Protected != 0)
4156             if (extSps->nalRefIdc        != 1 ||
4157                 extSps->constraints.set0 != 0 ||
4158                 extSps->constraints.set1 != 0 ||
4159                 extSps->constraints.set2 != 0 ||
4160                 extSps->constraints.set3 != 0 ||
4161                 extSps->constraints.set4 != 0 ||
4162                 extSps->constraints.set5 != 0 ||
4163                 extSps->constraints.set6 != 0 ||
4164                 extSps->constraints.set7 != 0)
4165                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
4166 
4167         if (extBits->PPSBuffer)
4168         {
4169             if (extPps->seqParameterSetId != extSps->seqParameterSetId ||
4170                 extPps->numSliceGroupsMinus1 > 0                       ||
4171                 extPps->numRefIdxL0DefaultActiveMinus1 > 31            ||
4172                 extPps->numRefIdxL1DefaultActiveMinus1 > 31            ||
4173                 //Check of weightedPredFlag is actually not needed, as it was read from 1 bit in extBits->PPSBuffer
4174                 extPps->weightedPredFlag > 1                           ||
4175                 extPps->weightedBipredIdc > 2                          ||
4176                 extPps->picInitQpMinus26 < -26                         ||
4177                 extPps->picInitQpMinus26 > 25                          ||
4178                 extPps->picInitQsMinus26 != 0                          ||
4179                 extPps->chromaQpIndexOffset < -12                      ||
4180                 extPps->chromaQpIndexOffset > 12                       ||
4181                 extPps->deblockingFilterControlPresentFlag == 0        ||
4182                 extPps->redundantPicCntPresentFlag != 0                ||
4183                 extPps->picScalingMatrixPresentFlag != 0               ||
4184                 extPps->secondChromaQpIndexOffset < -12                ||
4185                 extPps->secondChromaQpIndexOffset > 12)
4186                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
4187 
4188             // the following fields aren't supported by snb/ivb_win7 drivers directlyand requires pps patching
4189             // patching is not possible whe protection is on
4190             if (par.Protected != 0)
4191                 if (extSps->nalRefIdc != 1)
4192                     return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
4193         }
4194     }
4195 
4196 #if (MFX_VERSION >= 1026)
4197     if (!CheckTriStateOption(extOpt3->ExtBrcAdaptiveLTR)) changed = true;
4198 
4199     if (IsOn(extOpt3->ExtBrcAdaptiveLTR) && IsOff(extOpt2->ExtBRC))
4200     {
4201         extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
4202         changed = true;
4203     }
4204 
4205     if (IsOn(extOpt3->ExtBrcAdaptiveLTR) && par.mfx.RateControlMethod != 0 && par.mfx.RateControlMethod != MFX_RATECONTROL_CBR && par.mfx.RateControlMethod != MFX_RATECONTROL_VBR)
4206     {
4207         extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
4208         changed = true;
4209     }
4210 
4211     if (IsOn(extOpt3->ExtBrcAdaptiveLTR) && (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0)
4212     {
4213         extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
4214         changed = true;
4215     }
4216 
4217     if (IsOn(extOpt3->ExtBrcAdaptiveLTR) && par.mfx.NumRefFrame != 0)
4218     {
4219         mfxU16 nrfMin = (par.mfx.GopRefDist > 1 ? 2 : 1);
4220         bool bPyr = (extOpt2->BRefType == MFX_B_REF_PYRAMID);
4221         if (bPyr) nrfMin = GetMinNumRefFrameForPyramid(par);
4222 
4223         if (par.mfx.NumRefFrame <= nrfMin)
4224         {
4225             extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
4226             changed = true;
4227         }
4228     }
4229 
4230     if (IsOn(extOpt3->ExtBrcAdaptiveLTR) && extDdi->NumActiveRefP != 0)
4231     {
4232         if (extDdi->NumActiveRefP <= 1)
4233         {
4234             extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
4235             changed = true;
4236         }
4237     }
4238 #endif // (MFX_VERSION >= 1026)
4239 
4240     if (IsMvcProfile(par.mfx.CodecProfile) && MFX_ERR_UNSUPPORTED == CheckMVCSeqDescQueryLike(extMvc))
4241     {
4242         unsupported = true;
4243     }
4244 
4245     par.SyncCalculableToVideoParam();
4246     par.AlignCalcWithBRCParamMultiplier();
4247 
4248     if (par.calcParam.numTemporalLayer > 0 && par.mfx.EncodedOrder != 0)
4249     {
4250         changed = true;
4251         memset(extTemp->Layer, 0, sizeof(extTemp->Layer)); // unnamed structures can't be used in templates
4252         Zero(par.calcParam.scale);
4253         Zero(par.calcParam.tid);
4254         par.calcParam.numTemporalLayer = 0;
4255         par.calcParam.tempScalabilityMode = 0;
4256     }
4257 
4258     if (par.calcParam.tempScalabilityMode && par.mfx.GopRefDist > 1)
4259     {
4260         changed = true;
4261         par.mfx.GopRefDist = 1;
4262     }
4263 
4264     if (par.mfx.RateControlMethod == MFX_RATECONTROL_VCM && par.mfx.GopRefDist > 1)
4265     {
4266         changed = true;
4267         par.mfx.GopRefDist = 1;
4268     }
4269 
4270     if (extTemp->BaseLayerPID + par.calcParam.numTemporalLayer > 64)
4271     {
4272         unsupported = true;
4273         extTemp->BaseLayerPID = 0;
4274     }
4275 
4276     if (par.calcParam.numTemporalLayer > 0 &&
4277         IsAvcProfile(par.mfx.CodecProfile) &&
4278         extTemp->Layer[0].Scale != 1)
4279     {
4280         unsupported = true;
4281         extTemp->Layer[0].Scale = 0;
4282     }
4283 
4284     for (mfxU32 i = 1; i < par.calcParam.numTemporalLayer; i++)
4285     {
4286         if (par.calcParam.scale[i] <= par.calcParam.scale[i - 1] || // increasing
4287             par.calcParam.scale[i] %  par.calcParam.scale[i - 1])   // divisible
4288         {
4289             unsupported = true;
4290             extTemp->Layer[par.calcParam.tid[i]].Scale = 0;
4291         }
4292 
4293         if (par.calcParam.tempScalabilityMode &&
4294             par.calcParam.scale[i] != par.calcParam.scale[i - 1] * 2)
4295         {
4296             unsupported = true;
4297             extTemp->Layer[par.calcParam.tid[i]].Scale = 0;
4298         }
4299     }
4300 
4301 
4302     if (extOpt2->IntRefType > 3 || (extOpt2->IntRefType && hwCaps.ddi_caps.RollingIntraRefresh == 0))
4303     {
4304         extOpt2->IntRefType = 0;
4305         unsupported = true;
4306     }
4307     if((extOpt2->IntRefType >= 2) &&
4308         (platform < MFX_HW_BDW))
4309     {
4310         extOpt2->IntRefType = 0;
4311         unsupported = true;
4312     }
4313 
4314     if (!hasSupportVME(platform) &&
4315         (extOpt2->IntRefType > MFX_REFRESH_HORIZONTAL))
4316     {
4317         extOpt2->IntRefType = MFX_REFRESH_HORIZONTAL;
4318         changed = true;
4319     }
4320 
4321     if (extOpt2->IntRefType && par.mfx.GopRefDist > 1)
4322     {
4323         extOpt2->IntRefType = 0;
4324         changed = true;
4325     }
4326 
4327     if (extOpt2->IntRefType && par.mfx.NumRefFrame > 1 && par.calcParam.tempScalabilityMode == 0)
4328     {
4329         extOpt2->IntRefType = 0;
4330         changed = true;
4331     }
4332 
4333     if (extOpt2->IntRefType && par.calcParam.numTemporalLayer && par.calcParam.tempScalabilityMode == 0)
4334     {
4335         extOpt2->IntRefType = 0;
4336         changed = true;
4337     }
4338 
4339     if (extOpt2->IntRefQPDelta < -51 || extOpt2->IntRefQPDelta > 51)
4340     {
4341         extOpt2->IntRefQPDelta = 0;
4342         changed = true;
4343     }
4344 
4345     if (extOpt2->IntRefCycleSize != 0 &&
4346         par.mfx.GopPicSize != 0 &&
4347         extOpt2->IntRefCycleSize >= par.mfx.GopPicSize)
4348     {
4349         // refresh cycle length shouldn't be greater or equal to GOP size
4350         extOpt2->IntRefType = 0;
4351         extOpt2->IntRefCycleSize = 0;
4352         changed = true;
4353     }
4354 
4355     if (extOpt3->IntRefCycleDist != 0 &&
4356         par.mfx.GopPicSize != 0 &&
4357         extOpt3->IntRefCycleDist >= par.mfx.GopPicSize)
4358     {
4359         // refresh period length shouldn't be greater or equal to GOP size
4360         extOpt2->IntRefType = 0;
4361         extOpt3->IntRefCycleDist = 0;
4362         changed = true;
4363     }
4364 
4365     if (extOpt3->IntRefCycleDist != 0 &&
4366         extOpt2->IntRefCycleSize != 0 &&
4367         extOpt2->IntRefCycleSize > extOpt3->IntRefCycleDist)
4368     {
4369         // refresh period shouldn't be greater than refresh cycle size
4370         extOpt3->IntRefCycleDist = 0;
4371         changed = true;
4372     }
4373 
4374     if (extOpt2->IntRefType == MFX_REFRESH_SLICE)
4375     {
4376         if (extOpt2->IntRefCycleSize && !extOpt3->NumSliceP && !par.mfx.NumSlice)
4377         {
4378             extOpt2->IntRefType = MFX_REFRESH_HORIZONTAL;
4379             changed = true;
4380         }
4381         if (extOpt2->IntRefCycleSize && extOpt3->NumSliceP && (extOpt2->IntRefCycleSize != extOpt3->NumSliceP))
4382         {
4383             extOpt2->IntRefCycleSize = extOpt3->NumSliceP;
4384             changed = true;
4385         }
4386         if ((extOpt3->NumSliceP != 0) && (par.mfx.GopPicSize != 0) && (extOpt3->NumSliceP > par.mfx.GopPicSize))
4387         {
4388             extOpt2->IntRefType = 0;
4389             changed = true;
4390         }
4391         if ((extOpt3->IntRefCycleDist != 0) && (extOpt3->NumSliceP != 0) && (extOpt3->NumSliceP > extOpt3->IntRefCycleDist))
4392         {
4393             // refresh period shouldn't be greater than refresh cycle size
4394             extOpt3->IntRefCycleDist = 0;
4395             changed = true;
4396         }
4397         if ((extOpt2->MaxSliceSize) || (extOpt2->NumMbPerSlice) || (!sliceRowAlligned))
4398         {
4399             extOpt2->IntRefType = 0;
4400             extOpt2->IntRefCycleSize = 0;
4401             unsupported = true;
4402         }
4403     }
4404 
4405     if (extOpt2->Trellis & ~(MFX_TRELLIS_OFF | MFX_TRELLIS_I | MFX_TRELLIS_P | MFX_TRELLIS_B))
4406     {
4407         extOpt2->Trellis &= (MFX_TRELLIS_OFF | MFX_TRELLIS_I | MFX_TRELLIS_P | MFX_TRELLIS_B);
4408         changed = true;
4409     }
4410 
4411     if ((extOpt2->Trellis & MFX_TRELLIS_OFF) && (extOpt2->Trellis & ~MFX_TRELLIS_OFF))
4412     {
4413         extOpt2->Trellis = MFX_TRELLIS_OFF;
4414         changed = true;
4415     }
4416 
4417 
4418     /*if (extOpt2->Trellis && hwCaps.EnhancedEncInput == 0)
4419     {
4420         extOpt2->Trellis = 0;
4421         unsupported = true;
4422     }*/
4423 
4424     if (extOpt2->BRefType        != 0 &&
4425         extOpt2->BRefType        != MFX_B_REF_OFF &&
4426         par.mfx.CodecLevel       != 0 &&
4427         par.mfx.FrameInfo.Width  != 0 &&
4428         par.mfx.FrameInfo.Height != 0)
4429     {
4430         const mfxU16 nfxMaxByLevel    = GetMaxNumRefFrame(par);
4431         const mfxU16 nfxMinForPyramid = GetMinNumRefFrameForPyramid(par);
4432 
4433         if (nfxMinForPyramid > nfxMaxByLevel)
4434         {
4435             // max dpb size is not enougn for pyramid
4436             changed = true;
4437             extOpt2->BRefType = MFX_B_REF_OFF;
4438         }
4439         else
4440         {
4441             if (par.mfx.NumRefFrame != 0 &&
4442                 par.mfx.NumRefFrame < nfxMinForPyramid)
4443             {
4444                 changed = true;
4445                 par.mfx.NumRefFrame = nfxMinForPyramid;
4446             }
4447         }
4448     }
4449 
4450     if (par.calcParam.numTemporalLayer >  1 &&
4451         par.mfx.CodecLevel             != 0 &&
4452         par.mfx.FrameInfo.Width        != 0 &&
4453         par.mfx.FrameInfo.Height       != 0)
4454     {
4455         mfxU16 const nrfMaxByLevel     = GetMaxNumRefFrame(par);
4456         mfxU16 const nrfMinForTemporal = mfxU16(1 << (par.calcParam.numTemporalLayer - 2));
4457 
4458         if (nrfMinForTemporal > nrfMaxByLevel)
4459         {
4460             // max dpb size is not enougn for requested number of temporal layers
4461             changed = true;
4462             par.calcParam.numTemporalLayer = 1;
4463         }
4464         else
4465         {
4466             if (par.mfx.NumRefFrame != 0 &&
4467                 par.mfx.NumRefFrame < nrfMinForTemporal)
4468             {
4469                 changed = true;
4470                 par.mfx.NumRefFrame = nrfMinForTemporal;
4471             }
4472         }
4473     }
4474 
4475     if (extRoi->NumROI && extRoi->ROIMode != MFX_ROI_MODE_QP_DELTA && extRoi->ROIMode != MFX_ROI_MODE_PRIORITY)
4476     {
4477         unsupported = true;
4478         extRoi->NumROI = 0;
4479     }
4480 
4481     if (extRoi->NumROI && hwCaps.ddi_caps.ROIBRCDeltaQPLevelSupport == 0)
4482     {
4483         unsupported = true;
4484         extRoi->NumROI = 0;
4485     }
4486 
4487     if (extRoi->NumROI)
4488     {
4489         if (extRoi->NumROI > hwCaps.ddi_caps.MaxNumOfROI)
4490         {
4491             if (hwCaps.ddi_caps.MaxNumOfROI == 0)
4492                 unsupported = true;
4493             else
4494                 changed = true;
4495 
4496             extRoi->NumROI = hwCaps.ddi_caps.MaxNumOfROI;
4497         }
4498     }
4499 
4500     for (mfxU16 i = 0; i < extRoi->NumROI; i++)
4501     {
4502         sts = CheckAndFixRoiQueryLike(par, (mfxRoiDesc*)(&(extRoi->ROI[i])), extRoi->ROIMode);
4503         if (sts < MFX_ERR_NONE)
4504             unsupported = true;
4505         else if (sts != MFX_ERR_NONE)
4506             changed = true;
4507     }
4508 
4509     if (extDirtyRect->NumRect > MFX_MAX_DIRTY_RECT_COUNT)
4510     {
4511         changed = true;
4512         extDirtyRect->NumRect = MFX_MAX_DIRTY_RECT_COUNT;
4513     }
4514 
4515     if (extDirtyRect->NumRect && hwCaps.ddi_caps.DirtyRectSupport == 0)
4516     {
4517         unsupported = true;
4518         extDirtyRect->NumRect = 0;
4519     }
4520 
4521     for (mfxU16 i = 0; i < extDirtyRect->NumRect; i++)
4522     {
4523         sts = CheckAndFixRectQueryLike(par, (mfxRectDesc*)(&(extDirtyRect->Rect[i])));
4524         if (sts < MFX_ERR_NONE)
4525             unsupported = true;
4526         else if (sts != MFX_ERR_NONE)
4527             changed = true;
4528     }
4529 
4530     if (extMoveRect->NumRect > MFX_MAX_MOVE_RECT_COUNT)
4531     {
4532         changed = true;
4533         extMoveRect->NumRect = MFX_MAX_MOVE_RECT_COUNT;
4534     }
4535 
4536     if (extMoveRect->NumRect && hwCaps.ddi_caps.MoveRectSupport == 0)
4537     {
4538         unsupported = true;
4539         extMoveRect->NumRect = 0;
4540     }
4541 
4542     for (mfxU16 i = 0; i < extMoveRect->NumRect; i++)
4543     {
4544         sts = CheckAndFixMovingRectQueryLike(par, (mfxMovingRectDesc*)(&(extMoveRect->Rect[i])));
4545         if (sts < MFX_ERR_NONE)
4546             unsupported = true;
4547         else if (sts != MFX_ERR_NONE)
4548             changed = true;
4549     }
4550 
4551     if (extPwt)
4552     {
4553         mfxU16 maxLuma[2] = {0};
4554         mfxU16 maxChroma[2] = {0};
4555         bool out_of_caps = false;
4556         if (0 == hwCaps.ddi_caps.NoWeightedPred)
4557         {
4558 // On linux, WP is FEI specific feature. So when legay encoder calls Query(), do not
4559 // enable the flag of this capability.
4560 #if defined (MFX_VA_LINUX)
4561             if (isENCPAK)
4562             {
4563 #endif
4564             if (hwCaps.ddi_caps.LumaWeightedPred)
4565             {
4566                 maxLuma[0] = std::min<mfxU16>(hwCaps.ddi_caps.MaxNum_WeightedPredL0, 32);
4567                 maxLuma[1] = std::min<mfxU16>(hwCaps.ddi_caps.MaxNum_WeightedPredL1, 32);
4568             }
4569             if (hwCaps.ddi_caps.ChromaWeightedPred)
4570             {
4571                 maxChroma[0] = std::min<mfxU16>(hwCaps.ddi_caps.MaxNum_WeightedPredL0, 32);
4572                 maxChroma[1] = std::min<mfxU16>(hwCaps.ddi_caps.MaxNum_WeightedPredL1, 32);
4573             }
4574 #if defined (MFX_VA_LINUX)
4575             }
4576 #endif
4577         }
4578 
4579         for (mfxU16 lx = 0; lx < 2; lx++)
4580         {
4581             for (mfxU16 i = 0; i < 32 && !out_of_caps && extPwt->LumaWeightFlag[lx][i]; i++)
4582                 out_of_caps = (i >= maxLuma[lx]);
4583             for (mfxU16 i = 0; i < 32 && !out_of_caps && extPwt->ChromaWeightFlag[lx][i]; i++)
4584                 out_of_caps = (i >= maxChroma[lx]);
4585         }
4586 
4587         if (out_of_caps)
4588         {
4589             Zero(extPwt->LumaWeightFlag);
4590             Zero(extPwt->ChromaWeightFlag);
4591 
4592             for (mfxU16 lx = 0; lx < 2; lx++)
4593             {
4594                 for (mfxU16 i = 0; i < maxLuma[lx]; i++)
4595                     extPwt->LumaWeightFlag[lx][i] = 1;
4596                 for (mfxU16 i = 0; i < maxChroma[lx]; i++)
4597                     extPwt->ChromaWeightFlag[lx][i] = 1;
4598             }
4599 
4600             changed = true;
4601         }
4602 
4603         if (platform >= MFX_HW_KBL)
4604         {
4605             if (extPwt->LumaLog2WeightDenom && extPwt->LumaLog2WeightDenom != 6)
4606             {
4607                 extPwt->LumaLog2WeightDenom = 6;
4608                 changed = true;
4609             }
4610             if (extPwt->ChromaLog2WeightDenom && extPwt->ChromaLog2WeightDenom != 6)
4611             {
4612                 extPwt->ChromaLog2WeightDenom = 6;
4613                 changed = true;
4614             }
4615         }
4616     }
4617 
4618     if (!CheckRangeDflt(extOpt2->SkipFrame, 0, 3, 0)) changed = true;
4619 
4620     if ( extOpt2->SkipFrame && hwCaps.ddi_caps.SkipFrame == 0 && par.mfx.RateControlMethod != MFX_RATECONTROL_CQP)
4621     {
4622         extOpt2->SkipFrame = 0;
4623         changed = true;
4624     }
4625 
4626     bool mfxRateControlHwSupport =
4627         hwCaps.ddi_caps.FrameSizeToleranceSupport &&
4628         (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR ||
4629          par.mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
4630          par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR);
4631 
4632     bool slidingWindowSupported  =
4633             par.mfx.RateControlMethod == MFX_RATECONTROL_LA  ||
4634             par.mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD ||
4635             par.mfx.RateControlMethod == MFX_RATECONTROL_LA_EXT ||
4636             (mfxRateControlHwSupport && !IsOn(extOpt2->ExtBRC));
4637 
4638      if (extOpt3->WinBRCMaxAvgKbps || extOpt3->WinBRCSize)
4639      {
4640          if (!slidingWindowSupported)
4641          {
4642              extOpt3->WinBRCMaxAvgKbps = 0;
4643              extOpt3->WinBRCSize = 0;
4644              par.calcParam.WinBRCMaxAvgKbps = 0;
4645              unsupported = true;
4646          }
4647          else if (extOpt3->WinBRCSize==0)
4648          {
4649              warning = true;
4650          }
4651          else if (mfxRateControlHwSupport && !IsOn(extOpt2->ExtBRC))
4652          {
4653              if (par.mfx.FrameInfo.FrameRateExtN != 0 && par.mfx.FrameInfo.FrameRateExtD != 0)
4654              {
4655                  mfxU16 iframerate = (mfxU16)ceil((mfxF64)par.mfx.FrameInfo.FrameRateExtN / par.mfx.FrameInfo.FrameRateExtD);
4656                  if (extOpt3->WinBRCSize != iframerate)
4657                  {
4658                      extOpt3->WinBRCSize = iframerate;
4659                      changed = true;
4660                  }
4661              }
4662              else
4663              {
4664                  CalculateMFXFramerate((mfxF64)extOpt3->WinBRCSize, &par.mfx.FrameInfo.FrameRateExtN, &par.mfx.FrameInfo.FrameRateExtD);
4665                  changed = true;
4666              }
4667              if (par.calcParam.maxKbps)
4668              {
4669                  if (par.calcParam.WinBRCMaxAvgKbps != par.calcParam.maxKbps)
4670                  {
4671                      par.calcParam.WinBRCMaxAvgKbps = (mfxU16)par.calcParam.maxKbps;
4672                      changed = true;
4673                  }
4674              }
4675              else if (par.calcParam.WinBRCMaxAvgKbps)
4676              {
4677                  if (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR &&
4678                      par.calcParam.targetKbps &&
4679                      par.calcParam.WinBRCMaxAvgKbps != par.calcParam.targetKbps)
4680                  {
4681                      par.calcParam.WinBRCMaxAvgKbps = par.calcParam.targetKbps;
4682                      changed = true;
4683                  }
4684 
4685                  if (par.calcParam.targetKbps && par.calcParam.WinBRCMaxAvgKbps < par.calcParam.targetKbps)
4686                  {
4687                      extOpt3->WinBRCMaxAvgKbps = 0;
4688                      par.calcParam.WinBRCMaxAvgKbps = 0;
4689                      extOpt3->WinBRCSize = 0;
4690                      unsupported = true;
4691                  }
4692                  else
4693                  {
4694                      par.calcParam.maxKbps = par.calcParam.WinBRCMaxAvgKbps;
4695                      changed = true;
4696                  }
4697              }
4698              else
4699              {
4700                  warning = true;
4701              }
4702          }
4703          else if (par.calcParam.targetKbps && par.calcParam.WinBRCMaxAvgKbps < par.calcParam.targetKbps)
4704          {
4705              extOpt3->WinBRCMaxAvgKbps = 0;
4706              par.calcParam.WinBRCMaxAvgKbps = 0;
4707              extOpt3->WinBRCSize = 0;
4708              unsupported = true;
4709          }
4710      }
4711 
4712     if (   extOpt2->MinQPI || extOpt2->MaxQPI
4713         || extOpt2->MinQPP || extOpt2->MaxQPP
4714         || extOpt2->MinQPB || extOpt2->MaxQPB)
4715     {
4716         if (!CheckRangeDflt(extOpt2->MaxQPI, 0, 51, 0)) changed = true;
4717         if (!CheckRangeDflt(extOpt2->MaxQPP, 0, 51, 0)) changed = true;
4718         if (!CheckRangeDflt(extOpt2->MaxQPB, 0, 51, 0)) changed = true;
4719         if (!CheckRangeDflt(extOpt2->MinQPI, 0, (extOpt2->MaxQPI ? extOpt2->MaxQPI : 51), 0)) changed = true;
4720         if (!CheckRangeDflt(extOpt2->MinQPP, 0, (extOpt2->MaxQPP ? extOpt2->MaxQPP : 51), 0)) changed = true;
4721         if (!CheckRangeDflt(extOpt2->MinQPB, 0, (extOpt2->MaxQPB ? extOpt2->MaxQPB : 51), 0)) changed = true;
4722     }
4723 
4724     if (!CheckTriStateOption(extOpt3->BRCPanicMode)) changed = true;
4725     if (IsOff(extOpt3->BRCPanicMode)
4726      && (bRateControlLA(par.mfx.RateControlMethod)
4727      || (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP)
4728      || (vaType != MFX_HW_VAAPI))) // neither CQP nor LA BRC modes nor Windows support BRC panic mode disabling
4729     {
4730         extOpt3->BRCPanicMode = MFX_CODINGOPTION_UNKNOWN;
4731         unsupported = true;
4732     }
4733 
4734     if (!CheckTriStateOption(extOpt3->EnableMBQP)) changed = true;
4735 
4736     if (IsOn(extOpt3->EnableMBQP) && !(hwCaps.ddi_caps.MbQpDataSupport && par.mfx.RateControlMethod == MFX_RATECONTROL_CQP))
4737     {
4738         extOpt3->EnableMBQP = MFX_CODINGOPTION_OFF;
4739         changed = true;
4740     }
4741 
4742 #if MFX_VERSION >= 1023
4743     if (!CheckTriStateOption(extOpt3->EnableMBForceIntra)) changed = true;
4744 
4745     // at the moment LINUX , IOTG, OPEN SRC -  feature unsupported
4746     if (IsOn(extOpt3->EnableMBForceIntra))
4747     {
4748         extOpt3->EnableMBForceIntra = 0;
4749         changed = true;
4750     }
4751 #endif
4752 
4753     if (!CheckTriStateOption(extOpt3->MBDisableSkipMap)) changed = true;
4754 
4755     if (IsOn(extOpt3->MBDisableSkipMap) && vaType != MFX_HW_VAAPI)
4756     {
4757         extOpt3->MBDisableSkipMap = MFX_CODINGOPTION_OFF;
4758         changed = true;
4759     }
4760 
4761     if (!CheckRangeDflt(extOpt2->DisableDeblockingIdc, 0, 2, 0)) changed = true;
4762     if (!CheckTriStateOption(extOpt2->EnableMAD)) changed = true;
4763 
4764     if (!CheckTriStateOption(extOpt2->AdaptiveI)) changed = true;
4765     if (IsOn(extOpt2->AdaptiveI) && (par.mfx.GopOptFlag & MFX_GOP_STRICT))
4766     {
4767         extOpt2->AdaptiveI = MFX_CODINGOPTION_OFF;
4768         changed = true;
4769     }
4770     if (IsOn(extOpt2->AdaptiveI) &&
4771         (!(IsExtBrcSceneChangeSupported(par) && !(extBRC->pthis))
4772 #if defined(MFX_ENABLE_ENCTOOLS)
4773         && IsOff(extConfig->AdaptiveI)
4774 #endif
4775        ))
4776     {
4777         extOpt2->AdaptiveI = MFX_CODINGOPTION_OFF;
4778         changed = true;
4779     }
4780     if (IsOn(extOpt2->AdaptiveI) && (par.mfx.GopOptFlag & MFX_GOP_STRICT))
4781     {
4782         extOpt2->AdaptiveI = MFX_CODINGOPTION_OFF;
4783         changed = true;
4784     }
4785 
4786     if (IsOn(extOpt3->ExtBrcAdaptiveLTR) &&
4787         (!(IsExtBrcSceneChangeSupported(par) && !(extBRC->pthis))))
4788     {
4789         extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
4790         changed = true;
4791     }
4792 
4793     if (!CheckTriStateOption(extOpt2->AdaptiveB)) changed = true;
4794     if (IsOn(extOpt2->AdaptiveB) &&
4795         (!(IsExtBrcSceneChangeSupported(par) && !(extBRC->pthis))
4796 #if defined(MFX_ENABLE_ENCTOOLS)
4797             && IsOff(extConfig->AdaptiveB)
4798 #endif
4799             ))
4800     {
4801         extOpt2->AdaptiveB = MFX_CODINGOPTION_OFF;
4802         changed = true;
4803     }
4804 
4805     if (IsOn(extOpt2->AdaptiveB) && (par.mfx.GopOptFlag & MFX_GOP_STRICT))
4806     {
4807         extOpt2->AdaptiveB = MFX_CODINGOPTION_OFF;
4808         changed = true;
4809     }
4810 
4811     if (extOpt3->PRefType == MFX_P_REF_PYRAMID &&  par.mfx.GopRefDist > 1)
4812     {
4813         extOpt3->PRefType = MFX_P_REF_DEFAULT;
4814         changed = true;
4815     }
4816 
4817     if (!CheckRangeDflt(extOpt3->WeightedPred,
4818             (mfxU16)MFX_WEIGHTED_PRED_UNKNOWN,
4819             (mfxU16)MFX_WEIGHTED_PRED_EXPLICIT,
4820             (mfxU16)MFX_WEIGHTED_PRED_DEFAULT))
4821             changed = true;
4822 
4823     if (!CheckRangeDflt(extOpt3->WeightedBiPred,
4824             (mfxU16)MFX_WEIGHTED_PRED_UNKNOWN,
4825             (mfxU16)MFX_WEIGHTED_PRED_IMPLICIT,
4826             (mfxU16)MFX_WEIGHTED_PRED_DEFAULT))
4827             changed = true;
4828 
4829     if (    hwCaps.ddi_caps.NoWeightedPred
4830         && (extOpt3->WeightedPred == MFX_WEIGHTED_PRED_EXPLICIT
4831         || extOpt3->WeightedBiPred == MFX_WEIGHTED_PRED_EXPLICIT))
4832     {
4833         extOpt3->WeightedPred = MFX_WEIGHTED_PRED_DEFAULT;
4834         extOpt3->WeightedBiPred = MFX_WEIGHTED_PRED_DEFAULT;
4835         unsupported = true;
4836     }
4837 
4838     if (!CheckTriStateOption(extOpt3->FadeDetection)) changed = true;
4839 
4840     if (isENCPAK && (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) && IsOn(feiParam->SingleFieldProcessing))
4841     {
4842         feiParam->SingleFieldProcessing = MFX_CODINGOPTION_OFF;
4843         changed = true;
4844     }
4845 
4846     if (isENCPAK && IsOn(feiParam->SingleFieldProcessing) && !par.mfx.EncodedOrder)
4847     {
4848         feiParam->SingleFieldProcessing = MFX_CODINGOPTION_OFF;
4849         unsupported = true;
4850     }
4851 
4852 #if defined (MFX_VA_LINUX)
4853     // disable WP for legacy encoder on linux
4854     if ((!isENCPAK)
4855         && (extOpt3->WeightedPred   == MFX_WEIGHTED_PRED_EXPLICIT ||
4856             extOpt3->WeightedBiPred == MFX_WEIGHTED_PRED_EXPLICIT ||
4857             extOpt3->WeightedBiPred == MFX_WEIGHTED_PRED_IMPLICIT))
4858     {
4859         extOpt3->WeightedPred   = MFX_WEIGHTED_PRED_DEFAULT;
4860         extOpt3->WeightedBiPred = MFX_WEIGHTED_PRED_DEFAULT;
4861         changed = true;
4862     }
4863 #endif
4864 
4865     if ((isENCPAK) && (extOpt3->FadeDetection  == MFX_CODINGOPTION_ON))
4866     {
4867         // FD is not supported for FEI
4868         extOpt3->FadeDetection = MFX_CODINGOPTION_OFF;
4869         unsupported = true;
4870     }
4871 
4872 #ifdef MFX_ENABLE_MFE
4873     //ToDo: move to separate function
4874     mfxExtMultiFrameParam & mfeParam = GetExtBufferRef(par);
4875     if (mfeParam.MFMode > MFX_MF_MANUAL)
4876     {
4877         mfeParam.MFMode = MFX_MF_DEFAULT;
4878         changed = true;
4879     }
4880 
4881     /*explicitly force default number of frames, higher number will cause performance degradation
4882     multi-slice can be supported only through slice map control for MFE
4883     Adding any of Mad/MBQP/NonSkipMap/ForceIntraMap causing additional surfaces for kernel, leading to surface state cache size overhead*/
4884 
4885     mfxU16 numFrames = GetDefaultNumMfeFrames(par.mfx.TargetUsage, par.mfx.FrameInfo, platform, feiParam->Func,
4886         par.mfx.NumSlice,
4887         (extOpt2->EnableMAD == MFX_CODINGOPTION_ON) ||  (extOpt3->EnableMBQP == MFX_CODINGOPTION_ON) ||
4888         (extOpt3->MBDisableSkipMap == MFX_CODINGOPTION_ON) || (extOpt3->EnableMBForceIntra == MFX_CODINGOPTION_ON), config, par.mfx.RateControlMethod);
4889     if (mfeParam.MaxNumFrames > numFrames)
4890     {
4891         mfeParam.MaxNumFrames = numFrames;
4892         changed = true;
4893     }
4894     if (extOpt2->IntRefType && (mfeParam.MaxNumFrames > 1 || (!mfeParam.MaxNumFrames && mfeParam.MFMode >= MFX_MF_AUTO)))
4895     {
4896         mfeParam.MaxNumFrames = 1;
4897         changed = true;
4898     }
4899     // MFE+ROI encoding in non CQP mode produces gpu hang. This case is temporary disabled.
4900     if (extRoi->NumROI && (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP) && (mfeParam.MaxNumFrames > 1 || (!mfeParam.MaxNumFrames && mfeParam.MFMode >= MFX_MF_AUTO)))
4901     {
4902         mfeParam.MFMode = MFX_MF_DISABLED;
4903         mfeParam.MaxNumFrames = 1;
4904         changed = true;
4905     }
4906     if (mfeParam.MaxNumFrames != 1 && mfeParam.MFMode == MFX_MF_DISABLED)
4907     {
4908         mfeParam.MaxNumFrames = 1;
4909         changed = true;
4910     }
4911     if (mfeParam.MaxNumFrames > 1 && mfeParam.MFMode == MFX_MF_DEFAULT)
4912     {
4913         mfeParam.MFMode = MFX_MF_AUTO;
4914         changed = true;
4915     }
4916     if (mfeParam.MaxNumFrames > 1 && par.mfx.LowPower == MFX_CODINGOPTION_ON)
4917     {
4918         mfeParam.MaxNumFrames = 1;
4919         mfeParam.MFMode = MFX_MF_DEFAULT;
4920         changed = true;
4921     }
4922     mfxExtMultiFrameControl & mfeControl = GetExtBufferRef(par);
4923     if (mfeControl.Timeout && mfeParam.MFMode != MFX_MF_AUTO)
4924     {
4925         mfeControl.Timeout = 0;
4926         changed = true;
4927     }
4928 #else
4929     (void)config;
4930 #endif
4931 
4932 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
4933     if (!CheckTriStateOption(extOpt3->EncodedUnitsInfo))  changed = true;
4934     if ((par.calcParam.numTemporalLayer > 1 || IsMvcProfile(par.mfx.CodecProfile)) && IsOn(extOpt3->EncodedUnitsInfo))
4935     {
4936         extOpt3->EncodedUnitsInfo = MFX_CODINGOPTION_OFF;
4937         unsupported = true;
4938     }
4939 #endif
4940 
4941 #ifdef MFX_ENABLE_H264_REPARTITION_CHECK
4942     if (!CheckTriStateOptionWithAdaptive(extOpt3->RepartitionCheckEnable)) changed = true;
4943 #endif // MFX_ENABLE_H264_REPARTITION_CHECK
4944 
4945     return unsupported
4946         ? MFX_ERR_UNSUPPORTED
4947         : (changed || warning)
4948             ? MFX_WRN_INCOMPATIBLE_VIDEO_PARAM
4949             : MFX_ERR_NONE;
4950 }
4951 
4952 // checks MVC per-view parameters (bitrates, buffer size, initial delay, level)
CheckVideoParamMvcQueryLike(MfxVideoParam & par)4953 mfxStatus MfxHwH264Encode::CheckVideoParamMvcQueryLike(MfxVideoParam & par)
4954 {
4955     bool changed     = false;
4956 
4957     mfxExtCodingOptionSPSPPS & extBits = GetExtBufferRef(par);
4958     mfxExtSpsHeader          & extSps  = GetExtBufferRef(par);
4959 
4960 // first of all allign CodecLevel with general (not per-view) parameters: resolution, framerate, DPB size
4961     if (par.mfx.FrameInfo.Width  != 0 &&
4962         par.mfx.FrameInfo.Height != 0)
4963     {
4964         mfxU16 minLevel = GetLevelLimitByFrameSize(par);
4965         if (par.calcParam.mvcPerViewPar.codecLevel != 0 && par.calcParam.mvcPerViewPar.codecLevel < minLevel)
4966         {
4967             if (extBits.SPSBuffer)
4968                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
4969 
4970             changed = true;
4971             par.calcParam.mvcPerViewPar.codecLevel = minLevel;
4972         }
4973         if (par.calcParam.mvcPerViewPar.codecLevel == 0)
4974             par.calcParam.mvcPerViewPar.codecLevel = minLevel;
4975     }
4976 
4977     if (extSps.vui.flags.timingInfoPresent   &&
4978         par.mfx.FrameInfo.Width         != 0 &&
4979         par.mfx.FrameInfo.Height        != 0 &&
4980         par.mfx.FrameInfo.FrameRateExtN != 0 &&
4981         par.mfx.FrameInfo.FrameRateExtD != 0)
4982     {
4983         mfxU16 minLevel = GetLevelLimitByMbps(par);
4984         if (par.calcParam.mvcPerViewPar.codecLevel != 0 && par.calcParam.mvcPerViewPar.codecLevel < minLevel)
4985         {
4986             if (extBits.SPSBuffer)
4987                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
4988 
4989             changed = true;
4990             par.calcParam.mvcPerViewPar.codecLevel = minLevel;
4991         }
4992     }
4993 
4994     if (par.mfx.NumRefFrame      != 0 &&
4995         par.mfx.FrameInfo.Width  != 0 &&
4996         par.mfx.FrameInfo.Height != 0)
4997     {
4998         mfxU16 minLevel = GetLevelLimitByDpbSize(par);
4999         if (par.calcParam.mvcPerViewPar.codecLevel != 0 && par.calcParam.mvcPerViewPar.codecLevel < minLevel)
5000         {
5001             if (extBits.SPSBuffer)
5002                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5003 
5004             changed = false;
5005             par.calcParam.mvcPerViewPar.codecLevel = minLevel;
5006         }
5007     }
5008 
5009     // check MVC per-view parameters (bitrates, buffer size, initial delay, level)
5010     if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP && par.calcParam.mvcPerViewPar.targetKbps != 0)
5011     {
5012         if (par.mfx.FrameInfo.Width         != 0 &&
5013             par.mfx.FrameInfo.Height        != 0 &&
5014             par.mfx.FrameInfo.FrameRateExtN != 0 &&
5015             par.mfx.FrameInfo.FrameRateExtD != 0)
5016         {
5017             mfxF64 rawDataBitrate = 12.0 * par.mfx.FrameInfo.Width * par.mfx.FrameInfo.Height *
5018                 par.mfx.FrameInfo.FrameRateExtN / par.mfx.FrameInfo.FrameRateExtD;
5019             mfxU32 minTargetKbps = mfxU32(std::min<mfxF64>(0xffffffff, rawDataBitrate / 1000.0 / 500.0));
5020 
5021             if (par.calcParam.mvcPerViewPar.targetKbps < minTargetKbps)
5022             {
5023                 changed = true;
5024                 par.calcParam.mvcPerViewPar.targetKbps = minTargetKbps;
5025             }
5026         }
5027 
5028         if (extSps.vui.flags.nalHrdParametersPresent || extSps.vui.flags.vclHrdParametersPresent)
5029         {
5030             mfxU16 profile = MFX_PROFILE_AVC_HIGH;
5031             for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
5032             {
5033                 if (mfxU16 minLevel = GetLevelLimitByMaxBitrate(profile, par.calcParam.mvcPerViewPar.targetKbps))
5034                 {
5035                     if (par.calcParam.mvcPerViewPar.codecLevel != 0 && par.calcParam.mvcPerViewPar.codecLevel < minLevel)
5036                     {
5037                         if (extBits.SPSBuffer)
5038                             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5039 
5040                         changed = true;
5041                         par.calcParam.mvcPerViewPar.codecLevel   = minLevel;
5042                     }
5043                     break;
5044                 }
5045             }
5046 
5047             if (profile == MFX_PROFILE_UNKNOWN)
5048                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5049         }
5050     }
5051 
5052     if (par.calcParam.mvcPerViewPar.targetKbps != 0 && par.calcParam.mvcPerViewPar.maxKbps != 0)
5053     {
5054         if (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR)
5055         {
5056             if (par.calcParam.mvcPerViewPar.maxKbps != par.calcParam.mvcPerViewPar.targetKbps)
5057             {
5058                 changed = true;
5059                 if (extSps.vui.flags.nalHrdParametersPresent || extSps.vui.flags.vclHrdParametersPresent)
5060                     par.calcParam.mvcPerViewPar.targetKbps = par.calcParam.mvcPerViewPar.maxKbps;
5061                 else
5062                     par.calcParam.mvcPerViewPar.maxKbps = par.calcParam.mvcPerViewPar.targetKbps;
5063             }
5064         }
5065         else if (
5066             par.mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
5067             par.mfx.RateControlMethod == MFX_RATECONTROL_WIDI_VBR)
5068         {
5069             if (par.calcParam.mvcPerViewPar.maxKbps < par.calcParam.mvcPerViewPar.targetKbps)
5070             {
5071                 if (extBits.SPSBuffer && (
5072                     extSps.vui.flags.nalHrdParametersPresent ||
5073                     extSps.vui.flags.vclHrdParametersPresent))
5074                     return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5075 
5076                 changed = true;
5077                 par.calcParam.mvcPerViewPar.maxKbps = par.calcParam.mvcPerViewPar.targetKbps;
5078             }
5079         }
5080     }
5081 
5082     if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP && par.calcParam.mvcPerViewPar.maxKbps != 0)
5083     {
5084         mfxU16 profile = MFX_PROFILE_AVC_HIGH;
5085         for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
5086         {
5087             if (mfxU16 minLevel = GetLevelLimitByMaxBitrate(profile, par.calcParam.mvcPerViewPar.maxKbps))
5088             {
5089                 if (par.calcParam.mvcPerViewPar.codecLevel != 0 && par.calcParam.mvcPerViewPar.codecLevel < minLevel)
5090                 {
5091                     if (extBits.SPSBuffer)
5092                         return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5093 
5094                     changed = true;
5095                     par.calcParam.mvcPerViewPar.codecLevel = minLevel;
5096                 }
5097                 break;
5098             }
5099         }
5100 
5101         if (profile == MFX_PROFILE_UNKNOWN)
5102             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5103     }
5104 
5105     if (par.calcParam.mvcPerViewPar.bufferSizeInKB != 0)
5106     {
5107         if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP)
5108         {
5109             mfxU32 uncompressedSizeInKb = GetMaxCodedFrameSizeInKB(par);
5110             if (par.calcParam.mvcPerViewPar.bufferSizeInKB < uncompressedSizeInKb)
5111             {
5112                 changed = true;
5113                 par.calcParam.mvcPerViewPar.bufferSizeInKB = uncompressedSizeInKb;
5114             }
5115         }
5116         else
5117         {
5118             mfxF64 avgFrameSizeInKB = 0;
5119             if (par.mfx.RateControlMethod       != MFX_RATECONTROL_AVBR &&
5120                 par.mfx.FrameInfo.FrameRateExtN != 0 &&
5121                 par.mfx.FrameInfo.FrameRateExtD != 0 &&
5122                 par.calcParam.mvcPerViewPar.targetKbps != 0)
5123             {
5124                 mfxF64 frameRate = mfxF64(par.mfx.FrameInfo.FrameRateExtN) / par.mfx.FrameInfo.FrameRateExtD;
5125                 avgFrameSizeInKB = par.calcParam.mvcPerViewPar.targetKbps / frameRate / 8;
5126 
5127                 if (par.calcParam.mvcPerViewPar.bufferSizeInKB < 2 * avgFrameSizeInKB)
5128                 {
5129                     if (extBits.SPSBuffer && (
5130                         extSps.vui.flags.nalHrdParametersPresent ||
5131                         extSps.vui.flags.vclHrdParametersPresent))
5132                         return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5133 
5134                     changed = true;
5135                     par.calcParam.mvcPerViewPar.bufferSizeInKB = mfxU16(2 * avgFrameSizeInKB + 1);
5136                 }
5137             }
5138 
5139             mfxU16 profile = MFX_PROFILE_AVC_HIGH;
5140             for (; profile != MFX_PROFILE_UNKNOWN; profile = GetNextProfile(profile))
5141             {
5142                 if (mfxU16 minLevel = GetLevelLimitByBufferSize(profile, par.calcParam.mvcPerViewPar.bufferSizeInKB))
5143                 {
5144                     if (par.calcParam.mvcPerViewPar.codecLevel != 0 && par.calcParam.mvcPerViewPar.codecLevel < minLevel)
5145                     {
5146                         if (extBits.SPSBuffer)
5147                             return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5148 
5149                         changed = true;
5150                         par.calcParam.mvcPerViewPar.codecLevel = minLevel;
5151                     }
5152                     break;
5153                 }
5154             }
5155 
5156             if (profile == MFX_PROFILE_UNKNOWN)
5157                 return Error(MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
5158 
5159             if (par.mfx.RateControlMethod != MFX_RATECONTROL_CQP &&
5160                 par.mfx.RateControlMethod != MFX_RATECONTROL_AVBR &&
5161                 par.calcParam.mvcPerViewPar.initialDelayInKB != 0)
5162             {
5163                 if (par.calcParam.mvcPerViewPar.initialDelayInKB > par.calcParam.mvcPerViewPar.bufferSizeInKB)
5164                 {
5165                     changed = true;
5166                     par.calcParam.mvcPerViewPar.initialDelayInKB = par.calcParam.mvcPerViewPar.bufferSizeInKB / 2;
5167                 }
5168 
5169                 if (avgFrameSizeInKB != 0 && par.calcParam.mvcPerViewPar.initialDelayInKB < avgFrameSizeInKB)
5170                 {
5171                     changed = true;
5172                     par.calcParam.mvcPerViewPar.initialDelayInKB = mfxU16(std::min<mfxF64>(par.calcParam.mvcPerViewPar.bufferSizeInKB, avgFrameSizeInKB));
5173                 }
5174             }
5175         }
5176     }
5177 
5178     return changed ? MFX_WRN_INCOMPATIBLE_VIDEO_PARAM : MFX_ERR_NONE;
5179 }
5180 
5181 // check mfxExtMVCSeqDesc as in Query
CheckMVCSeqDescQueryLike(mfxExtMVCSeqDesc * mvcSeqDesc)5182 mfxStatus MfxHwH264Encode::CheckMVCSeqDescQueryLike(mfxExtMVCSeqDesc * mvcSeqDesc)
5183 {
5184     bool unsupported = false;
5185     if (mvcSeqDesc->NumView > 0 && mvcSeqDesc->NumView != 2)
5186     {
5187         unsupported = true;
5188         mvcSeqDesc->NumView = 0;
5189     }
5190 
5191     if (mvcSeqDesc->NumOP > 1024)
5192     {
5193         unsupported = true;
5194         mvcSeqDesc->NumOP = 0;
5195     }
5196 
5197     if (mvcSeqDesc->NumOP > 0 && mvcSeqDesc->NumViewId > 1024 * mvcSeqDesc->NumOP)
5198     {
5199         unsupported = true;
5200         mvcSeqDesc->NumViewId = 0;
5201     }
5202 
5203     if (mvcSeqDesc->NumViewAlloc > 0 && (mvcSeqDesc->NumViewAlloc < mvcSeqDesc->NumView))
5204     {
5205         unsupported = true;
5206         mvcSeqDesc->NumViewAlloc = 0;
5207     }
5208 
5209     return unsupported ? MFX_ERR_UNSUPPORTED : MFX_ERR_NONE;
5210 }
5211 
5212 // check mfxExtMVCSeqDesc before encoding
CheckAndFixMVCSeqDesc(mfxExtMVCSeqDesc * mvcSeqDesc,bool isViewOutput)5213 mfxStatus MfxHwH264Encode::CheckAndFixMVCSeqDesc(mfxExtMVCSeqDesc * mvcSeqDesc, bool isViewOutput)
5214 {
5215     if (mvcSeqDesc == nullptr)
5216     {
5217         return MFX_ERR_NULL_PTR;
5218     }
5219 
5220     bool unsupported = false;
5221     bool changed = false;
5222     if (mvcSeqDesc->NumView > 2 || mvcSeqDesc->NumView < 2)
5223     {
5224         unsupported = true;
5225         mvcSeqDesc->NumView = 0;
5226     }
5227 
5228     if (mvcSeqDesc->NumOP > 1024)
5229     {
5230         unsupported = true;
5231         mvcSeqDesc->NumOP = 0;
5232     }
5233 
5234     if (mvcSeqDesc->NumOP > 0 && mvcSeqDesc->NumViewId > 1024 * mvcSeqDesc->NumOP)
5235     {
5236         unsupported = true;
5237         mvcSeqDesc->NumViewId = 0;
5238     }
5239 
5240     if (mvcSeqDesc->NumViewAlloc > 0 && mvcSeqDesc->NumViewAlloc < mvcSeqDesc->NumView)
5241     {
5242         changed = true;
5243         mvcSeqDesc->NumViewAlloc = 0;
5244         mvcSeqDesc->View = 0;
5245     }
5246 
5247     if (mvcSeqDesc->NumViewAlloc > 0)
5248     {
5249         if (mvcSeqDesc->View == 0)
5250         {
5251             unsupported = true;
5252         }
5253         else
5254         {
5255             if (mvcSeqDesc->View[0].ViewId != 0 && isViewOutput)
5256             {
5257                  changed = true;
5258                 mvcSeqDesc->View[0].ViewId = 0;
5259             }
5260         }
5261     }
5262 
5263     if (mvcSeqDesc->NumViewIdAlloc > 0 && mvcSeqDesc->NumViewIdAlloc < mvcSeqDesc->NumViewId)
5264     {
5265         changed = true;
5266         mvcSeqDesc->NumViewId = 0;
5267         mvcSeqDesc->NumViewIdAlloc = 0;
5268         mvcSeqDesc->ViewId = 0;
5269     }
5270 
5271     if (mvcSeqDesc->NumViewIdAlloc > 0)
5272     {
5273         if (mvcSeqDesc->ViewId == 0)
5274         {
5275             unsupported = true;
5276         }
5277         else
5278         {
5279             if (mvcSeqDesc->ViewId[0] != 0 && isViewOutput)
5280             {
5281                 changed = true;
5282                 mvcSeqDesc->ViewId[0] = 0;
5283             }
5284         }
5285     }
5286 
5287     if (mvcSeqDesc->NumOPAlloc > 0 &&  mvcSeqDesc->NumOPAlloc < mvcSeqDesc->NumOP)
5288     {
5289         changed = true;
5290         mvcSeqDesc->NumOP = 0;
5291         mvcSeqDesc->NumOPAlloc = 0;
5292         mvcSeqDesc->OP = 0;
5293     }
5294 
5295     if (mvcSeqDesc->NumOPAlloc > 0 && mvcSeqDesc->OP == 0)
5296     {
5297         unsupported = true;
5298     }
5299 
5300     return unsupported ? MFX_ERR_UNSUPPORTED :
5301         changed ? MFX_WRN_INCOMPATIBLE_VIDEO_PARAM : MFX_ERR_NONE;
5302 }
5303 
InheritDefaultValues(MfxVideoParam const & parInit,MfxVideoParam & parReset,MFX_ENCODE_CAPS const & hwCaps,mfxVideoParam const * parResetIn)5304 void MfxHwH264Encode::InheritDefaultValues(
5305     MfxVideoParam const & parInit,
5306     MfxVideoParam &       parReset,
5307     MFX_ENCODE_CAPS const & hwCaps,
5308     mfxVideoParam const * parResetIn)
5309 {
5310     mfxExtCodingOption const &  extOptInit      = GetExtBufferRef(parInit);
5311     mfxExtCodingOption &        extOptReset     = GetExtBufferRef(parReset);
5312     mfxExtCodingOption3 const & extOpt3Init     = GetExtBufferRef(parInit);
5313     mfxExtCodingOption3 &       extOpt3Reset    = GetExtBufferRef(parReset);
5314     mfxExtCodingOption2 const & extOpt2Init     = GetExtBufferRef(parInit);
5315     mfxExtCodingOption2 &       extOpt2Reset    = GetExtBufferRef(parReset);
5316 
5317     mfxU32 TCBRCTargetFrameSize = 0;
5318 
5319     InheritOption(extOptInit.NalHrdConformance,         extOptReset.NalHrdConformance);
5320     InheritOption(extOpt3Init.LowDelayBRC,              extOpt3Reset.LowDelayBRC);
5321     InheritOption(extOpt3Init.AdaptiveMaxFrameSize,     extOpt3Reset.AdaptiveMaxFrameSize);
5322     InheritOption(parInit.mfx.RateControlMethod,        parReset.mfx.RateControlMethod);
5323     InheritOption(parInit.mfx.FrameInfo.FrameRateExtN,  parReset.mfx.FrameInfo.FrameRateExtN);
5324     InheritOption(parInit.mfx.FrameInfo.FrameRateExtD,  parReset.mfx.FrameInfo.FrameRateExtD);
5325     InheritOption(parInit.mfx.BRCParamMultiplier,       parReset.mfx.BRCParamMultiplier);
5326 
5327     if (IsTCBRC(parReset, hwCaps))
5328     {
5329         // old bitrate is used in TCBRC case
5330         TCBRCTargetFrameSize = GetAvgFrameSizeInBytes(parReset, false);
5331         if (extOpt2Reset.MaxFrameSize == 0 && parReset.mfx.MaxKbps != 0)
5332             extOpt2Reset.MaxFrameSize = GetAvgFrameSizeInBytes(parReset, true);
5333         parReset.mfx.TargetKbps = 0;
5334         parReset.mfx.MaxKbps    = 0;
5335     }
5336 
5337     InheritOption(parInit.AsyncDepth,             parReset.AsyncDepth);
5338     InheritOption(parInit.mfx.CodecId,            parReset.mfx.CodecId);
5339     InheritOption(parInit.mfx.CodecProfile,       parReset.mfx.CodecProfile);
5340     InheritOption(parInit.mfx.CodecLevel,         parReset.mfx.CodecLevel);
5341     InheritOption(parInit.mfx.NumThread,          parReset.mfx.NumThread);
5342     InheritOption(parInit.mfx.TargetUsage,        parReset.mfx.TargetUsage);
5343     InheritOption(parInit.mfx.GopPicSize,         parReset.mfx.GopPicSize);
5344     InheritOption(parInit.mfx.GopRefDist,         parReset.mfx.GopRefDist);
5345     InheritOption(parInit.mfx.GopOptFlag,         parReset.mfx.GopOptFlag);
5346     InheritOption(parInit.mfx.IdrInterval,        parReset.mfx.IdrInterval);
5347     InheritOption(parInit.mfx.BufferSizeInKB,     parReset.mfx.BufferSizeInKB);
5348     InheritOption(parInit.mfx.NumSlice,           parReset.mfx.NumSlice);
5349     InheritOption(parInit.mfx.NumRefFrame,        parReset.mfx.NumRefFrame);
5350     InheritOption(parInit.mfx.LowPower,           parReset.mfx.LowPower);
5351 
5352     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_CBR && parReset.mfx.RateControlMethod == MFX_RATECONTROL_CBR)
5353     {
5354         InheritOption(parInit.mfx.InitialDelayInKB, parReset.mfx.InitialDelayInKB);
5355         InheritOption(parInit.mfx.TargetKbps,       parReset.mfx.TargetKbps);
5356     }
5357 
5358     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_VBR && parReset.mfx.RateControlMethod == MFX_RATECONTROL_VBR)
5359     {
5360         InheritOption(parInit.mfx.InitialDelayInKB, parReset.mfx.InitialDelayInKB);
5361         InheritOption(parInit.mfx.TargetKbps,       parReset.mfx.TargetKbps);
5362         InheritOption(parInit.mfx.MaxKbps,          parReset.mfx.MaxKbps);
5363     }
5364 
5365     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_CQP && parReset.mfx.RateControlMethod == MFX_RATECONTROL_CQP)
5366     {
5367         InheritOption(parInit.mfx.QPI, parReset.mfx.QPI);
5368         InheritOption(parInit.mfx.QPP, parReset.mfx.QPP);
5369         InheritOption(parInit.mfx.QPB, parReset.mfx.QPB);
5370     }
5371 
5372     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_AVBR && parReset.mfx.RateControlMethod == MFX_RATECONTROL_AVBR)
5373     {
5374         InheritOption(parInit.mfx.Accuracy,    parReset.mfx.Accuracy);
5375         InheritOption(parInit.mfx.Convergence, parReset.mfx.Convergence);
5376     }
5377 
5378     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_ICQ && parReset.mfx.RateControlMethod == MFX_RATECONTROL_LA_ICQ)
5379         InheritOption(parInit.mfx.ICQQuality, parReset.mfx.ICQQuality);
5380 
5381     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_VCM && parReset.mfx.RateControlMethod == MFX_RATECONTROL_VCM)
5382     {
5383         InheritOption(parInit.mfx.InitialDelayInKB, parReset.mfx.InitialDelayInKB);
5384         InheritOption(parInit.mfx.TargetKbps,       parReset.mfx.TargetKbps);
5385         InheritOption(parInit.mfx.MaxKbps,          parReset.mfx.MaxKbps);
5386     }
5387 
5388 
5389     InheritOption(parInit.mfx.FrameInfo.FourCC,         parReset.mfx.FrameInfo.FourCC);
5390     InheritOption(parInit.mfx.FrameInfo.FourCC,         parReset.mfx.FrameInfo.FourCC);
5391     InheritOption(parInit.mfx.FrameInfo.Width,          parReset.mfx.FrameInfo.Width);
5392     InheritOption(parInit.mfx.FrameInfo.Height,         parReset.mfx.FrameInfo.Height);
5393     InheritOption(parInit.mfx.FrameInfo.CropX,          parReset.mfx.FrameInfo.CropX);
5394     InheritOption(parInit.mfx.FrameInfo.CropY,          parReset.mfx.FrameInfo.CropY);
5395     InheritOption(parInit.mfx.FrameInfo.CropW,          parReset.mfx.FrameInfo.CropW);
5396     InheritOption(parInit.mfx.FrameInfo.CropH,          parReset.mfx.FrameInfo.CropH);
5397     InheritOption(parInit.mfx.FrameInfo.AspectRatioW,   parReset.mfx.FrameInfo.AspectRatioW);
5398     InheritOption(parInit.mfx.FrameInfo.AspectRatioH,   parReset.mfx.FrameInfo.AspectRatioH);
5399 
5400     InheritOption(extOptInit.RateDistortionOpt,     extOptReset.RateDistortionOpt);
5401     InheritOption(extOptInit.MECostType,            extOptReset.MECostType);
5402     InheritOption(extOptInit.MESearchType,          extOptReset.MESearchType);
5403     InheritOption(extOptInit.MVSearchWindow.x,      extOptReset.MVSearchWindow.x);
5404     InheritOption(extOptInit.MVSearchWindow.y,      extOptReset.MVSearchWindow.y);
5405     InheritOption(extOptInit.EndOfSequence,         extOptReset.EndOfSequence);
5406     InheritOption(extOptInit.FramePicture,          extOptReset.FramePicture);
5407     InheritOption(extOptInit.CAVLC,                 extOptReset.CAVLC);
5408     InheritOption(extOptInit.SingleSeiNalUnit,      extOptReset.SingleSeiNalUnit);
5409     InheritOption(extOptInit.VuiVclHrdParameters,   extOptReset.VuiVclHrdParameters);
5410     InheritOption(extOptInit.RefPicListReordering,  extOptReset.RefPicListReordering);
5411     InheritOption(extOptInit.ResetRefList,          extOptReset.ResetRefList);
5412     InheritOption(extOptInit.RefPicMarkRep,         extOptReset.RefPicMarkRep);
5413     InheritOption(extOptInit.FieldOutput,           extOptReset.FieldOutput);
5414     InheritOption(extOptInit.IntraPredBlockSize,    extOptReset.IntraPredBlockSize);
5415     InheritOption(extOptInit.InterPredBlockSize,    extOptReset.InterPredBlockSize);
5416     InheritOption(extOptInit.MVPrecision,           extOptReset.MVPrecision);
5417     InheritOption(extOptInit.MaxDecFrameBuffering,  extOptReset.MaxDecFrameBuffering);
5418     InheritOption(extOptInit.AUDelimiter,           extOptReset.AUDelimiter);
5419     InheritOption(extOptInit.EndOfStream,           extOptReset.EndOfStream);
5420     InheritOption(extOptInit.PicTimingSEI,          extOptReset.PicTimingSEI);
5421     InheritOption(extOptInit.VuiNalHrdParameters,   extOptReset.VuiNalHrdParameters);
5422 
5423     if (!parResetIn || !(mfxExtCodingOption2 const *)GetExtBuffer(*parResetIn)) //user should be able to disable IntraRefresh via Reset()
5424     {
5425         InheritOption(extOpt2Init.IntRefType,      extOpt2Reset.IntRefType);
5426         InheritOption(extOpt2Init.IntRefCycleSize, extOpt2Reset.IntRefCycleSize);
5427     }
5428     InheritOption(extOpt2Init.DisableVUI,      extOpt2Reset.DisableVUI);
5429     InheritOption(extOpt2Init.SkipFrame,       extOpt2Reset.SkipFrame);
5430     InheritOption(extOpt3Init.PRefType,        extOpt3Reset.PRefType);
5431 
5432     InheritOption(extOpt2Init.ExtBRC,  extOpt2Reset.ExtBRC);
5433 
5434     InheritOption(extOpt3Init.NumSliceI, extOpt3Reset.NumSliceI);
5435     InheritOption(extOpt3Init.NumSliceP, extOpt3Reset.NumSliceP);
5436     InheritOption(extOpt3Init.NumSliceB, extOpt3Reset.NumSliceB);
5437     if (!parResetIn || !(mfxExtCodingOption3 const *)GetExtBuffer(*parResetIn))
5438         InheritOption(extOpt3Init.IntRefCycleDist, extOpt3Reset.IntRefCycleDist);
5439 
5440     if (parInit.mfx.RateControlMethod == MFX_RATECONTROL_QVBR && parReset.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
5441     {
5442         InheritOption(parInit.mfx.InitialDelayInKB, parReset.mfx.InitialDelayInKB);
5443         InheritOption(parInit.mfx.TargetKbps,       parReset.mfx.TargetKbps);
5444         InheritOption(parInit.mfx.MaxKbps,          parReset.mfx.MaxKbps);
5445         InheritOption(extOpt3Init.QVBRQuality,      extOpt3Reset.QVBRQuality);
5446     }
5447 
5448 
5449 
5450     mfxExtBRC & extBRCInit  = GetExtBufferRef(parInit);
5451     mfxExtBRC & extBRCReset = GetExtBufferRef(parReset);
5452 
5453     if (!extBRCReset.pthis &&
5454         !extBRCReset.Init &&
5455         !extBRCReset.Reset &&
5456         !extBRCReset.Close &&
5457         !extBRCReset.GetFrameCtrl &&
5458         !extBRCReset.Update)
5459     {
5460         extBRCReset = extBRCInit;
5461     }
5462 
5463 #if defined(MFX_ENABLE_ENCTOOLS)
5464     mfxExtEncToolsConfig &configInit = GetExtBufferRef(parInit);
5465     mfxExtEncToolsConfig &configReset = GetExtBufferRef(parReset);
5466 
5467     if (!IsEncToolsOptOn(configReset) &&
5468         IsEncToolsOptOn(configInit))
5469         ResetEncToolsPar(configReset, 0);
5470 
5471     InheritOption(configInit.AdaptiveI, configReset.AdaptiveI);
5472     InheritOption(configInit.AdaptiveB, configReset.AdaptiveB);
5473     InheritOption(configInit.AdaptiveRefP, configReset.AdaptiveRefP);
5474     InheritOption(configInit.AdaptiveRefB, configReset.AdaptiveRefB);
5475     InheritOption(configInit.SceneChange, configReset.SceneChange);
5476     InheritOption(configInit.AdaptiveLTR, configReset.AdaptiveLTR);
5477     InheritOption(configInit.AdaptivePyramidQuantP, configReset.AdaptivePyramidQuantP);
5478     InheritOption(configInit.AdaptivePyramidQuantB, configReset.AdaptivePyramidQuantB);
5479     InheritOption(configInit.BRCBufferHints, configReset.BRCBufferHints);
5480     InheritOption(configInit.BRC, configReset.BRC);
5481 #endif
5482 
5483     parReset.SyncVideoToCalculableParam();
5484     parReset.calcParam.TCBRCTargetFrameSize = TCBRCTargetFrameSize;
5485 
5486     // not inherited:
5487     // InheritOption(parInit.mfx.FrameInfo.PicStruct,      parReset.mfx.FrameInfo.PicStruct);
5488     // InheritOption(parInit.IOPattern,                    parReset.IOPattern);
5489     // InheritOption(parInit.mfx.FrameInfo.ChromaFormat,   parReset.mfx.FrameInfo.ChromaFormat);
5490 }
5491 
5492 
5493 namespace
5494 {
IsDyadic(mfxU32 tempScales[8],mfxU32 numTempLayers)5495     bool IsDyadic(mfxU32 tempScales[8], mfxU32 numTempLayers)
5496     {
5497         if (numTempLayers > 0)
5498             for (mfxU32 i = 1; i < numTempLayers; ++i)
5499                 if (tempScales[i] != 2 * tempScales[i - 1])
5500                     return false;
5501         return true;
5502     }
5503 
IsPowerOf2(mfxU32 n)5504     bool IsPowerOf2(mfxU32 n)
5505     {
5506         return (n & (n - 1)) == 0;
5507     }
5508 };
5509 
IsHRDBasedBRCMethod(mfxU16 RateControlMethod)5510 bool IsHRDBasedBRCMethod(mfxU16  RateControlMethod)
5511 {
5512     return  RateControlMethod != MFX_RATECONTROL_CQP && RateControlMethod != MFX_RATECONTROL_AVBR &&
5513             RateControlMethod != MFX_RATECONTROL_ICQ &&
5514             RateControlMethod != MFX_RATECONTROL_LA && RateControlMethod != MFX_RATECONTROL_LA_ICQ;
5515 }
isSWBRC(MfxVideoParam const & par)5516 bool MfxHwH264Encode::isSWBRC(MfxVideoParam const & par)
5517 {
5518     mfxExtCodingOption2       &extOpt2 = GetExtBufferRef(par);
5519     return (bRateControlLA(par.mfx.RateControlMethod) || (IsOn(extOpt2.ExtBRC) && (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR || par.mfx.RateControlMethod == MFX_RATECONTROL_VBR)));
5520 }
5521 
isAdaptiveQP(MfxVideoParam const & video)5522 bool MfxHwH264Encode::isAdaptiveQP(MfxVideoParam const & video)
5523 {
5524     if ((video.mfx.GopRefDist == 8) &&
5525         (video.mfx.FrameInfo.PicStruct == 0 || video.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) &&
5526         video.calcParam.numTemporalLayer == 0
5527         )
5528     {
5529         mfxExtCodingOption3 &extOpt3 = GetExtBufferRef(video);
5530         return IsOff(extOpt3.EnableQPOffset);
5531     }
5532     return false;
5533 }
5534 
5535 
SetDefaults(MfxVideoParam & par,MFX_ENCODE_CAPS const & hwCaps,bool setExtAlloc,eMFXHWType platform,eMFXVAType vaType,eMFXGTConfig config)5536 void MfxHwH264Encode::SetDefaults(
5537     MfxVideoParam &         par,
5538     MFX_ENCODE_CAPS const & hwCaps,
5539     bool                    setExtAlloc,
5540     eMFXHWType              platform,
5541     eMFXVAType              vaType,
5542     eMFXGTConfig            config)
5543 {
5544     mfxExtCodingOption *       extOpt  = GetExtBuffer(par);
5545     mfxExtCodingOption2 *      extOpt2 = GetExtBuffer(par);
5546     mfxExtCodingOption3 *      extOpt3 = GetExtBuffer(par);
5547     mfxExtCodingOptionDDI *    extDdi  = GetExtBuffer(par);
5548     mfxExtVideoSignalInfo *    extVsi  = GetExtBuffer(par);
5549     mfxExtCodingOptionSPSPPS * extBits = GetExtBuffer(par);
5550     mfxExtSpsHeader *          extSps  = GetExtBuffer(par);
5551     mfxExtPpsHeader *          extPps  = GetExtBuffer(par);
5552     mfxExtChromaLocInfo*       extCli  = GetExtBuffer(par);
5553     mfxExtFeiParam* feiParam = (mfxExtFeiParam*)GetExtBuffer(par);
5554 #if defined(MFX_ENABLE_MFE)
5555     mfxExtMultiFrameParam* mfeParam = GetExtBuffer(par);
5556     mfxExtMultiFrameControl* mfeControl = GetExtBuffer(par);
5557 #endif
5558 
5559 #if defined(MFX_ENABLE_ENCTOOLS)
5560     mfxExtEncToolsConfig *extConfig = GetExtBuffer(par);
5561 #endif
5562 
5563     bool isENCPAK = (feiParam->Func == MFX_FEI_FUNCTION_ENCODE) ||
5564                     (feiParam->Func == MFX_FEI_FUNCTION_ENC) ||
5565                     (feiParam->Func == MFX_FEI_FUNCTION_PAK);
5566 
5567     bool isPAK      = feiParam->Func == MFX_FEI_FUNCTION_PAK;
5568     bool isENCorPAK = feiParam->Func == MFX_FEI_FUNCTION_ENC || isPAK;
5569 
5570     if (extOpt2->UseRawRef)
5571         extDdi->RefRaw = extOpt2->UseRawRef;
5572     else if (!extOpt2->UseRawRef)
5573         extOpt2->UseRawRef = extDdi->RefRaw;
5574 
5575     if (extOpt2->UseRawRef == MFX_CODINGOPTION_UNKNOWN)
5576         extOpt2->UseRawRef = MFX_CODINGOPTION_OFF;
5577 
5578     if (IsOn(par.mfx.LowPower))
5579     {
5580         if (par.mfx.GopRefDist == 0)
5581             par.mfx.GopRefDist = 1;
5582         if (par.mfx.FrameInfo.PicStruct == 0)
5583             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
5584     }
5585 
5586     if (extOpt2->MaxSliceSize)
5587     {
5588         if (par.mfx.GopRefDist == 0)
5589             par.mfx.GopRefDist = 1;
5590         if (par.mfx.FrameInfo.PicStruct == 0)
5591             par.mfx.FrameInfo.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
5592         if (par.AsyncDepth == 0)
5593             par.AsyncDepth = 1;
5594         if (!IsDriverSliceSizeControlEnabled(par, hwCaps))
5595         {
5596             if (par.mfx.RateControlMethod == 0)
5597                 par.mfx.RateControlMethod = MFX_RATECONTROL_LA;
5598             if (extOpt2->LookAheadDepth == 0)
5599                 extOpt2->LookAheadDepth = 1;
5600             if (extOpt2->LookAheadDS == MFX_LOOKAHEAD_DS_UNKNOWN)
5601                 extOpt2->LookAheadDS = MFX_LOOKAHEAD_DS_2x;
5602         }
5603         else
5604         {
5605             if (par.mfx.RateControlMethod == 0)
5606                 par.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
5607         }
5608     }
5609 #if defined(MFX_ENABLE_MFE)
5610     if (mfeParam)
5611     {
5612         //can be changed
5613         if (!mfeParam->MFMode && mfeParam->MaxNumFrames)
5614             mfeParam->MFMode = MFX_MF_AUTO;
5615         if (mfeParam->MFMode >= MFX_MF_AUTO && !mfeParam->MaxNumFrames)
5616         {
5617             mfeParam->MaxNumFrames = GetDefaultNumMfeFrames(par.mfx.TargetUsage, par.mfx.FrameInfo, platform, feiParam->Func,
5618                 par.mfx.NumSlice,
5619                 (extOpt2->EnableMAD == MFX_CODINGOPTION_ON) || (extOpt3->EnableMBQP == MFX_CODINGOPTION_ON) ||
5620                 (extOpt3->MBDisableSkipMap == MFX_CODINGOPTION_ON) || (extOpt3->EnableMBForceIntra == MFX_CODINGOPTION_ON), config, par.mfx.RateControlMethod);
5621         }
5622     }
5623     if (mfeControl)
5624     {
5625         if (!mfeControl->Timeout && mfeParam->MFMode == MFX_MF_AUTO)
5626         {
5627             mfeControl->Timeout = calculateMfeTimeout(par.mfx.FrameInfo);
5628         }
5629     }
5630 #endif
5631 
5632 
5633     mfxU8 fieldCodingPossible = IsFieldCodingPossible(par);
5634 
5635     if (par.IOPattern == 0)
5636         par.IOPattern = setExtAlloc
5637             ? mfxU16(MFX_IOPATTERN_IN_VIDEO_MEMORY)
5638             : mfxU16(MFX_IOPATTERN_IN_SYSTEM_MEMORY);
5639 
5640     if (par.AsyncDepth == 0)
5641         par.AsyncDepth = GetDefaultAsyncDepth(par);
5642 
5643     if (par.mfx.TargetUsage == 0)
5644         par.mfx.TargetUsage = 4;
5645 
5646     if (par.mfx.NumSlice == 0)
5647     {
5648         if (extOpt2->NumMbPerSlice != 0) {
5649             par.mfx.NumSlice = (
5650                 (par.mfx.FrameInfo.Width / 16) *
5651                 (par.mfx.FrameInfo.Height / 16 / (fieldCodingPossible ? 2 : 1)) +
5652                 extOpt2->NumMbPerSlice - 1) / extOpt2->NumMbPerSlice;
5653         }
5654         else
5655             par.mfx.NumSlice = 1;
5656     }
5657 
5658     if (par.mfx.RateControlMethod == 0)
5659         par.mfx.RateControlMethod = MFX_RATECONTROL_CBR;
5660 
5661     if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP &&
5662         par.calcParam.cqpHrdMode == 0)
5663     {
5664         mfxU16 maxQP = 51;
5665         mfxU16 minQP = IsOn(par.mfx.LowPower) ? 10 : 1;   // 10 is min QP for VDENC
5666         if (!par.mfx.QPI)
5667             par.mfx.QPI = mfxU16(std::max<mfxI32>(par.mfx.QPP - 1, minQP) * !!par.mfx.QPP);
5668         if (!par.mfx.QPI)
5669             par.mfx.QPI = mfxU16(std::max<mfxI32>(par.mfx.QPB - 2, minQP) * !!par.mfx.QPB);
5670         if (!par.mfx.QPI)
5671             par.mfx.QPI = std::max<mfxU16>(minQP, (maxQP + 1) / 2);
5672         if (!par.mfx.QPP)
5673             par.mfx.QPP = std::min<mfxU16>(par.mfx.QPI + 1, maxQP);
5674         if (!par.mfx.QPB)
5675             par.mfx.QPB = std::min<mfxU16>(par.mfx.QPP + 1, maxQP);
5676     }
5677 
5678     if (par.mfx.RateControlMethod == MFX_RATECONTROL_AVBR)
5679     {
5680         if (par.mfx.Accuracy == 0)
5681             par.mfx.Accuracy = 100;
5682 
5683         if (par.mfx.Convergence == 0)
5684             par.mfx.Convergence = AVBR_CONVERGENCE_MAX;
5685     }
5686 
5687     if (par.mfx.RateControlMethod == MFX_RATECONTROL_ICQ || par.mfx.RateControlMethod == MFX_RATECONTROL_LA_ICQ)
5688     {
5689         if (par.mfx.ICQQuality == 0)
5690             par.mfx.ICQQuality = 26;
5691     }
5692 
5693     if (par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
5694     {
5695         if (extOpt3->QVBRQuality == 0)
5696             extOpt3->QVBRQuality = 26;
5697     }
5698 
5699     if (par.mfx.GopRefDist == 0)
5700     {
5701         if (IsAvcBaseProfile(par.mfx.CodecProfile) ||
5702             par.mfx.CodecProfile == MFX_PROFILE_AVC_CONSTRAINED_HIGH ||
5703             (par.calcParam.numTemporalLayer > 0 && par.calcParam.tempScalabilityMode) ||
5704             hwCaps.ddi_caps.SliceIPOnly)
5705         {
5706             par.mfx.GopRefDist = 1;
5707         }
5708         else if (par.calcParam.numTemporalLayer > 1)
5709         { // svc temporal layers
5710             par.mfx.GopRefDist = 1;
5711             extOpt2->BRefType = MFX_B_REF_OFF;
5712 
5713             if (IsDyadic(par.calcParam.scale, par.calcParam.numTemporalLayer) &&
5714                 par.mfx.GopPicSize % par.calcParam.scale[par.calcParam.numTemporalLayer - 1] == 0)
5715             {
5716                 if (par.calcParam.numTemporalLayer == 2)
5717                 {
5718                     par.mfx.GopRefDist = 2;
5719                     extOpt2->BRefType = MFX_B_REF_OFF;
5720                 }
5721                 else
5722                 {
5723                     par.mfx.GopRefDist = 4;
5724                     extOpt2->BRefType = MFX_B_REF_PYRAMID;
5725                 }
5726             }
5727         }
5728         else
5729         {
5730             par.mfx.GopRefDist = (IsOn(extOpt2->AdaptiveI) ||
5731                                   IsOn(extOpt2->AdaptiveB) ||
5732 #if defined(MFX_ENABLE_ENCTOOLS)
5733                                   IsOn(extConfig->AdaptiveI) ||
5734                                   IsOn(extConfig->AdaptiveB) ||
5735 #endif
5736                                   IsAdaptiveLtrOn(par))? 8 : GetDefaultGopRefDist(par.mfx.TargetUsage, platform);
5737             if (par.mfx.GopPicSize > 0 && par.mfx.GopPicSize <= par.mfx.GopRefDist)
5738                 par.mfx.GopRefDist = par.mfx.GopPicSize;
5739         }
5740 
5741         if (par.mfx.RateControlMethod & MFX_RATECONTROL_LA_EXT)
5742         {
5743             par.mfx.GopRefDist = 3;
5744         }
5745     }
5746     if ((par.mfx.RateControlMethod == MFX_RATECONTROL_LA || par.mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD || par.mfx.RateControlMethod == MFX_RATECONTROL_LA_EXT) && (extOpt3->WinBRCMaxAvgKbps || extOpt3->WinBRCSize))
5747     {
5748         if (!extOpt3->WinBRCMaxAvgKbps)
5749         {
5750             extOpt3->WinBRCMaxAvgKbps = par.mfx.TargetKbps * 2;
5751             par.calcParam.WinBRCMaxAvgKbps = par.calcParam.targetKbps * 2;
5752         }
5753         if (!extOpt3->WinBRCSize)
5754         {
5755             extOpt3->WinBRCSize = (mfxU16)(par.mfx.FrameInfo.FrameRateExtN / par.mfx.FrameInfo.FrameRateExtD);
5756             extOpt3->WinBRCSize = (!extOpt3->WinBRCSize) ? 30 : extOpt3->WinBRCSize;
5757         }
5758     }
5759 
5760 
5761     //WA for MVC quality problem on progressive content.
5762     if (IsMvcProfile(par.mfx.CodecProfile)) {
5763         extDdi->NumActiveRefP = extDdi->NumActiveRefBL0 = extDdi->NumActiveRefBL1 = 1;
5764     }
5765     if (extDdi->NumActiveRefP == 0)
5766     {
5767         if (isENCPAK)
5768         {
5769             // FEI has it's own limits
5770             extDdi->NumActiveRefP = extOpt3->NumRefActiveP[0];
5771 
5772             if (extDdi->NumActiveRefP == 0)
5773             {
5774                 extDdi->NumActiveRefP = isPAK ? 16 : 4;
5775             }
5776         }
5777         else
5778         {
5779             mfxU16 maxNumActivePL0 = GetMaxNumRefActivePL0(par.mfx.TargetUsage, platform, IsOn(par.mfx.LowPower), par.mfx.FrameInfo);
5780             extDdi->NumActiveRefP = extOpt3->NumRefActiveP[0] ? std::min(maxNumActivePL0, extOpt3->NumRefActiveP[0])
5781                 : GetDefaultNumRefActivePL0(par.mfx, platform);
5782         }
5783     }
5784 
5785     if (par.mfx.GopRefDist > 1)
5786     {
5787         if (extDdi->NumActiveRefBL0 == 0)
5788         {
5789             if (isENCPAK)
5790             {
5791                 // FEI has it's own limits
5792                 extDdi->NumActiveRefBL0 = extOpt3->NumRefActiveBL0[0];
5793 
5794                 if (extDdi->NumActiveRefBL0 == 0)
5795                 {
5796                     extDdi->NumActiveRefBL0 = isPAK ? 16 : 4;
5797                 }
5798             }
5799             else
5800             {
5801                 mfxU16 maxNumActiveBL0 = GetMaxNumRefActiveBL0(par.mfx.TargetUsage, platform, IsOn(par.mfx.LowPower));
5802                 extDdi->NumActiveRefBL0 = extOpt3->NumRefActiveBL0[0] ? std::min(maxNumActiveBL0, extOpt3->NumRefActiveBL0[0])
5803                     : GetDefaultNumRefActiveBL0(par.mfx, platform);
5804             }
5805         } /* if (extDdi->NumActiveRefBL0 == 0) */
5806 
5807         if (extDdi->NumActiveRefBL1 == 0)
5808         {
5809             if (isENCPAK)
5810             {
5811                 // FEI has it's own limits
5812                 extDdi->NumActiveRefBL1 = extOpt3->NumRefActiveBL1[0];
5813 
5814                 if (extDdi->NumActiveRefBL1 == 0)
5815                 {
5816                     // FEI ENCODE uses 2 references for interlaced
5817                     extDdi->NumActiveRefBL1 = isPAK ? 16 : (!(par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) ? 2 : 1);
5818                 }
5819             }
5820             else
5821             {
5822                 mfxU16 maxNumActiveBL1 = GetMaxNumRefActiveBL1(par.mfx.TargetUsage, platform, par.mfx.FrameInfo.PicStruct, IsOn(par.mfx.LowPower));
5823                 extDdi->NumActiveRefBL1 = extOpt3->NumRefActiveBL1[0] ? std::min(maxNumActiveBL1, extOpt3->NumRefActiveBL1[0])
5824                     : GetDefaultNumRefActiveBL1(par.mfx, platform);
5825             }
5826         } /* if (extDdi->NumActiveRefBL1 == 0) */
5827     }
5828 
5829     if (par.mfx.GopPicSize == 0)
5830     {
5831         mfxU32 maxScale = (par.calcParam.numTemporalLayer) > 0
5832             ? par.calcParam.scale[par.calcParam.numTemporalLayer - 1]
5833             : 1;
5834         par.mfx.GopPicSize = mfxU16((256 + maxScale - 1) / maxScale * maxScale);
5835     }
5836 
5837     if (extOpt2->BRefType == MFX_B_REF_UNKNOWN)
5838     {
5839         assert(par.mfx.GopRefDist > 0);
5840         assert(par.mfx.GopPicSize > 0);
5841 
5842         if (platform >= MFX_HW_HSW && platform != MFX_HW_VLV &&
5843             IsDyadic(par.calcParam.scale, par.calcParam.numTemporalLayer) &&
5844             par.mfx.GopRefDist >= 4 &&
5845             (!par.mfx.NumRefFrame || par.mfx.NumRefFrame >= GetMinNumRefFrameForPyramid(par)) &&
5846             (!IsMvcProfile(par.mfx.CodecProfile) || (IsPowerOf2(par.mfx.GopRefDist) && (par.mfx.GopPicSize % par.mfx.GopRefDist) == 0)) &&
5847             par.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE)
5848         {
5849             extOpt2->BRefType = MFX_B_REF_PYRAMID;
5850         }
5851         else
5852         {
5853             extOpt2->BRefType = MFX_B_REF_OFF;
5854         }
5855     }
5856 
5857     if (par.mfx.FrameInfo.FourCC == 0)
5858         par.mfx.FrameInfo.FourCC = MFX_FOURCC_NV12;
5859 
5860     if (par.mfx.FrameInfo.ChromaFormat == 0)
5861         par.mfx.FrameInfo.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
5862 
5863     if (par.mfx.FrameInfo.CropW == 0)
5864         par.mfx.FrameInfo.CropW = par.mfx.FrameInfo.Width - par.mfx.FrameInfo.CropX;
5865 
5866     if (par.mfx.FrameInfo.CropH == 0)
5867         par.mfx.FrameInfo.CropH = par.mfx.FrameInfo.Height - par.mfx.FrameInfo.CropY;
5868 
5869     if (par.mfx.FrameInfo.AspectRatioW == 0)
5870         par.mfx.FrameInfo.AspectRatioW = 1;
5871 
5872     if (par.mfx.FrameInfo.AspectRatioH == 0)
5873         par.mfx.FrameInfo.AspectRatioH = 1;
5874 
5875     if (extOpt->InterPredBlockSize == MFX_BLOCKSIZE_UNKNOWN)
5876         extOpt->InterPredBlockSize = MFX_BLOCKSIZE_MIN_4X4;
5877 
5878     if (extOpt->MVPrecision == MFX_MVPRECISION_UNKNOWN)
5879         extOpt->MVPrecision = MFX_MVPRECISION_QUARTERPEL;
5880 
5881     if (extOpt->RateDistortionOpt == MFX_CODINGOPTION_UNKNOWN)
5882         extOpt->RateDistortionOpt = MFX_CODINGOPTION_OFF;
5883 
5884     if (extOpt->RateDistortionOpt == MFX_CODINGOPTION_UNKNOWN)
5885         extOpt->RateDistortionOpt = MFX_CODINGOPTION_OFF;
5886 
5887     if (extOpt->EndOfSequence == MFX_CODINGOPTION_UNKNOWN)
5888         extOpt->EndOfSequence = MFX_CODINGOPTION_OFF;
5889 
5890     if (extOpt->RefPicListReordering == MFX_CODINGOPTION_UNKNOWN)
5891         extOpt->RefPicListReordering = MFX_CODINGOPTION_OFF;
5892 
5893     if (extOpt->ResetRefList == MFX_CODINGOPTION_UNKNOWN)
5894         extOpt->ResetRefList = MFX_CODINGOPTION_OFF;
5895 
5896     if (extOpt->RefPicMarkRep == MFX_CODINGOPTION_UNKNOWN)
5897         extOpt->RefPicMarkRep = MFX_CODINGOPTION_OFF;
5898 
5899     if (extOpt->FieldOutput == MFX_CODINGOPTION_UNKNOWN)
5900         extOpt->FieldOutput = MFX_CODINGOPTION_OFF;
5901 
5902     if (extOpt->AUDelimiter == MFX_CODINGOPTION_UNKNOWN)
5903         extOpt->AUDelimiter = (par.calcParam.tempScalabilityMode)
5904             ? mfxU16(MFX_CODINGOPTION_OFF)
5905             : mfxU16(MFX_CODINGOPTION_ON);
5906 
5907     if (extOpt->EndOfStream == MFX_CODINGOPTION_UNKNOWN)
5908         extOpt->EndOfStream = MFX_CODINGOPTION_OFF;
5909 
5910     if (isENCorPAK)
5911     {
5912         SetDefaultOff(extOpt->PicTimingSEI);
5913     }
5914     else
5915     {
5916         SetDefaultOn(extOpt->PicTimingSEI);
5917     }
5918 
5919     if (extOpt->ViewOutput == MFX_CODINGOPTION_UNKNOWN)
5920         extOpt->ViewOutput = MFX_CODINGOPTION_OFF;
5921 
5922     if (extOpt->VuiNalHrdParameters == MFX_CODINGOPTION_UNKNOWN)
5923         extOpt->VuiNalHrdParameters =
5924             par.mfx.RateControlMethod == MFX_RATECONTROL_CQP ||
5925             par.mfx.RateControlMethod == MFX_RATECONTROL_AVBR ||
5926             (bRateControlLA(par.mfx.RateControlMethod) && par.mfx.RateControlMethod != MFX_RATECONTROL_LA_HRD) ||
5927             IsOn(extOpt2->DisableVUI)
5928                 ? mfxU16(MFX_CODINGOPTION_OFF)
5929                 : mfxU16(MFX_CODINGOPTION_ON);
5930 
5931     if (extOpt->VuiVclHrdParameters == MFX_CODINGOPTION_UNKNOWN)
5932         extOpt->VuiVclHrdParameters = MFX_CODINGOPTION_OFF;
5933 
5934     if (extOpt->NalHrdConformance == MFX_CODINGOPTION_UNKNOWN)
5935         extOpt->NalHrdConformance = IsOn(extOpt->VuiNalHrdParameters) || IsOn(extOpt->VuiVclHrdParameters)
5936             ? mfxU16(MFX_CODINGOPTION_ON)
5937             : mfxU16(MFX_CODINGOPTION_OFF);
5938 
5939     if (extOpt->CAVLC == MFX_CODINGOPTION_UNKNOWN)
5940         extOpt->CAVLC = (IsAvcBaseProfile(par.mfx.CodecProfile) || hwCaps.ddi_caps.NoCabacSupport)
5941             ? mfxU16(MFX_CODINGOPTION_ON)
5942             : mfxU16(MFX_CODINGOPTION_OFF);
5943 
5944     if (extOpt->SingleSeiNalUnit == MFX_CODINGOPTION_UNKNOWN)
5945         extOpt->SingleSeiNalUnit = MFX_CODINGOPTION_ON;
5946 
5947     if (extDdi->MEInterpolationMethod == ENC_INTERPOLATION_TYPE_NONE)
5948         extDdi->MEInterpolationMethod = ENC_INTERPOLATION_TYPE_AVC6TAP;
5949 
5950     if (extDdi->RefRaw == MFX_CODINGOPTION_UNKNOWN)
5951         extDdi->RefRaw = MFX_CODINGOPTION_OFF;
5952 
5953     if (extDdi->DirectSpatialMvPredFlag == MFX_CODINGOPTION_UNKNOWN)
5954         extDdi->DirectSpatialMvPredFlag = MFX_CODINGOPTION_ON;
5955 
5956     if (extDdi->Hme == MFX_CODINGOPTION_UNKNOWN)
5957         extDdi->Hme = MFX_CODINGOPTION_ON;
5958 
5959     if (extOpt2->ExtBRC == MFX_CODINGOPTION_UNKNOWN)
5960         extOpt2->ExtBRC = MFX_CODINGOPTION_OFF;
5961 
5962     if (extOpt2->LookAheadDepth == 0)
5963     {
5964         if (par.mfx.RateControlMethod == MFX_RATECONTROL_LA_ICQ)
5965             extOpt2->LookAheadDepth = std::max<mfxU16>(10, 2 * par.mfx.GopRefDist);
5966         else if (bRateControlLA(par.mfx.RateControlMethod))
5967             extOpt2->LookAheadDepth = std::max<mfxU16>(40, 2 * par.mfx.GopRefDist);
5968 
5969     }
5970     if (extDdi->LookAheadDependency == 0)
5971     {
5972         if (bIntRateControlLA(par.mfx.RateControlMethod) && par.mfx.RateControlMethod != MFX_RATECONTROL_LA_ICQ)
5973         {
5974             extDdi->LookAheadDependency = std::min<mfxU16>(10, extOpt2->LookAheadDepth / 4);
5975             extDdi->LookAheadDependency = mfx::clamp<mfxU16>(extDdi->LookAheadDependency, std::min<mfxU16>(par.mfx.GopRefDist + 1, extOpt2->LookAheadDepth * 2 / 3), (extOpt2->LookAheadDepth * 2 / 3));
5976         }
5977         else
5978         {
5979             extDdi->LookAheadDependency = extOpt2->LookAheadDepth;
5980         }
5981     }
5982 
5983     if (extOpt2->LookAheadDS == MFX_LOOKAHEAD_DS_UNKNOWN) // default: use LA 2X for TU3-7 and LA 1X for TU1-2
5984     {
5985         if (par.mfx.TargetUsage > 2 ||
5986             (par.mfx.FrameInfo.Width >= 1920 && (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE)) || // customer's issue
5987             (par.mfx.FrameInfo.Width > 3000) )
5988             extOpt2->LookAheadDS = MFX_LOOKAHEAD_DS_2x;
5989         else
5990             extOpt2->LookAheadDS = MFX_LOOKAHEAD_DS_OFF;
5991     }
5992 
5993     if ((extOpt2->LookAheadDS != MFX_LOOKAHEAD_DS_OFF) &&
5994         (extOpt2->LookAheadDS != MFX_LOOKAHEAD_DS_2x) &&
5995         (extOpt2->LookAheadDS != MFX_LOOKAHEAD_DS_4x))
5996         extOpt2->LookAheadDS = MFX_LOOKAHEAD_DS_OFF;
5997 
5998     if (extDdi->QpUpdateRange == 0)
5999         extDdi->QpUpdateRange = 10;
6000 
6001     if (extDdi->RegressionWindow == 0)
6002         extDdi->RegressionWindow = 20;
6003 
6004     if (extOpt2->BitrateLimit == MFX_CODINGOPTION_UNKNOWN)
6005         extOpt2->BitrateLimit = MFX_CODINGOPTION_ON;
6006 
6007     if (extOpt2->RepeatPPS == MFX_CODINGOPTION_UNKNOWN)
6008         extOpt2->RepeatPPS = MFX_CODINGOPTION_ON;
6009 
6010     mfxExtBRC const & extBRC = GetExtBufferRef(par);
6011 
6012     if (extOpt3->PRefType == MFX_P_REF_DEFAULT)
6013     {
6014         if (par.mfx.GopRefDist == 1 &&
6015             par.calcParam.numTemporalLayer == 0 &&
6016             extDdi->NumActiveRefP != 1 &&
6017             (par.mfx.FrameInfo.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) &&
6018             ((IsExtBrcSceneChangeSupported(par) && !extBRC.pthis)
6019 
6020             ))
6021             extOpt3->PRefType = MFX_P_REF_PYRAMID;
6022         else if (par.mfx.GopRefDist == 1)
6023             extOpt3->PRefType = MFX_P_REF_SIMPLE;
6024     }
6025 
6026     if (!extOpt3->EnableQPOffset)
6027     {
6028         mfxU16 minQP = 1;
6029         mfxU16 maxQP = 51;
6030         if (par.mfx.RateControlMethod == MFX_RATECONTROL_CQP
6031             && (extOpt2->BRefType == MFX_B_REF_PYRAMID || extOpt3->PRefType == MFX_P_REF_PYRAMID))
6032         {
6033             extOpt3->EnableQPOffset = MFX_CODINGOPTION_ON;
6034             mfxI16 QPX = (par.mfx.GopRefDist == 1) ? par.mfx.QPP : par.mfx.QPB;
6035 
6036             for (mfxI16 i = 0; i < 8; i++)
6037                 extOpt3->QPOffset[i] = mfx::clamp<mfxI16>(i + (par.mfx.GopRefDist > 1), (mfxI16)minQP - QPX, (mfxI16)maxQP - QPX);
6038         }
6039         else
6040             extOpt3->EnableQPOffset = MFX_CODINGOPTION_OFF;
6041     }
6042 
6043     if (IsOff(extOpt3->EnableQPOffset))
6044         Zero(extOpt3->QPOffset);
6045 
6046     if (extOpt2->MinQPI || extOpt2->MinQPP || extOpt2->MinQPB ||
6047         extOpt2->MaxQPI || extOpt2->MaxQPP || extOpt2->MaxQPB)
6048     {
6049         if (!extOpt2->MaxQPI)
6050            extOpt2->MaxQPI = 51;
6051         if (!extOpt2->MaxQPP)
6052            extOpt2->MaxQPP = 51;
6053         if (!extOpt2->MaxQPB)
6054             extOpt2->MaxQPB = 51;
6055     }
6056     extDdi->MaxMVs = 32;
6057     extDdi->SkipCheck = 1;
6058     extDdi->DirectCheck = 1;
6059     extDdi->BiDirSearch = 1;
6060     extDdi->FieldPrediction = fieldCodingPossible;
6061     extDdi->MVPrediction = 1;
6062 
6063     if (extDdi->StrengthN == 0)
6064         extDdi->StrengthN = 220;
6065 
6066     if (par.mfx.NumRefFrame == 0)
6067     {
6068         mfxU16 const nrfAdapt           =
6069             (IsOn(extOpt3->ExtBrcAdaptiveLTR)
6070 #if defined(MFX_ENABLE_ENCTOOLS)
6071                 || (!IsOff(extConfig->AdaptiveLTR))
6072 #endif
6073 
6074             ) ? 2 : 0;
6075         mfxU16 const nrfMin             = (par.mfx.GopRefDist > 1 ? 2 : 1) + nrfAdapt;
6076         mfxU16 const nrfDefault         = std::max<mfxU16>(nrfMin, GetDefaultNumRefFrames(par.mfx.TargetUsage) + nrfAdapt);
6077         mfxU16 const nrfMaxByCaps       = mfx::clamp<mfxU16>(hwCaps.ddi_caps.MaxNum_Reference, 1, 8) * 2;
6078         mfxU16 const nrfMaxByLevel      = GetMaxNumRefFrame(par);
6079         mfxU16 const nrfMinForPyramid   = GetMinNumRefFrameForPyramid(par) + nrfAdapt;
6080         mfxU16 const nrfMinForTemporal  = mfxU16(nrfMin + par.calcParam.numTemporalLayer - 1);
6081         mfxU16 const nrfMinForInterlace = 2; // HSW and IVB don't support 1 reference frame for interlace
6082 
6083         if (par.calcParam.numTemporalLayer > 1)
6084             par.mfx.NumRefFrame = nrfMinForTemporal;
6085         else if (extOpt2->BRefType != MFX_B_REF_OFF)
6086             par.mfx.NumRefFrame = nrfMinForPyramid;
6087         else if (extOpt2->IntRefType)
6088             par.mfx.NumRefFrame = 1;
6089         else if ((par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_PROGRESSIVE) == 0)
6090             par.mfx.NumRefFrame = std::min({std::max(nrfDefault, nrfMinForInterlace), nrfMaxByLevel, nrfMaxByCaps});
6091         else if (extOpt3->PRefType == MFX_P_REF_PYRAMID)
6092             par.mfx.NumRefFrame = std::max<mfxU16>((mfxU16)par.calcParam.PPyrInterval, nrfDefault);
6093         else
6094             par.mfx.NumRefFrame = std::min({nrfDefault, nrfMaxByLevel, nrfMaxByCaps});
6095 
6096         if (IsOn(par.mfx.LowPower) && (extOpt3->PRefType != MFX_P_REF_PYRAMID))
6097         {
6098             par.mfx.NumRefFrame = std::min<mfxU16>(hwCaps.ddi_caps.MaxNum_Reference, par.mfx.NumRefFrame);
6099         }
6100 
6101         par.calcParam.PPyrInterval = std::min<mfxU32>(par.calcParam.PPyrInterval, par.mfx.NumRefFrame);
6102     }
6103 
6104     if (extOpt->IntraPredBlockSize == MFX_BLOCKSIZE_UNKNOWN)
6105         extOpt->IntraPredBlockSize = GetDefaultIntraPredBlockSize(par, platform);
6106 
6107     if (par.mfx.CodecProfile == MFX_PROFILE_UNKNOWN)
6108     {
6109         par.mfx.CodecProfile = MFX_PROFILE_AVC_BASELINE;
6110 
6111         if ((par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_TFF) ||
6112             (par.mfx.FrameInfo.PicStruct & MFX_PICSTRUCT_FIELD_BFF))
6113             par.mfx.CodecProfile = MFX_PROFILE_AVC_MAIN;
6114 
6115         if (par.mfx.GopRefDist > 1)
6116             par.mfx.CodecProfile = MFX_PROFILE_AVC_MAIN;
6117 
6118         if (IsOff(extOpt->CAVLC))
6119             par.mfx.CodecProfile = MFX_PROFILE_AVC_MAIN;
6120 
6121         if (extOpt->IntraPredBlockSize >= MFX_BLOCKSIZE_MIN_8X8)
6122             par.mfx.CodecProfile = MFX_PROFILE_AVC_HIGH;
6123     }
6124 
6125     if (par.mfx.CodecLevel == MFX_LEVEL_UNKNOWN)
6126         par.mfx.CodecLevel = GetMinLevelForAllParameters(par);
6127 
6128     if (extOpt2->BufferingPeriodSEI == MFX_BPSEI_DEFAULT
6129         && IsOn(extOpt->RecoveryPointSEI)
6130         && extOpt2->IntRefType == 0
6131         && !isENCorPAK)
6132     {
6133         extOpt2->BufferingPeriodSEI = MFX_BPSEI_IFRAME;
6134     }
6135 
6136     SetDefaultOff(extOpt2->DisableVUI);
6137     SetDefaultOn(extOpt3->AspectRatioInfoPresent);
6138     SetDefaultOff(extOpt3->OverscanInfoPresent);
6139     SetDefaultOn(extOpt3->TimingInfoPresent);
6140     SetDefaultOn(extOpt2->FixedFrameRate);
6141     SetDefaultOff(extOpt3->LowDelayHrd);
6142     SetDefaultOn(extOpt3->BitstreamRestriction);
6143     SetDefaultOff(extOpt->RecoveryPointSEI);
6144     SetDefaultOff(extOpt3->DirectBiasAdjustment);
6145     SetDefaultOff(extOpt3->GlobalMotionBiasAdjustment);
6146     SetDefaultOff(extOpt3->LowDelayBRC);
6147 
6148 #ifdef MFX_ENABLE_H264_REPARTITION_CHECK
6149 #endif // MFX_ENABLE_H264_REPARTITION_CHECK
6150 
6151 #if (MFX_VERSION >= 1026)
6152     if (extOpt3->ExtBrcAdaptiveLTR == MFX_CODINGOPTION_UNKNOWN)
6153     {
6154         extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_OFF;
6155         // remove check when sample extbrc is same as implicit extbrc
6156         // currently added for no behaviour change in sample extbrc
6157         if (IsExtBrcSceneChangeSupported(par) && !extBRC.pthis)
6158         {
6159             extOpt3->ExtBrcAdaptiveLTR = MFX_CODINGOPTION_ON;
6160             // make sure to call CheckVideoParamQueryLike
6161             // or add additional conditions above (num ref & num active)
6162         }
6163     }
6164 
6165     if (extOpt2->AdaptiveI == MFX_CODINGOPTION_UNKNOWN)
6166     {
6167         if ((IsExtBrcSceneChangeSupported(par) && !extBRC.pthis)
6168 #if defined(MFX_ENABLE_ENCTOOLS)
6169            || (!IsOff(extConfig->AdaptiveI))
6170 #endif
6171             )
6172             extOpt2->AdaptiveI = MFX_CODINGOPTION_ON;
6173         else
6174             extOpt2->AdaptiveI = MFX_CODINGOPTION_OFF;
6175     }
6176 
6177     if (extOpt2->AdaptiveB == MFX_CODINGOPTION_UNKNOWN)
6178     {
6179         if ((IsExtBrcSceneChangeSupported(par) && !extBRC.pthis)
6180 #if defined(MFX_ENABLE_ENCTOOLS)
6181         || (!IsOff(extConfig->AdaptiveB) && !IsOff(extConfig->AdaptiveI))
6182 #endif
6183             )
6184             extOpt2->AdaptiveB = MFX_CODINGOPTION_ON;
6185         else
6186             extOpt2->AdaptiveB = MFX_CODINGOPTION_OFF;
6187     }
6188 #endif //(MFX_VERSION >= 1026)
6189 
6190     CheckVideoParamQueryLike(par, hwCaps, platform, vaType, config);
6191 
6192     if (extOpt3->NumSliceI == 0 && extOpt3->NumSliceP == 0 && extOpt3->NumSliceB == 0)
6193         extOpt3->NumSliceI = extOpt3->NumSliceP = extOpt3->NumSliceB = par.mfx.NumSlice;
6194 
6195     if (extOpt2->MBBRC == MFX_CODINGOPTION_UNKNOWN)
6196     {
6197         if (par.mfx.RateControlMethod == MFX_RATECONTROL_ICQ)
6198         {
6199             // for ICQ BRC mode MBBRC is ignored by driver and always treated as ON
6200             // need to change extOpt2->MBBRC respectively to notify application about it
6201             extOpt2->MBBRC = MFX_CODINGOPTION_ON;
6202         }
6203         else
6204         {
6205             // turn off MBBRC by default
6206             extOpt2->MBBRC = MFX_CODINGOPTION_OFF;
6207         }
6208     }
6209 
6210     if (extOpt2->IntRefType && extOpt2->IntRefCycleSize == 0)
6211     {
6212         if (extOpt2->IntRefType == MFX_REFRESH_SLICE)
6213         {
6214             extOpt2->IntRefCycleSize = extOpt3->NumSliceP;
6215         }
6216         else
6217         {
6218             // set intra refresh cycle to 1 sec by default
6219             extOpt2->IntRefCycleSize =
6220                 (mfxU16)((par.mfx.FrameInfo.FrameRateExtN + par.mfx.FrameInfo.FrameRateExtD - 1) / par.mfx.FrameInfo.FrameRateExtD);
6221         }
6222     }
6223 
6224     if (par.calcParam.mvcPerViewPar.codecLevel == MFX_LEVEL_UNKNOWN)
6225         par.calcParam.mvcPerViewPar.codecLevel = MFX_LEVEL_AVC_1;
6226 
6227     if (extOpt3->EnableMBQP == MFX_CODINGOPTION_UNKNOWN) {
6228 #if defined(ENABLE_APQ_LQ)  && defined(MFX_ENABLE_ENCTOOLS)
6229         if ((par.mfx.RateControlMethod == MFX_RATECONTROL_CQP || (!IsOff(extConfig->BRC)))
6230             && (!IsOff(extConfig->AdaptivePyramidQuantP) || !IsOff(extConfig->AdaptivePyramidQuantB)))
6231         {
6232             extOpt3->EnableMBQP = MFX_CODINGOPTION_ON;
6233         }
6234         else
6235 #endif
6236         extOpt3->EnableMBQP = MFX_CODINGOPTION_OFF;
6237     }
6238 
6239     if (extOpt3->MBDisableSkipMap == MFX_CODINGOPTION_UNKNOWN)
6240         extOpt3->MBDisableSkipMap = MFX_CODINGOPTION_OFF;
6241 
6242 #if MFX_VERSION >= 1023
6243     if (extOpt3->EnableMBForceIntra == MFX_CODINGOPTION_UNKNOWN)
6244         extOpt3->EnableMBForceIntra = MFX_CODINGOPTION_OFF;
6245 #endif
6246 
6247     if (par.calcParam.cqpHrdMode == 0)
6248     {
6249         if (par.calcParam.maxKbps == 0)
6250         {
6251             if (par.mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
6252                 par.mfx.RateControlMethod == MFX_RATECONTROL_WIDI_VBR ||
6253                 par.mfx.RateControlMethod == MFX_RATECONTROL_VCM ||
6254                 par.mfx.RateControlMethod == MFX_RATECONTROL_QVBR ||
6255                 par.mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD)
6256             {
6257                 mfxU32 maxBps = par.calcParam.targetKbps * MAX_BITRATE_RATIO;
6258                 if (IsOn(extOpt->NalHrdConformance) ||
6259                     IsOn(extOpt->VuiVclHrdParameters))
6260                     maxBps = std::min(maxBps, GetMaxBitrate(par));
6261 
6262                 par.calcParam.maxKbps = maxBps / 1000;
6263                 assert(par.calcParam.maxKbps >= par.calcParam.targetKbps);
6264             }
6265             else if (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR)
6266             {
6267                 par.calcParam.maxKbps = par.calcParam.targetKbps;
6268             }
6269         }
6270 
6271         if (par.calcParam.bufferSizeInKB == 0)
6272         {
6273             if (bRateControlLA(par.mfx.RateControlMethod) && (par.mfx.RateControlMethod != MFX_RATECONTROL_LA_HRD))
6274             {
6275                 par.calcParam.bufferSizeInKB = GetMaxCodedFrameSizeInKB(par);
6276             }
6277             else
6278             {
6279                 mfxU32 bufferSizeInBits = std::min(
6280                     GetMaxBufferSize(par),                           // limit by spec
6281                     par.calcParam.maxKbps * DEFAULT_CPB_IN_SECONDS); // limit by common sense
6282 
6283                 par.calcParam.bufferSizeInKB = !IsHRDBasedBRCMethod(par.mfx.RateControlMethod)
6284                         ? GetMaxCodedFrameSizeInKB(par)
6285                         : bufferSizeInBits / 8000;
6286             }
6287             par.calcParam.bufferSizeInKB = std::max(par.calcParam.bufferSizeInKB, par.calcParam.initialDelayInKB);
6288 
6289         }
6290 
6291         if (par.calcParam.initialDelayInKB == 0 && IsHRDBasedBRCMethod(par.mfx.RateControlMethod))
6292         {
6293             par.calcParam.initialDelayInKB = par.calcParam.bufferSizeInKB / 2;
6294         }
6295     }
6296 
6297     if (IsMvcProfile(par.mfx.CodecProfile))
6298     {
6299         CheckVideoParamMvcQueryLike(par);
6300 
6301         if (par.calcParam.cqpHrdMode == 0)
6302         {
6303             if (par.calcParam.mvcPerViewPar.maxKbps == 0)
6304             {
6305                 if (par.mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
6306                     par.mfx.RateControlMethod == MFX_RATECONTROL_WIDI_VBR ||
6307                     par.mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD)
6308                 {
6309                     mfxU32 maxBps = par.calcParam.mvcPerViewPar.targetKbps * MAX_BITRATE_RATIO;
6310                     if (IsOn(extOpt->NalHrdConformance) ||
6311                         IsOn(extOpt->VuiVclHrdParameters))
6312                         maxBps = std::min(maxBps, GetMaxPerViewBitrate(par));
6313 
6314                     par.calcParam.mvcPerViewPar.maxKbps = maxBps / 1000;
6315                     assert(par.calcParam.mvcPerViewPar.maxKbps >= par.calcParam.mvcPerViewPar.targetKbps);
6316                 }
6317                 else if (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR)
6318                 {
6319                     par.calcParam.mvcPerViewPar.maxKbps = par.calcParam.mvcPerViewPar.targetKbps;
6320                 }
6321             }
6322 
6323             if (par.calcParam.mvcPerViewPar.bufferSizeInKB == 0)
6324             {
6325                 mfxU32 bufferSizeInBits = std::min(
6326                     GetMaxPerViewBufferSize(par),                                  // limit by spec
6327                     par.calcParam.mvcPerViewPar.maxKbps * DEFAULT_CPB_IN_SECONDS); // limit by common sense
6328 
6329                 par.calcParam.mvcPerViewPar.bufferSizeInKB = !IsHRDBasedBRCMethod(par.mfx.RateControlMethod)
6330                     ? GetMaxCodedFrameSizeInKB(par)
6331                     : bufferSizeInBits / 8000;
6332                 par.calcParam.mvcPerViewPar.bufferSizeInKB = std::max(par.calcParam.mvcPerViewPar.bufferSizeInKB,
6333                     2 * par.calcParam.mvcPerViewPar.initialDelayInKB);
6334             }
6335             // HRD buffer size can be different for the same level for AVC and MVC profiles.
6336             // So in case of MVC we need to copy MVC-specific buffer size to calcParam.bufferSizeInKB to assure that application will get enough size for bitstream buffer allocation
6337             par.calcParam.bufferSizeInKB = par.calcParam.mvcPerViewPar.bufferSizeInKB;
6338             par.calcParam.initialDelayInKB = std::min(par.calcParam.initialDelayInKB, par.calcParam.bufferSizeInKB);
6339 
6340             if (par.calcParam.mvcPerViewPar.initialDelayInKB == 0 && IsHRDBasedBRCMethod(par.mfx.RateControlMethod))
6341             {
6342                 par.calcParam.mvcPerViewPar.initialDelayInKB = par.calcParam.mvcPerViewPar.bufferSizeInKB / 2;
6343             }
6344         }
6345     }
6346 
6347     if (extOpt->MaxDecFrameBuffering == 0)
6348     {
6349         extOpt->MaxDecFrameBuffering = par.mfx.NumRefFrame;
6350     }
6351 
6352     if (extDdi->DisablePSubMBPartition == MFX_CODINGOPTION_UNKNOWN)
6353     {
6354         extDdi->DisablePSubMBPartition = MFX_CODINGOPTION_OFF;
6355 
6356         // check restriction A.3.3 (f)
6357         if (IsAvcBaseProfile(par.mfx.CodecProfile) && par.mfx.CodecLevel <= MFX_LEVEL_AVC_3)
6358             extDdi->DisablePSubMBPartition = MFX_CODINGOPTION_ON;
6359     }
6360 
6361     if (extDdi->DisableBSubMBPartition == MFX_CODINGOPTION_UNKNOWN)
6362     {
6363         extDdi->DisableBSubMBPartition = MFX_CODINGOPTION_OFF;
6364 
6365         // check restriction A.3.3 (f)
6366         if (IsAvcBaseProfile(par.mfx.CodecProfile) && par.mfx.CodecLevel <= MFX_LEVEL_AVC_3)
6367             extDdi->DisableBSubMBPartition = MFX_CODINGOPTION_ON;
6368     }
6369 
6370     if (extDdi->WeightedBiPredIdc == 0)
6371     {
6372         extDdi->WeightedBiPredIdc = (par.mfx.GopRefDist == 3 && !IsMvcProfile(par.mfx.CodecProfile) && extOpt2->BRefType == MFX_B_REF_OFF)
6373             ? 2  // explicit weighted biprediction (when 2 B frames in a row)
6374             : 0; // no weighted biprediction
6375     }
6376 
6377     if (extDdi->CabacInitIdcPlus1 == 0)
6378     {
6379         extDdi->CabacInitIdcPlus1 = GetCabacInitIdc(par.mfx.TargetUsage) + 1;
6380     }
6381 
6382     bool IsEnabledSwBrc = isSWBRC(par);
6383 
6384     if (par.calcParam.TCBRCTargetFrameSize == 0)
6385     {
6386         par.calcParam.TCBRCTargetFrameSize = IsTCBRC(par, hwCaps) ? GetAvgFrameSizeInBytes(par, false) : 0;
6387     }
6388 
6389     if ((hwCaps.ddi_caps.UserMaxFrameSizeSupport != 0 || IsEnabledSwBrc) &&
6390         (par.mfx.RateControlMethod != MFX_RATECONTROL_CBR &&
6391          par.mfx.RateControlMethod != MFX_RATECONTROL_CQP) &&
6392         extOpt2->MaxFrameSize == 0)
6393     {
6394         extOpt2->MaxFrameSize = std::max(extOpt3->MaxFrameSizeI, extOpt3->MaxFrameSizeP);
6395 
6396         if (!extOpt2->MaxFrameSize)
6397         {
6398             extOpt2->MaxFrameSize = (IsOn(extOpt3->LowDelayBRC)) ?
6399                 GetAvgFrameSizeInBytes(par, true):
6400                 std::min(GetMaxFrameSize(par), GetFirstMaxFrameSize(par));
6401         }
6402     }
6403 
6404 #if MFX_VERSION >= 1023
6405     if (extOpt3->AdaptiveMaxFrameSize == MFX_CODINGOPTION_UNKNOWN )
6406         extOpt3->AdaptiveMaxFrameSize =
6407             ((platform >= MFX_HW_ICL) && IsOn(par.mfx.LowPower) && hwCaps.AdaptiveMaxFrameSizeSupport)
6408             ? mfxU16(MFX_CODINGOPTION_ON) : mfxU16(MFX_CODINGOPTION_OFF);
6409 #endif
6410 
6411 #ifdef MFX_ENABLE_H264_REPARTITION_CHECK
6412     if (extOpt3->RepartitionCheckEnable == MFX_CODINGOPTION_UNKNOWN)
6413         extOpt3->RepartitionCheckEnable = MFX_CODINGOPTION_ADAPTIVE;
6414 #endif // MFX_ENABLE_H264_REPARTITION_CHECK
6415 
6416     par.ApplyDefaultsToMvcSeqDesc();
6417 
6418 
6419     if (extBits->SPSBuffer == 0)
6420     {
6421         mfxFrameInfo const & fi = par.mfx.FrameInfo;
6422 
6423 
6424         extSps->nalRefIdc                       = par.calcParam.tempScalabilityMode ? 3 : 1;
6425         extSps->nalUnitType                     = 7;
6426         extSps->profileIdc                      = mfxU8(par.mfx.CodecProfile & MASK_PROFILE_IDC);
6427         extSps->constraints.set0                = mfxU8(!!(par.mfx.CodecProfile & MASK_CONSTRAINT_SET0_FLAG));
6428         extSps->constraints.set1                = mfxU8(!!(par.mfx.CodecProfile & MASK_CONSTRAINT_SET1_FLAG));
6429         if (par.calcParam.numTemporalLayer > 0 && IsAvcBaseProfile(par.mfx.CodecProfile))
6430             extSps->constraints.set1            = 1; // tempScalabilityMode requires constraint base profile
6431         extSps->constraints.set2                = mfxU8(!!(par.mfx.CodecProfile & MASK_CONSTRAINT_SET2_FLAG));
6432         extSps->constraints.set3                = mfxU8(!!(par.mfx.CodecProfile & MASK_CONSTRAINT_SET3_FLAG));
6433         extSps->constraints.set4                = mfxU8(!!(par.mfx.CodecProfile & MASK_CONSTRAINT_SET4_FLAG));
6434         extSps->constraints.set5                = mfxU8(!!(par.mfx.CodecProfile & MASK_CONSTRAINT_SET5_FLAG));
6435         extSps->constraints.set6                = 0;
6436         extSps->constraints.set7                = 0;
6437         extSps->levelIdc                        = IsMvcProfile(par.mfx.CodecProfile) ? mfxU8(par.calcParam.mvcPerViewPar.codecLevel) : mfxU8(par.mfx.CodecLevel);
6438         extSps->seqParameterSetId               = mfxU8(extBits->SPSId);
6439         extSps->chromaFormatIdc                 = mfxU8(MFX_CHROMAFORMAT_YUV420);//in case if RGB or YUY2 passed we still need encode in 420
6440         extSps->separateColourPlaneFlag         = 0;
6441         extSps->bitDepthLumaMinus8              = 0;
6442         extSps->bitDepthChromaMinus8            = 0;
6443         extSps->qpprimeYZeroTransformBypassFlag = 0;
6444         extSps->seqScalingMatrixPresentFlag     = 0;
6445         extSps->log2MaxFrameNumMinus4           = 4;//GetDefaultLog2MaxFrameNumMinux4(par);
6446         extSps->picOrderCntType                 = (extOpt2->SkipFrame == MFX_SKIPFRAME_INSERT_DUMMY) ? 0  : GetDefaultPicOrderCount(par);
6447         extSps->log2MaxPicOrderCntLsbMinus4     = extOpt2->SkipFrame ? ((mfxU8)CeilLog2(2 * par.mfx.GopPicSize) + 1 - 4) : GetDefaultLog2MaxPicOrdCntMinus4(par);
6448         extSps->log2MaxPicOrderCntLsbMinus4     = std::min<mfxU8>(12, extSps->log2MaxPicOrderCntLsbMinus4);
6449         extSps->deltaPicOrderAlwaysZeroFlag     = 1;
6450         extSps->maxNumRefFrames                 = mfxU8(par.mfx.NumRefFrame);
6451         extSps->gapsInFrameNumValueAllowedFlag  = par.calcParam.numTemporalLayer > 1
6452             || par.calcParam.tempScalabilityMode; // for tempScalabilityMode change of temporal structure shouldn't change SPS.
6453         extSps->frameMbsOnlyFlag                = (fi.PicStruct == MFX_PICSTRUCT_PROGRESSIVE) ? 1 : 0;
6454         extSps->picWidthInMbsMinus1             = (fi.Width / 16) - 1;
6455         extSps->picHeightInMapUnitsMinus1       = (fi.Height / 16 / (2 - extSps->frameMbsOnlyFlag)) - 1;
6456         extSps->direct8x8InferenceFlag          = 1;
6457 
6458         //Fix cropping for ARGB and YUY2 formats, need to redesign in case real 444 or 422 support in AVC.
6459         mfxU16 croma_format = fi.ChromaFormat;
6460         if(croma_format == MFX_CHROMAFORMAT_YUV444 || croma_format == MFX_CHROMAFORMAT_YUV422)
6461             croma_format = MFX_CHROMAFORMAT_YUV420;
6462         mfxU16 cropUnitX = CROP_UNIT_X[croma_format];
6463         mfxU16 cropUnitY = CROP_UNIT_Y[croma_format] * (2 - extSps->frameMbsOnlyFlag);
6464 
6465         extSps->frameCropLeftOffset   = (fi.CropX / cropUnitX);
6466         extSps->frameCropRightOffset  = (fi.Width - fi.CropW - fi.CropX) / cropUnitX;
6467         extSps->frameCropTopOffset    = (fi.CropY / cropUnitY);
6468         extSps->frameCropBottomOffset = (fi.Height - fi.CropH - fi.CropY) / cropUnitY;
6469         extSps->frameCroppingFlag     =
6470             extSps->frameCropLeftOffset || extSps->frameCropRightOffset ||
6471             extSps->frameCropTopOffset  || extSps->frameCropBottomOffset;
6472 
6473         extSps->vuiParametersPresentFlag = !IsOn(extOpt2->DisableVUI);
6474 
6475         if (extSps->vuiParametersPresentFlag)
6476         {
6477             AspectRatioConverter arConv(fi.AspectRatioW, fi.AspectRatioH);
6478             extSps->vui.flags.aspectRatioInfoPresent = (fi.AspectRatioH && fi.AspectRatioW) && !IsOff(extOpt3->AspectRatioInfoPresent);
6479             extSps->vui.aspectRatioIdc               = arConv.GetSarIdc();
6480             extSps->vui.sarWidth                     = arConv.GetSarWidth();
6481             extSps->vui.sarHeight                    = arConv.GetSarHeight();
6482 
6483             extSps->vui.flags.overscanInfoPresent = !IsOff(extOpt3->OverscanInfoPresent);
6484             extSps->vui.flags.overscanAppropriate = !IsOff(extOpt3->OverscanAppropriate);
6485 
6486             extSps->vui.videoFormat                    = mfxU8(extVsi->VideoFormat);
6487             extSps->vui.flags.videoFullRange           = extVsi->VideoFullRange;
6488             extSps->vui.flags.colourDescriptionPresent = extVsi->ColourDescriptionPresent;
6489             extSps->vui.colourPrimaries                = mfxU8(extVsi->ColourPrimaries);
6490             extSps->vui.transferCharacteristics        = mfxU8(extVsi->TransferCharacteristics);
6491             extSps->vui.matrixCoefficients             = mfxU8(extVsi->MatrixCoefficients);
6492             extSps->vui.flags.videoSignalTypePresent   =
6493                 extSps->vui.videoFormat                    != 5 ||
6494                 extSps->vui.flags.videoFullRange           != 0 ||
6495                 extSps->vui.flags.colourDescriptionPresent != 0;
6496 
6497             extSps->vui.flags.chromaLocInfoPresent     = !!extCli->ChromaLocInfoPresentFlag;
6498             extSps->vui.chromaSampleLocTypeTopField    = mfxU8(extCli->ChromaSampleLocTypeTopField);
6499             extSps->vui.chromaSampleLocTypeBottomField = mfxU8(extCli->ChromaSampleLocTypeBottomField);
6500 
6501             extSps->vui.flags.timingInfoPresent = !IsOff(extOpt3->TimingInfoPresent);
6502             extSps->vui.numUnitsInTick          = fi.FrameRateExtD;
6503             extSps->vui.timeScale               = fi.FrameRateExtN * 2;
6504             extSps->vui.flags.fixedFrameRate    = !IsOff(extOpt2->FixedFrameRate);
6505 
6506 
6507             extSps->vui.flags.nalHrdParametersPresent = IsOn(extOpt->VuiNalHrdParameters);
6508             extSps->vui.flags.vclHrdParametersPresent = IsOn(extOpt->VuiVclHrdParameters);
6509 
6510             extSps->vui.nalHrdParameters.cpbCntMinus1 = 0;
6511             extSps->vui.nalHrdParameters.bitRateScale = SCALE_FROM_DRIVER;
6512             extSps->vui.nalHrdParameters.cpbSizeScale = 2;
6513 
6514             if (par.calcParam.cqpHrdMode)
6515             {
6516                 extSps->vui.nalHrdParameters.bitRateValueMinus1[0] = GetMaxBitrateValue(par.calcParam.decorativeHrdParam.maxKbps) - 1;
6517                 extSps->vui.nalHrdParameters.cpbSizeValueMinus1[0] = GetCpbSizeValue(par.calcParam.decorativeHrdParam.bufferSizeInKB, 2) - 1;
6518                 extSps->vui.nalHrdParameters.cbrFlag[0] = par.calcParam.cqpHrdMode == 1 ? 1 : 0;
6519             }
6520             else
6521             {
6522                 //FIXME: extSps isn't syncronized with m_video after next assignment for ViewOutput mode. Need to Init ExtSps HRD for MVC keeping them syncronized
6523                 if (IsMvcProfile(par.mfx.CodecProfile))
6524                 {
6525                     extSps->vui.nalHrdParameters.bitRateValueMinus1[0] = GetMaxBitrateValue(par.calcParam.mvcPerViewPar.maxKbps) - 1;
6526                     extSps->vui.nalHrdParameters.cpbSizeValueMinus1[0] = GetCpbSizeValue(par.calcParam.mvcPerViewPar.bufferSizeInKB, 2) - 1;
6527                 }
6528                 else
6529                 {
6530                     extSps->vui.nalHrdParameters.bitRateValueMinus1[0] = GetMaxBitrateValue(par.calcParam.maxKbps) - 1;
6531                     extSps->vui.nalHrdParameters.cpbSizeValueMinus1[0] = GetCpbSizeValue(par.calcParam.bufferSizeInKB, 2) - 1;
6532                 }
6533             extSps->vui.nalHrdParameters.cbrFlag[0]                         = (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR);
6534             }
6535             extSps->vui.nalHrdParameters.initialCpbRemovalDelayLengthMinus1 = 23;
6536             extSps->vui.nalHrdParameters.cpbRemovalDelayLengthMinus1        = 23;
6537             extSps->vui.nalHrdParameters.dpbOutputDelayLengthMinus1         = 23;
6538             extSps->vui.nalHrdParameters.timeOffsetLength                   = 24;
6539 
6540             extSps->vui.vclHrdParameters.cpbCntMinus1                       = 0;
6541             extSps->vui.vclHrdParameters.bitRateScale                       = SCALE_FROM_DRIVER;
6542             extSps->vui.vclHrdParameters.cpbSizeScale                       = 2;
6543             if (IsMvcProfile(par.mfx.CodecProfile))
6544             {
6545                 extSps->vui.vclHrdParameters.bitRateValueMinus1[0] = GetMaxBitrateValue(par.calcParam.mvcPerViewPar.maxKbps) - 1;
6546                 extSps->vui.vclHrdParameters.cpbSizeValueMinus1[0] = GetCpbSizeValue(par.calcParam.mvcPerViewPar.bufferSizeInKB, 2) - 1;
6547             }
6548             else
6549             {
6550                 extSps->vui.vclHrdParameters.bitRateValueMinus1[0] = GetMaxBitrateValue(par.calcParam.maxKbps) - 1;
6551                 extSps->vui.vclHrdParameters.cpbSizeValueMinus1[0] = GetCpbSizeValue(par.calcParam.bufferSizeInKB, 2) - 1;
6552             }
6553             extSps->vui.vclHrdParameters.cbrFlag[0]                         = (par.mfx.RateControlMethod == MFX_RATECONTROL_CBR);
6554             extSps->vui.vclHrdParameters.initialCpbRemovalDelayLengthMinus1 = 23;
6555             extSps->vui.vclHrdParameters.cpbRemovalDelayLengthMinus1        = 23;
6556             extSps->vui.vclHrdParameters.dpbOutputDelayLengthMinus1         = 23;
6557             extSps->vui.vclHrdParameters.timeOffsetLength                   = 24;
6558 
6559             extSps->vui.flags.lowDelayHrd                                   = IsOn(extOpt3->LowDelayHrd);;
6560             extSps->vui.flags.picStructPresent                              = IsOn(extOpt->PicTimingSEI);
6561 
6562             extSps->vui.flags.bitstreamRestriction           = !IsOff(extOpt3->BitstreamRestriction);
6563             extSps->vui.flags.motionVectorsOverPicBoundaries = !IsOff(extOpt3->MotionVectorsOverPicBoundaries);
6564             extSps->vui.maxBytesPerPicDenom                  = 2;
6565             extSps->vui.maxBitsPerMbDenom                    = 1;
6566             extSps->vui.log2MaxMvLengthHorizontal            = mfxU8(CeilLog2(4 * MAX_H_MV - 1));
6567             extSps->vui.log2MaxMvLengthVertical              = mfxU8(CeilLog2(4 * GetMaxVmv(par.mfx.CodecLevel) - 1));
6568             extSps->vui.numReorderFrames                     = GetNumReorderFrames(par);
6569             extSps->vui.maxDecFrameBuffering                 = mfxU8(extOpt->MaxDecFrameBuffering);
6570 
6571             extSps->vuiParametersPresentFlag =
6572                 extSps->vui.flags.aspectRatioInfoPresent  ||
6573                 extSps->vui.flags.overscanInfoPresent     ||
6574                 extSps->vui.flags.videoSignalTypePresent  ||
6575                 extSps->vui.flags.chromaLocInfoPresent    ||
6576                 extSps->vui.flags.timingInfoPresent       ||
6577                 extSps->vui.flags.nalHrdParametersPresent ||
6578                 extSps->vui.flags.vclHrdParametersPresent ||
6579                 extSps->vui.flags.picStructPresent        ||
6580                 extSps->vui.flags.bitstreamRestriction;
6581         }
6582     }
6583 
6584     if (extBits->PPSBufSize == 0)
6585     {
6586         extPps->nalRefIdc                             = par.calcParam.tempScalabilityMode ? 3 : 1;
6587         extPps->picParameterSetId                     = mfxU8(extBits->PPSId);
6588         extPps->seqParameterSetId                     = mfxU8(extBits->SPSId);
6589         extPps->entropyCodingModeFlag                 = IsOff(extOpt->CAVLC);
6590         extPps->bottomFieldPicOrderInframePresentFlag = 0;
6591         extPps->numSliceGroupsMinus1                  = 0;
6592         extPps->sliceGroupMapType                     = 0;
6593         extPps->numRefIdxL0DefaultActiveMinus1        = 0;
6594         extPps->numRefIdxL1DefaultActiveMinus1        = 0;
6595         extPps->weightedPredFlag                      = mfxU8(extOpt3->WeightedPred == MFX_WEIGHTED_PRED_EXPLICIT);
6596         extPps->weightedBipredIdc                     = extOpt3->WeightedBiPred ? mfxU8(extOpt3->WeightedBiPred - 1) : mfxU8(extDdi->WeightedBiPredIdc);
6597         extPps->picInitQpMinus26                      = 0;
6598         extPps->picInitQsMinus26                      = 0;
6599         extPps->chromaQpIndexOffset                   = 0;
6600         extPps->deblockingFilterControlPresentFlag    = 1;
6601         extPps->constrainedIntraPredFlag              = 0;
6602         extPps->redundantPicCntPresentFlag            = 0;
6603         extPps->moreRbspData                          =
6604             !IsAvcBaseProfile(par.mfx.CodecProfile) &&
6605             par.mfx.CodecProfile != MFX_PROFILE_AVC_MAIN;
6606         extPps->transform8x8ModeFlag                  = extDdi->Transform8x8Mode == MFX_CODINGOPTION_UNKNOWN ?
6607             extOpt->IntraPredBlockSize > MFX_BLOCKSIZE_MIN_16X16 : IsOn(extDdi->Transform8x8Mode);
6608         extPps->picScalingMatrixPresentFlag           = 0;
6609         extPps->secondChromaQpIndexOffset             = 0;
6610     }
6611 
6612 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
6613     SetDefaultOff(extOpt3->EncodedUnitsInfo);
6614 #endif
6615 
6616     par.SyncCalculableToVideoParam();
6617     par.AlignCalcWithBRCParamMultiplier();
6618 }
6619 
CheckPayloads(const mfxPayload * const * payload,mfxU16 numPayload)6620 mfxStatus MfxHwH264Encode::CheckPayloads(
6621     const mfxPayload* const* payload,
6622     mfxU16 numPayload)
6623 {
6624     const mfxU8 SUPPORTED_SEI[] = {
6625         0, // 00 buffering_period
6626         0, // 01 pic_timing
6627         1, // 02 pan_scan_rect
6628         1, // 03 filler_payload
6629         1, // 04 user_data_registered_itu_t_t35
6630         1, // 05 user_data_unregistered
6631         1, // 06 recovery_point
6632         0, // 07 dec_ref_pic_marking_repetition
6633         0, // 08 spare_pic
6634         1, // 09 scene_info
6635         0, // 10 sub_seq_info
6636         0, // 11 sub_seq_layer_characteristics
6637         0, // 12 sub_seq_characteristics
6638         1, // 13 full_frame_freeze
6639         1, // 14 full_frame_freeze_release
6640         1, // 15 full_frame_snapshot
6641         1, // 16 progressive_refinement_segment_start
6642         1, // 17 progressive_refinement_segment_end
6643         0, // 18 motion_constrained_slice_group_set
6644         1, // 19 film_grain_characteristics
6645         1, // 20 deblocking_filter_display_preference
6646         1, // 21 stereo_video_info
6647         0, // 22 post_filter_hint
6648         0, // 23 tone_mapping_info
6649         0, // 24 scalability_info
6650         0, // 25 sub_pic_scalable_layer
6651         0, // 26 non_required_layer_rep
6652         0, // 27 priority_layer_info
6653         0, // 28 layers_not_present
6654         0, // 29 layer_dependency_change
6655         0, // 30 scalable_nesting
6656         0, // 31 base_layer_temporal_hrd
6657         0, // 32 quality_layer_integrity_check
6658         0, // 33 redundant_pic_property
6659         0, // 34 tl0_dep_rep_index
6660         0, // 35 tl_switching_point
6661         0, // 36 parallel_decoding_info
6662         0, // 37 mvc_scalable_nesting
6663         0, // 38 view_scalability_info
6664         0, // 39 multiview_scene_info
6665         0, // 40 multiview_acquisition_info
6666         0, // 41 non_required_view_component
6667         0, // 42 view_dependency_change
6668         0, // 43 operation_points_not_present
6669         0, // 44 base_view_temporal_hrd
6670         1, // 45 frame_packing_arrangement
6671     };
6672 
6673     for (mfxU16 i = 0; i < numPayload; ++i)
6674     {
6675         // Particular payload can absent
6676         // Check only present payloads
6677         if (payload[i] && payload[i]->NumBit > 0)
6678         {
6679             MFX_CHECK_NULL_PTR1(payload[i]->Data);
6680 
6681             // Check buffer size
6682             MFX_CHECK(
6683                 payload[i]->NumBit <= 8u * payload[i]->BufSize,
6684                 MFX_ERR_UNDEFINED_BEHAVIOR);
6685 
6686             // Sei messages type constraints
6687             MFX_CHECK(
6688                 payload[i]->Type < (sizeof SUPPORTED_SEI / sizeof SUPPORTED_SEI[0]) &&
6689                 SUPPORTED_SEI[payload[i]->Type] == 1,
6690                 MFX_ERR_UNDEFINED_BEHAVIOR);
6691         }
6692     }
6693 
6694     return MFX_ERR_NONE;
6695 }
6696 
CheckRunTimeExtBuffers(MfxVideoParam const & video,mfxEncodeCtrl * ctrl,mfxFrameSurface1 * surface,mfxBitstream * bs,MFX_ENCODE_CAPS const & caps,eMFXHWType platform)6697 mfxStatus MfxHwH264Encode::CheckRunTimeExtBuffers(
6698     MfxVideoParam const   & video,
6699     mfxEncodeCtrl         * ctrl,
6700     mfxFrameSurface1      * surface,
6701     mfxBitstream          * bs,
6702     MFX_ENCODE_CAPS const & caps,
6703     eMFXHWType              platform)
6704 {
6705     MFX_CHECK_NULL_PTR3(ctrl, surface, bs);
6706     mfxStatus checkSts = MFX_ERR_NONE;
6707 
6708     mfxExtFeiParam const & feiParam = GetExtBufferRef(video);
6709     bool single_field_mode = IsOn(feiParam.SingleFieldProcessing);
6710 
6711     for (mfxU32 i = 0; i < bs->NumExtParam; i++)
6712     {
6713         MFX_CHECK_NULL_PTR1(bs->ExtParam[i]);
6714 
6715         if (!IsRuntimeOutputExtBufferIdSupported(video, bs->ExtParam[i]->BufferId))
6716             checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM; // don't return error in runtime, just ignore unsupported ext buffer and return warning
6717     }
6718 
6719     for (mfxU32 i = 0; i < ctrl->NumExtParam; i++)
6720     {
6721         MFX_CHECK_NULL_PTR1(ctrl->ExtParam[i]);
6722 
6723         if (!IsRunTimeExtBufferIdSupported(video, ctrl->ExtParam[i]->BufferId))
6724             checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM; // don't return error in runtime, just ignore unsupported ext buffer and return warning
6725 
6726         bool buffer_pair = MfxHwH264Encode::GetExtBuffer(
6727                             ctrl->ExtParam + i + 1,
6728                             ctrl->NumExtParam - i - 1,
6729                             ctrl->ExtParam[i]->BufferId)
6730                             ||
6731                            MfxHwH264Encode::GetExtBuffer(
6732                             ctrl->ExtParam,
6733                             i,
6734                             ctrl->ExtParam[i]->BufferId);
6735 
6736         // In single-field mode only one buffer is required for one field encoding
6737         bool buffer_pair_allowed = !single_field_mode ? IsRunTimeExtBufferPairAllowed(video, ctrl->ExtParam[i]->BufferId) : false;
6738 
6739         // if initialized PicStruct is UNKNOWN, to check runtime PicStruct
6740         bool buffer_pair_required = !single_field_mode ? IsRunTimeExtBufferPairRequired(video, ctrl->ExtParam[i]->BufferId) : false;
6741 
6742         if (buffer_pair_required)
6743         {
6744             switch (video.mfx.FrameInfo.PicStruct)
6745             {
6746             case MFX_PICSTRUCT_PROGRESSIVE:
6747                 buffer_pair_required = false;
6748                 break;
6749             case MFX_PICSTRUCT_UNKNOWN:
6750                 // for runtime PicStruct, it may be set as (MFX_PICSTRUCT_PROGRESSIVE |
6751                 // MFX+PICSTRUCT_FIELD_TFF/BFF) for progressive frames
6752                 if (surface->Info.PicStruct & MFX_PICSTRUCT_PROGRESSIVE)
6753                 {
6754                     buffer_pair_required = false;
6755                 }
6756                 break;
6757             default:
6758                 break;
6759             }
6760         }
6761 
6762         if (buffer_pair && !buffer_pair_allowed)
6763         {
6764             // Ignore second buffer and return warning
6765             checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6766         }
6767         else if (!buffer_pair && buffer_pair_required)
6768         {
6769             // Return error if only one per-field buffer provided
6770             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
6771         }
6772     }
6773 
6774     mfxU16 PicStruct = (video.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_UNKNOWN) ? video.mfx.FrameInfo.PicStruct : surface->Info.PicStruct;
6775     mfxU16 NumFields = (PicStruct & MFX_PICSTRUCT_PROGRESSIVE) ? 1 : 2;
6776 
6777     if (feiParam.Func == MFX_FEI_FUNCTION_ENCODE)
6778     {
6779         for (mfxU16 fieldId = 0; fieldId < NumFields; fieldId++)
6780         {
6781             // In case of single-field processing, only one buffer is attached
6782             mfxU32 idxToPickBuffer = single_field_mode ? 0 : fieldId;
6783 
6784             // FEI frame control buffer is mandatory for encoding
6785             mfxExtFeiEncFrameCtrl* feiEncCtrl =
6786                 reinterpret_cast<mfxExtFeiEncFrameCtrl*>(MfxHwH264Encode::GetExtBuffer(ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_FEI_ENC_CTRL, idxToPickBuffer));
6787             MFX_CHECK(feiEncCtrl, MFX_ERR_UNDEFINED_BEHAVIOR);
6788 
6789             if (feiEncCtrl->MVPredictor)
6790             {
6791                 // TODO: check it in single-field
6792                 if (IsOff(feiParam.SingleFieldProcessing))
6793                 {
6794                     // MV predictor is never used for I frame
6795                     MFX_CHECK(!(ctrl->FrameType & (!fieldId ? MFX_FRAMETYPE_I : MFX_FRAMETYPE_xI)), MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
6796                 }
6797 
6798                 //mfxExtFeiEncMVPredictors should be attached when MVPredictor is enabled
6799                 mfxExtBuffer* feiEncMVPredictors = MfxHwH264Encode::GetExtBuffer(ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_FEI_ENC_MV_PRED, idxToPickBuffer);
6800                 MFX_CHECK(feiEncMVPredictors, MFX_ERR_UNDEFINED_BEHAVIOR);
6801             }
6802 
6803             if (feiEncCtrl->PerMBInput)
6804             {
6805                 //mfxExtFeiEncMBCtrl should be attached when PerMBInput is enabled
6806                 mfxExtBuffer* feiEncMBCtrl = MfxHwH264Encode::GetExtBuffer(ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_FEI_ENC_MB, idxToPickBuffer);
6807                 MFX_CHECK(feiEncMBCtrl, MFX_ERR_UNDEFINED_BEHAVIOR);
6808             }
6809 
6810             if (feiEncCtrl->PerMBQp)
6811             {
6812                 //mfxExtFeiEncQP should be attached when PerMBQp is enabled
6813                 mfxExtBuffer* feiEncQp = MfxHwH264Encode::GetExtBuffer(ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_FEI_ENC_QP, idxToPickBuffer);
6814                 MFX_CHECK(feiEncQp, MFX_ERR_UNDEFINED_BEHAVIOR);
6815             }
6816         }
6817     }
6818 
6819     {
6820         mfxStatus sts = CheckFEIRunTimeExtBuffersContent(video, ctrl, surface, bs);
6821         MFX_CHECK(sts >= MFX_ERR_NONE, sts);
6822         if (sts != MFX_ERR_NONE)
6823             checkSts = sts;
6824     }
6825 
6826 #if defined (MFX_ENABLE_H264_ROUNDING_OFFSET)
6827     for (mfxU16 fieldId = 0; fieldId < NumFields; fieldId++)
6828     {
6829         mfxExtAVCRoundingOffset* extRoundingOffset =
6830                 reinterpret_cast<mfxExtAVCRoundingOffset*>(MfxHwH264Encode::GetExtBuffer(ctrl->ExtParam, ctrl->NumExtParam, MFX_EXTBUFF_AVC_ROUNDING_OFFSET, fieldId));
6831         if (extRoundingOffset)
6832         {
6833             if (IsOn(extRoundingOffset->EnableRoundingIntra))
6834             {
6835                 if (extRoundingOffset->RoundingOffsetIntra > 7)
6836                 {
6837                     checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6838                     extRoundingOffset->RoundingOffsetIntra = extRoundingOffset->RoundingOffsetIntra % 7;
6839                 }
6840             }
6841 
6842             if (IsOn(extRoundingOffset->EnableRoundingInter))
6843             {
6844                 if (extRoundingOffset->RoundingOffsetInter > 7)
6845                 {
6846                     checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6847                     extRoundingOffset->RoundingOffsetInter = extRoundingOffset->RoundingOffsetInter % 7;
6848                 }
6849             }
6850         }
6851     }
6852 #endif
6853 
6854     mfxExtAVCRefListCtrl const * extRefListCtrl = GetExtBuffer(*ctrl);
6855     if (extRefListCtrl && video.calcParam.numTemporalLayer > 0 && video.calcParam.tempScalabilityMode == 0)
6856         checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6857 
6858 
6859     mfxExtAVCRefLists const * extRefLists = GetExtBuffer(*ctrl);
6860     if (extRefLists && video.calcParam.numTemporalLayer > 0 && video.calcParam.tempScalabilityMode == 0)
6861         checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6862 
6863     // check timestamp from mfxExtPictureTimingSEI
6864     mfxExtPictureTimingSEI const * extPt   = GetExtBuffer(*ctrl);
6865 
6866     if (extPt)
6867     {
6868         for (mfxU32 i = 0; i < 3; i++)
6869         {
6870             // return warning if there is any 0xffff template except for CtType
6871             if (extPt->TimeStamp[i].CountingType       == 0xffff ||
6872                 extPt->TimeStamp[i].NFrames            == 0xffff ||
6873                 extPt->TimeStamp[i].SecondsValue       == 0xffff ||
6874                 extPt->TimeStamp[i].MinutesValue       == 0xffff ||
6875                 extPt->TimeStamp[i].HoursValue         == 0xffff ||
6876                 extPt->TimeStamp[i].TimeOffset         == 0xffff ||
6877                 extPt->TimeStamp[i].ClockTimestampFlag == 0xffff ||
6878                 extPt->TimeStamp[i].NuitFieldBasedFlag == 0xffff ||
6879                 extPt->TimeStamp[i].FullTimestampFlag  == 0xffff ||
6880                 extPt->TimeStamp[i].DiscontinuityFlag  == 0xffff ||
6881                 extPt->TimeStamp[i].CntDroppedFlag     == 0xffff ||
6882                 extPt->TimeStamp[i].SecondsFlag        == 0xffff ||
6883                 extPt->TimeStamp[i].MinutesFlag        == 0xffff ||
6884                 extPt->TimeStamp[i].HoursFlag          == 0xffff)
6885             {
6886                 checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6887             }
6888         }
6889     }
6890 
6891     // check ROI
6892     mfxExtEncoderROI const * extRoi = GetExtBuffer(*ctrl);
6893 
6894     if (extRoi) {
6895         // check below should have the same logic as in MfxHwH264Encode::ConfigureTask
6896         // the difference that ConfigureTask doesn't copy bad arg to DdiTask
6897         // CheckRunTimeExtBuffers just reports MFX_WRN_INCOMPATIBLE_VIDEO_PARAM for the same args
6898 
6899         mfxU16 const MaxNumOfROI = caps.ddi_caps.MaxNumOfROI;
6900         mfxU16 actualNumRoi = extRoi->NumROI;
6901         if (extRoi->NumROI)
6902         {
6903             if (extRoi->NumROI > MaxNumOfROI)
6904             {
6905                 checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6906                 actualNumRoi = MaxNumOfROI;
6907             }
6908 
6909             if (extRoi->ROIMode != MFX_ROI_MODE_QP_DELTA && extRoi->ROIMode != MFX_ROI_MODE_PRIORITY)
6910             {
6911                 checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6912                 actualNumRoi = 0;
6913             }
6914 
6915             if (video.mfx.RateControlMethod != MFX_RATECONTROL_CQP && caps.ddi_caps.ROIBRCDeltaQPLevelSupport == 0)
6916             {
6917                 checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6918                 actualNumRoi = 0;
6919             }
6920         }
6921 
6922         for (mfxU16 i = 0; i < actualNumRoi; i++)
6923         {
6924                 mfxRoiDesc task_roi = {extRoi->ROI[i].Left,  extRoi->ROI[i].Top,
6925                                        extRoi->ROI[i].Right, extRoi->ROI[i].Bottom, extRoi->ROI[i].Priority};
6926 
6927                 // check runtime ROI
6928                 mfxStatus sts = CheckAndFixRoiQueryLike(video, &task_roi, extRoi->ROIMode);
6929                 if (sts != MFX_ERR_NONE)
6930                 {
6931                     checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6932                 }
6933         }
6934     }
6935 
6936     mfxExtDirtyRect const * extDirtyRect = GetExtBuffer(*ctrl);
6937 
6938     if (extDirtyRect)
6939     {
6940         checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6941     }
6942 
6943 
6944     mfxExtMoveRect const * extMoveRect = GetExtBuffer(*ctrl);
6945 
6946     if (extMoveRect)
6947     {
6948         checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6949     }
6950 
6951 
6952 #if defined(MFX_ENABLE_MFE)
6953 
6954     mfxExtMultiFrameParam const & mfeParam = GetExtBufferRef(video);
6955     mfxExtMultiFrameControl * mfeCtrl = GetExtBuffer(*ctrl);
6956 
6957     if(mfeCtrl && mfeParam.MFMode == MFX_MF_MANUAL && mfeCtrl->Timeout)
6958     {
6959         checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6960         mfeCtrl->Timeout = 0;
6961     }
6962 #endif
6963     mfxExtPredWeightTable *extPwt = GetExtBuffer(*ctrl);
6964     if (extPwt && (platform >= MFX_HW_KBL))
6965     {
6966         if (extPwt->LumaLog2WeightDenom && (extPwt->LumaLog2WeightDenom != 6))
6967         {
6968             checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6969         }
6970         if (extPwt->ChromaLog2WeightDenom && (extPwt->ChromaLog2WeightDenom != 6))
6971         {
6972             checkSts = MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
6973         }
6974     }
6975 
6976     return checkSts;
6977 }
6978 
CheckFEIRunTimeExtBuffersContent(MfxVideoParam const & video,mfxEncodeCtrl * ctrl,mfxFrameSurface1 * surface,mfxBitstream * bs)6979 mfxStatus MfxHwH264Encode::CheckFEIRunTimeExtBuffersContent(
6980     MfxVideoParam const & video,
6981     mfxEncodeCtrl       * ctrl,
6982     mfxFrameSurface1    * surface,
6983     mfxBitstream        * bs)
6984 {
6985     MFX_CHECK_NULL_PTR3(ctrl, surface, bs);
6986     mfxStatus checkSts = MFX_ERR_NONE;
6987 
6988 #if defined (MFX_ENABLE_H264_VIDEO_FEI_ENCPAK)
6989     mfxExtFeiParam const * feiParam = GetExtBuffer(video);
6990     bool isFeiENCPAK = feiParam->Func == MFX_FEI_FUNCTION_ENCODE;
6991 
6992     if (!isFeiENCPAK) return MFX_ERR_NONE;
6993 
6994     mfxU32 FrameSizeInMB = surface->Info.Width * surface->Info.Height / 256;
6995     mfxU16 PicStruct = (video.mfx.FrameInfo.PicStruct != MFX_PICSTRUCT_UNKNOWN) ? video.mfx.FrameInfo.PicStruct : surface->Info.PicStruct;
6996     mfxU32 NumMB = (PicStruct & MFX_PICSTRUCT_PROGRESSIVE) ? FrameSizeInMB : FrameSizeInMB / 2;
6997 
6998     // check input extbuffer
6999     for (mfxU32 i = 0; i < ctrl->NumExtParam; ++i)
7000     {
7001         MFX_CHECK_NULL_PTR1(ctrl->ExtParam[i]);
7002 
7003         switch (ctrl->ExtParam[i]->BufferId)
7004         {
7005         case MFX_EXTBUFF_CODING_OPTION3:
7006         {
7007             mfxExtCodingOption3* extOpt3 = reinterpret_cast<mfxExtCodingOption3*>(ctrl->ExtParam[i]);
7008             //per-frame bias adjustment is not supported for FEI.
7009             if (IsOn(extOpt3->DirectBiasAdjustment) || IsOn(extOpt3->GlobalMotionBiasAdjustment))
7010                 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7011         }
7012             break;
7013 
7014         case MFX_EXTBUFF_MBQP:
7015             // mfxExtMBQP is not allowed for FEI. FEI has it's own buffer: mfxExtFeiEncQP
7016             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7017             break;
7018 
7019         case MFX_EXTBUFF_FEI_SLICE:
7020         {
7021             mfxExtFeiSliceHeader* pSliceHeader = reinterpret_cast<mfxExtFeiSliceHeader*>(ctrl->ExtParam[i]);
7022             MFX_CHECK_NULL_PTR1(pSliceHeader->Slice);
7023             // Need to provide control for each slice in runtime if mfxExtFeiSliceHeader attached
7024             MFX_CHECK(GetMaxNumSlices(video) >= pSliceHeader->NumSlice && pSliceHeader->NumSlice, MFX_ERR_INVALID_VIDEO_PARAM);
7025 
7026             for (mfxU32 slice = 0; slice < pSliceHeader->NumSlice; ++slice)
7027             {
7028                 MFX_CHECK(pSliceHeader->Slice[slice].DisableDeblockingFilterIdc <=  2, MFX_ERR_INVALID_VIDEO_PARAM);
7029                 MFX_CHECK(pSliceHeader->Slice[slice].SliceAlphaC0OffsetDiv2     <=  6, MFX_ERR_INVALID_VIDEO_PARAM);
7030                 MFX_CHECK(pSliceHeader->Slice[slice].SliceAlphaC0OffsetDiv2     >= -6, MFX_ERR_INVALID_VIDEO_PARAM);
7031                 MFX_CHECK(pSliceHeader->Slice[slice].SliceBetaOffsetDiv2        <=  6, MFX_ERR_INVALID_VIDEO_PARAM);
7032                 MFX_CHECK(pSliceHeader->Slice[slice].SliceBetaOffsetDiv2        >= -6, MFX_ERR_INVALID_VIDEO_PARAM);
7033             }
7034         }
7035             break;
7036 
7037         case MFX_EXTBUFF_FEI_ENC_CTRL:
7038         {
7039             mfxExtFeiEncFrameCtrl* feiEncCtrl = reinterpret_cast<mfxExtFeiEncFrameCtrl*>(ctrl->ExtParam[i]);
7040 
7041             MFX_CHECK(feiEncCtrl->SearchWindow != 0, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7042 
7043             mfxExtCodingOption const* extOpt = GetExtBuffer(video);
7044             if ( ( extOpt->IntraPredBlockSize == MFX_BLOCKSIZE_MIN_16X16 || (video.mfx.CodecProfile & 0xff) == MFX_PROFILE_AVC_BASELINE
7045                 || (video.mfx.CodecProfile & 0xff) == MFX_PROFILE_AVC_MAIN ) && !(feiEncCtrl->IntraPartMask & 0x02))
7046             {
7047                 // For Main and Baseline profiles 8x8 transform is prohibited
7048                 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7049             }
7050             if (feiEncCtrl->MVPredictor)
7051             {
7052                 MFX_CHECK(feiEncCtrl->NumMVPredictors[0] <= 4, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7053                 MFX_CHECK(feiEncCtrl->NumMVPredictors[1] <= 4, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7054             }
7055         }
7056             break;
7057 
7058         case MFX_EXTBUFF_FEI_REPACK_CTRL:
7059         {
7060             mfxExtFeiRepackCtrl* feiRepackCtrl = reinterpret_cast<mfxExtFeiRepackCtrl*>(ctrl->ExtParam[i]);
7061             MFX_CHECK(feiRepackCtrl->NumPasses <= 4, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7062         }
7063             break;
7064 
7065         case MFX_EXTBUFF_FEI_ENC_MV_PRED:
7066         {
7067             mfxExtFeiEncMVPredictors* feiEncMVPredictors = reinterpret_cast<mfxExtFeiEncMVPredictors*>(ctrl->ExtParam[i]);
7068             MFX_CHECK(feiEncMVPredictors->NumMBAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7069             MFX_CHECK(feiEncMVPredictors->MB         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7070         }
7071             break;
7072 
7073         case MFX_EXTBUFF_FEI_ENC_MB:
7074         {
7075             mfxExtFeiEncMBCtrl* feiEncMBCtrl = reinterpret_cast<mfxExtFeiEncMBCtrl*>(ctrl->ExtParam[i]);
7076             MFX_CHECK(feiEncMBCtrl->NumMBAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7077             MFX_CHECK(feiEncMBCtrl->MB         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7078         }
7079             break;
7080 
7081         case MFX_EXTBUFF_FEI_ENC_QP:
7082         {
7083             mfxExtFeiEncQP* feiEncQP = reinterpret_cast<mfxExtFeiEncQP*>(ctrl->ExtParam[i]);
7084 #if MFX_VERSION >= 1023
7085             MFX_CHECK(feiEncQP->NumMBAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7086             MFX_CHECK(feiEncQP->MB         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7087 #else
7088             MFX_CHECK(feiEncQP->NumQPAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7089             MFX_CHECK(feiEncQP->QP         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7090 #endif
7091         }
7092             break;
7093 
7094         case MFX_EXTBUFF_PRED_WEIGHT_TABLE:
7095         {
7096             mfxExtPredWeightTable* feiWeightTable = reinterpret_cast<mfxExtPredWeightTable*>(ctrl->ExtParam[i]);
7097             const mfxU32 iWeight = 0, iOffset = 1, iY = 0, iCb = 1, iCr = 2;
7098 
7099             if (feiWeightTable->LumaLog2WeightDenom > 7)
7100             {
7101                 // out_of_scope, set default value 6
7102                 feiWeightTable->LumaLog2WeightDenom = 6;
7103                 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7104             }
7105 
7106             if (feiWeightTable->ChromaLog2WeightDenom > 7)
7107             {
7108                 // for FEI Encode, chroma weight pred is not supported, so set default value 0
7109                 feiWeightTable->ChromaLog2WeightDenom = 0;
7110                 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7111             }
7112 
7113             for (mfxU32 m = 0; m < 2; m++) // l0, l1
7114             {
7115                 for (mfxU32 n = 0; n < 32; n++) // [ref list entry]
7116                 {
7117                     if (feiWeightTable->LumaWeightFlag[m][n])
7118                     {
7119                         // check luma weights
7120                         if (feiWeightTable->Weights[m][n][iY][iWeight] > 127 ||
7121                             feiWeightTable->Weights[m][n][iY][iWeight] < -128)
7122                         {
7123                             // out_of_scope, use default value pow(2, Denom)
7124                             feiWeightTable->Weights[m][n][iY][iWeight] = (1 << feiWeightTable->LumaLog2WeightDenom);
7125                             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7126                         }
7127 
7128                         // check luma offset
7129                         if (feiWeightTable->Weights[m][n][iY][iOffset] > 127 ||
7130                             feiWeightTable->Weights[m][n][iY][iOffset] < -128)
7131                         {
7132                             // out_of_scope, use default value 0
7133                             feiWeightTable->Weights[m][n][iY][iOffset] = 0;
7134                             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7135                         }
7136                     }
7137 
7138                     if (feiWeightTable->ChromaWeightFlag[m][n])
7139                     {
7140                         for (mfxU32 x = iCb; x <= iCr; x++) // [Cb, Cr]
7141                         {
7142                             for (mfxU32 y = iWeight; y <= iOffset; y++) // [weight, offset]
7143                             {
7144                                 if (feiWeightTable->Weights[m][n][x][y] > 127 ||
7145                                     feiWeightTable->Weights[m][n][x][y] < -128)
7146                                 {
7147                                     feiWeightTable->Weights[m][n][x][y] = 0;
7148                                     return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7149                                 }
7150                             }
7151                         }
7152                     }
7153                 }
7154             }
7155 
7156             // checking for (8-298) in H.264-201704 spec:
7157             // −128 <= w0C + w1C <= ( ( logWDC == 7 ) ? 127 : 128 )
7158             for (mfxU32 m = 0; m < 32; m++) // L0 index
7159             {
7160                 for (mfxU32 n = 0; n < 32; n++) // L1 index
7161                 {
7162                     if (feiWeightTable->LumaWeightFlag[0][m] && feiWeightTable->LumaWeightFlag[1][n])
7163                     {
7164                         if ((feiWeightTable->Weights[0][m][0][0] + feiWeightTable->Weights[1][n][0][0] < -128) ||
7165                             (feiWeightTable->Weights[0][m][0][0] + feiWeightTable->Weights[1][n][0][0] > ((feiWeightTable->LumaLog2WeightDenom == 7) ? 127 : 128)))
7166                             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7167                     }
7168                     if (feiWeightTable->ChromaWeightFlag[0][m] && feiWeightTable->ChromaWeightFlag[1][n])
7169                     {
7170                         if (((feiWeightTable->Weights[0][m][1][0] + feiWeightTable->Weights[1][n][1][0] < -128) ||
7171                              (feiWeightTable->Weights[0][m][1][0] + feiWeightTable->Weights[1][n][1][0] > ((feiWeightTable->ChromaLog2WeightDenom == 7) ? 127 : 128))) ||
7172                             ((feiWeightTable->Weights[0][m][2][0] + feiWeightTable->Weights[1][n][2][0] < -128) ||
7173                              (feiWeightTable->Weights[0][m][2][0] + feiWeightTable->Weights[1][n][2][0] > ((feiWeightTable->ChromaLog2WeightDenom == 7) ? 127 : 128))))
7174                             return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7175                     }
7176                 }
7177             }
7178         }
7179             break;
7180 
7181         default:
7182             // All input buffers ids are already checked at CheckRunTimeExtBuffers
7183             break;
7184         }
7185     }
7186 
7187     // check output extbuffer
7188     for (mfxU32 i = 0; i < bs->NumExtParam; ++i)
7189     {
7190         MFX_CHECK_NULL_PTR1(bs->ExtParam[i]);
7191 
7192         switch (bs->ExtParam[i]->BufferId)
7193         {
7194             case MFX_EXTBUFF_FEI_ENC_MB_STAT:
7195             {
7196                 mfxExtFeiEncMBStat* feiEncMBStat = reinterpret_cast<mfxExtFeiEncMBStat*>(bs->ExtParam[i]);
7197                 MFX_CHECK(feiEncMBStat->NumMBAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7198                 MFX_CHECK(feiEncMBStat->MB         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7199             }
7200             break;
7201 
7202             case MFX_EXTBUFF_FEI_ENC_MV:
7203             {
7204                 mfxExtFeiEncMV* feiEncMV = reinterpret_cast<mfxExtFeiEncMV*>(bs->ExtParam[i]);
7205                 MFX_CHECK(feiEncMV->NumMBAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7206                 MFX_CHECK(feiEncMV->MB         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7207             }
7208             break;
7209 
7210             case MFX_EXTBUFF_FEI_PAK_CTRL:
7211             {
7212                 mfxExtFeiPakMBCtrl* feiPakMBCtrl = reinterpret_cast<mfxExtFeiPakMBCtrl*>(bs->ExtParam[i]);
7213                 MFX_CHECK(feiPakMBCtrl->NumMBAlloc == NumMB, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7214                 MFX_CHECK(feiPakMBCtrl->MB         != NULL,  MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7215             }
7216             break;
7217 
7218 #if (MFX_VERSION >= 1025)
7219             case MFX_EXTBUFF_FEI_REPACK_STAT:
7220             {
7221                 mfxExtFeiRepackStat* feiRepackStat = reinterpret_cast<mfxExtFeiRepackStat*>
7222                                                      (bs->ExtParam[i]);
7223                 MFX_CHECK(feiRepackStat->NumPasses == 0, MFX_ERR_INCOMPATIBLE_VIDEO_PARAM);
7224             }
7225             break;
7226 #endif
7227 
7228             default:
7229                 if (IsRuntimeOutputExtBufferIdSupported(video, bs->ExtParam[i]->BufferId))
7230                     break; //Allow supported buffers
7231                 //unsupported output extbuffer is attached.
7232                 return MFX_ERR_INCOMPATIBLE_VIDEO_PARAM;
7233 
7234                 break;
7235         }
7236     }
7237 
7238 #else
7239     (void)video;
7240     (void)bs;
7241 #endif
7242 
7243     return checkSts;
7244 }
7245 
CheckRunTimePicStruct(mfxU16 runtPs,mfxU16 initPs)7246 mfxStatus MfxHwH264Encode::CheckRunTimePicStruct(
7247     mfxU16 runtPs,
7248     mfxU16 initPs)
7249 {
7250     static mfxU16 const PRG  = MFX_PICSTRUCT_PROGRESSIVE;
7251     static mfxU16 const TFF  = MFX_PICSTRUCT_FIELD_TFF;
7252     static mfxU16 const BFF  = MFX_PICSTRUCT_FIELD_BFF;
7253     static mfxU16 const UNK  = MFX_PICSTRUCT_UNKNOWN;
7254     static mfxU16 const DBL  = MFX_PICSTRUCT_FRAME_DOUBLING;
7255     static mfxU16 const TRPL = MFX_PICSTRUCT_FRAME_TRIPLING;
7256     static mfxU16 const REP  = MFX_PICSTRUCT_FIELD_REPEATED;
7257 
7258     if ((initPs == PRG && runtPs == UNK)         ||
7259         (initPs == PRG && runtPs == PRG)         ||
7260         (initPs == PRG && runtPs == (PRG | DBL)) ||
7261         (initPs == PRG && runtPs == (PRG | TRPL)))
7262         return MFX_ERR_NONE;
7263 
7264     if ((initPs == BFF && runtPs == UNK) ||
7265         (initPs == BFF && runtPs == BFF) ||
7266         (initPs == UNK && runtPs == BFF) ||
7267         (initPs == TFF && runtPs == UNK) ||
7268         (initPs == TFF && runtPs == TFF) ||
7269         (initPs == UNK && runtPs == TFF))
7270         return MFX_ERR_NONE;
7271 
7272     if ((initPs == UNK && runtPs == (PRG | BFF))       ||
7273         (initPs == UNK && runtPs == (PRG | TFF))       ||
7274         (initPs == UNK && runtPs == (PRG | BFF | REP)) ||
7275         (initPs == UNK && runtPs == (PRG | TFF | REP)) ||
7276         (initPs == UNK && runtPs == PRG)               ||
7277         (initPs == BFF && runtPs == PRG)               ||
7278         (initPs == TFF && runtPs == PRG))
7279         return MFX_ERR_NONE;
7280 
7281     if (initPs == UNK && runtPs == UNK)
7282         return MFX_ERR_UNDEFINED_BEHAVIOR;
7283 
7284     return MFX_WRN_INCOMPATIBLE_VIDEO_PARAM;
7285 }
7286 
IsRecoveryPointSeiMessagePresent(const mfxPayload * const * payload,mfxU16 numPayload,mfxU32 payloadLayout)7287 bool MfxHwH264Encode::IsRecoveryPointSeiMessagePresent(
7288     const mfxPayload* const* payload,
7289     mfxU16 numPayload,
7290     mfxU32 payloadLayout)
7291 {
7292     if (!payload)
7293         return false;
7294 
7295     mfxU32 step = payloadLayout == 0 /*MFX_PAYLOAD_LAYOUT_ALL*/ ? 1 : 2;
7296     mfxU32 i    = payloadLayout == 2 /*MFX_PAYLOAD_LAYOUT_ODD*/ ? 1 : 0;
7297 
7298     for (; i < numPayload; i += step)
7299         if (payload[i] && payload[i]->NumBit > 0 && payload[i]->Type == 6)
7300             break;
7301 
7302     return i < numPayload;
7303 }
7304 
CopyFrameDataBothFields(VideoCORE * core,mfxFrameData const & dst,mfxFrameData const & src,mfxFrameInfo const & info)7305 mfxStatus MfxHwH264Encode::CopyFrameDataBothFields(
7306     VideoCORE *          core,
7307     mfxFrameData const & dst,
7308     mfxFrameData const & src,
7309     mfxFrameInfo const & info)
7310 {
7311     mfxFrameSurface1 surfSrc = { {0,}, info, src };
7312     mfxFrameSurface1 surfDst = { {0,}, info, dst };
7313     return core->DoFastCopyWrapper(&surfDst,MFX_MEMTYPE_INTERNAL_FRAME|MFX_MEMTYPE_DXVA2_DECODER_TARGET|MFX_MEMTYPE_FROM_ENCODE, &surfSrc, MFX_MEMTYPE_EXTERNAL_FRAME|MFX_MEMTYPE_SYSTEM_MEMORY);
7314 }
7315 
GetExtBuffer(mfxExtBuffer ** extBuf,mfxU32 numExtBuf,mfxU32 id,mfxU32 offset)7316 mfxExtBuffer* MfxHwH264Encode::GetExtBuffer(mfxExtBuffer** extBuf, mfxU32 numExtBuf, mfxU32 id, mfxU32 offset)
7317 {
7318     if (extBuf != 0)
7319     {
7320         mfxU32 count = 0;
7321         for (mfxU32 i = 0; i < numExtBuf; ++i)
7322         {
7323             if (extBuf[i] != 0 && extBuf[i]->BufferId == id && count++ == offset) // assuming aligned buffers
7324             {
7325                 return (extBuf[i]);
7326             }
7327         }
7328     }
7329 
7330     return 0;
7331 }
7332 
7333 
ConvertFrameTypeMfx2Ddi(mfxU32 type)7334 mfxU8 MfxHwH264Encode::ConvertFrameTypeMfx2Ddi(mfxU32 type)
7335 {
7336     switch (type & MFX_FRAMETYPE_IPB)
7337     {
7338     case MFX_FRAMETYPE_I: return CODING_TYPE_I;
7339     case MFX_FRAMETYPE_P: return CODING_TYPE_P;
7340     case MFX_FRAMETYPE_B: return CODING_TYPE_B;
7341     default: assert(!"Unsupported frame type"); return 0;
7342     }
7343 }
7344 
ConvertLowDelayBRCMfx2Ddi(mfxU16 type,bool bTCBRC)7345 ENCODE_FRAME_SIZE_TOLERANCE MfxHwH264Encode::ConvertLowDelayBRCMfx2Ddi(mfxU16 type, bool bTCBRC)
7346 {
7347     switch (type) {
7348         case MFX_CODINGOPTION_ON:
7349             return bTCBRC ? eFrameSizeTolerance_Normal : eFrameSizeTolerance_ExtremelyLow;
7350         default:
7351             return eFrameSizeTolerance_Normal;
7352     }
7353 }
7354 
ConvertMfxFrameType2SliceType(mfxU8 type)7355 mfxU8 MfxHwH264Encode::ConvertMfxFrameType2SliceType(mfxU8 type)
7356 {
7357     switch (type & MFX_FRAMETYPE_IPB)
7358     {
7359     case MFX_FRAMETYPE_I: return SLICE_TYPE_I + 5;
7360     case MFX_FRAMETYPE_P: return SLICE_TYPE_P + 5;
7361     case MFX_FRAMETYPE_B: return SLICE_TYPE_B + 5;
7362     default: assert("bad codingType"); return 0xff;
7363     }
7364 }
7365 
7366 
GetFirstMbInSlice() const7367 mfxU32 SliceDivider::GetFirstMbInSlice() const
7368 {
7369     assert(m_currSliceFirstMbRow * m_numMbInRow < 0x10000000);
7370     return m_currSliceFirstMbRow * m_numMbInRow;
7371 }
7372 
GetNumMbInSlice() const7373 mfxU32 SliceDivider::GetNumMbInSlice() const
7374 {
7375     assert(m_currSliceNumMbRow * m_numMbInRow < 0x10000000);
7376     return m_currSliceNumMbRow * m_numMbInRow;
7377 }
7378 
GetNumSlice() const7379 mfxU32 SliceDivider::GetNumSlice() const
7380 {
7381     assert(0 < m_numSlice && m_numSlice < 0x10000000);
7382     return m_numSlice;
7383 }
7384 
7385 
SliceDividerArbitraryRowSlice(mfxU32 numSlice,mfxU32 widthInMbs,mfxU32 heightInMbs)7386 SliceDividerArbitraryRowSlice::SliceDividerArbitraryRowSlice(
7387     mfxU32 numSlice,
7388     mfxU32 widthInMbs,
7389     mfxU32 heightInMbs)
7390 {
7391     m_pfNext              = &SliceDividerArbitraryRowSlice::Next;
7392     m_numSlice            = std::max(numSlice, 1u);
7393     m_numMbInRow          = widthInMbs;
7394     m_numMbRow            = heightInMbs;
7395     m_leftSlice           = m_numSlice;
7396     m_leftMbRow           = m_numMbRow;
7397     m_currSliceFirstMbRow = 0;
7398     m_currSliceNumMbRow   = m_leftMbRow / m_leftSlice;
7399 }
7400 
Next(SliceDividerState & state)7401 bool SliceDividerArbitraryRowSlice::Next(SliceDividerState & state)
7402 {
7403     state.m_leftMbRow -= state.m_currSliceNumMbRow;
7404     state.m_leftSlice -= 1;
7405 
7406     if (state.m_leftSlice == 0)
7407     {
7408         assert(state.m_leftMbRow == 0);
7409         return false;
7410     }
7411     else
7412     {
7413         state.m_currSliceFirstMbRow += state.m_currSliceNumMbRow;
7414         state.m_currSliceNumMbRow = state.m_leftMbRow / state.m_leftSlice;
7415         assert(state.m_currSliceNumMbRow != 0);
7416         return true;
7417     }
7418 }
7419 
7420 
SliceDividerOneSlice(mfxU32,mfxU32 widthInMbs,mfxU32 heightInMbs)7421 SliceDividerOneSlice::SliceDividerOneSlice(
7422     mfxU32 /*numSlice*/,
7423     mfxU32 widthInMbs,
7424     mfxU32 heightInMbs)
7425 {
7426     m_pfNext              = &SliceDividerOneSlice::Next;
7427     m_numSlice            = 1;
7428     m_numMbInRow          = widthInMbs;
7429     m_numMbRow            = heightInMbs;
7430     m_leftSlice           = 1;
7431     m_leftMbRow           = heightInMbs;
7432     m_currSliceFirstMbRow = 0;
7433     m_currSliceNumMbRow   = heightInMbs;
7434 }
7435 
Next(SliceDividerState & state)7436 bool SliceDividerOneSlice::Next(SliceDividerState & state)
7437 {
7438     state.m_leftMbRow = 0;
7439     state.m_leftSlice = 0;
7440     return false;
7441 }
7442 
7443 
7444 namespace
7445 {
7446     // nearest but less than n
GetNearestPowerOf2(mfxU32 n)7447     mfxU32 GetNearestPowerOf2(mfxU32 n)
7448     {
7449         mfxU32 mask = 0x80000000;
7450         for (; mask > 0; mask >>= 1)
7451             if (n & mask)
7452                 break;
7453         return mask;
7454     }
7455 };
7456 
SliceDividerRow2Row(mfxU32 numSlice,mfxU32 widthInMbs,mfxU32 heightInMbs)7457 SliceDividerRow2Row::SliceDividerRow2Row(
7458     mfxU32 numSlice,
7459     mfxU32 widthInMbs,
7460     mfxU32 heightInMbs)
7461 {
7462     m_pfNext              = &SliceDividerRow2Row::Next;
7463     m_numSlice            = std::max(numSlice, 1u);
7464     m_numMbInRow          = widthInMbs;
7465     m_numMbRow            = heightInMbs;
7466     m_leftSlice           = m_numSlice;
7467     m_leftMbRow           = m_numMbRow;
7468     m_currSliceFirstMbRow = 0;
7469     m_currSliceNumMbRow   = m_leftMbRow / m_leftSlice;
7470 
7471     // check if frame is divisible to requested number of slices
7472     mfxU32 numMbRowInSlice = std::max(1u, m_numMbRow / m_numSlice);
7473     numMbRowInSlice = GetNearestPowerOf2(numMbRowInSlice) << 1;
7474     if ((m_numMbRow + numMbRowInSlice - 1) / numMbRowInSlice < m_numSlice)
7475         numMbRowInSlice >>= 1; // As number of slices can only be increased, try smaller slices
7476 
7477     m_numSlice = (m_numMbRow + numMbRowInSlice - 1) / numMbRowInSlice;
7478     m_leftSlice = m_numSlice;
7479     m_currSliceNumMbRow = std::min<mfxU32>(numMbRowInSlice, m_leftMbRow);
7480 }
7481 
Next(SliceDividerState & state)7482 bool SliceDividerRow2Row::Next(SliceDividerState & state)
7483 {
7484     state.m_leftMbRow -= state.m_currSliceNumMbRow;
7485     state.m_leftSlice -= 1;
7486 
7487     if (state.m_leftSlice == 0)
7488     {
7489         assert(state.m_leftMbRow == 0);
7490         return false;
7491     }
7492     else
7493     {
7494         state.m_currSliceFirstMbRow += state.m_currSliceNumMbRow;
7495         if (state.m_currSliceNumMbRow > state.m_leftMbRow)
7496             state.m_currSliceNumMbRow = state.m_leftMbRow;
7497         assert(state.m_currSliceNumMbRow != 0);
7498         return true;
7499     }
7500 }
7501 
7502 
SliceDividerRowSlice(mfxU32 numSlice,mfxU32 widthInMbs,mfxU32 heightInMbs)7503 SliceDividerRowSlice::SliceDividerRowSlice(
7504     mfxU32 numSlice,
7505     mfxU32 widthInMbs,
7506     mfxU32 heightInMbs)
7507 {
7508     m_pfNext              = &SliceDividerRowSlice::Next;
7509     m_numSlice            = mfx::clamp(numSlice, 1u, heightInMbs);
7510     m_numMbInRow          = widthInMbs;
7511     m_numMbRow            = heightInMbs;
7512     m_currSliceFirstMbRow = 0;
7513     m_leftMbRow           = heightInMbs;
7514 
7515     mfxU32 H  = heightInMbs;      // frame height
7516     mfxU32 n  = m_numSlice;       // num slices
7517     mfxU32 sh = (H + n - 1) / n;  // slice height
7518 
7519     // check if frame is divisible to requested number of slices
7520     // so that size of last slice is no bigger than other slices
7521     while (sh * (n - 1) >= H)
7522     {
7523         n++;
7524         sh = (H + n - 1) / n;
7525     }
7526 
7527     m_currSliceNumMbRow   = sh;
7528     m_numSlice            = n;
7529     m_leftSlice           = n;
7530 }
7531 
Next(SliceDividerState & state)7532 bool SliceDividerRowSlice::Next(SliceDividerState & state)
7533 {
7534     state.m_leftMbRow -= state.m_currSliceNumMbRow;
7535     state.m_leftSlice -= 1;
7536 
7537     if (state.m_leftSlice == 0)
7538     {
7539         assert(state.m_leftMbRow == 0);
7540         return false;
7541     }
7542     else
7543     {
7544         state.m_currSliceFirstMbRow += state.m_currSliceNumMbRow;
7545         if (state.m_currSliceNumMbRow > state.m_leftMbRow)
7546             state.m_currSliceNumMbRow = state.m_leftMbRow;
7547         assert(state.m_currSliceNumMbRow != 0);
7548         return true;
7549     }
7550 }
7551 
SliceDividerTemporalScalability(mfxU32 sliceSizeInMbs,mfxU32 widthInMbs,mfxU32 heightInMbs)7552 SliceDividerTemporalScalability::SliceDividerTemporalScalability(
7553     mfxU32 sliceSizeInMbs,
7554     mfxU32 widthInMbs,
7555     mfxU32 heightInMbs)
7556 {
7557     m_pfNext              = &SliceDividerTemporalScalability::Next;
7558     m_numMbInRow          = 1;
7559     m_numMbRow            = heightInMbs*widthInMbs;
7560     m_currSliceFirstMbRow = 0;
7561     m_leftMbRow           = m_numMbRow;
7562     m_numSlice            = (m_numMbRow + sliceSizeInMbs - 1) / sliceSizeInMbs;
7563     m_currSliceNumMbRow   = sliceSizeInMbs;
7564     m_leftSlice           = m_numSlice;
7565 }
7566 
Next(SliceDividerState & state)7567 bool SliceDividerTemporalScalability::Next(SliceDividerState & state)
7568 {
7569     state.m_leftMbRow -= state.m_currSliceNumMbRow;
7570     state.m_leftSlice -= 1;
7571 
7572     if (state.m_leftSlice == 0)
7573     {
7574         assert(state.m_leftMbRow == 0);
7575         return false;
7576     }
7577     else
7578     {
7579         state.m_currSliceFirstMbRow += state.m_currSliceNumMbRow;
7580         if (state.m_currSliceNumMbRow > state.m_leftMbRow)
7581             state.m_currSliceNumMbRow = state.m_leftMbRow;
7582         assert(state.m_currSliceNumMbRow != 0);
7583         return true;
7584     }
7585 }
7586 
SliceDividerLowPowerTemporalScalability(mfxU32 sliceSizeInMbs,mfxU32 widthInMbs,mfxU32 heightInMbs)7587 SliceDividerLowPowerTemporalScalability::SliceDividerLowPowerTemporalScalability(
7588     mfxU32 sliceSizeInMbs,
7589     mfxU32 widthInMbs,
7590     mfxU32 heightInMbs)
7591 {
7592     m_pfNext              = &SliceDividerLowPowerTemporalScalability::Next;
7593     m_numMbInRow          = 1;
7594     m_numMbRow            = heightInMbs*widthInMbs;
7595     m_currSliceFirstMbRow = 0;
7596     m_leftMbRow           = m_numMbRow;
7597     m_numSlice            = (m_numMbRow + sliceSizeInMbs - 1) / sliceSizeInMbs;
7598     m_currSliceNumMbRow   = sliceSizeInMbs;
7599     m_leftSlice           = m_numSlice;
7600 }
7601 
Next(SliceDividerState & state)7602 bool SliceDividerLowPowerTemporalScalability::Next(SliceDividerState & state)
7603 {
7604     state.m_leftMbRow -= state.m_currSliceNumMbRow;
7605     state.m_leftSlice -= 1;
7606 
7607     if (state.m_leftSlice == 0)
7608     {
7609         assert(state.m_leftMbRow == 0);
7610         return false;
7611     }
7612     else
7613     {
7614         state.m_currSliceFirstMbRow = 0; //state.m_currSliceNumMbRow;
7615         if (state.m_currSliceNumMbRow > state.m_leftMbRow)
7616             state.m_currSliceNumMbRow = state.m_leftMbRow;
7617         assert(state.m_currSliceNumMbRow != 0);
7618         return true;
7619     }
7620 }
7621 
SliceDividerLowPower(mfxU32 numSlice,mfxU32 widthInMbs,mfxU32 heightInMbs)7622 SliceDividerLowPower::SliceDividerLowPower(
7623     mfxU32 numSlice,
7624     mfxU32 widthInMbs,
7625     mfxU32 heightInMbs)
7626 {
7627     m_pfNext              = &SliceDividerLowPower::Next;
7628     m_numSlice            = mfx::clamp(numSlice, 1u, heightInMbs);
7629     m_numMbInRow          = widthInMbs;
7630     m_numMbRow            = heightInMbs;
7631     m_currSliceFirstMbRow = 0;
7632     m_leftMbRow           = heightInMbs;
7633 
7634     mfxU32 H  = heightInMbs;      // frame height
7635     mfxU32 n  = m_numSlice;       // num slices
7636     mfxU32 sh = (H + n - 1) / n;  // slice height
7637 
7638     // check if frame is divisible to requested number of slices
7639     // so that size of last slice is no bigger than other slices
7640     while (sh * (n - 1) >= H)
7641     {
7642         n++;
7643         sh = (H + n - 1) / n;
7644     }
7645 
7646     m_currSliceNumMbRow   = sh;
7647     m_numSlice            = n;
7648     m_leftSlice           = n;
7649 }
7650 
Next(SliceDividerState & state)7651 bool SliceDividerLowPower::Next(SliceDividerState & state)
7652 {
7653     state.m_leftMbRow -= state.m_currSliceNumMbRow;
7654     state.m_leftSlice -= 1;
7655 
7656     if (state.m_leftSlice == 0)
7657     {
7658         assert(state.m_leftMbRow == 0);
7659         return false;
7660     }
7661     else
7662     {
7663         state.m_currSliceFirstMbRow = 0;//state.m_currSliceNumMbRow;
7664         if (state.m_currSliceNumMbRow > state.m_leftMbRow)
7665             state.m_currSliceNumMbRow = state.m_leftMbRow;
7666         assert(state.m_currSliceNumMbRow != 0);
7667         return true;
7668     }
7669 }
7670 
MakeSliceDivider(SliceDividerType sliceHwCaps,mfxU32 sliceSizeInMbs,mfxU32 numSlice,mfxU32 widthInMbs,mfxU32 heightInMbs,bool isLowPower)7671 SliceDivider MfxHwH264Encode::MakeSliceDivider(
7672     SliceDividerType sliceHwCaps,
7673     mfxU32  sliceSizeInMbs,
7674     mfxU32  numSlice,
7675     mfxU32  widthInMbs,
7676     mfxU32  heightInMbs,
7677     bool isLowPower)
7678 {
7679     if(isLowPower){
7680         if(sliceHwCaps != SliceDividerType::ONESLICE && sliceSizeInMbs > 0)
7681             return SliceDividerLowPowerTemporalScalability(sliceSizeInMbs, widthInMbs, heightInMbs);
7682 
7683         return SliceDividerLowPower(numSlice, widthInMbs, heightInMbs);
7684     }
7685 
7686     if(sliceHwCaps != SliceDividerType::ONESLICE && sliceSizeInMbs > 0)
7687         return SliceDividerTemporalScalability(sliceSizeInMbs, widthInMbs, heightInMbs);
7688 
7689     switch (sliceHwCaps)
7690     {
7691     case SliceDividerType::ROW2ROW:  return SliceDividerRow2Row(numSlice, widthInMbs, heightInMbs);
7692     case SliceDividerType::ROWSLICE:  return SliceDividerRowSlice(numSlice, widthInMbs, heightInMbs);
7693     case SliceDividerType::ARBITRARY_ROW_SLICE:  return SliceDividerArbitraryRowSlice(numSlice, widthInMbs, heightInMbs);
7694     //If arbitrary slice size supported by HW make legacy HSW division, need to implement arbitrary case
7695     case SliceDividerType::ARBITRARY_MB_SLICE:  return SliceDividerRowSlice(numSlice, widthInMbs, heightInMbs);
7696     default: return SliceDividerOneSlice(numSlice, widthInMbs, heightInMbs);
7697     }
7698 }
7699 
7700 
7701 namespace
7702 {
TestSliceDivider(mfxU32 requestedNumSlice,mfxU32 width,mfxU32 height,mfxU32 refNumSlice,mfxU32 refNumMbRowsInSlice,mfxU32 refNumMbRowsInLastSlice)7703     bool TestSliceDivider(
7704         mfxU32 requestedNumSlice,
7705         mfxU32 width,
7706         mfxU32 height,
7707         mfxU32 refNumSlice,
7708         mfxU32 refNumMbRowsInSlice,
7709         mfxU32 refNumMbRowsInLastSlice)
7710     {
7711         mfxU32 numMbsInRow = (width + 15) / 16;
7712         SliceDivider sd = SliceDividerRow2Row(requestedNumSlice, numMbsInRow, (height + 15) / 16);
7713 
7714         mfxU32 numSlice = sd.GetNumSlice();
7715         if (numSlice != refNumSlice)
7716             return false;
7717 
7718         mfxU32 predictedPirstMbInSlice = 0;
7719         for (mfxU32 i = 0; i < numSlice; i++)
7720         {
7721             mfxU32 firstMbInSlice = sd.GetFirstMbInSlice();
7722             mfxU32 numMbInSlice = sd.GetNumMbInSlice();
7723 
7724             if (firstMbInSlice != predictedPirstMbInSlice)
7725                 return false;
7726 
7727             bool hasNext = sd.Next();
7728             if (hasNext != (i + 1 < numSlice))
7729                 return false;
7730 
7731             if (hasNext)
7732             {
7733                 if (numMbInSlice != refNumMbRowsInSlice * numMbsInRow)
7734                     return false;
7735             }
7736             else
7737             {
7738                 if (numMbInSlice != refNumMbRowsInLastSlice * numMbsInRow)
7739                     return false;
7740             }
7741 
7742             predictedPirstMbInSlice += numMbInSlice;
7743         }
7744 
7745         return true;
7746     }
7747 
TestSliceDividerWithReport(mfxU32 requestedNumSlice,mfxU32 width,mfxU32 height,mfxU32 refNumSlice,mfxU32 refNumMbRowsInSlice,mfxU32 refNumMbRowsInLastSlice)7748     bool TestSliceDividerWithReport(
7749         mfxU32 requestedNumSlice,
7750         mfxU32 width,
7751         mfxU32 height,
7752         mfxU32 refNumSlice,
7753         mfxU32 refNumMbRowsInSlice,
7754         mfxU32 refNumMbRowsInLastSlice)
7755     {
7756         if (!TestSliceDivider(requestedNumSlice, width, height, refNumSlice, refNumMbRowsInSlice, refNumMbRowsInLastSlice))
7757         {
7758             //std::cout << "Failed with requestedNumSlice=" << requestedNumSlice << " width=" << width << " height=" << height << std::endl;
7759             return false;
7760         }
7761 
7762         //std::cout << "Passed with requestedNumSlice=" << requestedNumSlice << " width=" << width << " height=" << height << std::endl;
7763         return true;
7764     }
7765 }
7766 
Test()7767 void SliceDividerRow2Row::Test()
7768 {
7769     TestSliceDividerWithReport( 2,  720,  480,  2, 16, 14);
7770     TestSliceDividerWithReport( 4,  720,  480,  4,  8,  6);
7771     TestSliceDividerWithReport( 8,  720,  480,  8,  4,  2);
7772     TestSliceDividerWithReport(16,  720,  480, 30,  1,  1);
7773     TestSliceDividerWithReport( 2, 1920, 1080,  2, 64,  4);
7774     TestSliceDividerWithReport( 4, 1920, 1080,  5, 16,  4);
7775     TestSliceDividerWithReport( 8, 1920, 1080,  9,  8,  4);
7776     TestSliceDividerWithReport(16, 1920, 1080, 17,  4,  4);
7777     TestSliceDividerWithReport( 8, 1280,  720, 12,  4,  1);
7778     TestSliceDividerWithReport( 8,  480,  320, 10,  2,  2);
7779 
7780     TestSliceDividerWithReport( 2,  720,  480 / 2,  2,  8,  7);
7781     TestSliceDividerWithReport( 4,  720,  480 / 2,  4,  4,  3);
7782     TestSliceDividerWithReport( 8,  720,  480 / 2,  8,  2,  1);
7783     TestSliceDividerWithReport(16,  720,  480 / 2, 15,  1,  1);
7784     TestSliceDividerWithReport( 2, 1920, 1080 / 2,  2, 32,  2);
7785     TestSliceDividerWithReport( 4, 1920, 1080 / 2,  5,  8,  2);
7786     TestSliceDividerWithReport( 8, 1920, 1080 / 2,  9,  4,  2);
7787     TestSliceDividerWithReport(16, 1920, 1080 / 2, 17,  2,  2);
7788     TestSliceDividerWithReport( 8, 1280,  720 / 2, 12,  2,  1);
7789     TestSliceDividerWithReport( 8,  480,  320 / 2, 10,  1,  1);
7790 }
7791 
MfxVideoParam()7792 MfxVideoParam::MfxVideoParam()
7793     : mfxVideoParam()
7794     , m_extOpt()
7795     , m_extOpt2()
7796     , m_extOpt3()
7797     , m_extOptSpsPps()
7798     , m_extVideoSignal()
7799     , m_extOpaque()
7800     , m_extMvcSeqDescr()
7801     , m_extPicTiming()
7802     , m_extTempLayers()
7803     , m_extEncResetOpt()
7804     , m_extEncRoi()
7805     , m_extFeiParam()
7806     , m_extChromaLoc()
7807     , m_extPwt()
7808     , m_extDirtyRect()
7809     , m_extMoveRect()
7810     , m_extOptDdi()
7811     , m_extSps()
7812     , m_extPps()
7813     , m_extFeiOpt()
7814     , m_extFeiSPS()
7815     , m_extFeiPPS()
7816 #if defined(__MFXBRC_H__)
7817     , m_extBRC()
7818 #if defined(MFX_ENABLE_ENCTOOLS)
7819     , m_encTools()
7820     , m_encToolsConfig()
7821 #endif
7822 #endif
7823 #if defined(MFX_ENABLE_MFE)
7824     , m_MfeParam()
7825     , m_MfeControl()
7826 #endif
7827     , calcParam()
7828 {
7829     memset(m_extParam, 0, sizeof(m_extParam));
7830     memset(m_extFeiSlice, 0, sizeof(m_extFeiSlice));
7831 }
7832 
MfxVideoParam(MfxVideoParam const & par)7833 MfxVideoParam::MfxVideoParam(MfxVideoParam const & par)
7834 {
7835     Construct(par);
7836     calcParam = par.calcParam;
7837 }
7838 
MfxVideoParam(mfxVideoParam const & par)7839 MfxVideoParam::MfxVideoParam(mfxVideoParam const & par)
7840 {
7841     Construct(par);
7842     SyncVideoToCalculableParam();
7843 }
7844 
operator =(MfxVideoParam const & par)7845 MfxVideoParam& MfxVideoParam::operator=(MfxVideoParam const & par)
7846 {
7847     Construct(par);
7848     calcParam = par.calcParam;
7849     return *this;
7850 }
7851 
operator =(mfxVideoParam const & par)7852 MfxVideoParam& MfxVideoParam::operator=(mfxVideoParam const & par)
7853 {
7854     Construct(par);
7855     SyncVideoToCalculableParam();
7856     return *this;
7857 }
7858 
SyncVideoToCalculableParam()7859 void MfxVideoParam::SyncVideoToCalculableParam()
7860 {
7861     mfxU32 multiplier = std::max<mfxU16>(mfx.BRCParamMultiplier, 1);
7862 
7863     calcParam.PPyrInterval = (mfx.NumRefFrame > 0) ? std::min<mfxU32>(DEFAULT_PPYR_INTERVAL, mfx.NumRefFrame) : DEFAULT_PPYR_INTERVAL;
7864 
7865     calcParam.bufferSizeInKB   = mfx.BufferSizeInKB   * multiplier;
7866     if (IsOn(m_extOpt.VuiNalHrdParameters)
7867         && !IsOn(m_extOpt.VuiVclHrdParameters)
7868         && IsOff(m_extOpt.NalHrdConformance)
7869         && mfx.RateControlMethod == MFX_RATECONTROL_CQP
7870         && mfx.FrameInfo.FrameRateExtN != 0
7871         && mfx.FrameInfo.FrameRateExtD != 0
7872         && mfx.BufferSizeInKB != 0
7873         && mfx.InitialDelayInKB != 0
7874         && mfx.TargetKbps != 0)
7875     {
7876         calcParam.cqpHrdMode = mfx.MaxKbps > 0 ? 2 : 1;
7877     }
7878 
7879     if (calcParam.cqpHrdMode)
7880     {
7881         calcParam.decorativeHrdParam.bufferSizeInKB  = calcParam.bufferSizeInKB;
7882         calcParam.decorativeHrdParam.initialDelayInKB = mfx.InitialDelayInKB * multiplier;
7883         calcParam.decorativeHrdParam.targetKbps       = mfx.TargetKbps       * multiplier;
7884         calcParam.decorativeHrdParam.maxKbps          = mfx.MaxKbps > 0 ? mfx.MaxKbps       * multiplier : calcParam.decorativeHrdParam.targetKbps;
7885     }
7886 
7887     if (mfx.RateControlMethod != MFX_RATECONTROL_CQP
7888         && mfx.RateControlMethod != MFX_RATECONTROL_ICQ
7889         && mfx.RateControlMethod != MFX_RATECONTROL_LA_ICQ)
7890     {
7891         calcParam.initialDelayInKB = mfx.InitialDelayInKB * multiplier;
7892         calcParam.targetKbps       = mfx.TargetKbps       * multiplier;
7893         calcParam.maxKbps          = mfx.MaxKbps          * multiplier;
7894     }
7895     else
7896     {
7897         calcParam.bufferSizeInKB = calcParam.initialDelayInKB = calcParam.maxKbps = 0;
7898     }
7899     if (mfx.RateControlMethod == MFX_RATECONTROL_LA ||
7900         mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD ||
7901         mfx.RateControlMethod == MFX_RATECONTROL_LA_EXT)
7902         calcParam.WinBRCMaxAvgKbps = m_extOpt3.WinBRCMaxAvgKbps * multiplier;
7903 
7904     {
7905         calcParam.numTemporalLayer = 0;
7906         calcParam.tid[0]   = 0;
7907         calcParam.scale[0] = 1;
7908         for (mfxU32 i = 0; i < 8; i++)
7909         {
7910             if (m_extTempLayers.Layer[i].Scale != 0)
7911             {
7912                 calcParam.tid[calcParam.numTemporalLayer]   = i;
7913                 calcParam.scale[calcParam.numTemporalLayer] = m_extTempLayers.Layer[i].Scale;
7914                 calcParam.numTemporalLayer++;
7915             }
7916         }
7917 
7918         if (calcParam.numTemporalLayer)
7919             calcParam.tempScalabilityMode = 1;
7920 
7921         calcParam.numDependencyLayer = 1;
7922         calcParam.numLayersTotal     = 1;
7923     }
7924 
7925     if (IsMvcProfile(mfx.CodecProfile))
7926     {
7927         mfxExtMVCSeqDesc * extMvc = GetExtBuffer(*this);
7928         if (extMvc && extMvc->NumView)
7929         {
7930             calcParam.mvcPerViewPar.bufferSizeInKB   = calcParam.bufferSizeInKB / extMvc->NumView;
7931             if (mfx.RateControlMethod != MFX_RATECONTROL_CQP
7932                 && mfx.RateControlMethod != MFX_RATECONTROL_ICQ
7933                 && mfx.RateControlMethod != MFX_RATECONTROL_LA_ICQ)
7934             {
7935                 calcParam.mvcPerViewPar.initialDelayInKB = calcParam.initialDelayInKB / extMvc->NumView;
7936                 calcParam.mvcPerViewPar.targetKbps       = calcParam.targetKbps / extMvc->NumView;
7937                 calcParam.mvcPerViewPar.maxKbps          = calcParam.maxKbps / extMvc->NumView;
7938             }
7939             else
7940             {
7941                 calcParam.mvcPerViewPar.initialDelayInKB = calcParam.mvcPerViewPar.targetKbps = calcParam.mvcPerViewPar.maxKbps = 0;
7942             }
7943         }
7944         calcParam.mvcPerViewPar.codecLevel       = mfx.CodecLevel;
7945     }
7946 
7947 }
7948 
SyncCalculableToVideoParam()7949 void MfxVideoParam::SyncCalculableToVideoParam()
7950 {
7951     mfxU32 maxVal32 = calcParam.bufferSizeInKB;
7952 
7953     if (mfx.RateControlMethod != MFX_RATECONTROL_CQP)
7954     {
7955         maxVal32 = std::max(maxVal32, calcParam.targetKbps);
7956 
7957         if (mfx.RateControlMethod != MFX_RATECONTROL_AVBR) {
7958             if (mfx.RateControlMethod == MFX_RATECONTROL_VBR || mfx.RateControlMethod == MFX_RATECONTROL_QVBR)
7959                 maxVal32 = std::max({maxVal32, calcParam.maxKbps, calcParam.initialDelayInKB});
7960             else
7961                 maxVal32 = std::max({maxVal32, calcParam.maxKbps, calcParam.initialDelayInKB, calcParam.WinBRCMaxAvgKbps});
7962         }
7963     }
7964 
7965     mfx.BRCParamMultiplier = mfxU16((maxVal32 + 0x10000) / 0x10000);
7966     if (calcParam.cqpHrdMode == 0 || calcParam.bufferSizeInKB)
7967     {
7968         mfx.BufferSizeInKB     = mfxU16(calcParam.bufferSizeInKB / mfx.BRCParamMultiplier);
7969     }
7970 
7971     if (mfx.RateControlMethod == MFX_RATECONTROL_CBR ||
7972         mfx.RateControlMethod == MFX_RATECONTROL_VBR ||
7973         mfx.RateControlMethod == MFX_RATECONTROL_VCM ||
7974         mfx.RateControlMethod == MFX_RATECONTROL_AVBR||
7975         mfx.RateControlMethod == MFX_RATECONTROL_QVBR ||
7976         (bRateControlLA(mfx.RateControlMethod) && (mfx.RateControlMethod != MFX_RATECONTROL_LA_ICQ)))
7977     {
7978         mfx.TargetKbps = mfxU16(calcParam.targetKbps / mfx.BRCParamMultiplier);
7979 
7980         if (mfx.RateControlMethod != MFX_RATECONTROL_AVBR)
7981         {
7982             mfx.InitialDelayInKB = mfxU16(calcParam.initialDelayInKB / mfx.BRCParamMultiplier);
7983             mfx.MaxKbps          = mfxU16(calcParam.maxKbps / mfx.BRCParamMultiplier);
7984         }
7985     }
7986     if (mfx.RateControlMethod == MFX_RATECONTROL_LA ||
7987         mfx.RateControlMethod == MFX_RATECONTROL_LA_HRD ||
7988         mfx.RateControlMethod == MFX_RATECONTROL_LA_EXT)
7989         m_extOpt3.WinBRCMaxAvgKbps = mfxU16(calcParam.WinBRCMaxAvgKbps / mfx.BRCParamMultiplier);
7990 }
7991 
AlignCalcWithBRCParamMultiplier()7992 void MfxVideoParam::AlignCalcWithBRCParamMultiplier()
7993 {
7994     if(!mfx.BRCParamMultiplier)
7995         return;
7996 
7997     if (mfx.RateControlMethod != MFX_RATECONTROL_CQP)
7998     {
7999         calcParam.bufferSizeInKB   = mfx.BufferSizeInKB   * mfx.BRCParamMultiplier;
8000         calcParam.initialDelayInKB = mfx.InitialDelayInKB * mfx.BRCParamMultiplier;
8001         calcParam.targetKbps       = mfx.TargetKbps       * mfx.BRCParamMultiplier;
8002         calcParam.maxKbps          = mfx.MaxKbps          * mfx.BRCParamMultiplier;
8003         calcParam.WinBRCMaxAvgKbps = m_extOpt3.WinBRCMaxAvgKbps * mfx.BRCParamMultiplier;
8004     }
8005 }
8006 
Construct(mfxVideoParam const & par)8007 void MfxVideoParam::Construct(mfxVideoParam const & par)
8008 {
8009     mfxVideoParam & base = *this;
8010     base = par;
8011 
8012     Zero(m_extParam);
8013     Zero(calcParam);
8014 
8015     NumExtParam = 0;
8016 
8017 #define CONSTRUCT_EXT_BUFFER(type, name)        \
8018     InitExtBufHeader(name);                     \
8019     if (type * opts = GetExtBuffer(par))        \
8020     {    name = *opts; }              \
8021     m_extParam[NumExtParam++] = &name.Header;
8022 #define CONSTRUCT_EXT_BUFFER_EX(type, name, field)        \
8023     InitExtBufHeader(name[field]);                        \
8024     if (type * opts = GetExtBuffer(par, field))           \
8025     name[field] = *opts;                                  \
8026     m_extParam[NumExtParam++] = &name[field].Header;
8027 
8028     CONSTRUCT_EXT_BUFFER(mfxExtCodingOption,         m_extOpt);
8029     CONSTRUCT_EXT_BUFFER(mfxExtCodingOptionSPSPPS,   m_extOptSpsPps);
8030     CONSTRUCT_EXT_BUFFER(mfxExtVideoSignalInfo,      m_extVideoSignal);
8031     CONSTRUCT_EXT_BUFFER(mfxExtOpaqueSurfaceAlloc,   m_extOpaque);
8032 
8033     // perform deep copy of the mfxExtMVCSeqDesc buffer
8034     InitExtBufHeader(m_extMvcSeqDescr);
8035     if (mfxExtMVCSeqDesc * buffer = GetExtBuffer(par))
8036         ConstructMvcSeqDesc(*buffer);
8037     m_extParam[NumExtParam++] = &m_extMvcSeqDescr.Header;
8038 
8039     CONSTRUCT_EXT_BUFFER(mfxExtPictureTimingSEI,     m_extPicTiming);
8040     CONSTRUCT_EXT_BUFFER(mfxExtAvcTemporalLayers,    m_extTempLayers);
8041     CONSTRUCT_EXT_BUFFER(mfxExtCodingOptionDDI,      m_extOptDdi);
8042     CONSTRUCT_EXT_BUFFER(mfxExtSpsHeader,            m_extSps);
8043     CONSTRUCT_EXT_BUFFER(mfxExtPpsHeader,            m_extPps);
8044     CONSTRUCT_EXT_BUFFER(mfxExtCodingOption2,        m_extOpt2);
8045     CONSTRUCT_EXT_BUFFER(mfxExtEncoderResetOption,   m_extEncResetOpt);
8046     CONSTRUCT_EXT_BUFFER(mfxExtEncoderROI,           m_extEncRoi);
8047     CONSTRUCT_EXT_BUFFER(mfxExtCodingOption3,        m_extOpt3);
8048     CONSTRUCT_EXT_BUFFER(mfxExtChromaLocInfo,        m_extChromaLoc);
8049     CONSTRUCT_EXT_BUFFER(mfxExtFeiParam,             m_extFeiParam);
8050     CONSTRUCT_EXT_BUFFER(mfxExtPredWeightTable,      m_extPwt);
8051     CONSTRUCT_EXT_BUFFER(mfxExtDirtyRect,            m_extDirtyRect);
8052     CONSTRUCT_EXT_BUFFER(mfxExtMoveRect,             m_extMoveRect);
8053     CONSTRUCT_EXT_BUFFER(mfxExtFeiCodingOption,      m_extFeiOpt);
8054     CONSTRUCT_EXT_BUFFER_EX(mfxExtFeiSliceHeader,    m_extFeiSlice, 0);
8055     CONSTRUCT_EXT_BUFFER_EX(mfxExtFeiSliceHeader,    m_extFeiSlice, 1);
8056     CONSTRUCT_EXT_BUFFER(mfxExtFeiSPS,               m_extFeiSPS);
8057     CONSTRUCT_EXT_BUFFER(mfxExtFeiPPS,               m_extFeiPPS);
8058 
8059 #if defined(__MFXBRC_H__)
8060     CONSTRUCT_EXT_BUFFER(mfxExtBRC,                  m_extBRC);
8061 #endif
8062 #if defined(MFX_ENABLE_ENCTOOLS)
8063     CONSTRUCT_EXT_BUFFER(mfxEncTools,                m_encTools);
8064     CONSTRUCT_EXT_BUFFER(mfxExtEncToolsConfig,          m_encToolsConfig);
8065     CONSTRUCT_EXT_BUFFER(mfxEncToolsCtrlExtDevice,               m_extDevice);
8066     CONSTRUCT_EXT_BUFFER(mfxEncToolsCtrlExtAllocator,            m_extAllocator);
8067 #endif
8068 
8069 #if defined(MFX_ENABLE_MFE)
8070     CONSTRUCT_EXT_BUFFER(mfxExtMultiFrameParam, m_MfeParam);
8071     CONSTRUCT_EXT_BUFFER(mfxExtMultiFrameControl, m_MfeControl);
8072 #endif
8073 
8074 
8075 #undef CONSTRUCT_EXT_BUFFER
8076 #undef CONSTRUCT_EXT_BUFFER_EX
8077 
8078     ExtParam = m_extParam;
8079 }
8080 
ConstructMvcSeqDesc(mfxExtMVCSeqDesc const & desc)8081 void MfxVideoParam::ConstructMvcSeqDesc(
8082     mfxExtMVCSeqDesc const & desc)
8083 {
8084     m_extMvcSeqDescr.NumView        = desc.NumView;
8085     m_extMvcSeqDescr.NumViewAlloc   = desc.NumViewAlloc;
8086     m_extMvcSeqDescr.View           = 0;
8087     m_extMvcSeqDescr.NumViewId      = desc.NumViewId;
8088     m_extMvcSeqDescr.NumViewIdAlloc = desc.NumViewIdAlloc;
8089     m_extMvcSeqDescr.ViewId         = 0;
8090     m_extMvcSeqDescr.NumOP          = desc.NumOP;
8091     m_extMvcSeqDescr.NumOPAlloc     = desc.NumOPAlloc;
8092     m_extMvcSeqDescr.OP             = 0;
8093     m_extMvcSeqDescr.NumRefsTotal   = desc.NumRefsTotal;
8094 
8095     if (desc.View)
8096     {// potentially NumView and NumViewAlloc may differ, so reallocate for NumViewAlloc views
8097         m_storageView.resize(desc.NumViewAlloc);
8098         std::copy(desc.View,   desc.View   + desc.NumView,   m_storageView.begin());
8099         m_extMvcSeqDescr.View           = &m_storageView[0];
8100 
8101         if (desc.ViewId && desc.OP)
8102         {
8103             m_storageOp.resize(desc.NumOPAlloc);
8104             m_storageViewId.resize(desc.NumViewIdAlloc);
8105 
8106             std::copy(desc.OP,     desc.OP     + desc.NumOP,     m_storageOp.begin());
8107             std::copy(desc.ViewId, desc.ViewId + desc.NumViewId, m_storageViewId.begin());
8108 
8109             for (size_t i = 0; i < m_storageOp.size(); ++i)
8110             {
8111                 ptrdiff_t offset = desc.OP[i].TargetViewId - desc.ViewId;
8112                 m_storageOp[i].TargetViewId = &m_storageViewId[0] + offset;
8113             }
8114 
8115             m_extMvcSeqDescr.ViewId         = &m_storageViewId[0];
8116             m_extMvcSeqDescr.OP             = &m_storageOp[0];
8117         }
8118     }
8119 }
8120 
ApplyDefaultsToMvcSeqDesc()8121 void MfxVideoParam::ApplyDefaultsToMvcSeqDesc()
8122 {
8123     if (false == IsMvcProfile(mfx.CodecProfile))
8124     {
8125         m_extMvcSeqDescr.NumView = 1;
8126         return;
8127     }
8128 
8129     if (m_extMvcSeqDescr.NumView == 0)
8130         m_extMvcSeqDescr.NumView = 2;
8131 
8132     if (m_extMvcSeqDescr.View == 0)
8133     {
8134         m_extMvcSeqDescr.NumViewAlloc = m_extMvcSeqDescr.NumView;
8135         m_storageView.resize(m_extMvcSeqDescr.NumView);
8136         Zero(m_storageView);
8137         for (size_t i = 0; i < m_storageView.size(); i++)
8138             m_storageView[i].ViewId = mfxU16(i);
8139         m_extMvcSeqDescr.View           = &m_storageView[0];
8140     }
8141 
8142     if (m_extMvcSeqDescr.ViewId == 0)
8143     {
8144         m_extMvcSeqDescr.NumViewId = m_extMvcSeqDescr.NumViewIdAlloc = m_extMvcSeqDescr.NumView;
8145         m_storageViewId.resize(m_extMvcSeqDescr.NumViewId);
8146         Zero(m_storageViewId);
8147         for (size_t i = 0; i < m_extMvcSeqDescr.NumViewIdAlloc; i++)
8148             m_storageViewId[i] = mfxU16(i);
8149         m_extMvcSeqDescr.ViewId         = &m_storageViewId[0];
8150     }
8151 
8152     if (m_extMvcSeqDescr.OP == 0)
8153     {
8154         m_extMvcSeqDescr.NumOP = 1;
8155         m_extMvcSeqDescr.NumOPAlloc = 1;
8156         m_storageOp.resize(m_extMvcSeqDescr.NumOP);
8157         Zero(m_storageOp);
8158 
8159         m_storageOp[0].TemporalId     = 0;
8160         m_storageOp[0].LevelIdc       = mfx.CodecLevel;
8161         m_storageOp[0].NumViews       = mfxU16(m_storageViewId.size());
8162         m_storageOp[0].NumTargetViews = mfxU16(m_storageViewId.size());
8163         m_storageOp[0].TargetViewId   = &m_storageViewId[0];
8164 
8165         m_extMvcSeqDescr.OP             = m_storageOp.size() ? &m_storageOp[0] : 0;
8166     }
8167     else
8168     {
8169         for (mfxU32 i = 0; i < m_extMvcSeqDescr.NumOP; i++)
8170         {
8171             if (m_extMvcSeqDescr.OP[i].LevelIdc == 0)
8172                 m_extMvcSeqDescr.OP[i].LevelIdc = mfx.CodecLevel;
8173         }
8174     }
8175 }
8176 
AspectRatioConverter(mfxU16 sarw,mfxU16 sarh)8177 AspectRatioConverter::AspectRatioConverter(mfxU16 sarw, mfxU16 sarh) :
8178     m_sarIdc(0),
8179     m_sarWidth(0),
8180     m_sarHeight(0)
8181 {
8182     if (sarw != 0 && sarh != 0)
8183     {
8184         for (mfxU8 i = 1; i < sizeof(TABLE_E1) / sizeof(TABLE_E1[0]); i++)
8185         {
8186             if ((sarw % TABLE_E1[i].w) == 0 &&
8187                 (sarh % TABLE_E1[i].h) == 0 &&
8188                 (sarw / TABLE_E1[i].w) == (sarh / TABLE_E1[i].h))
8189             {
8190                 m_sarIdc    = i;
8191                 m_sarWidth  = TABLE_E1[i].w;
8192                 m_sarHeight = TABLE_E1[i].h;
8193                 return;
8194             }
8195         }
8196 
8197         m_sarIdc    = EXTENDED_SAR;
8198         m_sarWidth  = sarw;
8199         m_sarHeight = sarh;
8200     }
8201 }
8202 
AspectRatioConverter(mfxU8 sarIdc,mfxU16 sarw,mfxU16 sarh)8203 AspectRatioConverter::AspectRatioConverter(mfxU8 sarIdc, mfxU16 sarw, mfxU16 sarh)
8204 {
8205     if (sarIdc < sizeof(TABLE_E1) / sizeof(TABLE_E1[0]))
8206     {
8207         m_sarIdc    = sarIdc;
8208         m_sarWidth  = TABLE_E1[sarIdc].w;
8209         m_sarHeight = TABLE_E1[sarIdc].h;
8210     }
8211     else
8212     {
8213         m_sarIdc    = EXTENDED_SAR;
8214         m_sarWidth  = sarw;
8215         m_sarHeight = sarh;
8216     }
8217 }
8218 
8219 namespace
8220 {
8221 #   ifdef min
8222 #       undef min
8223 #   endif
8224 #   ifdef max
8225 #       undef max
8226 #   endif
8227 
8228     template <class Tfrom>
8229     class RangeChecker
8230     {
8231     public:
RangeChecker(Tfrom from)8232         RangeChecker(Tfrom from) : m_from(from) {}
8233 
operator Tto() const8234         template <class Tto> operator Tto() const
8235         {
8236             if (std::numeric_limits<Tto>::min() <= m_from && m_from <= std::numeric_limits<Tto>::max())
8237                 return static_cast<Tto>(m_from);
8238             throw InvalidBitstream();
8239         }
8240 
8241     private:
8242         Tfrom m_from;
8243     };
8244 
8245     class InputBitstreamCheckedRange
8246     {
8247     public:
InputBitstreamCheckedRange(InputBitstream & impl)8248         InputBitstreamCheckedRange(InputBitstream & impl) : m_impl(impl) {}
8249 
NumBitsRead() const8250         mfxU32 NumBitsRead() const { return m_impl.NumBitsRead(); }
NumBitsLeft() const8251         mfxU32 NumBitsLeft() const { return m_impl.NumBitsLeft(); }
8252 
GetBit()8253         mfxU8 GetBit() { return static_cast<mfxU8>(m_impl.GetBit()); }
8254 
GetBits(mfxU32 nbits)8255         RangeChecker<mfxU32> GetBits(mfxU32 nbits) { return m_impl.GetBits(nbits); }
GetUe()8256         RangeChecker<mfxU32> GetUe()               { return m_impl.GetUe(); }
GetSe()8257         RangeChecker<mfxI32> GetSe()               { return m_impl.GetSe(); }
8258 
8259     private:
8260         void operator =(InputBitstreamCheckedRange const &);
8261         InputBitstream & m_impl;
8262     };
8263 
ReadScalingList(InputBitstreamCheckedRange & reader,mfxU8 * scalingList,mfxU32 size)8264     void ReadScalingList(
8265         InputBitstreamCheckedRange & reader,
8266         mfxU8 *                      scalingList,
8267         mfxU32                       size)
8268     {
8269         mfxU8 lastScale = 8;
8270         mfxU8 nextScale = 8;
8271 
8272         for (mfxU32 i = 0; i < size; i++)
8273         {
8274             if (nextScale != 0)
8275             {
8276                 mfxI32 deltaScale = reader.GetSe();
8277                 if (deltaScale < -128 || deltaScale > 127)
8278                     throw InvalidBitstream();
8279 
8280                 nextScale = mfxU8((lastScale + deltaScale + 256) & 0xff);
8281             }
8282 
8283             scalingList[i] = (nextScale == 0) ? lastScale : nextScale;
8284             lastScale = scalingList[i];
8285         }
8286     }
8287 
ReadHrdParameters(InputBitstreamCheckedRange & reader,HrdParameters & hrd)8288     void ReadHrdParameters(
8289         InputBitstreamCheckedRange & reader,
8290         HrdParameters &              hrd)
8291     {
8292         hrd.cpbCntMinus1                        = reader.GetUe();
8293 
8294         if (hrd.cpbCntMinus1 > 31)
8295             throw InvalidBitstream();
8296 
8297         hrd.bitRateScale                        = reader.GetBits(4);
8298         hrd.cpbSizeScale                        = reader.GetBits(4);
8299 
8300         for (mfxU32 i = 0; i <= hrd.cpbCntMinus1; i++)
8301         {
8302             hrd.bitRateValueMinus1[i]           = reader.GetUe();
8303             hrd.cpbSizeValueMinus1[i]           = reader.GetUe();
8304             hrd.cbrFlag[i]                      = reader.GetBit();
8305         }
8306 
8307         hrd.initialCpbRemovalDelayLengthMinus1  = reader.GetBits(5);
8308         hrd.cpbRemovalDelayLengthMinus1         = reader.GetBits(5);
8309         hrd.dpbOutputDelayLengthMinus1          = reader.GetBits(5);
8310         hrd.timeOffsetLength                    = reader.GetBits(5);
8311     }
8312 
WriteHrdParameters(OutputBitstream & writer,HrdParameters const & hrd)8313     void WriteHrdParameters(
8314         OutputBitstream &     writer,
8315         HrdParameters const & hrd)
8316     {
8317         writer.PutUe(hrd.cpbCntMinus1);
8318         writer.PutBits(hrd.bitRateScale, 4);
8319         writer.PutBits(hrd.cpbSizeScale, 4);
8320 
8321         for (mfxU32 i = 0; i <= hrd.cpbCntMinus1; i++)
8322         {
8323             writer.PutUe(hrd.bitRateValueMinus1[i]);
8324             writer.PutUe(hrd.cpbSizeValueMinus1[i]);
8325             writer.PutBit(hrd.cbrFlag[i]);
8326         }
8327 
8328         writer.PutBits(hrd.initialCpbRemovalDelayLengthMinus1, 5);
8329         writer.PutBits(hrd.cpbRemovalDelayLengthMinus1, 5);
8330         writer.PutBits(hrd.dpbOutputDelayLengthMinus1, 5);
8331         writer.PutBits(hrd.timeOffsetLength, 5);
8332     }
8333 
MoreRbspData(InputBitstream reader)8334     bool MoreRbspData(InputBitstream reader)
8335     {
8336         mfxU32 bitsLeft = reader.NumBitsLeft();
8337 
8338         if (bitsLeft == 0)
8339             return false;
8340 
8341         if (reader.GetBit() == 0)
8342             return true;
8343 
8344         --bitsLeft;
8345         for (; bitsLeft > 0; --bitsLeft)
8346             if (reader.GetBit() == 1)
8347                 return true;
8348 
8349         return false;
8350     }
8351 };
8352 
ReadSpsHeader(InputBitstream & is,mfxExtSpsHeader & sps)8353 void MfxHwH264Encode::ReadSpsHeader(
8354     InputBitstream &  is,
8355     mfxExtSpsHeader & sps)
8356 {
8357     // set defaults for optional fields
8358     Zero(sps.vui);
8359     sps.chromaFormatIdc               = 1;
8360     sps.vui.videoFormat               = 5;
8361     sps.vui.colourPrimaries           = 2;
8362     sps.vui.transferCharacteristics   = 2;
8363     sps.vui.matrixCoefficients        = 2;
8364     sps.vui.flags.fixedFrameRate      = 1;
8365 
8366     InputBitstreamCheckedRange reader(is);
8367 
8368     mfxU32 unused                                           = reader.GetBit(); // forbiddenZeroBit
8369     std::ignore = unused;
8370 
8371     sps.nalRefIdc                                           = reader.GetBits(2);
8372     if (sps.nalRefIdc == 0)
8373         throw InvalidBitstream();
8374 
8375     sps.nalUnitType                                         = reader.GetBits(5);
8376     if (sps.nalUnitType != 7)
8377         throw InvalidBitstream();
8378 
8379     sps.profileIdc                                          = reader.GetBits(8);
8380     sps.constraints.set0                                    = reader.GetBit();
8381     sps.constraints.set1                                    = reader.GetBit();
8382     sps.constraints.set2                                    = reader.GetBit();
8383     sps.constraints.set3                                    = reader.GetBit();
8384     sps.constraints.set4                                    = reader.GetBit();
8385     sps.constraints.set5                                    = reader.GetBit();
8386     sps.constraints.set6                                    = reader.GetBit();
8387     sps.constraints.set7                                    = reader.GetBit();
8388     sps.levelIdc                                            = reader.GetBits(8);
8389     sps.seqParameterSetId                                   = reader.GetUe();
8390 
8391     if (sps.profileIdc == 100 || sps.profileIdc == 110 || sps.profileIdc == 122 ||
8392         sps.profileIdc == 244 || sps.profileIdc ==  44 || sps.profileIdc ==  83 ||
8393         sps.profileIdc ==  86 || sps.profileIdc == 118 || sps.profileIdc == 128)
8394     {
8395         sps.chromaFormatIdc                                 = reader.GetUe();
8396         if (sps.chromaFormatIdc == 3)
8397             unused                                          = reader.GetBit(); // separateColourPlaneFlag
8398 
8399         sps.bitDepthLumaMinus8                              = reader.GetUe();
8400         sps.bitDepthChromaMinus8                            = reader.GetUe();
8401 
8402         sps.qpprimeYZeroTransformBypassFlag                 = reader.GetBit();
8403         sps.seqScalingMatrixPresentFlag                     = reader.GetBit();
8404 
8405         if (sps.seqScalingMatrixPresentFlag)
8406         {
8407             for (mfxU32 i = 0; i < ((sps.chromaFormatIdc != 3) ? 8u : 12u); i++)
8408             {
8409                 sps.seqScalingListPresentFlag[i]            = reader.GetBit();
8410                 if (sps.seqScalingListPresentFlag[i])
8411                 {
8412                     (i < 6)
8413                         ? ReadScalingList(reader, sps.scalingList4x4[i],     16)
8414                         : ReadScalingList(reader, sps.scalingList8x8[i - 6], 64);
8415                 }
8416             }
8417         }
8418     }
8419 
8420     sps.log2MaxFrameNumMinus4                               = reader.GetUe();
8421     sps.picOrderCntType                                     = reader.GetUe();
8422 
8423     if (sps.picOrderCntType == 0)
8424     {
8425         sps.log2MaxPicOrderCntLsbMinus4                     = reader.GetUe();
8426     }
8427     else if (sps.picOrderCntType == 1)
8428     {
8429         sps.deltaPicOrderAlwaysZeroFlag                     = reader.GetBit();
8430         sps.offsetForNonRefPic                              = reader.GetSe();
8431         sps.offsetForTopToBottomField                       = reader.GetSe();
8432         sps.numRefFramesInPicOrderCntCycle                  = reader.GetUe();
8433 
8434         for (mfxU32 i = 0; i < sps.numRefFramesInPicOrderCntCycle; i++)
8435             sps.offsetForRefFrame[i]                        = reader.GetSe();
8436     }
8437 
8438     sps.maxNumRefFrames                                     = reader.GetUe();
8439     sps.gapsInFrameNumValueAllowedFlag                      = reader.GetBit();
8440     sps.picWidthInMbsMinus1                                 = reader.GetUe();
8441     sps.picHeightInMapUnitsMinus1                           = reader.GetUe();
8442     sps.frameMbsOnlyFlag                                    = reader.GetBit();
8443 
8444     if (!sps.frameMbsOnlyFlag)
8445         sps.mbAdaptiveFrameFieldFlag                        = reader.GetBit();
8446 
8447     sps.direct8x8InferenceFlag                              = reader.GetBit();
8448     sps.frameCroppingFlag                                   = reader.GetBit();
8449 
8450     if (sps.frameCroppingFlag)
8451     {
8452         sps.frameCropLeftOffset                             = reader.GetUe();
8453         sps.frameCropRightOffset                            = reader.GetUe();
8454         sps.frameCropTopOffset                              = reader.GetUe();
8455         sps.frameCropBottomOffset                           = reader.GetUe();
8456     }
8457 
8458     sps.vuiParametersPresentFlag                            = reader.GetBit();
8459     if (sps.vuiParametersPresentFlag)
8460     {
8461         sps.vui.flags.aspectRatioInfoPresent                = reader.GetBit();
8462         if (sps.vui.flags.aspectRatioInfoPresent)
8463         {
8464             sps.vui.aspectRatioIdc                          = reader.GetBits(8);
8465             if (sps.vui.aspectRatioIdc == 255)
8466             {
8467                 sps.vui.sarWidth                            = reader.GetBits(16);
8468                 sps.vui.sarHeight                           = reader.GetBits(16);
8469             }
8470         }
8471 
8472         sps.vui.flags.overscanInfoPresent                   = reader.GetBit();
8473         if (sps.vui.flags.overscanInfoPresent)
8474             sps.vui.flags.overscanAppropriate               = reader.GetBit();
8475 
8476         sps.vui.flags.videoSignalTypePresent                = reader.GetBit();
8477         if (sps.vui.flags.videoSignalTypePresent)
8478         {
8479             sps.vui.videoFormat                             = reader.GetBits(3);
8480             sps.vui.flags.videoFullRange                    = reader.GetBit();
8481             sps.vui.flags.colourDescriptionPresent          = reader.GetBit();
8482 
8483             if (sps.vui.flags.colourDescriptionPresent)
8484             {
8485                 sps.vui.colourPrimaries                     = reader.GetBits(8);
8486                 sps.vui.transferCharacteristics             = reader.GetBits(8);
8487                 sps.vui.matrixCoefficients                  = reader.GetBits(8);
8488             }
8489         }
8490 
8491         sps.vui.flags.chromaLocInfoPresent                  = reader.GetBit();
8492         if (sps.vui.flags.chromaLocInfoPresent)
8493         {
8494             sps.vui.chromaSampleLocTypeTopField             = reader.GetUe();
8495             sps.vui.chromaSampleLocTypeBottomField          = reader.GetUe();
8496         }
8497 
8498         sps.vui.flags.timingInfoPresent                     = reader.GetBit();
8499         if (sps.vui.flags.timingInfoPresent)
8500         {
8501             sps.vui.numUnitsInTick                          = reader.GetBits(32);
8502             sps.vui.timeScale                               = reader.GetBits(32);
8503             sps.vui.flags.fixedFrameRate                    = reader.GetBit();
8504         }
8505 
8506         sps.vui.flags.nalHrdParametersPresent               = reader.GetBit();
8507         if (sps.vui.flags.nalHrdParametersPresent)
8508             ReadHrdParameters(reader, sps.vui.nalHrdParameters);
8509 
8510         sps.vui.flags.vclHrdParametersPresent               = reader.GetBit();
8511         if (sps.vui.flags.vclHrdParametersPresent)
8512             ReadHrdParameters(reader, sps.vui.vclHrdParameters);
8513 
8514         if (sps.vui.flags.nalHrdParametersPresent || sps.vui.flags.vclHrdParametersPresent)
8515             sps.vui.flags.lowDelayHrd                       = reader.GetBit();
8516 
8517         sps.vui.flags.picStructPresent                      = reader.GetBit();
8518         sps.vui.flags.bitstreamRestriction                  = reader.GetBit();
8519 
8520         if (sps.vui.flags.bitstreamRestriction)
8521         {
8522             sps.vui.flags.motionVectorsOverPicBoundaries    = reader.GetBit();
8523             sps.vui.maxBytesPerPicDenom                     = reader.GetUe();
8524             sps.vui.maxBitsPerMbDenom                       = reader.GetUe();
8525             sps.vui.log2MaxMvLengthHorizontal               = reader.GetUe();
8526             sps.vui.log2MaxMvLengthVertical                 = reader.GetUe();
8527             sps.vui.numReorderFrames                        = reader.GetUe();
8528             sps.vui.maxDecFrameBuffering                    = reader.GetUe();
8529         }
8530     }
8531 }
8532 
ReadSpsIdOfPpsHeader(InputBitstream is)8533 mfxU8 MfxHwH264Encode::ReadSpsIdOfPpsHeader(
8534     InputBitstream is)
8535 {
8536     InputBitstreamCheckedRange reader(is);
8537     /*mfxU8 ppsId = */reader.GetUe();
8538 
8539     mfxU8 spsId = reader.GetUe();
8540     if (spsId > 31)
8541         throw InvalidBitstream();
8542 
8543     return spsId;
8544 }
8545 
ReadPpsHeader(InputBitstream & is,mfxExtSpsHeader const & sps,mfxExtPpsHeader & pps)8546 void MfxHwH264Encode::ReadPpsHeader(
8547     InputBitstream &        is,
8548     mfxExtSpsHeader const & sps,
8549     mfxExtPpsHeader &       pps)
8550 {
8551     InputBitstreamCheckedRange reader(is);
8552 
8553     mfxU32 unused                                               = reader.GetBit(); // forbiddenZeroBit
8554     std::ignore = unused;
8555 
8556     pps.nalRefIdc                                               = reader.GetBits(2);
8557     if (pps.nalRefIdc == 0)
8558         throw InvalidBitstream();
8559 
8560     mfxU8 nalUnitType                                           = reader.GetBits(5);
8561     if (nalUnitType != 8)
8562         throw InvalidBitstream();
8563 
8564     pps.picParameterSetId                                       = reader.GetUe();
8565     pps.seqParameterSetId                                       = reader.GetUe();
8566 
8567     if (pps.seqParameterSetId != sps.seqParameterSetId)
8568         throw InvalidBitstream();
8569 
8570     pps.entropyCodingModeFlag                                   = reader.GetBit();
8571 
8572     pps.bottomFieldPicOrderInframePresentFlag                   = reader.GetBit();;
8573 
8574     pps.numSliceGroupsMinus1                                    = reader.GetUe();
8575     if (pps.numSliceGroupsMinus1 > 0)
8576     {
8577         if (pps.numSliceGroupsMinus1 > 7)
8578             throw InvalidBitstream();
8579 
8580         pps.sliceGroupMapType                                   = reader.GetUe();
8581         if (pps.sliceGroupMapType == 0)
8582         {
8583             for (mfxU32 i = 0; i <= pps.numSliceGroupsMinus1; i++)
8584                 pps.sliceGroupInfo.t0.runLengthMinus1[i]        = reader.GetUe();
8585         }
8586         else if (pps.sliceGroupMapType == 2)
8587         {
8588             for (mfxU32 i = 0; i < pps.numSliceGroupsMinus1; i++)
8589             {
8590                 pps.sliceGroupInfo.t2.topLeft[i]                = reader.GetUe();
8591                 pps.sliceGroupInfo.t2.bottomRight[i]            = reader.GetUe();
8592             }
8593         }
8594         else if (
8595             pps.sliceGroupMapType == 3 ||
8596             pps.sliceGroupMapType == 4 ||
8597             pps.sliceGroupMapType == 5)
8598         {
8599             pps.sliceGroupInfo.t3.sliceGroupChangeDirectionFlag = reader.GetBit();
8600             pps.sliceGroupInfo.t3.sliceGroupChangeRate          = reader.GetUe();
8601         }
8602         else if (pps.sliceGroupMapType == 6)
8603         {
8604             pps.sliceGroupInfo.t6.picSizeInMapUnitsMinus1       = reader.GetUe();
8605             for (mfxU32 i = 0; i <= pps.sliceGroupInfo.t6.picSizeInMapUnitsMinus1; i++)
8606                 unused                                          = reader.GetBits(CeilLog2(pps.numSliceGroupsMinus1 + 1)); // sliceGroupId
8607         }
8608     }
8609 
8610     pps.numRefIdxL0DefaultActiveMinus1                          = reader.GetUe();
8611     pps.numRefIdxL1DefaultActiveMinus1                          = reader.GetUe();
8612 
8613     pps.weightedPredFlag                                        = reader.GetBit();
8614     pps.weightedBipredIdc                                       = reader.GetBits(2);
8615     pps.picInitQpMinus26                                        = reader.GetSe();
8616     pps.picInitQsMinus26                                        = reader.GetSe();
8617     pps.chromaQpIndexOffset                                     = reader.GetSe();;
8618 
8619     pps.deblockingFilterControlPresentFlag                      = reader.GetBit();
8620     pps.constrainedIntraPredFlag                                = reader.GetBit();
8621     pps.redundantPicCntPresentFlag                              = reader.GetBit();
8622 
8623     pps.moreRbspData = MoreRbspData(is);
8624     if (pps.moreRbspData)
8625     {
8626         pps.transform8x8ModeFlag                                = reader.GetBit();
8627         pps.picScalingMatrixPresentFlag                         = reader.GetBit();
8628         if (pps.picScalingMatrixPresentFlag)
8629         {
8630             for (mfxU32 i = 0; i < 6 + ((sps.chromaFormatIdc != 3) ? 2u : 6u) * pps.transform8x8ModeFlag; i++)
8631             {
8632                 mfxU32 picScalingListPresentFlag                = reader.GetBit();
8633                 if (picScalingListPresentFlag)
8634                 {
8635                     (i < 6)
8636                         ? ReadScalingList(reader, pps.scalingList4x4[i],     16)
8637                         : ReadScalingList(reader, pps.scalingList8x8[i - 6], 64);
8638                 }
8639             }
8640         }
8641 
8642         pps.secondChromaQpIndexOffset                           = reader.GetSe();
8643     }
8644 }
8645 
8646 namespace
8647 {
WriteSpsData(OutputBitstream & writer,mfxExtSpsHeader const & sps)8648     void WriteSpsData(
8649         OutputBitstream &       writer,
8650         mfxExtSpsHeader const & sps)
8651     {
8652         writer.PutBits(sps.profileIdc, 8);
8653         writer.PutBit(sps.constraints.set0);
8654         writer.PutBit(sps.constraints.set1);
8655         writer.PutBit(sps.constraints.set2);
8656         writer.PutBit(sps.constraints.set3);
8657         writer.PutBit(sps.constraints.set4);
8658         writer.PutBit(sps.constraints.set5);
8659         writer.PutBit(sps.constraints.set6);
8660         writer.PutBit(sps.constraints.set7);
8661         writer.PutBits(sps.levelIdc, 8);
8662         writer.PutUe(sps.seqParameterSetId);
8663         if (sps.profileIdc == 100 || sps.profileIdc == 110 || sps.profileIdc == 122 ||
8664             sps.profileIdc == 244 || sps.profileIdc ==  44 || sps.profileIdc ==  83 ||
8665             sps.profileIdc ==  86 || sps.profileIdc == 118 || sps.profileIdc == 128)
8666         {
8667             writer.PutUe(sps.chromaFormatIdc);
8668             if (sps.chromaFormatIdc == 3)
8669                 writer.PutBit(sps.separateColourPlaneFlag);
8670             writer.PutUe(sps.bitDepthLumaMinus8);
8671             writer.PutUe(sps.bitDepthChromaMinus8);
8672             writer.PutBit(sps.qpprimeYZeroTransformBypassFlag);
8673             writer.PutBit(sps.seqScalingMatrixPresentFlag);
8674             if (sps.seqScalingMatrixPresentFlag)
8675             {
8676                 assert("seq_scaling_matrix is unsupported");
8677             }
8678         }
8679         writer.PutUe(sps.log2MaxFrameNumMinus4);
8680         writer.PutUe(sps.picOrderCntType);
8681         if (sps.picOrderCntType == 0)
8682         {
8683             writer.PutUe(sps.log2MaxPicOrderCntLsbMinus4);
8684         }
8685         else if (sps.picOrderCntType == 1)
8686         {
8687             writer.PutBit(sps.deltaPicOrderAlwaysZeroFlag);
8688             writer.PutSe(sps.offsetForNonRefPic);
8689             writer.PutSe(sps.offsetForTopToBottomField);
8690             writer.PutUe(sps.numRefFramesInPicOrderCntCycle);
8691             for (mfxU32 i = 0; i < sps.numRefFramesInPicOrderCntCycle; i++)
8692                 writer.PutSe(sps.offsetForRefFrame[i]);
8693         }
8694         writer.PutUe(sps.maxNumRefFrames);
8695         writer.PutBit(sps.gapsInFrameNumValueAllowedFlag);
8696         writer.PutUe(sps.picWidthInMbsMinus1);
8697         writer.PutUe(sps.picHeightInMapUnitsMinus1);
8698         writer.PutBit(sps.frameMbsOnlyFlag);
8699         if (!sps.frameMbsOnlyFlag)
8700             writer.PutBit(sps.mbAdaptiveFrameFieldFlag);
8701         writer.PutBit(sps.direct8x8InferenceFlag);
8702         writer.PutBit(sps.frameCroppingFlag);
8703         if (sps.frameCroppingFlag)
8704         {
8705             writer.PutUe(sps.frameCropLeftOffset);
8706             writer.PutUe(sps.frameCropRightOffset);
8707             writer.PutUe(sps.frameCropTopOffset);
8708             writer.PutUe(sps.frameCropBottomOffset);
8709         }
8710         writer.PutBit(sps.vuiParametersPresentFlag);
8711         if (sps.vuiParametersPresentFlag)
8712         {
8713             writer.PutBit(sps.vui.flags.aspectRatioInfoPresent);
8714             if (sps.vui.flags.aspectRatioInfoPresent)
8715             {
8716                 writer.PutBits(sps.vui.aspectRatioIdc, 8);
8717                 if (sps.vui.aspectRatioIdc == 255)
8718                 {
8719                     writer.PutBits(sps.vui.sarWidth, 16);
8720                     writer.PutBits(sps.vui.sarHeight, 16);
8721                 }
8722             }
8723             writer.PutBit(sps.vui.flags.overscanInfoPresent);
8724             if (sps.vui.flags.overscanInfoPresent)
8725                 writer.PutBit(sps.vui.flags.overscanAppropriate);
8726             writer.PutBit(sps.vui.flags.videoSignalTypePresent);
8727             if (sps.vui.flags.videoSignalTypePresent)
8728             {
8729                 writer.PutBits(sps.vui.videoFormat, 3);
8730                 writer.PutBit(sps.vui.flags.videoFullRange);
8731                 writer.PutBit(sps.vui.flags.colourDescriptionPresent);
8732                 if (sps.vui.flags.colourDescriptionPresent)
8733                 {
8734                     writer.PutBits(sps.vui.colourPrimaries, 8);
8735                     writer.PutBits(sps.vui.transferCharacteristics, 8);
8736                     writer.PutBits(sps.vui.matrixCoefficients, 8);
8737                 }
8738             }
8739             writer.PutBit(sps.vui.flags.chromaLocInfoPresent);
8740             if (sps.vui.flags.chromaLocInfoPresent)
8741             {
8742                 writer.PutUe(sps.vui.chromaSampleLocTypeTopField);
8743                 writer.PutUe(sps.vui.chromaSampleLocTypeBottomField);
8744             }
8745             writer.PutBit(sps.vui.flags.timingInfoPresent);
8746             if (sps.vui.flags.timingInfoPresent)
8747             {
8748                 writer.PutBits(sps.vui.numUnitsInTick, 32);
8749                 writer.PutBits(sps.vui.timeScale, 32);
8750                 writer.PutBit(sps.vui.flags.fixedFrameRate);
8751             }
8752             writer.PutBit(sps.vui.flags.nalHrdParametersPresent);
8753             if (sps.vui.flags.nalHrdParametersPresent)
8754                 WriteHrdParameters(writer, sps.vui.nalHrdParameters);
8755             writer.PutBit(sps.vui.flags.vclHrdParametersPresent);
8756             if (sps.vui.flags.vclHrdParametersPresent)
8757                 WriteHrdParameters(writer, sps.vui.vclHrdParameters);
8758             if (sps.vui.flags.nalHrdParametersPresent || sps.vui.flags.vclHrdParametersPresent)
8759                 writer.PutBit(sps.vui.flags.lowDelayHrd);
8760             writer.PutBit(sps.vui.flags.picStructPresent);
8761             writer.PutBit(sps.vui.flags.bitstreamRestriction);
8762             if (sps.vui.flags.bitstreamRestriction)
8763             {
8764                 writer.PutBit(sps.vui.flags.motionVectorsOverPicBoundaries);
8765                 writer.PutUe(sps.vui.maxBytesPerPicDenom);
8766                 writer.PutUe(sps.vui.maxBitsPerMbDenom);
8767                 writer.PutUe(sps.vui.log2MaxMvLengthHorizontal);
8768                 writer.PutUe(sps.vui.log2MaxMvLengthVertical);
8769                 writer.PutUe(sps.vui.numReorderFrames);
8770                 writer.PutUe(sps.vui.maxDecFrameBuffering);
8771             }
8772         }
8773     }
8774 
WriteSpsMvcExtension(OutputBitstream & writer,mfxExtMVCSeqDesc const & extMvc)8775     void WriteSpsMvcExtension(
8776         OutputBitstream &        writer,
8777         mfxExtMVCSeqDesc const & extMvc)
8778     {
8779         writer.PutUe(extMvc.NumView - 1);                       // num_views_minus1
8780         for (mfxU32 i = 0; i < extMvc.NumView; i++)
8781             writer.PutUe(extMvc.View[i].ViewId);                // view_id[i]
8782         for (mfxU32 i = 1; i < extMvc.NumView; i++)
8783         {
8784             writer.PutUe(extMvc.View[i].NumAnchorRefsL0);       // num_anchor_refs_l0[i]
8785             for (mfxU32 j = 0; j < extMvc.View[i].NumAnchorRefsL0; j++)
8786                 writer.PutUe(extMvc.View[i].AnchorRefL0[j]);    // anchor_ref_l0[i][j]
8787             writer.PutUe(extMvc.View[i].NumAnchorRefsL1);       // num_anchor_refs_l1[i]
8788             for (mfxU32 j = 0; j < extMvc.View[i].NumAnchorRefsL1; j++)
8789                 writer.PutUe(extMvc.View[i].AnchorRefL1[j]);    // anchor_ref_l1[i][j]
8790         }
8791         for (mfxU32 i = 1; i < extMvc.NumView; i++)
8792         {
8793             writer.PutUe(extMvc.View[i].NumNonAnchorRefsL0);    // num_non_anchor_refs_l0[i]
8794             for (mfxU32 j = 0; j < extMvc.View[i].NumNonAnchorRefsL0; j++)
8795                 writer.PutUe(extMvc.View[i].NonAnchorRefL0[j]); // non_anchor_ref_l0[i][j]
8796             writer.PutUe(extMvc.View[i].NumNonAnchorRefsL1);    // num_non_anchor_refs_l1[i]
8797             for (mfxU32 j = 0; j < extMvc.View[i].NumNonAnchorRefsL1; j++)
8798                 writer.PutUe(extMvc.View[i].NonAnchorRefL1[j]); // non_anchor_ref_l1[i][j]
8799         }
8800         writer.PutUe(extMvc.NumOP - 1);                         // num_level_values_signalled_minus1
8801         for (mfxU32 i = 0; i < extMvc.NumOP; i++)
8802         {
8803             writer.PutBits(extMvc.OP[i].LevelIdc, 8);           // level_idc[i]
8804             writer.PutUe(0);                                    // num_applicable_ops_minus1[i]
8805             for (mfxU32 j = 0; j < 1; j++)
8806             {
8807                 writer.PutBits(extMvc.OP[i].TemporalId, 3);     // applicable_op_temporal_id[i][j]
8808                 writer.PutUe(extMvc.OP[i].NumTargetViews - 1);  // applicable_op_num_target_views_minus1[i][j]
8809                 for (mfxU32 k = 0; k < extMvc.OP[i].NumTargetViews; k++)
8810                     writer.PutUe(extMvc.OP[i].TargetViewId[k]); // applicable_op_target_view_id[i][j][k]
8811                 writer.PutUe(extMvc.OP[i].NumViews - 1);        // applicable_op_num_views_minus1[i][j]
8812             }
8813         }
8814     }
8815 
8816 }
8817 
WriteSpsHeader(OutputBitstream & writer,mfxExtSpsHeader const & sps)8818 mfxU32 MfxHwH264Encode::WriteSpsHeader(
8819     OutputBitstream &       writer,
8820     mfxExtSpsHeader const & sps)
8821 {
8822     mfxU32 initNumBits = writer.GetNumBits();
8823 
8824     const mfxU8 header[4] = { 0, 0, 0, 1 };
8825     writer.PutRawBytes(header, header + sizeof header / sizeof header[0]);
8826 
8827     writer.PutBit(0); // forbiddenZeroBit
8828     writer.PutBits(sps.nalRefIdc, 2);
8829     writer.PutBits(NALU_SPS, 5); // nalUnitType
8830     WriteSpsData(writer, sps);
8831     writer.PutTrailingBits();
8832 
8833     return writer.GetNumBits() - initNumBits;
8834 }
8835 
WriteSpsHeader(OutputBitstream & writer,mfxExtSpsHeader const & sps,mfxExtBuffer const & spsExt)8836 mfxU32 MfxHwH264Encode::WriteSpsHeader(
8837     OutputBitstream &        writer,
8838     mfxExtSpsHeader const &  sps,
8839     mfxExtBuffer const &     spsExt)
8840 {
8841     mfxU32 initNumBits = writer.GetNumBits();
8842 
8843     const mfxU8 header[4] = { 0, 0, 0, 1 };
8844     writer.PutRawBytes(header, header + sizeof header / sizeof header[0]);
8845 
8846     writer.PutBit(0);                   // forbidden_zero_bit
8847     writer.PutBits(sps.nalRefIdc, 2);   // nal_ref_idc
8848     writer.PutBits(sps.nalUnitType, 5); // nal_unit_type
8849 
8850     WriteSpsData(writer, sps);
8851 
8852     if (IsMvcProfile(sps.profileIdc))
8853     {
8854         assert(spsExt.BufferId == MFX_EXTBUFF_MVC_SEQ_DESC);
8855         mfxExtMVCSeqDesc const & extMvc = (mfxExtMVCSeqDesc const &)spsExt;
8856 
8857         writer.PutBit(1);               // bit_equal_to_one
8858         WriteSpsMvcExtension(writer, extMvc);
8859         writer.PutBit(0);               // mvc_vui_parameters_present_flag
8860     }
8861     writer.PutBit(0);                   // additional_extension2_flag
8862     writer.PutTrailingBits();
8863 
8864     return writer.GetNumBits() - initNumBits;
8865 }
8866 
WritePpsHeader(OutputBitstream & writer,mfxExtPpsHeader const & pps)8867 mfxU32 MfxHwH264Encode::WritePpsHeader(
8868     OutputBitstream &       writer,
8869     mfxExtPpsHeader const & pps)
8870 {
8871     mfxU32 initNumBits = writer.GetNumBits();
8872 
8873     const mfxU8 header[4] = { 0, 0, 0, 1 };
8874     writer.PutRawBytes(header, header + sizeof header / sizeof header[0]);
8875 
8876     writer.PutBit(0); // forbiddenZeroBit
8877     writer.PutBits(pps.nalRefIdc, 2);
8878     writer.PutBits(NALU_PPS, 5); // nalUnitType
8879     writer.PutUe(pps.picParameterSetId);
8880     writer.PutUe(pps.seqParameterSetId);
8881     writer.PutBit(pps.entropyCodingModeFlag);
8882     writer.PutBit(pps.bottomFieldPicOrderInframePresentFlag);
8883     writer.PutUe(pps.numSliceGroupsMinus1);
8884     if (pps.numSliceGroupsMinus1 > 0)
8885     {
8886         writer.PutUe(pps.sliceGroupMapType);
8887         if (pps.sliceGroupMapType == 0)
8888         {
8889             for (mfxU32 i = 0; i <= pps.numSliceGroupsMinus1; i++)
8890                 writer.PutUe(pps.sliceGroupInfo.t0.runLengthMinus1[i]);
8891         }
8892         else if (pps.sliceGroupMapType == 2)
8893         {
8894             for (mfxU32 i = 0; i < pps.numSliceGroupsMinus1; i++)
8895             {
8896                 writer.PutUe(pps.sliceGroupInfo.t2.topLeft[i]);
8897                 writer.PutUe(pps.sliceGroupInfo.t2.bottomRight[i]);
8898             }
8899         }
8900         else if (
8901             pps.sliceGroupMapType == 3 ||
8902             pps.sliceGroupMapType == 4 ||
8903             pps.sliceGroupMapType == 5)
8904         {
8905             writer.PutBit(pps.sliceGroupInfo.t3.sliceGroupChangeDirectionFlag);
8906             writer.PutUe(pps.sliceGroupInfo.t3.sliceGroupChangeRate);
8907         }
8908         else if (pps.sliceGroupMapType == 6)
8909         {
8910             writer.PutUe(pps.sliceGroupInfo.t6.picSizeInMapUnitsMinus1);
8911             assert("unsupprted slice_group_map_type = 6");
8912             for (mfxU32 i = 0; i <= pps.sliceGroupInfo.t6.picSizeInMapUnitsMinus1; i++)
8913                 writer.PutBits(1, CeilLog2(pps.numSliceGroupsMinus1 + 1));
8914         }
8915     }
8916     writer.PutUe(pps.numRefIdxL0DefaultActiveMinus1);
8917     writer.PutUe(pps.numRefIdxL1DefaultActiveMinus1);
8918     writer.PutBit(pps.weightedPredFlag);
8919     writer.PutBits(pps.weightedBipredIdc, 2);
8920     writer.PutSe(pps.picInitQpMinus26);
8921     writer.PutSe(pps.picInitQsMinus26);
8922     writer.PutSe(pps.chromaQpIndexOffset);
8923     writer.PutBit(pps.deblockingFilterControlPresentFlag);
8924     writer.PutBit(pps.constrainedIntraPredFlag);
8925     writer.PutBit(pps.redundantPicCntPresentFlag);
8926     if (pps.moreRbspData)
8927     {
8928         writer.PutBit(pps.transform8x8ModeFlag);
8929         writer.PutBit(pps.picScalingMatrixPresentFlag);
8930         if (pps.picScalingMatrixPresentFlag)
8931         {
8932             //for(int i=0; i < 6 + ((sps.chroma_format_idc != 3) ? 2:6)*pps.transform8x8ModeFlag; i++){
8933             for(int i=0; i < 6+2*(!!pps.transform8x8ModeFlag); i++){
8934                 //Put scaling list present flag
8935                 writer.PutBit(pps.picScalingListPresentFlag[i]);
8936                 if( pps.picScalingListPresentFlag[i] ){
8937                    if( i<6 )
8938                        WriteScalingList(writer, &pps.scalingList4x4[i][0], 16);
8939                    else
8940                        WriteScalingList(writer, &pps.scalingList8x8[i-6][0], 64);
8941                 }
8942             }
8943         }
8944         writer.PutSe(pps.secondChromaQpIndexOffset);
8945     }
8946     writer.PutTrailingBits();
8947 
8948     return writer.GetNumBits() - initNumBits;
8949 }
8950 
WriteScalingList(OutputBitstream & writer,const mfxU8 * scalingList,mfxI32 sizeOfScalingList)8951 void MfxHwH264Encode::WriteScalingList(
8952     OutputBitstream &       writer,
8953     const mfxU8* scalingList,
8954     mfxI32 sizeOfScalingList)
8955 {
8956     int16_t lastScale, nextScale;
8957     int32_t j;
8958 
8959     int16_t delta_scale;
8960     const int32_t* scan;
8961 
8962     lastScale=nextScale=8;
8963 
8964     if( sizeOfScalingList == 16 )
8965         scan = UMC_H264_ENCODER::dec_single_scan[0];
8966     else
8967         scan = UMC_H264_ENCODER::dec_single_scan_8x8[0];
8968 
8969     for( j = 0; j<sizeOfScalingList; j++ ){
8970          if( nextScale != 0 ){
8971             delta_scale = (int16_t)(scalingList[scan[j]]-lastScale);
8972             writer.PutSe(delta_scale);
8973             nextScale = scalingList[scan[j]];
8974          }
8975          lastScale = (nextScale==0) ? lastScale:nextScale;
8976     }
8977 }
8978 
WriteRefPicListModification(OutputBitstream & writer,ArrayRefListMod const & refListMod)8979 void MfxHwH264Encode::WriteRefPicListModification(
8980     OutputBitstream &       writer,
8981     ArrayRefListMod const & refListMod)
8982 {
8983     writer.PutBit(refListMod.Size() > 0);       // ref_pic_list_modification_flag_l0
8984     if (refListMod.Size() > 0)
8985     {
8986         for (mfxU32 i = 0; i < refListMod.Size(); i++)
8987         {
8988             writer.PutUe(refListMod[i].m_idc);  // modification_of_pic_nums_idc
8989             writer.PutUe(refListMod[i].m_diff); // abs_diff_pic_num_minus1 or
8990                                                 // long_term_pic_num or
8991                                                 // abs_diff_view_idx_minus1
8992         }
8993 
8994         writer.PutUe(RPLM_END);
8995     }
8996 }
8997 
WriteDecRefPicMarking(OutputBitstream & writer,DecRefPicMarkingInfo const & marking,mfxU32 idrPicFlag)8998 void MfxHwH264Encode::WriteDecRefPicMarking(
8999     OutputBitstream &            writer,
9000     DecRefPicMarkingInfo const & marking,
9001     mfxU32                       idrPicFlag)
9002 {
9003     if (idrPicFlag)
9004     {
9005         writer.PutBit(marking.no_output_of_prior_pics_flag);    // no_output_of_prior_pics_flag
9006         writer.PutBit(marking.long_term_reference_flag);        // long_term_reference_flag
9007     }
9008     else
9009     {
9010         writer.PutBit(marking.mmco.Size() > 0);                 // adaptive_ref_pic_marking_mode_flag
9011         if (marking.mmco.Size())
9012         {
9013             for (mfxU32 i = 0; i < marking.mmco.Size(); i++)
9014             {
9015                 writer.PutUe(marking.mmco[i]);                  // memory_management_control_operation
9016                 writer.PutUe(marking.value[2 * i]);             // difference_of_pic_nums_minus1 or
9017                                                                 // long_term_pic_num or
9018                                                                 // long_term_frame_idx or
9019                                                                 // max_long_term_frame_idx_plus1
9020                 if (marking.mmco[i] == MMCO_ST_TO_LT)
9021                     writer.PutUe(marking.value[2 * i + 1]);     // long_term_frame_idx
9022             }
9023 
9024             writer.PutUe(MMCO_END);
9025         }
9026     }
9027 }
9028 
WriteAud(OutputBitstream & writer,mfxU32 frameType)9029 mfxU32 MfxHwH264Encode::WriteAud(
9030     OutputBitstream & writer,
9031     mfxU32            frameType)
9032 {
9033     mfxU32 initNumBits = writer.GetNumBits();
9034 
9035     mfxU8 const header[4] = { 0, 0, 0, 1 };
9036     writer.PutRawBytes(header, header + sizeof header / sizeof header[0]);
9037     writer.PutBit(0);
9038     writer.PutBits(0, 2);
9039     writer.PutBits(NALU_AUD, 5);
9040     writer.PutBits(ConvertFrameTypeMfx2Ddi(frameType) - 1, 3);
9041     writer.PutTrailingBits();
9042 
9043     return writer.GetNumBits() - initNumBits;
9044 }
9045 
IsAvcProfile(mfxU32 profile)9046 bool MfxHwH264Encode::IsAvcProfile(mfxU32 profile)
9047 {
9048     return
9049         IsAvcBaseProfile(profile)           ||
9050         profile == MFX_PROFILE_AVC_MAIN     ||
9051         profile == MFX_PROFILE_AVC_EXTENDED ||
9052         IsAvcHighProfile(profile);
9053 }
9054 
IsAvcBaseProfile(mfxU32 profile)9055 bool MfxHwH264Encode::IsAvcBaseProfile(mfxU32 profile)
9056 {
9057     return
9058         profile == MFX_PROFILE_AVC_BASELINE ||
9059         profile == MFX_PROFILE_AVC_CONSTRAINED_BASELINE;
9060 }
9061 
IsAvcHighProfile(mfxU32 profile)9062 bool MfxHwH264Encode::IsAvcHighProfile(mfxU32 profile)
9063 {
9064     return
9065         profile == MFX_PROFILE_AVC_HIGH ||
9066         profile == MFX_PROFILE_AVC_CONSTRAINED_HIGH ||
9067         profile == MFX_PROFILE_AVC_PROGRESSIVE_HIGH;
9068 }
9069 
IsMvcProfile(mfxU32 profile)9070 bool MfxHwH264Encode::IsMvcProfile(mfxU32 profile)
9071 {
9072     return
9073         profile == MFX_PROFILE_AVC_STEREO_HIGH ||
9074         profile == MFX_PROFILE_AVC_MULTIVIEW_HIGH;
9075 }
9076 
9077 
operator ==(mfxExtSpsHeader const & lhs,mfxExtSpsHeader const & rhs)9078 bool MfxHwH264Encode::operator ==(
9079     mfxExtSpsHeader const & lhs,
9080     mfxExtSpsHeader const & rhs)
9081 {
9082     // part from the beginning of sps to nalHrdParameters
9083     mfxU8 const * lhsBegin1 = (mfxU8 const *)&lhs;
9084     mfxU8 const * rhsBegin1 = (mfxU8 const *)&rhs;
9085     mfxU8 const * lhsEnd1   = (mfxU8 const *)&lhs.vui.nalHrdParameters;
9086 
9087     // part from the end of vclHrdParameters to the end of sps
9088     mfxU8 const * lhsBegin2 = (mfxU8 const *)&lhs.vui.maxBytesPerPicDenom;
9089     mfxU8 const * rhsBegin2 = (mfxU8 const *)&rhs.vui.maxBytesPerPicDenom;
9090     mfxU8 const * lhsEnd2   = (mfxU8 const *)&lhs + sizeof(lhs);
9091 
9092     if (memcmp(lhsBegin1, rhsBegin1, lhsEnd1 - lhsBegin1) != 0 ||
9093         memcmp(lhsBegin2, rhsBegin2, lhsEnd2 - lhsBegin2) != 0)
9094         return false;
9095 
9096     if (lhs.vui.flags.nalHrdParametersPresent)
9097         if (!Equal(lhs.vui.nalHrdParameters, rhs.vui.nalHrdParameters))
9098             return false;
9099 
9100     if (lhs.vui.flags.vclHrdParametersPresent)
9101         if (!Equal(lhs.vui.vclHrdParameters, rhs.vui.vclHrdParameters))
9102             return false;
9103 
9104     return true;
9105 }
9106 
PackPrefixNalUnitSvc(mfxU8 * begin,mfxU8 * end,bool emulationControl,DdiTask const & task,mfxU32 fieldId,mfxU32 nalUnitType)9107 mfxU8 * MfxHwH264Encode::PackPrefixNalUnitSvc(
9108     mfxU8 *         begin,
9109     mfxU8 *         end,
9110     bool            emulationControl,
9111     DdiTask const & task,
9112     mfxU32          fieldId,
9113     mfxU32          nalUnitType)
9114 {
9115     OutputBitstream obs(begin, end, false);
9116 
9117     mfxU32 idrFlag   = (task.m_type[fieldId] & MFX_FRAMETYPE_IDR) ? 1 : 0;
9118     mfxU32 nalRefIdc = task.m_nalRefIdc[fieldId];
9119 
9120     mfxU32 useRefBasePicFlag = (task.m_type[fieldId] & MFX_FRAMETYPE_KEYPIC) ? 1 : 0;
9121 
9122     obs.PutBits(1, 24);                     // 001
9123     obs.PutBits(0, 1);                      // forbidden_zero_flag
9124     obs.PutBits(nalRefIdc, 2);              // nal_ref_idc
9125     obs.PutBits(nalUnitType, 5);            // nal_unit_type
9126     obs.PutBits(1, 1);                      // svc_extension_flag
9127     obs.PutBits(idrFlag, 1);                // idr_flag
9128     obs.PutBits(task.m_pid, 6);             // priority_id
9129     obs.PutBits(1, 1);                      // no_inter_layer_pred_flag
9130     obs.PutBits(task.m_did, 3);             // dependency_id
9131     obs.PutBits(task.m_qid, 4);             // quality_id
9132     obs.PutBits(task.m_tid, 3);             // temporal_id
9133     obs.PutBits(useRefBasePicFlag, 1);      // use_ref_base_pic_flag
9134     obs.PutBits(1, 1);                      // discardable_flag
9135     obs.PutBits(1, 1);                      // output_flag
9136     obs.PutBits(0x3, 2);                    // reserved_three_2bits
9137 
9138     OutputBitstream obs1(begin + obs.GetNumBits() / 8, end, emulationControl);
9139     if (nalRefIdc && nalUnitType == 14)
9140     {
9141         mfxU32 additional_prefix_nal_unit_extension_flag = 0;
9142 
9143         obs1.PutBit(task.m_storeRefBasePicFlag);
9144         if ((useRefBasePicFlag || task.m_storeRefBasePicFlag) && !idrFlag)
9145             WriteDecRefPicMarking(obs1, task.m_decRefPicMrk[fieldId], idrFlag);
9146 
9147         obs1.PutBit(additional_prefix_nal_unit_extension_flag);
9148         assert(additional_prefix_nal_unit_extension_flag == 0);
9149         obs1.PutTrailingBits();
9150     }
9151 
9152     return begin + obs.GetNumBits() / 8 + obs1.GetNumBits() / 8;
9153 }
9154 
9155 namespace
9156 {
MakePackedByteBuffer(mfxU8 * data,mfxU32 size,mfxU32 skipEmulCount)9157     ENCODE_PACKEDHEADER_DATA MakePackedByteBuffer(mfxU8 * data, mfxU32 size, mfxU32 skipEmulCount)
9158     {
9159         ENCODE_PACKEDHEADER_DATA desc = {};
9160         desc.pData                  = data;
9161         desc.BufferSize             = size;
9162         desc.DataLength             = size;
9163         desc.SkipEmulationByteCount = skipEmulCount;
9164         return desc;
9165     }
9166 
PrepareSpsPpsHeaders(MfxVideoParam const & par,std::vector<mfxExtSpsHeader> & sps,std::vector<mfxExtPpsHeader> & pps)9167     void PrepareSpsPpsHeaders(
9168         MfxVideoParam const &               par,
9169         std::vector<mfxExtSpsHeader> &      sps,
9170         std::vector<mfxExtPpsHeader> &      pps)
9171     {
9172         mfxExtSpsHeader const & extSps = GetExtBufferRef(par);
9173         mfxExtPpsHeader const & extPps = GetExtBufferRef(par);
9174 
9175         mfxU16 numViews  = extSps.profileIdc == MFX_PROFILE_AVC_STEREO_HIGH ? 2 : 1;
9176         mfxU16 heightMul = 2 - extSps.frameMbsOnlyFlag;
9177 
9178         // prepare sps for base layer
9179         sps[0] = extSps;
9180         sps[0].picWidthInMbsMinus1       = par.mfx.FrameInfo.Width / 16 - 1;
9181         sps[0].picHeightInMapUnitsMinus1 = par.mfx.FrameInfo.Height / 16 / heightMul - 1;
9182 
9183         if (numViews > 1)
9184         {
9185             // MVC requires SPS and number of Subset SPS.
9186             // HeaderPacker prepares 2 SPS NAL units:
9187             // one for base view (sps_id = 0, profile_idc = 100)
9188             // and another for all other views (sps_id = 1, profile_idc = 128).
9189             // Second SPS will be re-packed to SubsetSPS after return from driver.
9190             for (mfxU16 view = 0; view < numViews; view++)
9191             {
9192                 sps[view] = extSps;
9193                 pps[view] = extPps;
9194 
9195                 if (numViews > 1 && view == 0) // MVC base view
9196                     sps[view].profileIdc = MFX_PROFILE_AVC_HIGH;
9197 
9198                 sps[view].seqParameterSetId = mfxU8(!!view) & 0x1f;
9199                 pps[view].picParameterSetId = mfxU8(!!view);
9200                 pps[view].seqParameterSetId = sps[view].seqParameterSetId;
9201             }
9202             return;
9203         }
9204 
9205 
9206         pps[0] = extPps;
9207 
9208     }
9209 };
9210 
Init(MfxVideoParam const & par,MFX_ENCODE_CAPS const & hwCaps,bool emulPrev)9211 void HeaderPacker::Init(
9212     MfxVideoParam const &     par,
9213     MFX_ENCODE_CAPS const &   hwCaps,
9214     bool                      emulPrev)
9215 {
9216     mfxExtCodingOptionDDI const & extDdi  = GetExtBufferRef(par);
9217     mfxExtSpsHeader const       & extSps  = GetExtBufferRef(par);
9218     mfxExtCodingOption2 const   & extOpt2 = GetExtBufferRef(par);
9219 
9220     mfxU16 numViews = extSps.profileIdc == MFX_PROFILE_AVC_STEREO_HIGH ? 2 : 1;
9221 
9222     mfxU32 numSpsHeaders = numViews;
9223     mfxU32 numPpsHeaders = numViews;
9224 
9225 
9226     mfxU32 maxNumSlices = GetMaxNumSlices(par);
9227 
9228     m_sps.resize(numSpsHeaders);
9229     m_pps.resize(numPpsHeaders);
9230     m_packedSps.resize(numSpsHeaders);
9231     m_packedPps.resize(numPpsHeaders);
9232     m_packedSlices.resize(maxNumSlices);
9233     m_headerBuffer.resize(SPSPPS_BUFFER_SIZE);
9234     m_sliceBuffer.resize(SLICE_BUFFER_SIZE);
9235 
9236     Zero(m_sps);
9237     Zero(m_pps);
9238 
9239     Zero(m_packedAud);
9240     Zero(m_packedSps);
9241     Zero(m_packedPps);
9242     Zero(m_packedSlices);
9243     Zero(m_spsIdx);
9244     Zero(m_ppsIdx);
9245     Zero(m_refDqId);
9246     Zero(m_simulcast);
9247 
9248     m_emulPrev = emulPrev;
9249     m_isMVC = numViews > 1;
9250 
9251     m_numMbPerSlice = extOpt2.NumMbPerSlice;
9252 
9253     PrepareSpsPpsHeaders(par, m_sps, m_pps);
9254 
9255     // prepare data for slice level
9256     m_needPrefixNalUnit       = (par.calcParam.numTemporalLayer > 0) && (par.mfx.LowPower != MFX_CODINGOPTION_ON);//LowPower limitation for temporal scalability we need to patch bitstream with SVC NAL after encoding
9257 
9258     m_cabacInitIdc            = extDdi.CabacInitIdcPlus1 - 1;
9259     m_directSpatialMvPredFlag = extDdi.DirectSpatialMvPredFlag;
9260 
9261     // pack headers
9262     OutputBitstream obs(Begin(m_headerBuffer), End(m_headerBuffer), m_emulPrev);
9263 
9264     ENCODE_PACKEDHEADER_DATA * bufDesc  = Begin(m_packedSps);
9265     mfxU8 *                    bufBegin = Begin(m_headerBuffer);
9266     mfxU32                     numBits  = 0;
9267 
9268 
9269     // pack sps for base and enhanced spatial layers with did > 0
9270     for (size_t i = 0; i < m_sps.size(); i++)
9271     {
9272         numBits = WriteSpsHeader(obs, m_sps[i]);
9273         *bufDesc++ = MakePackedByteBuffer(bufBegin, numBits / 8, m_emulPrev ? 0 : 4);
9274         bufBegin += numBits / 8;
9275     }
9276 
9277     // pack pps for base and enhanced spatial layers
9278     bufDesc = Begin(m_packedPps);
9279     for (size_t i = 0; i < m_pps.size(); i++)
9280     {
9281         numBits = WritePpsHeader(obs, m_pps[i]);
9282         *bufDesc++ = MakePackedByteBuffer(bufBegin, numBits / 8, m_emulPrev ? 0 : 4);
9283         bufBegin += numBits / 8;
9284     }
9285 
9286     m_hwCaps = hwCaps;
9287 
9288     m_longStartCodes = IsOn(extDdi.LongStartCodes) && !IsOn(par.mfx.LowPower);
9289 
9290     m_isLowPower = IsOn(par.mfx.LowPower);
9291 }
9292 
ResizeSlices(mfxU32 num)9293 void HeaderPacker::ResizeSlices(mfxU32 num)
9294 {
9295     m_packedSlices.resize(num);
9296     Zero(m_packedSlices);
9297 }
9298 
9299 #ifndef MFX_AVC_ENCODING_UNIT_DISABLE
9300 /*
9301     Filling information about headers in HeadersInfo.
9302 */
GetHeadersInfo(std::vector<mfxEncodedUnitInfo> & HeadersInfo,DdiTask const & task,mfxU32 fid)9303 void HeaderPacker::GetHeadersInfo(std::vector<mfxEncodedUnitInfo> &HeadersInfo, DdiTask const& task, mfxU32 fid)
9304 {
9305     std::vector<ENCODE_PACKEDHEADER_DATA>::iterator it;
9306     mfxU32 offset = 0;
9307     if (task.m_insertAud[fid])
9308     {
9309         HeadersInfo.emplace_back();
9310         HeadersInfo.back().Type = NALU_AUD;
9311         HeadersInfo.back().Size = m_packedAud.DataLength;
9312         HeadersInfo.back().Offset = offset;
9313         offset += HeadersInfo.back().Size;
9314     }
9315     if (task.m_insertSps[fid])
9316     {
9317         for (it = m_packedSps.begin(); it < m_packedSps.end(); ++it)
9318         {
9319             HeadersInfo.emplace_back();
9320             HeadersInfo.back().Type = NALU_SPS;
9321             HeadersInfo.back().Size = it->DataLength;
9322             HeadersInfo.back().Offset = offset;
9323             offset += HeadersInfo.back().Size;
9324         }
9325     }
9326     if (task.m_insertPps[fid])
9327     {
9328         for (it = m_packedPps.begin(); it < m_packedPps.end(); ++it)
9329         {
9330             HeadersInfo.emplace_back();
9331             HeadersInfo.back().Type = NALU_PPS;
9332             HeadersInfo.back().Size = it->DataLength;
9333             HeadersInfo.back().Offset = offset;
9334             offset += HeadersInfo.back().Size;
9335         }
9336     }
9337 }
9338 #endif
9339 
PackAud(DdiTask const & task,mfxU32 fieldId)9340 ENCODE_PACKEDHEADER_DATA const & HeaderPacker::PackAud(
9341     DdiTask const & task,
9342     mfxU32          fieldId)
9343 {
9344     mfxU8 * audBegin = m_packedPps.back().pData + m_packedPps.back().DataLength;
9345 
9346     OutputBitstream obs(audBegin, End(m_headerBuffer), m_emulPrev);
9347     mfxU32 numBits = WriteAud(obs, task.m_type[fieldId]);
9348     m_packedAud = MakePackedByteBuffer(audBegin, numBits / 8, m_emulPrev ? 0 : 4);
9349 
9350     return m_packedAud;
9351 }
9352 
PackSlices(DdiTask const & task,mfxU32 fieldId)9353 std::vector<ENCODE_PACKEDHEADER_DATA> const & HeaderPacker::PackSlices(
9354     DdiTask const & task,
9355     mfxU32          fieldId)
9356 {
9357     const mfxU32 maxSliceHeaderSize = 50;  //maximum coded slice header size in bytes
9358     size_t numSlices = task.m_SliceInfo.size() ?
9359         task.m_SliceInfo.size() :
9360         task.m_numSlice[fieldId];
9361 
9362     if (task.m_SliceInfo.size())
9363     {
9364         m_numMbPerSlice = 0;
9365     }
9366 
9367     if (numSlices)
9368     {
9369         m_packedSlices.resize(numSlices);
9370         if (m_sliceBuffer.size() < (numSlices * maxSliceHeaderSize))
9371         {
9372             m_sliceBuffer.resize(numSlices * maxSliceHeaderSize);
9373         }
9374     }
9375     Zero(m_sliceBuffer);
9376     Zero(m_packedSlices);
9377 
9378     mfxU8 * sliceBufferBegin = Begin(m_sliceBuffer);
9379     mfxU8 * sliceBufferEnd   = End(m_sliceBuffer);
9380 
9381     for (mfxU32 i = 0; i < m_packedSlices.size(); i++)
9382     {
9383         mfxU8 * endOfPrefix = m_needPrefixNalUnit && task.m_did == 0 && task.m_qid == 0
9384             ? PackPrefixNalUnitSvc(sliceBufferBegin, sliceBufferEnd, true, task, fieldId)
9385             : sliceBufferBegin;
9386 
9387         OutputBitstream obs(endOfPrefix, sliceBufferEnd, false); // pack without emulation control
9388 
9389         if (task.m_SliceInfo.size())
9390             WriteSlice(obs, task, fieldId, task.m_SliceInfo[i].startMB, task.m_SliceInfo[i].numMB);
9391         else
9392             WriteSlice(obs, task, fieldId, i);
9393 
9394 
9395         m_packedSlices[i].pData                  = sliceBufferBegin;
9396         m_packedSlices[i].DataLength             = mfxU32((endOfPrefix - sliceBufferBegin) * 8 + obs.GetNumBits()); // for slices length is in bits
9397         m_packedSlices[i].BufferSize             = (m_packedSlices[i].DataLength + 7) / 8;
9398         m_packedSlices[i].SkipEmulationByteCount = mfxU32(endOfPrefix - sliceBufferBegin + 3);
9399 
9400         sliceBufferBegin += m_packedSlices[i].BufferSize;
9401     }
9402 
9403     if (task.m_AUStartsFromSlice[fieldId])
9404         m_packedSlices[0].SkipEmulationByteCount = 4;
9405 
9406     return m_packedSlices;
9407 }
9408 
WritePredWeightTable(OutputBitstream & obs,MFX_ENCODE_CAPS const & hwCaps,DdiTask const & task,mfxU32 fieldId,mfxU32 chromaArrayType)9409 void WritePredWeightTable(
9410     OutputBitstream &       obs,
9411     MFX_ENCODE_CAPS const & hwCaps,
9412     DdiTask const &         task,
9413     mfxU32                  fieldId,
9414     mfxU32                  chromaArrayType)
9415 {
9416     // Transform field parity to field number before buffer request (PWT attached according to field order, not parity)
9417     // However in case of FEI single field mode, only one buffer is attached.
9418     mfxU32 fieldNum = task.m_singleFieldMode ? 0 : task.m_fid[fieldId];
9419     const mfxExtPredWeightTable* pPWT = GetExtBuffer(task.m_ctrl, fieldNum);
9420 
9421     if (!pPWT)
9422         pPWT = &task.m_pwt[fieldId];
9423     else if ((task.m_hwType >= MFX_HW_KBL) &&
9424         ((pPWT->LumaLog2WeightDenom && pPWT->LumaLog2WeightDenom != 6) ||
9425         (pPWT->ChromaLog2WeightDenom && pPWT->ChromaLog2WeightDenom != 6)))
9426         pPWT = &task.m_pwt[fieldId];
9427 
9428     mfxU32 nRef[2] = {
9429         std::max(1u, task.m_list0[fieldId].Size()),
9430         std::max(1u, task.m_list1[fieldId].Size())
9431     };
9432     mfxU32 maxWeights[2] = { hwCaps.ddi_caps.MaxNum_WeightedPredL0, hwCaps.ddi_caps.MaxNum_WeightedPredL1 };
9433     bool present;
9434 
9435     obs.PutUe(pPWT->LumaLog2WeightDenom);
9436 
9437     if (chromaArrayType != 0)
9438         obs.PutUe(pPWT->ChromaLog2WeightDenom);
9439 
9440     for (mfxU32 lx = 0; lx <= (mfxU32)!!(task.m_type[fieldId] & MFX_FRAMETYPE_B); lx++)
9441     {
9442         for (mfxU32 i = 0; i < nRef[lx]; i++)
9443         {
9444             present = !!pPWT->LumaWeightFlag[lx][i] && hwCaps.ddi_caps.LumaWeightedPred;
9445 
9446             if (i < maxWeights[lx])
9447             {
9448                 obs.PutBit(present);
9449 
9450                 if (present)
9451                 {
9452                     obs.PutSe(pPWT->Weights[lx][i][0][0]);
9453                     obs.PutSe(pPWT->Weights[lx][i][0][1]);
9454                 }
9455             }
9456             else
9457             {
9458                 obs.PutBit(0);
9459             }
9460 
9461             if (chromaArrayType != 0)
9462             {
9463                 present = !!pPWT->ChromaWeightFlag[lx][i] && hwCaps.ddi_caps.ChromaWeightedPred;
9464 
9465                 if (i < maxWeights[lx])
9466                 {
9467                     obs.PutBit(present);
9468 
9469                     if (present)
9470                     {
9471                         for (mfxU32 j = 1; j < 3; j++)
9472                         {
9473                             obs.PutSe(pPWT->Weights[lx][i][j][0]);
9474                             obs.PutSe(pPWT->Weights[lx][i][j][1]);
9475                         }
9476                     }
9477                 }
9478                 else
9479                 {
9480                     obs.PutBit(0);
9481                 }
9482             }
9483         }
9484     }
9485 }
9486 
WriteSlice(OutputBitstream & obs,DdiTask const & task,mfxU32 fieldId,mfxU32 sliceId)9487 mfxU32 HeaderPacker::WriteSlice(
9488     OutputBitstream & obs,
9489     DdiTask const &   task,
9490     mfxU32            fieldId,
9491     mfxU32            sliceId)
9492 {
9493     mfxU32 sliceType    = ConvertMfxFrameType2SliceType(task.m_type[fieldId]) % 5;
9494     mfxU32 refPicFlag   = !!(task.m_type[fieldId] & MFX_FRAMETYPE_REF);
9495     mfxU32 idrPicFlag   = !!(task.m_type[fieldId] & MFX_FRAMETYPE_IDR);
9496     mfxU32 nalRefIdc    = task.m_nalRefIdc[fieldId];
9497     mfxU32 nalUnitType  = (task.m_did == 0 && task.m_qid == 0) ? (idrPicFlag ? NALU_IDR : NALU_NON_IDR) : NALU_CODED_SLICE_EXT;
9498     mfxU32 fieldPicFlag = task.GetPicStructForEncode() != MFX_PICSTRUCT_PROGRESSIVE;
9499 
9500     mfxExtSpsHeader const & sps = task.m_viewIdx ? m_sps[task.m_viewIdx] : m_sps[m_spsIdx[task.m_did][task.m_qid]];
9501     mfxExtPpsHeader const & pps =
9502         task.m_viewIdx ? m_pps[task.m_viewIdx] : m_pps[m_ppsIdx[task.m_did][task.m_qid]];
9503 
9504     // if frame_mbs_only_flag = 0 and current task implies encoding of progressive frame
9505     // then picture height in MBs isn't equal to PicHeightInMapUnits. Multiplier required
9506     mfxU32 picHeightMultiplier = (sps.frameMbsOnlyFlag == 0) && (fieldPicFlag == 0) ? 2 : 1;
9507     mfxU32 picHeightInMBs      = (sps.picHeightInMapUnitsMinus1 + 1) * picHeightMultiplier;
9508 
9509     SliceDivider divider = MakeSliceDivider(
9510         SliceDividerType(m_hwCaps.ddi_caps.SliceStructure),
9511         m_numMbPerSlice,
9512         (mfxU32)m_packedSlices.size(),
9513         sps.picWidthInMbsMinus1 + 1,
9514         picHeightInMBs,
9515         m_isLowPower);
9516 
9517     mfxU32 firstMbInSlice = 0;
9518     for (mfxU32 i = 0; i <= sliceId; i++, divider.Next())
9519         firstMbInSlice = divider.GetFirstMbInSlice();
9520 
9521     mfxU32 sliceHeaderRestrictionFlag = 0;
9522 
9523     mfxU8 startcode[4] = { 0, 0, 0, 1};
9524     mfxU8 * pStartCode = startcode;
9525 #if !defined(ANDROID)
9526     if (!m_longStartCodes)
9527     {
9528         if (task.m_AUStartsFromSlice[fieldId] == false || sliceId > 0)
9529             pStartCode++;
9530     }
9531 #endif
9532     obs.PutRawBytes(pStartCode, startcode + sizeof startcode);
9533     obs.PutBit(0);
9534     obs.PutBits(nalRefIdc, 2);
9535     obs.PutBits(nalUnitType, 5);
9536 
9537     mfxU32 noInterLayerPredFlag = (task.m_qid == 0) ? m_simulcast[task.m_did] : 0;
9538     if (nalUnitType == 20)
9539     {
9540         mfxU32 useRefBasePicFlag = (task.m_type[fieldId] & MFX_FRAMETYPE_KEYPIC) ? 1 : 0;
9541         obs.PutBits(1, 1);          // svc_extension_flag
9542         obs.PutBits(idrPicFlag, 1);
9543         obs.PutBits(task.m_pid, 6);
9544         obs.PutBits(noInterLayerPredFlag, 1);
9545         obs.PutBits(task.m_did, 3);
9546         obs.PutBits(task.m_qid, 4);
9547         obs.PutBits(task.m_tid, 3);
9548         obs.PutBits(useRefBasePicFlag, 1);      // use_ref_base_pic_flag
9549         obs.PutBits(1, 1);          // discardable_flag
9550         obs.PutBits(1, 1);          // output_flag
9551         obs.PutBits(0x3, 2);        // reserved_three_2bits
9552     }
9553 
9554     obs.PutUe(firstMbInSlice);
9555     obs.PutUe(sliceType + 5);
9556     obs.PutUe(pps.picParameterSetId);
9557     obs.PutBits(task.m_frameNum, sps.log2MaxFrameNumMinus4 + 4);
9558     if (!sps.frameMbsOnlyFlag)
9559     {
9560         obs.PutBit(fieldPicFlag);
9561         if (fieldPicFlag)
9562             obs.PutBit(fieldId);
9563     }
9564     if (idrPicFlag)
9565         obs.PutUe(task.m_idrPicId);
9566     if (sps.picOrderCntType == 0)
9567     {
9568         obs.PutBits(task.GetPoc(fieldId), sps.log2MaxPicOrderCntLsbMinus4 + 4);
9569         if (pps.bottomFieldPicOrderInframePresentFlag && !fieldPicFlag)
9570             obs.PutSe(0); // delta_pic_order_cnt_bottom
9571     }
9572     if (sps.picOrderCntType == 1 && !sps.deltaPicOrderAlwaysZeroFlag)
9573     {
9574         obs.PutSe(0); // delta_pic_order_cnt[0]
9575         if (pps.bottomFieldPicOrderInframePresentFlag && !fieldPicFlag)
9576             obs.PutSe(0); // delta_pic_order_cnt[1]
9577     }
9578     if (task.m_qid == 0)
9579     {
9580         if (sliceType == SLICE_TYPE_B)
9581             obs.PutBit(IsOn(m_directSpatialMvPredFlag));
9582         if (sliceType != SLICE_TYPE_I)
9583         {
9584             mfxU32 numRefIdxL0ActiveMinus1 = std::max(1u, task.m_list0[fieldId].Size()) - 1;
9585             mfxU32 numRefIdxL1ActiveMinus1 = std::max(1u, task.m_list1[fieldId].Size()) - 1;
9586             mfxU32 numRefIdxActiveOverrideFlag =
9587                 (numRefIdxL0ActiveMinus1 != pps.numRefIdxL0DefaultActiveMinus1) ||
9588                 (numRefIdxL1ActiveMinus1 != pps.numRefIdxL1DefaultActiveMinus1 && sliceType == SLICE_TYPE_B);
9589 
9590             obs.PutBit(numRefIdxActiveOverrideFlag);
9591             if (numRefIdxActiveOverrideFlag)
9592             {
9593                 obs.PutUe(numRefIdxL0ActiveMinus1);
9594                 if (sliceType == SLICE_TYPE_B)
9595                     obs.PutUe(numRefIdxL1ActiveMinus1);
9596             }
9597         }
9598         if (sliceType != SLICE_TYPE_I)
9599             WriteRefPicListModification(obs, task.m_refPicList0Mod[fieldId]);
9600         if (sliceType == SLICE_TYPE_B)
9601             WriteRefPicListModification(obs, task.m_refPicList1Mod[fieldId]);
9602         if ((pps.weightedPredFlag  == 1 && sliceType == SLICE_TYPE_P) ||
9603             (pps.weightedBipredIdc == 1 && sliceType == SLICE_TYPE_B))
9604         {
9605             mfxU32 chromaArrayType = sps.separateColourPlaneFlag ? 0 : sps.chromaFormatIdc;
9606             WritePredWeightTable(obs, m_hwCaps, task, fieldId, chromaArrayType);
9607         }
9608         if (refPicFlag || task.m_nalRefIdc[fieldId])
9609         {
9610             WriteDecRefPicMarking(obs, task.m_decRefPicMrk[fieldId], idrPicFlag);
9611             mfxU32 storeRefBasePicFlag = 0;
9612             if (nalUnitType == 20 && !sliceHeaderRestrictionFlag)
9613                 obs.PutBit(storeRefBasePicFlag);
9614         }
9615     }
9616     if (pps.entropyCodingModeFlag && sliceType != SLICE_TYPE_I)
9617         obs.PutUe(m_cabacInitIdc);
9618     obs.PutSe(task.m_cqpValue[fieldId] - (pps.picInitQpMinus26 + 26));
9619     if (pps.deblockingFilterControlPresentFlag)
9620     {
9621         mfxU32 disableDeblockingFilterIdc = task.m_disableDeblockingIdc[fieldId][sliceId];
9622         mfxI32 sliceAlphaC0OffsetDiv2     = task.m_sliceAlphaC0OffsetDiv2[fieldId][sliceId];
9623         mfxI32 sliceBetaOffsetDiv2        = task.m_sliceBetaOffsetDiv2[fieldId][sliceId];
9624 
9625         obs.PutUe(disableDeblockingFilterIdc);
9626         if (disableDeblockingFilterIdc != 1)
9627         {
9628             obs.PutSe(sliceAlphaC0OffsetDiv2);
9629             obs.PutSe(sliceBetaOffsetDiv2);
9630         }
9631     }
9632 
9633     return obs.GetNumBits();
9634 }
9635 
WriteSlice(OutputBitstream & obs,DdiTask const & task,mfxU32 fieldId,mfxU32 firstMbInSlice,mfxU32)9636 mfxU32 HeaderPacker::WriteSlice(
9637     OutputBitstream & obs,
9638     DdiTask const &   task,
9639     mfxU32            fieldId,
9640     mfxU32            firstMbInSlice,
9641     mfxU32            /* numMbInSlice */)
9642 {
9643     mfxU32 sliceType    = ConvertMfxFrameType2SliceType(task.m_type[fieldId]) % 5;
9644     mfxU32 refPicFlag   = !!(task.m_type[fieldId] & MFX_FRAMETYPE_REF);
9645     mfxU32 idrPicFlag   = !!(task.m_type[fieldId] & MFX_FRAMETYPE_IDR);
9646     mfxU32 nalRefIdc    = task.m_nalRefIdc[fieldId];
9647     mfxU32 nalUnitType  = (task.m_did == 0 && task.m_qid == 0) ? (idrPicFlag ? 5 : 1) : 20;
9648     mfxU32 fieldPicFlag = task.GetPicStructForEncode() != MFX_PICSTRUCT_PROGRESSIVE;
9649 
9650     mfxExtSpsHeader const & sps = task.m_viewIdx ? m_sps[task.m_viewIdx] : m_sps[m_spsIdx[task.m_did][task.m_qid]];
9651     mfxExtPpsHeader const & pps =
9652         task.m_viewIdx ? m_pps[task.m_viewIdx] : m_pps[m_ppsIdx[task.m_did][task.m_qid]];
9653 
9654     // if frame_mbs_only_flag = 0 and current task implies encoding of progressive frame
9655     // then picture height in MBs isn't equal to PicHeightInMapUnits. Multiplier required
9656     //mfxU32 picHeightMultiplier = (sps.frameMbsOnlyFlag == 0) && (fieldPicFlag == 0) ? 2 : 1;
9657     //mfxU32 picHeightInMBs      = (sps.picHeightInMapUnitsMinus1 + 1) * picHeightMultiplier;
9658 
9659     mfxU32 sliceHeaderRestrictionFlag = 0;
9660 #if defined(ANDROID)
9661     mfxU8 startcode[4] = { 0, 0, 0, 1 };
9662 #else
9663     mfxU8 startcode[3] = { 0, 0, 1 };
9664 
9665     if (m_longStartCodes)
9666         obs.PutFillerBytes(0x00, 1);
9667 #endif
9668     obs.PutRawBytes(startcode, startcode + sizeof startcode);
9669     obs.PutBit(0);
9670     obs.PutBits(nalRefIdc, 2);
9671     obs.PutBits(nalUnitType, 5);
9672 
9673     mfxU32 noInterLayerPredFlag = (task.m_qid == 0) ? m_simulcast[task.m_did] : 0;
9674     if (nalUnitType == 20)
9675     {
9676         mfxU32 useRefBasePicFlag = (task.m_type[fieldId] & MFX_FRAMETYPE_KEYPIC) ? 1 : 0;
9677         obs.PutBits(1, 1);          // svc_extension_flag
9678         obs.PutBits(idrPicFlag, 1);
9679         obs.PutBits(task.m_pid, 6);
9680         obs.PutBits(noInterLayerPredFlag, 1);
9681         obs.PutBits(task.m_did, 3);
9682         obs.PutBits(task.m_qid, 4);
9683         obs.PutBits(task.m_tid, 3);
9684         obs.PutBits(useRefBasePicFlag, 1);      // use_ref_base_pic_flag
9685         obs.PutBits(1, 1);          // discardable_flag
9686         obs.PutBits(1, 1);          // output_flag
9687         obs.PutBits(0x3, 2);        // reserved_three_2bits
9688     }
9689 
9690     obs.PutUe(firstMbInSlice);
9691     obs.PutUe(sliceType + 5);
9692     obs.PutUe(pps.picParameterSetId);
9693     obs.PutBits(task.m_frameNum, sps.log2MaxFrameNumMinus4 + 4);
9694     if (!sps.frameMbsOnlyFlag)
9695     {
9696         obs.PutBit(fieldPicFlag);
9697         if (fieldPicFlag)
9698             obs.PutBit(fieldId);
9699     }
9700     if (idrPicFlag)
9701         obs.PutUe(task.m_idrPicId);
9702     if (sps.picOrderCntType == 0)
9703     {
9704         obs.PutBits(task.GetPoc(fieldId), sps.log2MaxPicOrderCntLsbMinus4 + 4);
9705         if (pps.bottomFieldPicOrderInframePresentFlag && !fieldPicFlag)
9706             obs.PutSe(0); // delta_pic_order_cnt_bottom
9707     }
9708     if (sps.picOrderCntType == 1 && !sps.deltaPicOrderAlwaysZeroFlag)
9709     {
9710         obs.PutSe(0); // delta_pic_order_cnt[0]
9711         if (pps.bottomFieldPicOrderInframePresentFlag && !fieldPicFlag)
9712             obs.PutSe(0); // delta_pic_order_cnt[1]
9713     }
9714     if (task.m_qid == 0)
9715     {
9716         if (sliceType == SLICE_TYPE_B)
9717             obs.PutBit(IsOn(m_directSpatialMvPredFlag));
9718         if (sliceType != SLICE_TYPE_I)
9719         {
9720             mfxU32 numRefIdxL0ActiveMinus1 = std::max(1u, task.m_list0[fieldId].Size()) - 1;
9721             mfxU32 numRefIdxL1ActiveMinus1 = std::max(1u, task.m_list1[fieldId].Size()) - 1;
9722             mfxU32 numRefIdxActiveOverrideFlag =
9723                 (numRefIdxL0ActiveMinus1 != pps.numRefIdxL0DefaultActiveMinus1) ||
9724                 (numRefIdxL1ActiveMinus1 != pps.numRefIdxL1DefaultActiveMinus1 && sliceType == SLICE_TYPE_B);
9725 
9726             obs.PutBit(numRefIdxActiveOverrideFlag);
9727             if (numRefIdxActiveOverrideFlag)
9728             {
9729                 obs.PutUe(numRefIdxL0ActiveMinus1);
9730                 if (sliceType == SLICE_TYPE_B)
9731                     obs.PutUe(numRefIdxL1ActiveMinus1);
9732             }
9733         }
9734         if (sliceType != SLICE_TYPE_I)
9735             WriteRefPicListModification(obs, task.m_refPicList0Mod[fieldId]);
9736         if (sliceType == SLICE_TYPE_B)
9737             WriteRefPicListModification(obs, task.m_refPicList1Mod[fieldId]);
9738         if ((pps.weightedPredFlag  == 1 && sliceType == SLICE_TYPE_P) ||
9739             (pps.weightedBipredIdc == 1 && sliceType == SLICE_TYPE_B))
9740         {
9741             mfxU32 chromaArrayType = sps.separateColourPlaneFlag ? 0 : sps.chromaFormatIdc;
9742             WritePredWeightTable(obs, m_hwCaps, task, fieldId, chromaArrayType);
9743         }
9744         if (refPicFlag)
9745         {
9746             WriteDecRefPicMarking(obs, task.m_decRefPicMrk[fieldId], idrPicFlag);
9747             mfxU32 storeRefBasePicFlag = 0;
9748             if (nalUnitType == 20 && !sliceHeaderRestrictionFlag)
9749                 obs.PutBit(storeRefBasePicFlag);
9750         }
9751     }
9752     if (pps.entropyCodingModeFlag && sliceType != SLICE_TYPE_I)
9753         obs.PutUe(m_cabacInitIdc);
9754     obs.PutSe(task.m_cqpValue[fieldId] - (pps.picInitQpMinus26 + 26));
9755     if (pps.deblockingFilterControlPresentFlag)
9756     {
9757         // task.m_disableDeblockingIdc[fieldId] is initialized for fixed number of slices
9758         // it can't be used to feed slice header generation for adaptive slice mode
9759         // always use slice id 0
9760         // the same for task.m_sliceAlphaC0OffsetDiv2 and task.m_sliceBetaOffsetDiv2
9761         mfxU32 disableDeblockingFilterIdc = task.m_disableDeblockingIdc[fieldId][0];
9762         mfxI32 sliceAlphaC0OffsetDiv2     = task.m_sliceAlphaC0OffsetDiv2[fieldId][0];
9763         mfxI32 sliceBetaOffsetDiv2        = task.m_sliceBetaOffsetDiv2[fieldId][0];
9764 
9765         obs.PutUe(disableDeblockingFilterIdc);
9766         if (disableDeblockingFilterIdc != 1)
9767         {
9768             obs.PutSe(sliceAlphaC0OffsetDiv2);
9769             obs.PutSe(sliceBetaOffsetDiv2);
9770         }
9771     }
9772 
9773     return obs.GetNumBits();
9774 }
9775 
9776 
9777 const mfxU8 M_N[2][3][3][2] = { // [isB][ctxIdx][cabac_init_idc][m, n]
9778     {// m and n values for 3 CABAC contexts 11-13 (mb_skip_flag for P frames)
9779         {{23, 33}, {22, 25}, {29, 16}},
9780         {{23,  2}, {34,  0}, {25,  0}},
9781         {{21,  0}, {16,  0}, {14,  0}}
9782     },
9783     {// m and n values for 3 CABAC contexts 24-26 (mb_skip_flag for B frames)
9784         {{18, 64}, {26, 34}, {20, 40}},
9785         {{ 9, 43}, {19, 22}, {20, 10}},
9786         {{29,  0}, {40,  0}, {29,  0}}
9787     },
9788 };
9789 
9790 const mfxI8 M_N_mbt_b[9][3][2] = { // [ctxIdx][cabac_init_idc][m, n]
9791     // m and n values for CABAC contexts 27-35 (mb_type for B frames)
9792     {{ 26,  67}, { 57,   2}, { 54,   0}},
9793     {{ 16,  90}, { 41,  36}, { 37,  42}},
9794     {{  9, 104}, { 26,  69}, { 12,  97}},
9795     {{-46, 127}, {-45, 127}, {-32, 127}},
9796     {{-20, 104}, {-15, 101}, {-22, 117}},
9797     {{  1,  67}, { -4,  76}, { -2,  74}},
9798     {{-13,  78}, { -6,  71}, { -4,  85}},
9799     {{-11,  65}, {-13,  79}, {-24, 102}},
9800     {{  1,  62}, {  5,  52}, {  5,  57}}
9801 };
9802 
9803 
9804 const mfxI8 M_N_mvd_b[14][3][2] = { // [ctxIdx][cabac_init_idc][m, n]
9805     // m and n values for CABAC contexts 40-53 (mvd_lx for B frames)
9806     {{ -3,  69}, { -2,  69}, {-11,  89}},
9807     {{ -6,  81}, { -5,  82}, {-15, 103}},
9808     {{-11,  96}, {-10,  96}, {-21, 116}},
9809     {{  6,  55}, {  2,  59}, { 19,  57}},
9810     {{  7,  67}, {  2,  75}, { 20,  58}},
9811     {{ -5,  86}, { -3,  87}, {  4,  84}},
9812     {{  2,  88}, { -3, 100}, {  6,  96}},
9813     {{  0,  58}, {  1,  56}, {  1,  63}},
9814     {{ -3,  76}, { -3,  74}, { -5,  85}},
9815     {{-10,  94}, { -6,  85}, {-13, 106}},
9816     {{  5,  54}, {  0,  59}, {  5,  63}},
9817     {{  4,  69}, { -3,  81}, {  6,  75}},
9818     {{ -3,  81}, { -7,  86}, { -3,  90}},
9819     {{  0,  88}, { -5,  95}, { -1, 101}}
9820 };
9821 
9822 const mfxI8 M_N_ref_b[6][3][2] = { // [ctxIdx][cabac_init_idc][m, n]
9823     // m and n values for CABAC contexts 54-59 (ref_idx_lx for B frames)
9824     {{ -7,  67}, { -1,  66}, {  3,  55}},
9825     {{ -5,  74}, { -1,  77}, { -4,  79}},
9826     {{ -4,  74}, {  1,  70}, { -2,  75}},
9827     {{ -5,  80}, { -2,  86}, {-12,  97}},
9828     {{ -7,  72}, { -5,  72}, { -7,  50}},
9829     {{  1,  58}, {  0,  61}, {  1,  60}},
9830 };
9831 
9832 const mfxI8 M_N_cbp_b[12][3][2] = { // [ctxIdx][cabac_init_idc][m, n]
9833     // m and n values for CABAC contexts 73-84 (coded_block_pattern for B frames)
9834     {{-27, 126}, {-39, 127}, {-36, 127}},
9835     {{-28,  98}, {-18,  91}, {-17,  91}},
9836     {{-25, 101}, {-17,  96}, {-14,  95}},
9837     {{-23,  67}, {-26,  81}, {-25,  84}},
9838     {{-28,  82}, {-35,  98}, {-25,  86}},
9839     {{-20,  94}, {-24, 102}, {-12,  89}},
9840     {{-16,  83}, {-23,  97}, {-17,  91}},
9841     {{-22, 110}, {-27, 119}, {-31, 127}},
9842     {{-21,  91}, {-24,  99}, {-14,  76}},
9843     {{-18, 102}, {-21, 110}, {-18, 103}},
9844     {{-13,  93}, {-18, 102}, {-13,  90}},
9845     {{-29, 127}, {-36, 127}, {-37, 127}}
9846 };
9847 
InitCabacContext(mfxI16 m,mfxI16 n,mfxU16 sliceQP,mfxU8 & ctx)9848 inline void InitCabacContext(mfxI16 m, mfxI16 n, mfxU16 sliceQP, mfxU8& ctx)
9849 {
9850     mfxI16 preCtxState = mfx::clamp<mfxI16>(( ( m * sliceQP ) >> 4 ) + n, 1, 126);
9851     if (preCtxState <= 63)
9852         ctx = mfxU8(63 - preCtxState); // MPS = 0
9853     else
9854         ctx = mfxU8((preCtxState - 64) | (1 << 6)); // MPS = 1
9855 }
9856 
9857 #define INIT_CABAC_CONTEXTS(idc, QP, MN, ctx) \
9858     for (mfxU32 i = 0; i < sizeof(ctx); i++) \
9859         InitCabacContext(MN[i][idc][0], MN[i][idc][1], mfxU16(QP), ctx[i]);
9860 
9861 
PackSkippedSlice(DdiTask const & task,mfxU32 fieldId)9862 ENCODE_PACKEDHEADER_DATA const & HeaderPacker::PackSkippedSlice(
9863             DdiTask const & task,
9864             mfxU32          fieldId)
9865 {
9866     Zero(m_packedSlices);
9867 
9868     mfxU8 * sliceBufferBegin = Begin(m_sliceBuffer);
9869     mfxU8 * sliceBufferEnd   = End(m_sliceBuffer);
9870 
9871     mfxU8 * endOfPrefix = m_needPrefixNalUnit && task.m_did == 0 && task.m_qid == 0
9872             ? PackPrefixNalUnitSvc(sliceBufferBegin, sliceBufferEnd, true, task, fieldId)
9873             : sliceBufferBegin;
9874 
9875     CabacPackerSimple packer(endOfPrefix, sliceBufferEnd, m_emulPrev);
9876     WriteSlice(packer, task, fieldId, 0);
9877 
9878     mfxExtSpsHeader const & sps = task.m_viewIdx ? m_sps[task.m_viewIdx] : m_sps[m_spsIdx[task.m_did][task.m_qid]];
9879     mfxExtPpsHeader const & pps =
9880         task.m_viewIdx ? m_pps[task.m_viewIdx] : m_pps[m_ppsIdx[task.m_did][task.m_qid]];
9881 
9882     mfxU32 picHeightMultiplier = (sps.frameMbsOnlyFlag == 0) && (task.GetPicStructForEncode() == MFX_PICSTRUCT_PROGRESSIVE) ? 2 : 1;
9883     mfxU32 picHeightInMB       = (sps.picHeightInMapUnitsMinus1 + 1) * picHeightMultiplier;
9884     mfxU32 picWidthInMB        = (sps.picWidthInMbsMinus1 + 1);
9885     mfxU32 picSizeInMB         = picWidthInMB * picHeightInMB;
9886 
9887     if (pps.entropyCodingModeFlag)
9888     {
9889         mfxU32 numAlignmentBits = (8 - (packer.GetNumBits() & 0x7)) & 0x7;
9890         packer.PutBits(0xff, numAlignmentBits);
9891 
9892         // encode dummy MB data
9893 
9894         mfxU8 cabacContexts[3]; // 3 CABAC contexts for mb_skip_flag
9895         mfxU32 sliceQP = task.m_cqpValue[fieldId];
9896 
9897         INIT_CABAC_CONTEXTS(m_cabacInitIdc, sliceQP, M_N[!!(task.m_type[fieldId] & MFX_FRAMETYPE_B)], cabacContexts);
9898 
9899         mfxU8 ctx276 = 63; // ctx for end_of_slice_flag: MPS = 0, pStateIdx = 63 (non-adapting prob state)
9900 
9901         if ((task.m_type[fieldId] & MFX_FRAMETYPE_B) && (task.m_type[fieldId] & MFX_FRAMETYPE_REF))
9902         {
9903             mfxU8 ctxMBT[9];
9904             mfxU8 ctxREF[6];
9905             mfxU8 ctxMVD[14];
9906             mfxU8 ctxCBP[12];
9907 
9908             INIT_CABAC_CONTEXTS(m_cabacInitIdc, sliceQP, M_N_mbt_b, ctxMBT);
9909             INIT_CABAC_CONTEXTS(m_cabacInitIdc, sliceQP, M_N_ref_b, ctxREF);
9910             INIT_CABAC_CONTEXTS(m_cabacInitIdc, sliceQP, M_N_mvd_b, ctxMVD);
9911             INIT_CABAC_CONTEXTS(m_cabacInitIdc, sliceQP, M_N_cbp_b, ctxCBP);
9912 
9913             for (mfxU32 uMB = 0; uMB < (picSizeInMB-1); uMB ++)
9914             {
9915                 bool mbA = !!(uMB % picWidthInMB); //is left MB available
9916                 bool mbB = (uMB >= picWidthInMB);   //is above MB available
9917 
9918                 packer.EncodeBin(&cabacContexts[mbA + mbB], 0); // encode mb_skip_flag = 0
9919 
9920                 // mb_type = 1 (B_L0_16x16) 1 0 0
9921                 packer.EncodeBin(&ctxMBT[mbA + mbB], 1);
9922                 packer.EncodeBin(&ctxMBT[3], 0);
9923                 packer.EncodeBin(&ctxMBT[5], 0);
9924 
9925                 if (task.m_list0[fieldId].Size() > 1)
9926                     packer.EncodeBin(&ctxREF[0], 0); // ref_idx_l0 = 0
9927 
9928                 packer.EncodeBin(&ctxMVD[0], 0); // mvd_l0[][][0] = 0
9929                 packer.EncodeBin(&ctxMVD[7], 0); // mvd_l0[][][1] = 0
9930 
9931                 // coded_block_pattern = 0 (0 0 0 0, 0)
9932                 packer.EncodeBin(&ctxCBP[mbA + 2 * mbB], 0);
9933                 packer.EncodeBin(&ctxCBP[  1 + 2 * mbB], 0);
9934                 packer.EncodeBin(&ctxCBP[mbA + 2 * 1  ], 0);
9935                 packer.EncodeBin(&ctxCBP[  1 + 2 * 1  ], 0);
9936                 packer.EncodeBin(&ctxCBP[4], 0);
9937 
9938                 packer.EncodeBin(&ctx276, 0); // end_of_slice_flag = 0
9939             }
9940 
9941             packer.EncodeBin(&cabacContexts[2], 0); // encode mb_skip_flag = 0
9942 
9943             // mb_type = 1 (B_L0_16x16) 1 0 0
9944             packer.EncodeBin(&ctxMBT[2], 1);
9945             packer.EncodeBin(&ctxMBT[3], 0);
9946             packer.EncodeBin(&ctxMBT[5], 0);
9947 
9948             if (task.m_list0[fieldId].Size() > 1)
9949                 packer.EncodeBin(&ctxREF[0], 0); // ref_idx_l0 = 0
9950 
9951             packer.EncodeBin(&ctxMVD[0], 0); // mvd_l0[][][0] = 0
9952             packer.EncodeBin(&ctxMVD[7], 0); // mvd_l0[][][1] = 0
9953 
9954             // coded_block_pattern = 0 (0 0 0 0, 0)
9955             packer.EncodeBin(&ctxCBP[3], 0);
9956             packer.EncodeBin(&ctxCBP[3], 0);
9957             packer.EncodeBin(&ctxCBP[3], 0);
9958             packer.EncodeBin(&ctxCBP[3], 0);
9959             packer.EncodeBin(&ctxCBP[4], 0);
9960 
9961         }
9962         else
9963         {
9964             for (mfxU32 uMB = 0; uMB < (picSizeInMB-1); uMB ++)
9965             {
9966                 packer.EncodeBin(&cabacContexts[0], 1); // encode mb_skip_flag = 1 for every MB.
9967                 packer.EncodeBin(&ctx276, 0); // encode end_of_slice_flag = 0 for every MB
9968             }
9969 
9970             packer.EncodeBin(&cabacContexts[0], 1); // encode mb_skip_flag = 1 for every MB.
9971         }
9972 
9973         packer.TerminateEncode();
9974     }
9975     else
9976     {
9977         if ((task.m_type[fieldId] & MFX_FRAMETYPE_B) && (task.m_type[fieldId] & MFX_FRAMETYPE_REF))
9978         {
9979             for (mfxU32 uMB = 0; uMB < picSizeInMB; uMB ++)
9980             {
9981                 packer.PutUe(0); // mb_skip_run = 0
9982                 packer.PutUe(1); // mb_type = 1 (B_L0_16x16)
9983 
9984                 if (task.m_list0[fieldId].Size() > 1)
9985                     packer.PutBit(1);// ref_idx_l0 = 0
9986 
9987                 packer.PutSe(0); // mvd_l0[][][0] = 0
9988                 packer.PutSe(0); // mvd_l0[][][1] = 0
9989 
9990                 packer.PutUe(0); // coded_block_pattern = 0
9991             }
9992         }
9993         else
9994         {
9995             packer.PutUe(picSizeInMB); // write mb_skip_run = picSizeInMBs
9996         }
9997 
9998         packer.PutTrailingBits();
9999 
10000         VM_ASSERT(packer.GetNumBits() % 8 == 0);
10001     }
10002 
10003     m_packedSlices[0].pData                  = sliceBufferBegin;
10004     m_packedSlices[0].DataLength             = mfxU32((endOfPrefix - sliceBufferBegin) + (packer.GetNumBits() / 8));
10005     m_packedSlices[0].BufferSize             = m_packedSlices[0].DataLength;
10006     m_packedSlices[0].SkipEmulationByteCount = m_emulPrev ? 0 : (mfxU32(endOfPrefix - sliceBufferBegin) + 3);
10007 
10008     return m_packedSlices[0];
10009 }
10010 
10011 #endif //MFX_ENABLE_H264_VIDEO_..._HW
10012 
10013