1 /*
2 * Copyright (c) 2020, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 //!
23 //! \file codechal_encode_sfc_base.cpp
24 //! \brief Implements the encode interface extension for CSC via VEBox/SFC.
25 //! \details Downsampling in this case is supported by the VEBox fixed function HW unit.
26 //!
27
28 #include "codechal_encode_sfc_base.h"
29 #include "codechal_encoder_base.h"
30 #include "hal_oca_interface.h"
31
32 #define CODECHAL_IS_BT601_CSPACE(format) \
33 ( (format == MHW_CSpace_BT601) || \
34 (format == MHW_CSpace_xvYCC601) || \
35 (format == MHW_CSpace_BT601Gray) || \
36 (format == MHW_CSpace_BT601_FullRange) || \
37 (format == MHW_CSpace_BT601Gray_FullRange) )
38
39 #define CODECHAL_IS_BT709_CSPACE(format) \
40 ( (format == MHW_CSpace_BT709) || \
41 (format == MHW_CSpace_xvYCC709) || \
42 (format == MHW_CSpace_BT709_FullRange) )
43
44 // Generic YUV to RGB conversion matrix from BT.601 standard
45 const float CODECHAL_CSC_BT601_YUV_RGB[9] =
46 {
47 1.000000f, 0.000000f, 1.402000f,
48 1.000000f, -0.344136f, -0.714136f,
49 1.000000f, 1.772000f, 0.000000f
50 };
51
52 // Generic YUV to RGB conversion matrix from BT.709 standard
53 const float CODECHAL_CSC_BT709_YUV_RGB[9] =
54 {
55 1.000000f, 0.000000f, 1.574800f,
56 1.000000f, -0.187324f, -0.468124f,
57 1.000000f, 1.855600f, 0.000000f
58 };
59
60 // Generic RGB to YUV conversion matrix from BT.601 standard
61 const float CODECHAL_CSC_BT601_RGB_YUV[9] =
62 {
63 0.299000f, 0.587000f, 0.114000f,
64 -0.168736f, -0.331264f, 0.500000f,
65 0.500000f, -0.418688f, -0.081312f
66 };
67
68 // Generic RGB to YUV conversion matrix from BT.709 standard
69 const float CODECHAL_CSC_BT709_RGB_YUV[9] =
70 {
71 0.212600f, 0.715200f, 0.072200f,
72 -0.114572f, -0.385428f, 0.500000f,
73 0.500000f, -0.454153f, -0.045847f
74 };
75
76 // BT2020 RGB to Non-constant YUV conversion matrix from R-REC-BT.2020-1-201406-I!!PDF-E.pdf
77 const float CODECHAL_CSC_BT2020_RGB_YUV[9] =
78 {
79 0.262700f, 0.678000f, 0.059300f, // Y
80 -0.139630f, -0.360370f, 0.500000f, // U
81 0.500000f, -0.459786f, -0.040214f // V
82 };
83
84 // BT2020 Non-constant YUV to RGB conversion matrix from R-REC-BT.2020-1-201406-I!!PDF-E.pdf
85 const float CODECHAL_CSC_BT2020_YUV_RGB[9] =
86 {
87 1.000000f, 0.000000f, 1.474600f, //R
88 1.000000f, -0.164553f, -0.571353f, //G
89 1.000000f, 1.881400f, 0.000000f //B
90 };
91
~CodecHalEncodeSfcBase()92 CodecHalEncodeSfcBase::~CodecHalEncodeSfcBase()
93 {
94 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
95
96 CODECHAL_ENCODE_FUNCTION_ENTER;
97
98 // pVeboxInterface->pfnDestroy() will be called in CodecHal_HwDestroy(), no need to destroy here
99
100 FreeResources();
101 }
102
IsCspace(MHW_CSPACE srcCspace,MHW_CSPACE dstCspace)103 bool CodecHalEncodeSfcBase::IsCspace(MHW_CSPACE srcCspace, MHW_CSPACE dstCspace)
104 {
105 switch (dstCspace)
106 {
107 case MHW_CSpace_RGB:
108 return (srcCspace == MHW_CSpace_sRGB ||
109 srcCspace == MHW_CSpace_stRGB);
110
111 case MHW_CSpace_YUV:
112 return (srcCspace == MHW_CSpace_BT709 ||
113 srcCspace == MHW_CSpace_BT601 ||
114 srcCspace == MHW_CSpace_BT601_FullRange ||
115 srcCspace == MHW_CSpace_BT709_FullRange ||
116 srcCspace == MHW_CSpace_xvYCC709 ||
117 srcCspace == MHW_CSpace_xvYCC601);
118
119 case MHW_CSpace_Gray:
120 return (srcCspace == MHW_CSpace_BT601Gray ||
121 srcCspace == MHW_CSpace_BT601Gray_FullRange);
122
123 case MHW_CSpace_Any:
124 return (srcCspace != MHW_CSpace_None);
125
126 case MHW_CSpace_BT2020:
127 return (srcCspace == MHW_CSpace_BT2020 ||
128 srcCspace == MHW_CSpace_BT2020_FullRange);
129
130 case MHW_CSpace_BT2020_RGB:
131 return (srcCspace == MHW_CSpace_BT2020_RGB ||
132 srcCspace == MHW_CSpace_BT2020_stRGB);
133
134 default:
135 return (srcCspace == dstCspace);
136 }
137
138 return false;
139 }
140
GetRgbRangeAndOffset(MHW_CSPACE srcCspace,float * rgbOffset,float * rgbExcursion)141 bool CodecHalEncodeSfcBase::GetRgbRangeAndOffset(
142 MHW_CSPACE srcCspace,
143 float *rgbOffset,
144 float *rgbExcursion)
145 {
146 bool ret = true;
147
148 switch (srcCspace)
149 {
150 case MHW_CSpace_sRGB:
151 case MHW_CSpace_BT2020_RGB:
152 *rgbOffset = 0.0f;
153 *rgbExcursion = 255.0f;
154 break;
155
156 case MHW_CSpace_stRGB:
157 case MHW_CSpace_BT2020_stRGB:
158 *rgbOffset = 16.0f;
159 *rgbExcursion = 219.0f;
160 break;
161
162 default:
163 ret = false;
164 break;
165 }
166
167 return ret;
168 }
169
GetYuvRangeAndOffset(MHW_CSPACE srcCspace,float * lumaOffset,float * lumaExcursion,float * chromaZero,float * chromaExcursion)170 bool CodecHalEncodeSfcBase::GetYuvRangeAndOffset(
171 MHW_CSPACE srcCspace,
172 float *lumaOffset,
173 float *lumaExcursion,
174 float *chromaZero,
175 float *chromaExcursion)
176 {
177 bool ret = true;
178
179 switch (srcCspace)
180 {
181 case MHW_CSpace_BT601_FullRange:
182 case MHW_CSpace_BT709_FullRange:
183 case MHW_CSpace_BT601Gray_FullRange:
184 case MHW_CSpace_BT2020_FullRange:
185 *lumaOffset = 0.0f;
186 *lumaExcursion = 255.0f;
187 *chromaZero = 128.0f;
188 *chromaExcursion = 255.0f;
189 break;
190
191 case MHW_CSpace_BT601:
192 case MHW_CSpace_BT709:
193 case MHW_CSpace_xvYCC601: // since matrix is the same as 601, use the same range
194 case MHW_CSpace_xvYCC709: // since matrix is the same as 709, use the same range
195 case MHW_CSpace_BT601Gray:
196 case MHW_CSpace_BT2020:
197 *lumaOffset = 16.0f;
198 *lumaExcursion = 219.0f;
199 *chromaZero = 128.0f;
200 *chromaExcursion = 224.0f;
201 break;
202
203 default:
204 ret = false;
205 break;
206 }
207
208 return ret;
209 }
210
CalcYuvToRgbMatrix(MHW_CSPACE srcCspace,MHW_CSPACE dstCspace,float * transferMatrix,float * outMatrix)211 bool CodecHalEncodeSfcBase::CalcYuvToRgbMatrix(
212 MHW_CSPACE srcCspace, // [in] YUV Color space
213 MHW_CSPACE dstCspace, // [in] RGB Color space
214 float *transferMatrix, // [in] Transfer matrix (3x3)
215 float *outMatrix) // [out] Conversion matrix (3x4)
216 {
217 bool ret = true;
218 float lumaOffset, lumaExcursion, chromaZero, chromaExcursion;
219 float rgbOffset, rgbExcursion;
220
221 ret = GetRgbRangeAndOffset(dstCspace, &rgbOffset, &rgbExcursion);
222 if (ret)
223 {
224 ret = GetYuvRangeAndOffset(srcCspace, &lumaOffset, &lumaExcursion, &chromaZero, &chromaExcursion);
225 }
226 if (ret)
227 {
228
229 // after + (3x3)(3x3)
230 outMatrix[0] = transferMatrix[0] * rgbExcursion / lumaExcursion;
231 outMatrix[4] = transferMatrix[3] * rgbExcursion / lumaExcursion;
232 outMatrix[8] = transferMatrix[6] * rgbExcursion / lumaExcursion;
233 outMatrix[1] = transferMatrix[1] * rgbExcursion / chromaExcursion;
234 outMatrix[5] = transferMatrix[4] * rgbExcursion / chromaExcursion;
235 outMatrix[9] = transferMatrix[7] * rgbExcursion / chromaExcursion;
236 outMatrix[2] = transferMatrix[2] * rgbExcursion / chromaExcursion;
237 outMatrix[6] = transferMatrix[5] * rgbExcursion / chromaExcursion;
238 outMatrix[10] = transferMatrix[8] * rgbExcursion / chromaExcursion;
239
240 // (3x1) - (3x3)(3x3)(3x1)
241 outMatrix[3] = rgbOffset - (outMatrix[0] * lumaOffset + outMatrix[1] * chromaZero + outMatrix[2] * chromaZero);
242 outMatrix[7] = rgbOffset - (outMatrix[4] * lumaOffset + outMatrix[5] * chromaZero + outMatrix[6] * chromaZero);
243 outMatrix[11] = rgbOffset - (outMatrix[8] * lumaOffset + outMatrix[9] * chromaZero + outMatrix[10] * chromaZero);
244 }
245 return ret;
246 }
247
CalcRgbToYuvMatrix(MHW_CSPACE srcCspace,MHW_CSPACE dstCspace,float * transferMatrix,float * outMatrix)248 bool CodecHalEncodeSfcBase::CalcRgbToYuvMatrix(
249 MHW_CSPACE srcCspace, // [in] RGB Color space
250 MHW_CSPACE dstCspace, // [in] YUV Color space
251 float *transferMatrix, // [in] Transfer matrix (3x3)
252 float *outMatrix) // [out] Conversion matrix (3x4)
253 {
254 bool ret = true;
255 float lumaOffset, lumaExcursion, chromaZero, chromaExcursion;
256 float rgbOffset, rgbExcursion;
257
258 ret = GetRgbRangeAndOffset(srcCspace, &rgbOffset, &rgbExcursion);
259 if (ret)
260 {
261 ret = GetYuvRangeAndOffset(dstCspace, &lumaOffset, &lumaExcursion, &chromaZero, &chromaExcursion);
262 }
263 if (ret)
264 {
265 // multiplication of + onwards
266 outMatrix[0] = transferMatrix[0] * lumaExcursion / rgbExcursion;
267 outMatrix[1] = transferMatrix[1] * lumaExcursion / rgbExcursion;
268 outMatrix[2] = transferMatrix[2] * lumaExcursion / rgbExcursion;
269 outMatrix[4] = transferMatrix[3] * chromaExcursion / rgbExcursion;
270 outMatrix[5] = transferMatrix[4] * chromaExcursion / rgbExcursion;
271 outMatrix[6] = transferMatrix[5] * chromaExcursion / rgbExcursion;
272 outMatrix[8] = transferMatrix[6] * chromaExcursion / rgbExcursion;
273 outMatrix[9] = transferMatrix[7] * chromaExcursion / rgbExcursion;
274 outMatrix[10] = transferMatrix[8] * chromaExcursion / rgbExcursion;
275
276 // before +
277 outMatrix[3] = lumaOffset - lumaExcursion * rgbOffset / rgbExcursion;
278 outMatrix[7] = chromaZero;
279 outMatrix[11] = chromaZero;
280 }
281 return ret;
282 }
283
GetCSCMatrix(MHW_CSPACE srcCspace,MHW_CSPACE dstCspace,float * cscMatrix)284 void CodecHalEncodeSfcBase::GetCSCMatrix(
285 MHW_CSPACE srcCspace, // [in] Source Color space
286 MHW_CSPACE dstCspace, // [in] Destination Color space
287 float *cscMatrix) // [out] CSC matrix to use
288 {
289 int32_t i;
290
291 // BT601/709 YUV to sRGB/stRGB conversion
292 if (IsCspace(srcCspace, MHW_CSpace_YUV))
293 {
294 if(IsCspace(dstCspace, MHW_CSpace_RGB))
295 {
296 if (CODECHAL_IS_BT601_CSPACE(srcCspace))
297 {
298 CalcYuvToRgbMatrix(srcCspace, dstCspace, (float *) CODECHAL_CSC_BT601_YUV_RGB, cscMatrix);
299 }
300 else // if (IS_BT709_CSPACE(srcCspace))
301 {
302 CalcYuvToRgbMatrix(srcCspace, dstCspace, (float *) CODECHAL_CSC_BT709_YUV_RGB, cscMatrix);
303 }
304 }
305 }
306 // sRGB/stRGB to BT601/709 YUV conversion
307 else if (IsCspace(srcCspace, MHW_CSpace_RGB))
308 {
309 if (IsCspace(dstCspace, MHW_CSpace_YUV))
310 {
311 if (CODECHAL_IS_BT601_CSPACE(dstCspace))
312 {
313 CalcRgbToYuvMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT601_RGB_YUV, cscMatrix);
314 }
315 else // if (IS_BT709_CSPACE(srcCspace))
316 {
317 CalcRgbToYuvMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT709_RGB_YUV, cscMatrix);
318 }
319 }
320 }
321 // BT2020 YUV to RGB conversion
322 else if (IsCspace(srcCspace, MHW_CSpace_BT2020))
323 {
324 if (IsCspace(dstCspace, MHW_CSpace_BT2020_RGB))
325 {
326 CalcYuvToRgbMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT2020_YUV_RGB, cscMatrix);
327 }
328 }
329 // BT2020 RGB to YUV conversion
330 else if (IsCspace(srcCspace, MHW_CSpace_BT2020_RGB))
331 {
332 if (IsCspace(dstCspace, MHW_CSpace_BT2020))
333 {
334 CalcRgbToYuvMatrix(srcCspace, dstCspace, (float *)CODECHAL_CSC_BT2020_RGB_YUV, cscMatrix);
335 }
336 }
337 else
338 {
339 CODECHAL_ENCODE_ASSERTMESSAGE("Not supported color space conversion(from %d to %d)", srcCspace, dstCspace);
340 }
341
342 CODECHAL_ENCODE_NORMALMESSAGE("");
343 for(i = 0; i < 3; i++)
344 {
345 CODECHAL_ENCODE_NORMALMESSAGE("%f\t%f\t%f\t%f",
346 cscMatrix[4 * i],
347 cscMatrix[4 * i + 1],
348 cscMatrix[4 * i + 2],
349 cscMatrix[4 * i + 3]);
350 }
351 }
352
GetCscMatrix(MHW_CSPACE srcCspace,MHW_CSPACE dstCspace,float * cscCoeff,float * cscInOffset,float * cscOutOffset)353 void CodecHalEncodeSfcBase::GetCscMatrix(
354 MHW_CSPACE srcCspace, // [in] Source Cspace
355 MHW_CSPACE dstCspace, // [in] Destination Cspace
356 float *cscCoeff, // [out] [3x3] Coefficients matrix
357 float *cscInOffset, // [out] [3x1] Input Offset matrix
358 float *cscOutOffset) // [out] [3x1] Output Offset matrix
359 {
360 float cscMatrix[12]{};
361 int32_t i;
362
363 GetCSCMatrix(
364 srcCspace,
365 dstCspace,
366 cscMatrix);
367
368 // Copy [3x3] into Coeff
369 for (i = 0; i < 3; i++)
370 {
371 MOS_SecureMemcpy(
372 &cscCoeff[i*3],
373 sizeof(float) * 3,
374 &cscMatrix[i*4],
375 sizeof(float) * 3);
376 }
377
378 // Get the input offsets
379 switch(srcCspace)
380 {
381 case MHW_CSpace_BT601:
382 case MHW_CSpace_BT601Gray:
383 case MHW_CSpace_xvYCC601:
384 case MHW_CSpace_BT709:
385 case MHW_CSpace_xvYCC709:
386 cscInOffset[0] = -16.0F;
387 cscInOffset[1] = -128.0F;
388 cscInOffset[2] = -128.0F;
389 break;
390
391 case MHW_CSpace_BT601_FullRange:
392 case MHW_CSpace_BT601Gray_FullRange:
393 case MHW_CSpace_BT709_FullRange:
394 cscInOffset[0] = 0.0F;
395 cscInOffset[1] = -128.0F;
396 cscInOffset[2] = -128.0F;
397 break;
398
399 case MHW_CSpace_sRGB:
400 cscInOffset[0] = 0.0F;
401 cscInOffset[1] = 0.0F;
402 cscInOffset[2] = 0.0F;
403 break;
404
405 case MHW_CSpace_stRGB:
406 cscInOffset[0] = -16.0F;
407 cscInOffset[1] = -16.0F;
408 cscInOffset[2] = -16.0F;
409 break;
410
411 //BT2020 YUV->RGB
412 case MHW_CSpace_BT2020:
413 cscInOffset[0] = -16.0F;
414 cscInOffset[1] = -128.0F;
415 cscInOffset[2] = -128.0F;
416 break;
417
418 case MHW_CSpace_BT2020_FullRange:
419 cscInOffset[0] = 0.0F;
420 cscInOffset[1] = -128.0F;
421 cscInOffset[2] = -128.0F;
422 break;
423
424 //BT2020 RGB->YUV
425 case MHW_CSpace_BT2020_RGB:
426 cscInOffset[0] = 0.0F;
427 cscInOffset[1] = 0.0F;
428 cscInOffset[2] = 0.0F;
429 break;
430
431 //BT2020 RGB->YUV
432 case MHW_CSpace_BT2020_stRGB:
433 cscInOffset[0] = -16.0F;
434 cscInOffset[1] = -16.0F;
435 cscInOffset[2] = -16.0F;
436 break;
437
438 default:
439 CODECHAL_PUBLIC_ASSERTMESSAGE("Unsupported Input ColorSpace for Vebox.");
440 }
441
442 // Get the output offsets
443 switch(dstCspace)
444 {
445 case MHW_CSpace_BT601:
446 case MHW_CSpace_BT601Gray:
447 case MHW_CSpace_xvYCC601:
448 case MHW_CSpace_BT709:
449 case MHW_CSpace_xvYCC709:
450 cscOutOffset[0] = 16.0F;
451 cscOutOffset[1] = 128.0F;
452 cscOutOffset[2] = 128.0F;
453 break;
454
455 case MHW_CSpace_BT601_FullRange:
456 case MHW_CSpace_BT601Gray_FullRange:
457 case MHW_CSpace_BT709_FullRange:
458 cscOutOffset[0] = 0.0F;
459 cscOutOffset[1] = 128.0F;
460 cscOutOffset[2] = 128.0F;
461 break;
462
463 case MHW_CSpace_sRGB:
464 cscOutOffset[0] = 0.0F;
465 cscOutOffset[1] = 0.0F;
466 cscOutOffset[2] = 0.0F;
467 break;
468
469 case MHW_CSpace_stRGB:
470 cscOutOffset[0] = 16.0F;
471 cscOutOffset[1] = 16.0F;
472 cscOutOffset[2] = 16.0F;
473 break;
474
475 //BT2020 RGB->YUV
476 case MHW_CSpace_BT2020:
477 cscOutOffset[0] = 16.0F;
478 cscOutOffset[1] = 128.0F;
479 cscOutOffset[2] = 128.0F;
480 break;
481
482 case MHW_CSpace_BT2020_FullRange:
483 cscOutOffset[0] = 0.0F;
484 cscOutOffset[1] = 128.0F;
485 cscOutOffset[2] = 128.0F;
486 break;
487
488 case MHW_CSpace_BT2020_RGB:
489 cscOutOffset[0] = 0.0F;
490 cscOutOffset[1] = 0.0F;
491 cscOutOffset[2] = 0.0F;
492 break;
493
494 case MHW_CSpace_BT2020_stRGB:
495 cscOutOffset[0] = 16.0F;
496 cscOutOffset[1] = 16.0F;
497 cscOutOffset[2] = 16.0F;
498 break;
499
500 default:
501 CODECHAL_PUBLIC_ASSERTMESSAGE("Unsupported Output ColorSpace for Vebox.");
502 }
503 }
504
GetAvsLineBufferSize() const505 inline int32_t CodecHalEncodeSfcBase::GetAvsLineBufferSize() const
506 {
507 if (!m_inputSurface || m_inputSurface->dwHeight == 0)
508 {
509 CODECHAL_ENCODE_ASSERTMESSAGE("Can't calculate buffer size! m_inputSurface == nullptr or dwHeight == 0");
510 return 0;
511 }
512 return MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 8) * CODECHAL_SFC_AVS_LINEBUFFER_SIZE_PER_VERTICAL_PIXEL;
513 }
514
GetStatisticsOutputBufferSize() const515 inline int32_t CodecHalEncodeSfcBase::GetStatisticsOutputBufferSize() const
516 {
517 if (!m_inputSurface || m_inputSurface->dwHeight == 0 || m_inputSurface->dwWidth == 0)
518 {
519 CODECHAL_ENCODE_ASSERTMESSAGE("Can't calculate buffer size! m_inputSurface == nullptr or dwHeight == 0 or dwWidth == 0");
520 return 0;
521 }
522 return MOS_ALIGN_CEIL(m_inputSurface->dwWidth, 64) *
523 (MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 4) + MOS_ROUNDUP_DIVIDE(GetSfcVeboxStatisticsSize() * sizeof(uint32_t), m_inputSurface->dwWidth));
524 }
525
GetVeboxRgbHistogramSize() const526 inline int32_t CodecHalEncodeSfcBase::GetVeboxRgbHistogramSize() const
527 {
528 return CODECHAL_SFC_VEBOX_ACE_HISTOGRAM_SIZE_PER_FRAME_PER_SLICE *
529 CODECHAL_SFC_NUM_RGB_CHANNEL *
530 GetVeboxMaxSlicesNum();
531 }
532
GetResLaceOrAceOrRgbHistogramBufferSize() const533 inline int32_t CodecHalEncodeSfcBase::GetResLaceOrAceOrRgbHistogramBufferSize() const
534 {
535 if (!m_inputSurface || m_inputSurface->dwHeight == 0 || m_inputSurface->dwWidth == 0)
536 {
537 CODECHAL_ENCODE_ASSERTMESSAGE("Can't calculate buffer size! m_inputSurface == nullptr or dwHeight == 0 or dwWidth == 0");
538 return 0;
539 }
540
541 int32_t sizeLace = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 64) *
542 MOS_ROUNDUP_DIVIDE(m_inputSurface->dwWidth, 64) *
543 CODECHAL_SFC_VEBOX_LACE_HISTOGRAM_256_BIN_PER_BLOCK;
544
545 int32_t sizeNoLace = CODECHAL_SFC_VEBOX_ACE_HISTOGRAM_SIZE_PER_FRAME_PER_SLICE *
546 CODECHAL_SFC_NUM_FRAME_PREVIOUS_CURRENT *
547 GetVeboxMaxSlicesNum();
548
549 return GetVeboxRgbHistogramSize() + GetVeboxRgbAceHistogramSizeReserved() + MOS_MAX(sizeLace, sizeNoLace);
550 }
551
AllocateResources()552 MOS_STATUS CodecHalEncodeSfcBase::AllocateResources()
553 {
554 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
555 uint32_t ycoeffTableSize;
556 uint32_t uvcoeffTableSize;
557 int32_t size;
558 char* ptr;
559 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
560
561 CODECHAL_ENCODE_FUNCTION_ENTER;
562
563 CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
564
565 // Allocate AVS line buffer
566 if (Mos_ResourceIsNull(&m_resAvsLineBuffer))
567 {
568 size = GetAvsLineBufferSize();
569 CODECHAL_ENCODE_CHK_COND_RETURN(size == 0, "Invalid buffer size");
570 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
571 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
572 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
573 allocParamsForBufferLinear.Format = Format_Buffer;
574 allocParamsForBufferLinear.dwBytes = size;
575
576 allocParamsForBufferLinear.pBufName = "SfcAvsLineBuffer";
577
578 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
579 m_osInterface,
580 &allocParamsForBufferLinear,
581 &m_resAvsLineBuffer));
582 }
583
584 //Initialize AVS parameters, try to do once
585 if (m_scaling && !m_avsParams.piYCoefsX)
586 {
587 m_avsParams.Format = Format_None;
588 m_avsParams.fScaleX = 0.0F;
589 m_avsParams.fScaleY = 0.0F;
590 m_avsParams.piYCoefsX = nullptr;
591
592 ycoeffTableSize = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9;
593 uvcoeffTableSize = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9;
594
595 size = (ycoeffTableSize + uvcoeffTableSize) * 2;
596
597 ptr = (char*)MOS_AllocAndZeroMemory(size);
598 CODECHAL_ENCODE_CHK_NULL_RETURN(ptr);
599
600 m_avsParams.piYCoefsX = (int32_t*)ptr;
601
602 ptr += ycoeffTableSize;
603 m_avsParams.piUVCoefsX = (int32_t*)ptr;
604
605 ptr += uvcoeffTableSize;
606 m_avsParams.piYCoefsY = (int32_t*)ptr;
607
608 ptr += ycoeffTableSize;
609 m_avsParams.piUVCoefsY = (int32_t*)ptr;
610 }
611
612 return eStatus;
613 }
614
FreeResources()615 MOS_STATUS CodecHalEncodeSfcBase::FreeResources()
616 {
617 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
618
619 CODECHAL_ENCODE_FUNCTION_ENTER;
620
621 CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
622
623 // Free AVS Line Buffer
624 m_osInterface->pfnFreeResource(m_osInterface, &m_resAvsLineBuffer);
625
626 // Free resLaceOrAceOrRgbHistogram
627 m_osInterface->pfnFreeResource(m_osInterface, &m_resLaceOrAceOrRgbHistogram);
628
629 // Free resStatisticsOutput
630 m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput);
631
632 // Free buffers in AVS parameters
633 MOS_FreeMemory(m_avsParams.piYCoefsX);
634 m_avsParams.piYCoefsX = nullptr;
635
636 return eStatus;
637 }
638
SetVeboxStateParams(PMHW_VEBOX_STATE_CMD_PARAMS params)639 MOS_STATUS CodecHalEncodeSfcBase::SetVeboxStateParams(
640 PMHW_VEBOX_STATE_CMD_PARAMS params)
641 {
642 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
643
644 CODECHAL_ENCODE_FUNCTION_ENTER;
645
646 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
647
648 params->bNoUseVeboxHeap = 0;
649
650 params->VeboxMode.ColorGamutExpansionEnable = 0;
651 params->VeboxMode.ColorGamutCompressionEnable = 0;
652 // On SKL, GlobalIECP must be enabled when the output pipe is Vebox or SFC
653 params->VeboxMode.GlobalIECPEnable = 1;
654 params->VeboxMode.DNEnable = 0;
655 params->VeboxMode.DIEnable = 0;
656 params->VeboxMode.DNDIFirstFrame = 0;
657 params->VeboxMode.DIOutputFrames = 0;
658 params->VeboxMode.PipeSynchronizeDisable = 0;
659 params->VeboxMode.DemosaicEnable = 0;
660 params->VeboxMode.VignetteEnable = 0;
661 params->VeboxMode.AlphaPlaneEnable = 0;
662 params->VeboxMode.HotPixelFilteringEnable = 0;
663 // 0-both slices enabled 1-Slice 0 enabled 2-Slice 1 enabled
664 // On SKL GT3 and GT4, there are 2 Veboxes. But only Vebox0 can be used,Vebox1 cannot be used
665 params->VeboxMode.SingleSliceVeboxEnable = 1;
666 params->VeboxMode.LACECorrectionEnable = 0;
667 params->VeboxMode.DisableEncoderStatistics = 1;
668 params->VeboxMode.DisableTemporalDenoiseFilter = 1;
669 params->VeboxMode.SinglePipeIECPEnable = 0;
670 params->VeboxMode.SFCParallelWriteEnable = 0;
671 params->VeboxMode.ScalarMode = 0;
672 params->VeboxMode.ForwardGammaCorrectionEnable = 0;
673
674 return eStatus;
675 }
676
SetVeboxSurfaceStateParams(PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS params)677 MOS_STATUS CodecHalEncodeSfcBase::SetVeboxSurfaceStateParams(
678 PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS params)
679 {
680 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
681
682 CODECHAL_ENCODE_FUNCTION_ENTER;
683
684 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
685
686 // Initialize SurfInput
687 params->SurfInput.bActive = true;
688 params->SurfInput.Format = m_inputSurface->Format;
689 params->SurfInput.dwWidth = m_inputSurface->dwWidth;
690 params->SurfInput.dwHeight = m_inputSurface->dwHeight;
691 params->SurfInput.dwPitch = m_inputSurface->dwPitch;
692 params->SurfInput.TileType = m_inputSurface->TileType;
693 params->SurfInput.TileModeGMM = m_inputSurface->TileModeGMM;
694 params->SurfInput.bGMMTileEnabled = m_inputSurface->bGMMTileEnabled;
695 params->SurfInput.dwYoffset = m_inputSurface->YPlaneOffset.iYOffset;
696 params->SurfInput.pOsResource = &m_inputSurface->OsResource;
697
698 auto& rcMaxSrc = params->SurfInput.rcMaxSrc;
699 rcMaxSrc.left = m_inputSurfaceRegion.X;
700 rcMaxSrc.top = m_inputSurfaceRegion.Y;
701 rcMaxSrc.right = m_inputSurfaceRegion.X + m_inputSurfaceRegion.Width;
702 rcMaxSrc.bottom = m_inputSurfaceRegion.Y + m_inputSurfaceRegion.Height;
703 CODECHAL_ENCODE_CHK_COND_RETURN(rcMaxSrc.right < MHW_VEBOX_MIN_WIDTH || rcMaxSrc.bottom < MHW_VEBOX_MIN_HEIGHT,
704 "Invalid VEBOX input surface description. Minimal W x H: %d x %d; Requested W x H: %d x %d", MHW_VEBOX_MIN_WIDTH, MHW_VEBOX_MIN_HEIGHT, rcMaxSrc.right, rcMaxSrc.bottom);
705
706 // Initialize SurfSTMM
707 params->SurfSTMM.dwPitch = m_inputSurface->dwPitch;
708
709 params->bDIEnable = false;
710 params->bOutputValid = (m_veboxOutputSurface != nullptr) ? true : false;
711
712 return eStatus;
713 }
714
SetVeboxDiIecpParams(PMHW_VEBOX_DI_IECP_CMD_PARAMS params)715 MOS_STATUS CodecHalEncodeSfcBase::SetVeboxDiIecpParams(
716 PMHW_VEBOX_DI_IECP_CMD_PARAMS params)
717 {
718 MOS_ALLOC_GFXRES_PARAMS allocParamsForBufferLinear;
719 int32_t size;
720 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
721 MOS_MEMCOMP_STATE mmcMode = MOS_MEMCOMP_DISABLED;
722
723 CODECHAL_ENCODE_FUNCTION_ENTER;
724 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
725
726 params->dwStartingX = 0;
727 params->dwEndingX = m_inputSurfaceRegion.Width - 1; // Must be taken from SPS
728 params->dwCurrInputSurfOffset = m_inputSurface->dwOffset;
729 params->pOsResCurrInput = &m_inputSurface->OsResource;
730 params->CurrInputSurfCtrl.Value = 0; //Keep it here untill VPHAL moving to new CMD definition and remove this parameter definition.
731 CODECHAL_ENCODE_CHK_COND_RETURN(m_inputSurfaceRegion.Width < MHW_VEBOX_MIN_WIDTH,
732 "Invalid VEBOX_DI_IECP.EndingX value. It must be greater or equal to %d", MHW_VEBOX_MIN_WIDTH);
733
734 CodecHalGetResourceInfo(
735 m_osInterface,
736 m_inputSurface);
737
738 m_osInterface->pfnGetMemoryCompressionMode(m_osInterface, &m_inputSurface->OsResource, &mmcMode);
739 if (mmcMode &&
740 (m_inputSurface->TileType == MOS_TILE_Y ||
741 m_inputSurface->TileType == MOS_TILE_YS))
742 {
743 m_inputSurface->bCompressible = true;
744 m_inputSurface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode;
745 }
746 else
747 {
748 m_inputSurface->CompressionMode = MOS_MMC_DISABLED;
749 }
750
751 params->CurInputSurfMMCState = (MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode);
752
753 // Allocate Resource to avoid Page Fault issue since HW will access it
754 if (Mos_ResourceIsNull(&m_resLaceOrAceOrRgbHistogram))
755 {
756 size = GetResLaceOrAceOrRgbHistogramBufferSize();
757 CODECHAL_ENCODE_CHK_COND_RETURN(size == 0, "Invalid buffer size");
758 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
759 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
760 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
761 allocParamsForBufferLinear.Format = Format_Buffer;
762 allocParamsForBufferLinear.dwBytes = size;
763 allocParamsForBufferLinear.pBufName = "ResLaceOrAceOrRgbHistogram";
764
765 m_osInterface->pfnAllocateResource(
766 m_osInterface,
767 &allocParamsForBufferLinear,
768 &m_resLaceOrAceOrRgbHistogram);
769 }
770
771 params->pOsResLaceOrAceOrRgbHistogram = &m_resLaceOrAceOrRgbHistogram;
772
773 // Allocate Resource to avoid Page Fault issue since HW will access it
774 if (Mos_ResourceIsNull(&m_resStatisticsOutput))
775 {
776 size = GetStatisticsOutputBufferSize();
777 CODECHAL_ENCODE_CHK_COND_RETURN(size == 0, "Invalid buffer size");
778 MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
779 allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
780 allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
781 allocParamsForBufferLinear.Format = Format_Buffer;
782 allocParamsForBufferLinear.dwBytes = size;
783 allocParamsForBufferLinear.pBufName = "ResStatisticsOutput";
784
785 m_osInterface->pfnAllocateResource(
786 m_osInterface,
787 &allocParamsForBufferLinear,
788 &m_resStatisticsOutput);
789 }
790
791 params->pOsResStatisticsOutput = &m_resStatisticsOutput;
792
793 return eStatus;
794 }
795
VeboxSetIecpParams(PMHW_VEBOX_IECP_PARAMS mhwVeboxIecpParams)796 MOS_STATUS CodecHalEncodeSfcBase::VeboxSetIecpParams(
797 PMHW_VEBOX_IECP_PARAMS mhwVeboxIecpParams)
798 {
799 // Calculate matrix if not done so before. CSC is expensive!
800 if ((m_cscInputCspace != m_inputSurfaceColorSpace) ||
801 (m_cscOutputCspace != m_outputSurfaceColorSpace))
802 {
803 float fTemp[3];
804
805 // Get the matrix to use for conversion
806 GetCscMatrix(
807 m_inputSurfaceColorSpace,
808 m_outputSurfaceColorSpace,
809 m_cscCoeff,
810 m_cscInOffset,
811 m_cscOutOffset);
812
813 // Vebox CSC converts RGB input to YUV for SFC
814 // Vebox only supports A8B8G8R8 input, swap the 1st and 3rd
815 // columns of the transfer matrix for A8R8G8B8 and X8R8G8B8
816 // This only happens when SFC output is used
817 if ((m_inputSurface->Format == Format_A8R8G8B8) ||
818 (m_inputSurface->Format == Format_X8R8G8B8))
819 {
820 fTemp[0] = m_cscCoeff[0];
821 fTemp[1] = m_cscCoeff[3];
822 fTemp[2] = m_cscCoeff[6];
823
824 m_cscCoeff[0] = m_cscCoeff[2];
825 m_cscCoeff[3] = m_cscCoeff[5];
826 m_cscCoeff[6] = m_cscCoeff[8];
827
828 m_cscCoeff[2] = fTemp[0];
829 m_cscCoeff[5] = fTemp[1];
830 m_cscCoeff[8] = fTemp[2];
831 }
832 }
833 // Store it for next BLT
834 m_cscInputCspace = m_inputSurfaceColorSpace;
835 m_cscOutputCspace = m_outputSurfaceColorSpace;
836 CODECHAL_ENCODE_VERBOSEMESSAGE("Input color space: %d, output color space: %d",
837 m_cscInputCspace, m_cscOutputCspace);
838
839 // copy into MHW parameters
840
841 mhwVeboxIecpParams->ColorSpace = m_inputSurfaceColorSpace;
842 mhwVeboxIecpParams->dstFormat = m_sfcOutputSurface->Format;
843 mhwVeboxIecpParams->srcFormat = m_inputSurface->Format;
844 mhwVeboxIecpParams->bCSCEnable = m_veboxCsc;
845 mhwVeboxIecpParams->pfCscCoeff = m_cscCoeff;
846 mhwVeboxIecpParams->pfCscInOffset = m_cscInOffset;
847 mhwVeboxIecpParams->pfCscOutOffset = m_cscOutOffset;
848 //mhwVeboxIecpParams->bAlphaEnable = m_alphaEnable; ??
849 //mhwVeboxIecpParams->wAlphaValue = m_alphaValue;
850
851 return MOS_STATUS_SUCCESS;
852 }
853
854 #if (_DEBUG || _RELEASE_INTERNAL)
DumpBuffers(CodechalDebugInterface * debugInterface)855 MOS_STATUS CodecHalEncodeSfcBase::DumpBuffers(CodechalDebugInterface* debugInterface)
856 {
857 CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
858 &m_resAvsLineBuffer,
859 CodechalDbgAttr::attrSfcBuffers,
860 "AvsLine",
861 GetAvsLineBufferSize()));
862
863 CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
864 &m_resLaceOrAceOrRgbHistogram,
865 CodechalDbgAttr::attrSfcBuffers,
866 "LaceOrAceOrRgbHistogram",
867 GetResLaceOrAceOrRgbHistogramBufferSize()));
868
869 CODECHAL_ENCODE_CHK_STATUS_RETURN(debugInterface->DumpBuffer(
870 &m_resStatisticsOutput,
871 CodechalDbgAttr::attrSfcBuffers,
872 "StatisticsOutput",
873 GetStatisticsOutputBufferSize()));
874
875 return MOS_STATUS_SUCCESS;
876 }
877 #endif
878
SetSfcStateParams(PMHW_SFC_INTERFACE sfcInterface,PMHW_SFC_STATE_PARAMS params,PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams)879 MOS_STATUS CodecHalEncodeSfcBase::SetSfcStateParams(
880 PMHW_SFC_INTERFACE sfcInterface,
881 PMHW_SFC_STATE_PARAMS params,
882 PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams)
883 {
884 uint16_t widthAlignUnit;
885 uint16_t heightAlignUnit;
886 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
887
888 CODECHAL_ENCODE_FUNCTION_ENTER;
889
890 CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface);
891 CODECHAL_ENCODE_CHK_NULL_RETURN(m_inputSurface);
892 CODECHAL_ENCODE_CHK_NULL_RETURN(m_sfcOutputSurface);
893 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
894
895 params->sfcPipeMode = MEDIASTATE_SFC_PIPE_VE_TO_SFC;
896 params->dwAVSFilterMode = MEDIASTATE_SFC_AVS_FILTER_8x8;
897 params->dwVDVEInputOrderingMode = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x8;
898
899 params->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
900
901 // Adjust SFC input surface alignment.
902 // As VEBOX doesn't do scaling, input size equals to output size
903 // For the VEBOX output to SFC, width is multiple of 16 and height is multiple of 4
904 widthAlignUnit = sfcInterface->m_veWidthAlignment;
905 heightAlignUnit = sfcInterface->m_veHeightAlignment;
906
907 // Width and height must be set using SPS params instead of real surface size
908 if (m_inputSurface->dwWidth < m_inputSurfaceRegion.Width ||
909 m_inputSurface->dwHeight < m_inputSurfaceRegion.Height)
910 {
911 CODECHAL_ENCODE_ASSERTMESSAGE("width and height must be less than or equal to surface size");
912 return MOS_STATUS_INVALID_PARAMETER;
913 }
914 params->dwInputFrameWidth = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Width, widthAlignUnit);
915 params->dwInputFrameHeight = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Height, heightAlignUnit);
916
917 params->dwChromaDownSamplingMode = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO420;
918 params->bAVSChromaUpsamplingEnable = m_scaling;
919
920 if ((params->fAVSXScalingRatio > 1.0F) || (params->fAVSYScalingRatio > 1.0F))
921 {
922 params->bBypassXAdaptiveFilter = false;
923 params->bBypassYAdaptiveFilter = false;
924 }
925 else
926 {
927 params->bBypassXAdaptiveFilter = true;
928 params->bBypassYAdaptiveFilter = true;
929 }
930
931 params->fChromaSubSamplingXSiteOffset = 0.0F;
932 params->fChromaSubSamplingYSiteOffset = 0.0F;
933
934 widthAlignUnit = 1;
935 heightAlignUnit = 1;
936
937 switch(m_sfcOutputSurface->Format)
938 {
939 case Format_NV12:
940 case Format_P010:
941 widthAlignUnit = 2;
942 heightAlignUnit = 2;
943 break;
944 case Format_YUY2:
945 case Format_UYVY:
946 widthAlignUnit = 2;
947 break;
948 default:
949 break;
950 }
951
952 // Default to Horizontal Left, Vertical Top
953 params->dwChromaDownSamplingHorizontalCoef = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ?
954 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
955 ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ?
956 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 :
957 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8);
958
959 params->dwChromaDownSamplingVerticalCoef = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ?
960 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
961 ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ?
962 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 :
963 MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8);
964
965 outSurfaceParams->dwWidth = m_sfcOutputSurface->dwWidth;
966 outSurfaceParams->dwHeight = m_sfcOutputSurface->dwHeight;
967 outSurfaceParams->dwPitch = m_sfcOutputSurface->dwPitch;
968 outSurfaceParams->TileType = m_sfcOutputSurface->TileType;
969 outSurfaceParams->TileModeGMM = m_sfcOutputSurface->TileModeGMM;
970 outSurfaceParams->bGMMTileEnabled = m_sfcOutputSurface->bGMMTileEnabled;
971 outSurfaceParams->ChromaSiting = m_chromaSiting;
972 outSurfaceParams->dwUYoffset = m_sfcOutputSurface->UPlaneOffset.iYOffset;
973
974 params->dwOutputFrameWidth = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwWidth, widthAlignUnit);
975 params->dwOutputFrameHeight = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwHeight, heightAlignUnit);
976 params->OutputFrameFormat = m_sfcOutputSurface->Format;
977 params->dwOutputSurfaceOffset = m_sfcOutputSurface->dwOffset;
978 params->pOsResOutputSurface = &m_sfcOutputSurface->OsResource;
979 params->pOsResAVSLineBuffer = &m_resAvsLineBuffer;
980
981 params->dwSourceRegionHeight = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Height, heightAlignUnit);
982 params->dwSourceRegionWidth = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Width, widthAlignUnit);
983 params->dwSourceRegionVerticalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Y, heightAlignUnit);
984 params->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.X, widthAlignUnit);
985 params->dwScaledRegionHeight = MOS_UF_ROUND(m_scaleY * params->dwSourceRegionHeight);
986 params->dwScaledRegionWidth = MOS_UF_ROUND(m_scaleX * params->dwSourceRegionWidth);
987 params->dwScaledRegionVerticalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.Y, heightAlignUnit);
988 params->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.X, widthAlignUnit);
989 params->fAVSXScalingRatio = m_scaleX;
990 params->fAVSYScalingRatio = m_scaleY;
991
992 params->fAlphaPixel = 1.0F;
993 params->bColorFillEnable = m_colorFill;
994 params->bCSCEnable = m_CSC;
995
996 // ARGB8,ABGR10,A16B16G16R16,VYUY and YVYU output format need to enable swap
997 if (m_sfcOutputSurface->Format == Format_X8R8G8B8 ||
998 m_sfcOutputSurface->Format == Format_A8R8G8B8 ||
999 m_sfcOutputSurface->Format == Format_R10G10B10A2 ||
1000 m_sfcOutputSurface->Format == Format_A16B16G16R16 ||
1001 m_sfcOutputSurface->Format == Format_VYUY ||
1002 m_sfcOutputSurface->Format == Format_YVYU)
1003 {
1004 params->bRGBASwapEnable = true;
1005 }
1006 else
1007 {
1008 params->bRGBASwapEnable = false;
1009 }
1010
1011
1012 // CodecHal does not support SFC rotation
1013 params->RotationMode = MHW_ROTATION_IDENTITY;
1014
1015 // For downsampling, expect output surface to be MMC disabled
1016 // For Jpeg, the only usage is CSC and the output surface format is RGB8, so also disable MMC
1017 params->bMMCEnable = false;
1018 params->MMCMode = MOS_MMC_DISABLED;
1019
1020 return eStatus;
1021 }
1022
SetSfcAvsStateParams(PMHW_SFC_INTERFACE sfcInterface)1023 MOS_STATUS CodecHalEncodeSfcBase::SetSfcAvsStateParams(
1024 PMHW_SFC_INTERFACE sfcInterface)
1025 {
1026 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1027 PMHW_SFC_AVS_STATE mhwSfcAvsState;
1028
1029 CODECHAL_ENCODE_FUNCTION_ENTER;
1030
1031 CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface);
1032 CODECHAL_ENCODE_CHK_NULL_RETURN(m_inputSurface);
1033
1034 mhwSfcAvsState = &m_avsState;
1035
1036 if (m_chromaSiting == MHW_CHROMA_SITING_NONE)
1037 {
1038 m_chromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER;
1039 }
1040
1041 mhwSfcAvsState->dwInputHorizontalSiting = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 :
1042 ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 :
1043 SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
1044
1045 mhwSfcAvsState->dwInputVerticalSitting = (m_chromaSiting & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 :
1046 ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 :
1047 SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
1048
1049 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->SetSfcSamplerTable(
1050 &m_lumaTable,
1051 &m_chromaTable,
1052 &m_avsParams,
1053 m_inputSurface->Format,
1054 m_scaleX,
1055 m_scaleY,
1056 m_chromaSiting,
1057 true,
1058 0,
1059 0));
1060 return eStatus;
1061 }
1062
SetSfcIefStateParams(PMHW_SFC_IEF_STATE_PARAMS params)1063 MOS_STATUS CodecHalEncodeSfcBase::SetSfcIefStateParams(
1064 PMHW_SFC_IEF_STATE_PARAMS params)
1065 {
1066 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1067
1068 CODECHAL_ENCODE_FUNCTION_ENTER;
1069
1070 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1071
1072 params->bIEFEnable = false;
1073 params->bCSCEnable = true;
1074
1075 params->pfCscCoeff = m_cscCoeff;
1076 params->pfCscInOffset = m_cscInOffset;
1077 params->pfCscOutOffset = m_cscOutOffset;
1078
1079 return eStatus;
1080 }
1081
Initialize(CodechalHwInterface * hwInterface,PMOS_INTERFACE osInterface)1082 MOS_STATUS CodecHalEncodeSfcBase::Initialize(
1083 CodechalHwInterface *hwInterface,
1084 PMOS_INTERFACE osInterface)
1085 {
1086
1087 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1088
1089 CODECHAL_ENCODE_FUNCTION_ENTER;
1090
1091 CODECHAL_ENCODE_CHK_NULL_RETURN(hwInterface);
1092 CODECHAL_ENCODE_CHK_NULL_RETURN(hwInterface->GetVeboxInterface());
1093 CODECHAL_ENCODE_CHK_NULL_RETURN(osInterface);
1094
1095 m_hwInterface = hwInterface;
1096 m_osInterface = osInterface;
1097
1098 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetVeboxInterface()->CreateHeap());
1099
1100 // Create VEBOX Context
1101 MOS_GPUCTX_CREATOPTIONS createOption;
1102 //
1103 // VeboxgpuContext could be created from both VP and Codec.
1104 // If there is no such as a GPU context it will create a new one and set the GPU component ID.
1105 // If there has been a valid GPU context it will not create another one anymore and the component ID will not be updated either.
1106 // Therefore if a codec veboxgpu context creation happens earlier than a vp veboxgpu context creation and set its component ID to MOS_GPU_COMPONENT_ENCODE,
1107 // VPBLT callstack would index a GpuAppTaskEvent of MOS_GPU_COMPONENT_ENCODE.
1108 //
1109 MOS_COMPONENT originalComponent = m_osInterface->Component;
1110 m_osInterface->Component = COMPONENT_VPCommon;
1111
1112 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
1113 m_osInterface,
1114 MOS_GPU_CONTEXT_VEBOX,
1115 MOS_GPU_NODE_VE,
1116 &createOption));
1117
1118 m_osInterface->Component = originalComponent;
1119
1120 // Register Vebox GPU context with the Batch Buffer completion event
1121 // Ignore if creation fails
1122 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
1123 m_osInterface,
1124 MOS_GPU_CONTEXT_VEBOX));
1125
1126 return eStatus;
1127 }
1128
SetParams(CODECHAL_ENCODE_SFC_PARAMS * params)1129 MOS_STATUS CodecHalEncodeSfcBase::SetParams(
1130 CODECHAL_ENCODE_SFC_PARAMS* params)
1131 {
1132 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1133
1134 CODECHAL_ENCODE_FUNCTION_ENTER;
1135
1136 CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1137 CODECHAL_ENCODE_CHK_NULL_RETURN(params->pInputSurface);
1138 CODECHAL_ENCODE_CHK_NULL_RETURN(params->pOutputSurface);
1139
1140 m_inputSurface = params->pInputSurface;
1141 // Vebox o/p should not be written to memory for SFC, VeboxOutputSurface should be nullptr
1142 m_veboxOutputSurface = nullptr;
1143 m_sfcOutputSurface = params->pOutputSurface;
1144
1145 // no scaling.
1146 m_scaling = false;
1147 m_colorFill = false;
1148
1149 // No CSC for SFC pipe
1150 m_veboxCsc = true;
1151
1152 m_scaleX = 1.0;
1153 m_scaleY = 1.0;
1154 m_chromaSiting = params->uiChromaSitingType;
1155
1156 eStatus = MOS_SecureMemcpy(&m_inputSurfaceRegion,
1157 sizeof(m_inputSurfaceRegion),
1158 ¶ms->rcInputSurfaceRegion,
1159 sizeof(params->rcInputSurfaceRegion));
1160
1161 eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion,
1162 sizeof(m_outputSurfaceRegion),
1163 ¶ms->rcOutputSurfaceRegion,
1164 sizeof(params->rcOutputSurfaceRegion));
1165
1166 CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources());
1167
1168 return eStatus;
1169 }
1170
AddSfcCommands(PMHW_SFC_INTERFACE sfcInterface,PMOS_COMMAND_BUFFER cmdBuffer)1171 MOS_STATUS CodecHalEncodeSfcBase::AddSfcCommands(
1172 PMHW_SFC_INTERFACE sfcInterface,
1173 PMOS_COMMAND_BUFFER cmdBuffer)
1174 {
1175 MHW_SFC_LOCK_PARAMS sfcLockParams;
1176 MHW_SFC_STATE_PARAMS sfcStateParams;
1177 MHW_SFC_OUT_SURFACE_PARAMS sfcOutSurfaceParams;
1178 MHW_SFC_IEF_STATE_PARAMS sfcIefStateParams;
1179 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1180
1181 CODECHAL_ENCODE_FUNCTION_ENTER;
1182
1183 CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface);
1184 CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1185
1186 MOS_ZeroMemory(&sfcLockParams, sizeof(sfcLockParams));
1187
1188 sfcLockParams.sfcPipeMode = MhwSfcInterface::SFC_PIPE_MODE_VEBOX;
1189 sfcLockParams.bOutputToMemory = false;
1190
1191 MOS_ZeroMemory(&sfcStateParams, sizeof(sfcStateParams));
1192 MOS_ZeroMemory(&sfcOutSurfaceParams, sizeof(sfcOutSurfaceParams));
1193 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcStateParams(sfcInterface, &sfcStateParams, &sfcOutSurfaceParams));
1194
1195 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcLock(cmdBuffer, &sfcLockParams));
1196 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcState(cmdBuffer, &sfcStateParams, &sfcOutSurfaceParams));
1197
1198 if (m_scaling)
1199 {
1200 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcAvsStateParams(sfcInterface));
1201 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsState(cmdBuffer, &m_avsState));
1202 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsLumaTable(cmdBuffer, &m_lumaTable));
1203 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsChromaTable(cmdBuffer, &m_chromaTable));
1204 }
1205
1206 if (m_CSC)
1207 {
1208 MOS_ZeroMemory(&sfcIefStateParams, sizeof(sfcIefStateParams));
1209 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcIefStateParams(&sfcIefStateParams));
1210 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcIefState(cmdBuffer, &sfcIefStateParams));
1211 }
1212
1213 CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcFrameStart(cmdBuffer, MhwSfcInterface::SFC_PIPE_MODE_VEBOX));
1214
1215 return eStatus;
1216 }
1217
RenderStart(CodechalEncoderState * encoder)1218 MOS_STATUS CodecHalEncodeSfcBase::RenderStart(
1219 CodechalEncoderState* encoder)
1220 {
1221 MHW_VEBOX_STATE_CMD_PARAMS veboxStateCmdParams;
1222 MHW_VEBOX_SURFACE_STATE_CMD_PARAMS veboxSurfaceStateCmdParams;
1223 MHW_VEBOX_DI_IECP_CMD_PARAMS veboxDiIecpCmdParams;
1224 MHW_VEBOX_IECP_PARAMS veboxIecpParams;
1225 MHW_VEBOX_SURFACE_CNTL_PARAMS veboxSurfCntlParams;
1226 MhwVeboxInterface *veboxInterface;
1227 PMHW_SFC_INTERFACE sfcInterface;
1228 MhwMiInterface *miInterface;
1229 PMOS_CONTEXT pOsContext = nullptr;
1230 MHW_MI_MMIOREGISTERS *mmioVeboxRegisters = nullptr;
1231 MOS_COMMAND_BUFFER cmdBuffer;
1232 bool requestFrameTracking;
1233 MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
1234
1235 CODECHAL_ENCODE_FUNCTION_ENTER;
1236
1237 CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface);
1238 CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
1239 CODECHAL_ENCODE_CHK_NULL_RETURN(pOsContext = m_osInterface->pOsContext);
1240 CODECHAL_ENCODE_CHK_NULL_RETURN(encoder);
1241 CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface = m_hwInterface->GetSfcInterface());
1242 CODECHAL_ENCODE_CHK_NULL_RETURN(veboxInterface = m_hwInterface->GetVeboxInterface());
1243 CODECHAL_ENCODE_CHK_NULL_RETURN(miInterface = m_hwInterface->GetMiInterface());
1244 CODECHAL_ENCODE_CHK_NULL_RETURN(mmioVeboxRegisters = miInterface->GetMmioRegisters());
1245
1246 // Switch GPU context to VEBOX
1247 m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX);
1248 // Reset allocation list and house keeping
1249 m_osInterface->pfnResetOsStates(m_osInterface);
1250
1251 // Send command buffer header at the beginning
1252 MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
1253 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
1254
1255 // the first task?
1256 requestFrameTracking = false;
1257 CODECHAL_ENCODE_CHK_STATUS_RETURN(encoder->SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking, mmioVeboxRegisters));
1258
1259 // If m_pollingSyncEnabled is set, insert HW semaphore to wait for external
1260 // raw surface processing to complete, before start CSC. Once the marker in
1261 // raw surface is overwritten by external operation, HW semaphore will be
1262 // signalled and CSC will start. This is to reduce SW latency between
1263 // external raw surface processing and CSC, in usages like remote gaming.
1264 if (encoder->m_pollingSyncEnabled)
1265 {
1266 MHW_MI_SEMAPHORE_WAIT_PARAMS miSemaphoreWaitParams;
1267 MOS_ZeroMemory((&miSemaphoreWaitParams), sizeof(miSemaphoreWaitParams));
1268 miSemaphoreWaitParams.presSemaphoreMem = &m_inputSurface->OsResource;
1269 miSemaphoreWaitParams.dwResourceOffset = encoder->m_syncMarkerOffset;
1270 miSemaphoreWaitParams.bPollingWaitMode = true;
1271 miSemaphoreWaitParams.dwSemaphoreData = encoder->m_syncMarkerValue;
1272 miSemaphoreWaitParams.CompareOperation = MHW_MI_SAD_NOT_EQUAL_SDD;
1273 CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiSemaphoreWaitCmd(&cmdBuffer, &miSemaphoreWaitParams));
1274 }
1275
1276 // Setup cmd prameters
1277 MOS_ZeroMemory(&veboxStateCmdParams, sizeof(veboxStateCmdParams));
1278 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxStateParams(&veboxStateCmdParams));
1279
1280 MOS_ZeroMemory(&veboxSurfaceStateCmdParams, sizeof(veboxSurfaceStateCmdParams));
1281 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxSurfaceStateParams(&veboxSurfaceStateCmdParams));
1282
1283 MOS_ZeroMemory(&veboxDiIecpCmdParams, sizeof(veboxDiIecpCmdParams));
1284 CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxDiIecpParams(&veboxDiIecpCmdParams));
1285
1286 MOS_ZeroMemory(&veboxSurfCntlParams, sizeof(veboxSurfCntlParams));
1287 veboxSurfCntlParams.bIsCompressed = m_inputSurface->bIsCompressed;
1288 veboxSurfCntlParams.CompressionMode = m_inputSurface->CompressionMode;
1289 CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaceControlBits(
1290 &veboxSurfCntlParams,
1291 (uint32_t *)&(veboxDiIecpCmdParams.CurrInputSurfCtrl.Value)));
1292
1293 // get csc matrix
1294 MOS_ZeroMemory(&veboxIecpParams, sizeof(veboxIecpParams));
1295 CODECHAL_ENCODE_CHK_STATUS_RETURN(VeboxSetIecpParams(&veboxIecpParams));
1296
1297 // send matrix into heap
1298 CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxIecpState(
1299 &veboxIecpParams));
1300
1301 // send Vebox and SFC cmds
1302 CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxState(&cmdBuffer, &veboxStateCmdParams, 0));
1303
1304 CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaces( &cmdBuffer, &veboxSurfaceStateCmdParams));
1305
1306 CODECHAL_ENCODE_CHK_STATUS_RETURN(AddSfcCommands(sfcInterface, &cmdBuffer));
1307
1308 HalOcaInterface::TraceMessage(cmdBuffer, (MOS_CONTEXT_HANDLE)pOsContext, __FUNCTION__, sizeof(__FUNCTION__));
1309 HalOcaInterface::OnDispatch(cmdBuffer, *m_osInterface, *miInterface, *mmioVeboxRegisters);
1310
1311 CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxDiIecp(&cmdBuffer, &veboxDiIecpCmdParams));
1312
1313 // If m_pollingSyncEnabled is set, write the marker to source surface for next MI_SEMAPHORE_WAIT to check.
1314 if (encoder->m_pollingSyncEnabled)
1315 {
1316 MHW_MI_STORE_DATA_PARAMS storeDataParams;
1317 storeDataParams.pOsResource = &m_inputSurface->OsResource;
1318 storeDataParams.dwResourceOffset = encoder->m_syncMarkerOffset;
1319 storeDataParams.dwValue = encoder->m_syncMarkerValue;
1320 CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams));
1321 }
1322
1323 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd(
1324 &cmdBuffer,
1325 nullptr));
1326
1327 CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(encoder->GetDebugInterface()->DumpCmdBuffer(
1328 &cmdBuffer,
1329 CODECHAL_MEDIA_STATE_CSC_DS_COPY,
1330 nullptr)));
1331
1332 m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1333 HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface);
1334
1335 CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
1336 m_osInterface,
1337 &cmdBuffer,
1338 encoder->m_videoContextUsesNullHw));
1339 return eStatus;
1340 }
1341