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