1 /*
2 * Copyright (c) 2014-2019, 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.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.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 
~CodecHalEncodeSfc()92 CodecHalEncodeSfc::~CodecHalEncodeSfc()
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 CodecHalEncodeSfc::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 CodecHalEncodeSfc::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 CodecHalEncodeSfc::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 CodecHalEncodeSfc::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 CodecHalEncodeSfc::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 CodecHalEncodeSfc::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 CodecHalEncodeSfc::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 
AllocateResources()505 MOS_STATUS CodecHalEncodeSfc::AllocateResources()
506 {
507     MOS_ALLOC_GFXRES_PARAMS    allocParamsForBufferLinear;
508     uint32_t                   ycoeffTableSize;
509     uint32_t                   uvcoeffTableSize;
510     int32_t                    size;
511     char*                      ptr;
512     MOS_STATUS                 eStatus = MOS_STATUS_SUCCESS;
513 
514     CODECHAL_ENCODE_FUNCTION_ENTER;
515 
516     CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
517 
518     // Allocate AVS line buffer
519     if (Mos_ResourceIsNull(&m_resAvsLineBuffer))
520     {
521         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
522         allocParamsForBufferLinear.Type     = MOS_GFXRES_BUFFER;
523         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
524         allocParamsForBufferLinear.Format   = Format_Buffer;
525         allocParamsForBufferLinear.dwBytes = MOS_ROUNDUP_DIVIDE(m_inputSurface->dwHeight, 8) * 5 * MHW_SFC_CACHELINE_SIZE;
526 
527         allocParamsForBufferLinear.pBufName = "SfcAvsLineBuffer";
528 
529         CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnAllocateResource(
530             m_osInterface,
531             &allocParamsForBufferLinear,
532             &m_resAvsLineBuffer));
533     }
534 
535     //Initialize AVS parameters, try to do once
536     if (m_scaling && !m_avsParams.piYCoefsX)
537     {
538         m_avsParams.Format    = Format_None;
539         m_avsParams.fScaleX   = 0.0F;
540         m_avsParams.fScaleY   = 0.0F;
541         m_avsParams.piYCoefsX = nullptr;
542 
543         ycoeffTableSize  = POLYPHASE_Y_COEFFICIENT_TABLE_SIZE_G9;
544         uvcoeffTableSize = POLYPHASE_UV_COEFFICIENT_TABLE_SIZE_G9;
545 
546         size = (ycoeffTableSize + uvcoeffTableSize) * 2;
547 
548         ptr = (char*)MOS_AllocAndZeroMemory(size);
549         CODECHAL_ENCODE_CHK_NULL_RETURN(ptr);
550 
551         m_avsParams.piYCoefsX  = (int32_t*)ptr;
552 
553         ptr += ycoeffTableSize;
554         m_avsParams.piUVCoefsX = (int32_t*)ptr;
555 
556         ptr += uvcoeffTableSize;
557         m_avsParams.piYCoefsY  = (int32_t*)ptr;
558 
559         ptr += ycoeffTableSize;
560         m_avsParams.piUVCoefsY = (int32_t*)ptr;
561     }
562 
563     return eStatus;
564 }
565 
FreeResources()566 MOS_STATUS CodecHalEncodeSfc::FreeResources()
567 {
568     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
569 
570     CODECHAL_ENCODE_FUNCTION_ENTER;
571 
572     CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
573 
574     // Free AVS Line Buffer
575     m_osInterface->pfnFreeResource(m_osInterface, &m_resAvsLineBuffer);
576 
577     // Free resLaceOrAceOrRgbHistogram
578     m_osInterface->pfnFreeResource(m_osInterface, &m_resLaceOrAceOrRgbHistogram);
579 
580     // Free resStatisticsOutput
581     m_osInterface->pfnFreeResource(m_osInterface, &m_resStatisticsOutput);
582 
583     // Free buffers in AVS parameters
584     MOS_FreeMemory(m_avsParams.piYCoefsX);
585     m_avsParams.piYCoefsX = nullptr;
586 
587     return eStatus;
588 }
589 
SetVeboxStateParams(PMHW_VEBOX_STATE_CMD_PARAMS params)590 MOS_STATUS CodecHalEncodeSfc::SetVeboxStateParams(
591     PMHW_VEBOX_STATE_CMD_PARAMS         params)
592 {
593     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
594 
595     CODECHAL_ENCODE_FUNCTION_ENTER;
596 
597     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
598 
599     params->bNoUseVeboxHeap                         = 0;
600 
601     params->VeboxMode.ColorGamutExpansionEnable     = 0;
602     params->VeboxMode.ColorGamutCompressionEnable   = 0;
603     // On SKL, GlobalIECP must be enabled when the output pipe is Vebox or SFC
604     params->VeboxMode.GlobalIECPEnable              = 1;
605     params->VeboxMode.DNEnable                      = 0;
606     params->VeboxMode.DIEnable                      = 0;
607     params->VeboxMode.DNDIFirstFrame                = 0;
608     params->VeboxMode.DIOutputFrames                = 0;
609     params->VeboxMode.PipeSynchronizeDisable        = 0;
610     params->VeboxMode.DemosaicEnable                = 0;
611     params->VeboxMode.VignetteEnable                = 0;
612     params->VeboxMode.AlphaPlaneEnable              = 0;
613     params->VeboxMode.HotPixelFilteringEnable       = 0;
614     // 0-both slices enabled   1-Slice 0 enabled   2-Slice 1 enabled
615     // On SKL GT3 and GT4, there are 2 Veboxes. But only Vebox0 can be used,Vebox1 cannot be used
616     params->VeboxMode.SingleSliceVeboxEnable        = 1;
617     params->VeboxMode.LACECorrectionEnable          = 0;
618     params->VeboxMode.DisableEncoderStatistics      = 1;
619     params->VeboxMode.DisableTemporalDenoiseFilter  = 1;
620     params->VeboxMode.SinglePipeIECPEnable          = 0;
621     params->VeboxMode.SFCParallelWriteEnable        = 0;
622     params->VeboxMode.ScalarMode                    = 0;
623     params->VeboxMode.ForwardGammaCorrectionEnable  = 0;
624 
625     return eStatus;
626 }
627 
SetVeboxSurfaceStateParams(PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS params)628 MOS_STATUS CodecHalEncodeSfc::SetVeboxSurfaceStateParams(
629     PMHW_VEBOX_SURFACE_STATE_CMD_PARAMS         params)
630 {
631     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
632 
633     CODECHAL_ENCODE_FUNCTION_ENTER;
634 
635     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
636 
637     // Initialize SurfInput
638     params->SurfInput.bActive                = true;
639     params->SurfInput.Format                 = m_inputSurface->Format;
640     params->SurfInput.dwWidth                = m_inputSurface->dwWidth;
641     params->SurfInput.dwHeight               = m_inputSurface->dwHeight;
642     params->SurfInput.dwPitch                = m_inputSurface->dwPitch;
643     params->SurfInput.TileType               = m_inputSurface->TileType;
644     params->SurfInput.TileModeGMM            = m_inputSurface->TileModeGMM;
645     params->SurfInput.bGMMTileEnabled        = m_inputSurface->bGMMTileEnabled;
646     params->SurfInput.dwYoffset              = m_inputSurface->YPlaneOffset.iYOffset;
647     params->SurfInput.pOsResource            = &m_inputSurface->OsResource;
648     params->SurfInput.rcMaxSrc.left          = m_inputSurfaceRegion.X;
649     params->SurfInput.rcMaxSrc.top           = m_inputSurfaceRegion.Y;
650     params->SurfInput.rcMaxSrc.right         = m_inputSurfaceRegion.X + m_inputSurfaceRegion.Width;
651     params->SurfInput.rcMaxSrc.bottom        = m_inputSurfaceRegion.Y + m_inputSurfaceRegion.Height;
652 
653     // Initialize SurfSTMM
654     params->SurfSTMM.dwPitch                 = m_inputSurface->dwPitch;
655 
656     params->bDIEnable                        = false;
657     params->bOutputValid                     = (m_veboxOutputSurface != nullptr) ? true : false;
658 
659     return eStatus;
660 }
661 
SetVeboxDiIecpParams(PMHW_VEBOX_DI_IECP_CMD_PARAMS params)662 MOS_STATUS CodecHalEncodeSfc::SetVeboxDiIecpParams(
663     PMHW_VEBOX_DI_IECP_CMD_PARAMS         params)
664 {
665     uint32_t                    width;
666     uint32_t                    height;
667     MOS_ALLOC_GFXRES_PARAMS     allocParamsForBufferLinear;
668     uint32_t                    size = 0, sizeLace = 0, sizeNoLace = 0;
669     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
670     MOS_MEMCOMP_STATE           mmcMode = MOS_MEMCOMP_DISABLED;
671 
672     CODECHAL_ENCODE_FUNCTION_ENTER;
673 
674     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
675 
676     height = m_inputSurface->dwHeight;
677     width  = m_inputSurface->dwWidth;
678 
679     params->dwStartingX             = 0;
680     params->dwEndingX               = width - 1;
681     params->dwCurrInputSurfOffset   = m_inputSurface->dwOffset;
682     params->pOsResCurrInput         = &m_inputSurface->OsResource;
683     params->CurrInputSurfCtrl.Value = 0;  //Keep it here untill VPHAL moving to new CMD definition and remove this parameter definition.
684 
685     CodecHalGetResourceInfo(
686         m_osInterface,
687         m_inputSurface);
688 
689     m_osInterface->pfnGetMemoryCompressionMode(m_osInterface, &m_inputSurface->OsResource, &mmcMode);
690     if (mmcMode &&
691         (m_inputSurface->TileType == MOS_TILE_Y ||
692          m_inputSurface->TileType == MOS_TILE_YS))
693     {
694         m_inputSurface->bCompressible = true;
695         m_inputSurface->CompressionMode = (MOS_RESOURCE_MMC_MODE)mmcMode;
696     }
697     else
698     {
699         m_inputSurface->CompressionMode = MOS_MMC_DISABLED;
700     }
701 
702     params->CurInputSurfMMCState = (MOS_MEMCOMP_STATE)(m_inputSurface->CompressionMode);
703 
704     // Allocate Resource to avoid Page Fault issue since HW will access it
705     if (Mos_ResourceIsNull(&m_resLaceOrAceOrRgbHistogram))
706     {
707         size = CODECHAL_SFC_VEBOX_RGB_HISTOGRAM_SIZE;
708 
709         sizeLace = MOS_ROUNDUP_DIVIDE(height, 64) *
710             MOS_ROUNDUP_DIVIDE(width, 64)  *
711             CODECHAL_SFC_VEBOX_LACE_HISTOGRAM_256_BIN_PER_BLOCK;
712 
713         sizeNoLace = CODECHAL_SFC_VEBOX_ACE_HISTOGRAM_SIZE_PER_FRAME_PER_SLICE *
714             CODECHAL_SFC_NUM_FRAME_PREVIOUS_CURRENT                   *
715             CODECHAL_SFC_VEBOX_MAX_SLICES;
716 
717         size += MOS_MAX(sizeLace, sizeNoLace);
718 
719         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
720         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
721         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
722         allocParamsForBufferLinear.Format = Format_Buffer;
723         allocParamsForBufferLinear.dwBytes = size;
724         allocParamsForBufferLinear.pBufName = "ResLaceOrAceOrRgbHistogram";
725 
726         m_osInterface->pfnAllocateResource(
727             m_osInterface,
728             &allocParamsForBufferLinear,
729             &m_resLaceOrAceOrRgbHistogram);
730     }
731 
732     params->pOsResLaceOrAceOrRgbHistogram = &m_resLaceOrAceOrRgbHistogram;
733 
734     // Allocate Resource to avoid Page Fault issue since HW will access it
735     if (Mos_ResourceIsNull(&m_resStatisticsOutput))
736     {
737         width = MOS_ALIGN_CEIL(width, 64);
738         height = MOS_ROUNDUP_DIVIDE(height, 4) + MOS_ROUNDUP_DIVIDE(CODECHAL_SFC_VEBOX_STATISTICS_SIZE * sizeof(uint32_t), width);
739         size = width * height;
740 
741         MOS_ZeroMemory(&allocParamsForBufferLinear, sizeof(MOS_ALLOC_GFXRES_PARAMS));
742         allocParamsForBufferLinear.Type = MOS_GFXRES_BUFFER;
743         allocParamsForBufferLinear.TileType = MOS_TILE_LINEAR;
744         allocParamsForBufferLinear.Format = Format_Buffer;
745         allocParamsForBufferLinear.dwBytes = size;
746         allocParamsForBufferLinear.pBufName = "ResStatisticsOutput";
747 
748         m_osInterface->pfnAllocateResource(
749             m_osInterface,
750             &allocParamsForBufferLinear,
751             &m_resStatisticsOutput);
752     }
753 
754     params->pOsResStatisticsOutput = &m_resStatisticsOutput;
755 
756     return eStatus;
757 }
758 
VeboxSetIecpParams(PMHW_VEBOX_IECP_PARAMS mhwVeboxIecpParams)759 MOS_STATUS CodecHalEncodeSfc::VeboxSetIecpParams(
760     PMHW_VEBOX_IECP_PARAMS         mhwVeboxIecpParams)
761 {
762     // Calculate matrix if not done so before. CSC is expensive!
763     if ((m_cscInputCspace != m_inputSurfaceColorSpace) ||
764         (m_cscOutputCspace != m_outputSurfaceColorSpace))
765     {
766         float       fTemp[3];
767 
768         // Get the matrix to use for conversion
769         GetCscMatrix(
770             m_inputSurfaceColorSpace,
771             m_outputSurfaceColorSpace,
772             m_cscCoeff,
773             m_cscInOffset,
774             m_cscOutOffset);
775 
776         // Vebox CSC converts RGB input to YUV for SFC
777         // Vebox only supports A8B8G8R8 input, swap the 1st and 3rd
778         // columns of the transfer matrix for A8R8G8B8 and X8R8G8B8
779         // This only happens when SFC output is used
780         if ((m_inputSurface->Format == Format_A8R8G8B8) ||
781             (m_inputSurface->Format == Format_X8R8G8B8))
782         {
783             fTemp[0] = m_cscCoeff[0];
784             fTemp[1] = m_cscCoeff[3];
785             fTemp[2] = m_cscCoeff[6];
786 
787             m_cscCoeff[0] = m_cscCoeff[2];
788             m_cscCoeff[3] = m_cscCoeff[5];
789             m_cscCoeff[6] = m_cscCoeff[8];
790 
791             m_cscCoeff[2] = fTemp[0];
792             m_cscCoeff[5] = fTemp[1];
793             m_cscCoeff[8] = fTemp[2];
794         }
795     }
796     // Store it for next BLT
797     m_cscInputCspace   = m_inputSurfaceColorSpace;
798     m_cscOutputCspace  = m_outputSurfaceColorSpace;
799     CODECHAL_ENCODE_VERBOSEMESSAGE("Input color space: %d, output color space: %d",
800                                         m_cscInputCspace, m_cscOutputCspace);
801 
802     // copy into MHW parameters
803 
804     mhwVeboxIecpParams->ColorSpace          = m_inputSurfaceColorSpace;
805     mhwVeboxIecpParams->dstFormat           = m_sfcOutputSurface->Format;
806     mhwVeboxIecpParams->srcFormat           = m_inputSurface->Format;
807     mhwVeboxIecpParams->bCSCEnable          = m_veboxCsc;
808     mhwVeboxIecpParams->pfCscCoeff          = m_cscCoeff;
809     mhwVeboxIecpParams->pfCscInOffset       = m_cscInOffset;
810     mhwVeboxIecpParams->pfCscOutOffset      = m_cscOutOffset;
811     //mhwVeboxIecpParams->bAlphaEnable      = m_alphaEnable;    ??
812     //mhwVeboxIecpParams->wAlphaValue       = m_alphaValue;
813 
814     return MOS_STATUS_SUCCESS;
815 }
816 
SetSfcStateParams(PMHW_SFC_INTERFACE sfcInterface,PMHW_SFC_STATE_PARAMS params,PMHW_SFC_OUT_SURFACE_PARAMS outSurfaceParams)817 MOS_STATUS CodecHalEncodeSfc::SetSfcStateParams(
818     PMHW_SFC_INTERFACE             sfcInterface,
819     PMHW_SFC_STATE_PARAMS          params,
820     PMHW_SFC_OUT_SURFACE_PARAMS    outSurfaceParams)
821 {
822     uint16_t                    widthAlignUnit;
823     uint16_t                    heightAlignUnit;
824     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
825 
826     CODECHAL_ENCODE_FUNCTION_ENTER;
827 
828     CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface);
829     CODECHAL_ENCODE_CHK_NULL_RETURN(m_inputSurface);
830     CODECHAL_ENCODE_CHK_NULL_RETURN(m_sfcOutputSurface);
831     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
832 
833     params->sfcPipeMode                    = MEDIASTATE_SFC_PIPE_VE_TO_SFC;
834     params->dwAVSFilterMode                = MEDIASTATE_SFC_AVS_FILTER_8x8;
835     params->dwVDVEInputOrderingMode        = MEDIASTATE_SFC_INPUT_ORDERING_VE_4x8;
836 
837     params->dwInputChromaSubSampling = MEDIASTATE_SFC_CHROMA_SUBSAMPLING_444;
838 
839     // Adjust SFC input surface alignment.
840     // As VEBOX doesn't do scaling, input size equals to output size
841     // For the VEBOX output to SFC, width is multiple of 16 and height is multiple of 4
842     widthAlignUnit                         = sfcInterface->m_veWidthAlignment;
843     heightAlignUnit                        = sfcInterface->m_veHeightAlignment;
844 
845     params->dwInputFrameWidth              = MOS_ALIGN_CEIL(m_inputSurface->dwWidth, widthAlignUnit);
846     params->dwInputFrameHeight             = MOS_ALIGN_CEIL(m_inputSurface->dwHeight, heightAlignUnit);
847 
848     params->dwChromaDownSamplingMode       = MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_444TO420;
849     params->bAVSChromaUpsamplingEnable     = m_scaling;
850 
851     if ((params->fAVSXScalingRatio > 1.0F) || (params->fAVSYScalingRatio > 1.0F))
852     {
853         params->bBypassXAdaptiveFilter     = false;
854         params->bBypassYAdaptiveFilter     = false;
855     }
856     else
857     {
858         params->bBypassXAdaptiveFilter     = true;
859         params->bBypassYAdaptiveFilter     = true;
860     }
861 
862     params->fChromaSubSamplingXSiteOffset  = 0.0F;
863     params->fChromaSubSamplingYSiteOffset  = 0.0F;
864 
865     widthAlignUnit  = 1;
866     heightAlignUnit = 1;
867 
868     switch(m_sfcOutputSurface->Format)
869     {
870         case Format_NV12:
871         case Format_P010:
872             widthAlignUnit     = 2;
873             heightAlignUnit    = 2;
874             break;
875         case Format_YUY2:
876         case Format_UYVY:
877             widthAlignUnit     = 2;
878             break;
879         default:
880             break;
881     }
882 
883     // Default to Horizontal Left, Vertical Top
884     params->dwChromaDownSamplingHorizontalCoef = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ?
885                                                   MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
886                                                   ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ?
887                                                   MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 :
888                                                   MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8);
889 
890     params->dwChromaDownSamplingVerticalCoef =   (m_chromaSiting  & MHW_CHROMA_SITING_VERT_CENTER) ?
891                                                   MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_4_OVER_8 :
892                                                   ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ?
893                                                   MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_8_OVER_8 :
894                                                   MEDIASTATE_SFC_CHROMA_DOWNSAMPLING_COEF_0_OVER_8);
895 
896     outSurfaceParams->dwWidth              = m_sfcOutputSurface->dwWidth;
897     outSurfaceParams->dwHeight             = m_sfcOutputSurface->dwHeight;
898     outSurfaceParams->dwPitch              = m_sfcOutputSurface->dwPitch;
899     outSurfaceParams->TileType             = m_sfcOutputSurface->TileType;
900     outSurfaceParams->TileModeGMM          = m_sfcOutputSurface->TileModeGMM;
901     outSurfaceParams->bGMMTileEnabled      = m_sfcOutputSurface->bGMMTileEnabled;
902     outSurfaceParams->ChromaSiting         = m_chromaSiting;
903     outSurfaceParams->dwUYoffset           = m_sfcOutputSurface->UPlaneOffset.iYOffset;
904 
905     params->dwOutputFrameWidth             = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwWidth, widthAlignUnit);
906     params->dwOutputFrameHeight            = MOS_ALIGN_CEIL(m_sfcOutputSurface->dwHeight, heightAlignUnit);
907     params->OutputFrameFormat              = m_sfcOutputSurface->Format;
908     params->dwOutputSurfaceOffset          = m_sfcOutputSurface->dwOffset;
909     params->pOsResOutputSurface            = &m_sfcOutputSurface->OsResource;
910     params->pOsResAVSLineBuffer            = &m_resAvsLineBuffer;
911 
912     params->dwSourceRegionHeight           = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Height, heightAlignUnit);
913     params->dwSourceRegionWidth            = MOS_ALIGN_FLOOR(m_inputSurfaceRegion.Width, widthAlignUnit);
914     params->dwSourceRegionVerticalOffset   = MOS_ALIGN_CEIL(m_inputSurfaceRegion.Y, heightAlignUnit);
915     params->dwSourceRegionHorizontalOffset = MOS_ALIGN_CEIL(m_inputSurfaceRegion.X, widthAlignUnit);
916     params->dwScaledRegionHeight           = MOS_UF_ROUND(m_scaleY * params->dwSourceRegionHeight);
917     params->dwScaledRegionWidth            = MOS_UF_ROUND(m_scaleX * params->dwSourceRegionWidth);
918     params->dwScaledRegionVerticalOffset   = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.Y, heightAlignUnit);
919     params->dwScaledRegionHorizontalOffset = MOS_ALIGN_FLOOR(m_outputSurfaceRegion.X, widthAlignUnit);
920     params->fAVSXScalingRatio              = m_scaleX;
921     params->fAVSYScalingRatio              = m_scaleY;
922 
923     params->fAlphaPixel                    = 1.0F;
924     params->bColorFillEnable               = m_colorFill;
925     params->bCSCEnable                     = m_CSC;
926 
927     // ARGB8,ABGR10,A16B16G16R16,VYUY and YVYU output format need to enable swap
928     if (m_sfcOutputSurface->Format == Format_X8R8G8B8     ||
929         m_sfcOutputSurface->Format == Format_A8R8G8B8     ||
930         m_sfcOutputSurface->Format == Format_R10G10B10A2  ||
931         m_sfcOutputSurface->Format == Format_A16B16G16R16 ||
932         m_sfcOutputSurface->Format == Format_VYUY         ||
933         m_sfcOutputSurface->Format == Format_YVYU)
934     {
935         params->bRGBASwapEnable = true;
936     }
937     else
938     {
939         params->bRGBASwapEnable = false;
940     }
941 
942 
943     // CodecHal does not support SFC rotation
944     params->RotationMode                   = MHW_ROTATION_IDENTITY;
945 
946     // For downsampling, expect output surface to be MMC disabled
947     // For Jpeg, the only usage is CSC and the output surface format is RGB8, so also disable MMC
948     params->bMMCEnable                     = false;
949     params->MMCMode                        = MOS_MMC_DISABLED;
950 
951     return eStatus;
952 }
953 
SetSfcAvsStateParams(PMHW_SFC_INTERFACE sfcInterface)954 MOS_STATUS CodecHalEncodeSfc::SetSfcAvsStateParams(
955     PMHW_SFC_INTERFACE             sfcInterface)
956 {
957     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
958     PMHW_SFC_AVS_STATE          mhwSfcAvsState;
959 
960     CODECHAL_ENCODE_FUNCTION_ENTER;
961 
962     CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface);
963     CODECHAL_ENCODE_CHK_NULL_RETURN(m_inputSurface);
964 
965     mhwSfcAvsState = &m_avsState;
966 
967     if (m_chromaSiting == MHW_CHROMA_SITING_NONE)
968     {
969         m_chromaSiting = MHW_CHROMA_SITING_HORZ_LEFT | MHW_CHROMA_SITING_VERT_CENTER;
970     }
971 
972     mhwSfcAvsState->dwInputHorizontalSiting = (m_chromaSiting & MHW_CHROMA_SITING_HORZ_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 :
973                                                ((m_chromaSiting & MHW_CHROMA_SITING_HORZ_RIGHT) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 :
974                                                SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
975 
976     mhwSfcAvsState->dwInputVerticalSitting = (m_chromaSiting  & MHW_CHROMA_SITING_VERT_CENTER) ? SFC_AVS_INPUT_SITING_COEF_4_OVER_8 :
977                                               ((m_chromaSiting & MHW_CHROMA_SITING_VERT_BOTTOM) ? SFC_AVS_INPUT_SITING_COEF_8_OVER_8 :
978                                               SFC_AVS_INPUT_SITING_COEF_0_OVER_8);
979 
980     CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->SetSfcSamplerTable(
981                                 &m_lumaTable,
982                                 &m_chromaTable,
983                                 &m_avsParams,
984                                 m_inputSurface->Format,
985                                 m_scaleX,
986                                 m_scaleY,
987                                 m_chromaSiting,
988                                 true,
989                                 0,
990                                 0));
991     return eStatus;
992 }
993 
SetSfcIefStateParams(PMHW_SFC_IEF_STATE_PARAMS params)994 MOS_STATUS CodecHalEncodeSfc::SetSfcIefStateParams(
995     PMHW_SFC_IEF_STATE_PARAMS         params)
996 {
997     MOS_STATUS                  eStatus = MOS_STATUS_SUCCESS;
998 
999     CODECHAL_ENCODE_FUNCTION_ENTER;
1000 
1001     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1002 
1003     params->bIEFEnable     = false;
1004     params->bCSCEnable     = true;
1005 
1006     params->pfCscCoeff     = m_cscCoeff;
1007     params->pfCscInOffset  = m_cscInOffset;
1008     params->pfCscOutOffset = m_cscOutOffset;
1009 
1010     return eStatus;
1011 }
1012 
Initialize(CodechalHwInterface * hwInterface,PMOS_INTERFACE osInterface)1013 MOS_STATUS CodecHalEncodeSfc::Initialize(
1014     CodechalHwInterface                *hwInterface,
1015     PMOS_INTERFACE                      osInterface)
1016 {
1017 
1018     MOS_STATUS                eStatus = MOS_STATUS_SUCCESS;
1019 
1020     CODECHAL_ENCODE_FUNCTION_ENTER;
1021 
1022     CODECHAL_ENCODE_CHK_NULL_RETURN(hwInterface);
1023     CODECHAL_ENCODE_CHK_NULL_RETURN(hwInterface->GetVeboxInterface());
1024     CODECHAL_ENCODE_CHK_NULL_RETURN(osInterface);
1025 
1026     m_hwInterface = hwInterface;
1027     m_osInterface = osInterface;
1028 
1029     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetVeboxInterface()->CreateHeap());
1030 
1031     // Create VEBOX Context
1032     MOS_GPUCTX_CREATOPTIONS createOption;
1033     //
1034     // VeboxgpuContext could be created from both VP and Codec.
1035     // If there is no such as a GPU context it will create a new one and set the GPU component ID.
1036     // If there has been a valid GPU context it won�t create another one anymore and the component ID won�t be updated either.
1037     // 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,
1038     // VPBLT callstack would index a GpuAppTaskEvent of MOS_GPU_COMPONENT_ENCODE.
1039     //
1040     MOS_COMPONENT originalComponent = m_osInterface->Component;
1041     m_osInterface->Component        = COMPONENT_VPCommon;
1042 
1043     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnCreateGpuContext(
1044         m_osInterface,
1045         MOS_GPU_CONTEXT_VEBOX,
1046         MOS_GPU_NODE_VE,
1047         &createOption));
1048 
1049     m_osInterface->Component        = originalComponent;
1050 
1051     // Register Vebox GPU context with the Batch Buffer completion event
1052     // Ignore if creation fails
1053     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnRegisterBBCompleteNotifyEvent(
1054         m_osInterface,
1055         MOS_GPU_CONTEXT_VEBOX));
1056 
1057     return eStatus;
1058 }
1059 
SetParams(CODECHAL_ENCODE_SFC_PARAMS * params)1060 MOS_STATUS CodecHalEncodeSfc::SetParams(
1061     CODECHAL_ENCODE_SFC_PARAMS*         params)
1062 {
1063     MOS_STATUS                eStatus = MOS_STATUS_SUCCESS;
1064 
1065     CODECHAL_ENCODE_FUNCTION_ENTER;
1066 
1067     CODECHAL_ENCODE_CHK_NULL_RETURN(params);
1068     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pInputSurface);
1069     CODECHAL_ENCODE_CHK_NULL_RETURN(params->pOutputSurface);
1070 
1071     m_inputSurface = params->pInputSurface;
1072     // Vebox o/p should not be written to memory for SFC, VeboxOutputSurface should be nullptr
1073     m_veboxOutputSurface = nullptr;
1074     m_sfcOutputSurface = params->pOutputSurface;
1075 
1076     // no scaling.
1077     m_scaling = false;
1078     m_colorFill = false;
1079 
1080     // No CSC for SFC pipe
1081     m_veboxCsc = true;
1082 
1083     m_scaleX = 1.0;
1084     m_scaleY = 1.0;
1085     m_chromaSiting = params->uiChromaSitingType;
1086 
1087     eStatus = MOS_SecureMemcpy(&m_inputSurfaceRegion,
1088         sizeof(m_inputSurfaceRegion),
1089         &params->rcInputSurfaceRegion,
1090         sizeof(params->rcInputSurfaceRegion));
1091 
1092     eStatus = MOS_SecureMemcpy(&m_outputSurfaceRegion,
1093         sizeof(m_outputSurfaceRegion),
1094         &params->rcOutputSurfaceRegion,
1095         sizeof(params->rcOutputSurfaceRegion));
1096 
1097     CODECHAL_ENCODE_CHK_STATUS_RETURN(AllocateResources());
1098 
1099     return eStatus;
1100 }
1101 
AddSfcCommands(PMHW_SFC_INTERFACE sfcInterface,PMOS_COMMAND_BUFFER cmdBuffer)1102 MOS_STATUS CodecHalEncodeSfc::AddSfcCommands(
1103     PMHW_SFC_INTERFACE              sfcInterface,
1104     PMOS_COMMAND_BUFFER             cmdBuffer)
1105 {
1106     MHW_SFC_LOCK_PARAMS            sfcLockParams;
1107     MHW_SFC_STATE_PARAMS           sfcStateParams;
1108     MHW_SFC_OUT_SURFACE_PARAMS     sfcOutSurfaceParams;
1109     MHW_SFC_IEF_STATE_PARAMS       sfcIefStateParams;
1110     MOS_STATUS                     eStatus = MOS_STATUS_SUCCESS;
1111 
1112     CODECHAL_ENCODE_FUNCTION_ENTER;
1113 
1114     CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface);
1115     CODECHAL_ENCODE_CHK_NULL_RETURN(cmdBuffer);
1116 
1117     MOS_ZeroMemory(&sfcLockParams, sizeof(sfcLockParams));
1118 
1119     sfcLockParams.sfcPipeMode     = MhwSfcInterface::SFC_PIPE_MODE_VEBOX;
1120     sfcLockParams.bOutputToMemory = false;
1121 
1122     MOS_ZeroMemory(&sfcStateParams, sizeof(sfcStateParams));
1123     MOS_ZeroMemory(&sfcOutSurfaceParams, sizeof(sfcOutSurfaceParams));
1124     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcStateParams(sfcInterface, &sfcStateParams, &sfcOutSurfaceParams));
1125 
1126     CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcLock(cmdBuffer, &sfcLockParams));
1127     CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcState(cmdBuffer, &sfcStateParams, &sfcOutSurfaceParams));
1128 
1129     if (m_scaling)
1130     {
1131         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcAvsStateParams(sfcInterface));
1132         CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsState(cmdBuffer, &m_avsState));
1133         CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsLumaTable(cmdBuffer, &m_lumaTable));
1134         CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcAvsChromaTable(cmdBuffer, &m_chromaTable));
1135     }
1136 
1137     if (m_CSC)
1138     {
1139         MOS_ZeroMemory(&sfcIefStateParams, sizeof(sfcIefStateParams));
1140         CODECHAL_ENCODE_CHK_STATUS_RETURN(SetSfcIefStateParams(&sfcIefStateParams));
1141         CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcIefState(cmdBuffer, &sfcIefStateParams));
1142     }
1143 
1144     CODECHAL_ENCODE_CHK_STATUS_RETURN(sfcInterface->AddSfcFrameStart(cmdBuffer, MhwSfcInterface::SFC_PIPE_MODE_VEBOX));
1145 
1146     return eStatus;
1147 }
1148 
RenderStart(CodechalEncoderState * encoder)1149 MOS_STATUS CodecHalEncodeSfc::RenderStart(
1150     CodechalEncoderState*       encoder)
1151 {
1152     MHW_VEBOX_STATE_CMD_PARAMS          veboxStateCmdParams;
1153     MHW_VEBOX_SURFACE_STATE_CMD_PARAMS  veboxSurfaceStateCmdParams;
1154     MHW_VEBOX_DI_IECP_CMD_PARAMS        veboxDiIecpCmdParams;
1155     MHW_VEBOX_IECP_PARAMS               veboxIecpParams;
1156     MHW_VEBOX_SURFACE_CNTL_PARAMS       veboxSurfCntlParams;
1157     MhwVeboxInterface                   *veboxInterface;
1158     PMHW_SFC_INTERFACE                  sfcInterface;
1159     MhwMiInterface                      *miInterface;
1160     PMOS_CONTEXT                        pOsContext = nullptr;
1161     MHW_MI_MMIOREGISTERS                *mmioVeboxRegisters = nullptr;
1162     MOS_COMMAND_BUFFER                  cmdBuffer;
1163     bool                                requestFrameTracking;
1164     MOS_STATUS                          eStatus = MOS_STATUS_SUCCESS;
1165 
1166     CODECHAL_ENCODE_FUNCTION_ENTER;
1167 
1168     CODECHAL_ENCODE_CHK_NULL_RETURN(m_hwInterface);
1169     CODECHAL_ENCODE_CHK_NULL_RETURN(m_osInterface);
1170     CODECHAL_ENCODE_CHK_NULL_RETURN(pOsContext = m_osInterface->pOsContext);
1171     CODECHAL_ENCODE_CHK_NULL_RETURN(encoder);
1172     CODECHAL_ENCODE_CHK_NULL_RETURN(sfcInterface = m_hwInterface->GetSfcInterface());
1173     CODECHAL_ENCODE_CHK_NULL_RETURN(veboxInterface = m_hwInterface->GetVeboxInterface());
1174     CODECHAL_ENCODE_CHK_NULL_RETURN(miInterface = m_hwInterface->GetMiInterface());
1175     CODECHAL_ENCODE_CHK_NULL_RETURN(mmioVeboxRegisters = miInterface->GetMmioRegisters());
1176 
1177     // Switch GPU context to VEBOX
1178     m_osInterface->pfnSetGpuContext(m_osInterface, MOS_GPU_CONTEXT_VEBOX);
1179     // Reset allocation list and house keeping
1180     m_osInterface->pfnResetOsStates(m_osInterface);
1181 
1182     // Send command buffer header at the beginning
1183     MOS_ZeroMemory(&cmdBuffer, sizeof(MOS_COMMAND_BUFFER));
1184     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnGetCommandBuffer(m_osInterface, &cmdBuffer, 0));
1185 
1186     // the first task?
1187     requestFrameTracking = false;
1188     CODECHAL_ENCODE_CHK_STATUS_RETURN(encoder->SendPrologWithFrameTracking(&cmdBuffer, requestFrameTracking));
1189 
1190     // If m_pollingSyncEnabled is set, insert HW semaphore to wait for external
1191     // raw surface processing to complete, before start CSC. Once the marker in
1192     // raw surface is overwritten by external operation, HW semaphore will be
1193     // signalled and CSC will start. This is to reduce SW latency between
1194     // external raw surface processing and CSC, in usages like remote gaming.
1195     if (encoder->m_pollingSyncEnabled)
1196     {
1197         MHW_MI_SEMAPHORE_WAIT_PARAMS miSemaphoreWaitParams;
1198         MOS_ZeroMemory((&miSemaphoreWaitParams), sizeof(miSemaphoreWaitParams));
1199         miSemaphoreWaitParams.presSemaphoreMem = &m_inputSurface->OsResource;
1200         miSemaphoreWaitParams.dwResourceOffset = encoder->m_syncMarkerOffset;
1201         miSemaphoreWaitParams.bPollingWaitMode = true;
1202         miSemaphoreWaitParams.dwSemaphoreData  = encoder->m_syncMarkerValue;
1203         miSemaphoreWaitParams.CompareOperation = MHW_MI_SAD_NOT_EQUAL_SDD;
1204         CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiSemaphoreWaitCmd(&cmdBuffer, &miSemaphoreWaitParams));
1205     }
1206 
1207     // Setup cmd prameters
1208     MOS_ZeroMemory(&veboxStateCmdParams, sizeof(veboxStateCmdParams));
1209     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxStateParams(&veboxStateCmdParams));
1210 
1211     MOS_ZeroMemory(&veboxSurfaceStateCmdParams, sizeof(veboxSurfaceStateCmdParams));
1212     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxSurfaceStateParams(&veboxSurfaceStateCmdParams));
1213 
1214     MOS_ZeroMemory(&veboxDiIecpCmdParams, sizeof(veboxDiIecpCmdParams));
1215     CODECHAL_ENCODE_CHK_STATUS_RETURN(SetVeboxDiIecpParams(&veboxDiIecpCmdParams));
1216 
1217     MOS_ZeroMemory(&veboxSurfCntlParams, sizeof(veboxSurfCntlParams));
1218     veboxSurfCntlParams.bIsCompressed   = m_inputSurface->bIsCompressed;
1219     veboxSurfCntlParams.CompressionMode = m_inputSurface->CompressionMode;
1220     CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaceControlBits(
1221         &veboxSurfCntlParams,
1222         (uint32_t *)&(veboxDiIecpCmdParams.CurrInputSurfCtrl.Value)));
1223 
1224     // get csc matrix
1225     MOS_ZeroMemory(&veboxIecpParams, sizeof(veboxIecpParams));
1226     CODECHAL_ENCODE_CHK_STATUS_RETURN(VeboxSetIecpParams(&veboxIecpParams));
1227 
1228     // send matrix into heap
1229     CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxIecpState(
1230         &veboxIecpParams));
1231 
1232     // send Vebox and SFC cmds
1233     CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxState(&cmdBuffer, &veboxStateCmdParams, 0));
1234 
1235     CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxSurfaces( &cmdBuffer, &veboxSurfaceStateCmdParams));
1236 
1237     CODECHAL_ENCODE_CHK_STATUS_RETURN(AddSfcCommands(sfcInterface, &cmdBuffer));
1238 
1239     HalOcaInterface::OnDispatch(cmdBuffer, *pOsContext, *miInterface, *mmioVeboxRegisters);
1240 
1241     CODECHAL_ENCODE_CHK_STATUS_RETURN(veboxInterface->AddVeboxDiIecp(&cmdBuffer, &veboxDiIecpCmdParams));
1242 
1243     // If m_pollingSyncEnabled is set, write the marker to source surface for next MI_SEMAPHORE_WAIT to check.
1244     if (encoder->m_pollingSyncEnabled)
1245     {
1246         MHW_MI_STORE_DATA_PARAMS storeDataParams;
1247         storeDataParams.pOsResource      = &m_inputSurface->OsResource;
1248         storeDataParams.dwResourceOffset = encoder->m_syncMarkerOffset;
1249         storeDataParams.dwValue          = encoder->m_syncMarkerValue;
1250         CODECHAL_ENCODE_CHK_STATUS_RETURN(miInterface->AddMiStoreDataImmCmd(&cmdBuffer, &storeDataParams));
1251     }
1252 
1253     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_hwInterface->GetMiInterface()->AddMiBatchBufferEnd(
1254         &cmdBuffer,
1255         nullptr));
1256 
1257     CODECHAL_DEBUG_TOOL(CODECHAL_ENCODE_CHK_STATUS_RETURN(encoder->GetDebugInterface()->DumpCmdBuffer(
1258         &cmdBuffer,
1259         CODECHAL_MEDIA_STATE_CSC_DS_COPY,
1260         nullptr)));
1261 
1262     m_osInterface->pfnReturnCommandBuffer(m_osInterface, &cmdBuffer, 0);
1263     HalOcaInterface::On1stLevelBBEnd(cmdBuffer, *m_osInterface->pOsContext);
1264 
1265     CODECHAL_ENCODE_CHK_STATUS_RETURN(m_osInterface->pfnSubmitCommandBuffer(
1266         m_osInterface,
1267         &cmdBuffer,
1268         encoder->m_videoContextUsesNullHw));
1269 
1270     return eStatus;
1271 }
1272