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         &params->rcInputSurfaceRegion,
1159         sizeof(params->rcInputSurfaceRegion));
1160 
1161     eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion,
1162         sizeof(m_outputSurfaceRegion),
1163         &params->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