1 /*
2 * Copyright (c) 2017-2018, 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_hevc_g9_kbl.cpp
24 //! \brief    HEVC dual-pipe encoder for GEN9 KBL.
25 //!
26 
27 #include "codechal_encode_hevc_g9_kbl.h"
28 #include "igcodeckrn_g9.h"
29 
30 //! HEVC encoder kernel header structure for G9 KBL
31 struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_KBL
32 {
33     int nKernelCount;                                                       //!< Total number of kernels
34 
35     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_2xDownSampling_Kernel;             //!< 2x down sampling kernel
36     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_32x32_PU_ModeDecision_Kernel;      //!< Intra 32x32 PU mode decision kernel
37     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_16x16_PU_SADComputation_Kernel;    //!< Intra 16x16 PU SAD computation kernel
38     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_16x16_PU_ModeDecision_Kernel;      //!< Intra 16x16 PU mode decision kernel
39     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_8x8_PU_Kernel;                     //!< Intra 8x8 PU mode decision kernel
40     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_8x8_PU_FMode_Kernel;               //!< Intra 8x8 PU final mode decision kernel
41     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_PB_32x32_PU_IntraCheck;              //!< P/B 32x32 PU intra mode check kernel
42     CODECHAL_KERNEL_HEADER HEVC_LCUEnc_PB_MB;                               //!< P/B MbEnc Kernel
43     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_DS4HME;                            //!< 4x Scaling kernel
44     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_P_HME;                               //!< P frame HME kernel
45     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_B_HME;                               //!< B frame HME kernel
46     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_I_COARSE;                            //!< Intra coarse kernel
47     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Init;                            //!< BRC init kernel
48     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Reset;                           //!< BRC reset kernel
49     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Update;                          //!< BRC update kernel
50     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_LCU_Update;                      //!< BRC LCU update kernel
51     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_PB_Pak;                              //!< P/B frame PAK kernel
52     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_PB_Adv;                              //!< P/B frame Adv kernel
53     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_BRC_Blockcopy;                       //!< BRC blockcopy kerenel
54     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_DS_Combined;                         //!< Down scale and format conversion kernel
55     CODECHAL_KERNEL_HEADER HEVC_LCUEnc_P_MB;                                //!< P frame MbEnc kernel
56     CODECHAL_KERNEL_HEADER Hevc_LCUEnc_P_Adv;                               //!< P frame Adv kernel
57 };
58 
59 //! \brief  typedef of struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_KBL
60 using PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_KBL = struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_KBL*;
61 
CheckSupportedColorFormat(PMOS_SURFACE surface)62 bool CodechalEncHevcStateG9Kbl::CheckSupportedColorFormat(
63     PMOS_SURFACE surface)
64 {
65     CODECHAL_ENCODE_FUNCTION_ENTER;
66 
67     if (!surface)
68     {
69         return false;
70     }
71 
72     bool isColorFormatSupported = false;
73     if (IS_Y_MAJOR_TILE_FORMAT(surface->TileType))
74     {
75         switch (surface->Format)
76         {
77         case Format_NV12:
78         case Format_P010:       // Planar 4:2:0, 10b
79             isColorFormatSupported = true;
80             break;
81 
82         default:
83             break;
84         }
85     }
86 
87     return isColorFormatSupported;
88 }
89 
GetKernelHeaderAndSize(void * binary,EncOperation operation,uint32_t krnStateIdx,void * krnHeader,uint32_t * krnSize)90 MOS_STATUS CodechalEncHevcStateG9Kbl::GetKernelHeaderAndSize(
91     void                           *binary,
92     EncOperation                   operation,
93     uint32_t                       krnStateIdx,
94     void                           *krnHeader,
95     uint32_t                       *krnSize)
96 {
97     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
98 
99     CODECHAL_ENCODE_FUNCTION_ENTER;
100 
101     CODECHAL_ENCODE_CHK_NULL_RETURN(binary);
102     CODECHAL_ENCODE_CHK_NULL_RETURN(krnHeader);
103     CODECHAL_ENCODE_CHK_NULL_RETURN(krnSize);
104 
105     PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_KBL kernelHeaderTable = (PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_KBL)binary;
106     PCODECHAL_KERNEL_HEADER currKrnHeader = nullptr;
107 
108     if (operation == ENC_SCALING4X)
109     {
110         currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_DS4HME;
111     }
112     else if (operation == ENC_ME)
113     {
114         // KBL supports P frame. P HME index CODECHAL_ENCODE_ME_IDX_P is 0 and B HME index CODECHAL_ENCODE_ME_IDX_B is 1
115         if (krnStateIdx == 0)
116         {
117             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_P_HME;
118         }
119         else
120         {
121             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_B_HME;
122         }
123     }
124     else if (operation == ENC_BRC)
125     {
126         switch (krnStateIdx)
127         {
128         case CODECHAL_HEVC_BRC_COARSE_INTRA:
129             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_COARSE;
130             break;
131 
132         case CODECHAL_HEVC_BRC_INIT:
133             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Init;
134             break;
135 
136         case CODECHAL_HEVC_BRC_RESET:
137             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Reset;
138             break;
139 
140         case CODECHAL_HEVC_BRC_FRAME_UPDATE:
141             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Update;
142             break;
143 
144         case CODECHAL_HEVC_BRC_LCU_UPDATE:
145             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_LCU_Update;
146             break;
147 
148         default:
149             CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported BRC mode requested");
150             eStatus = MOS_STATUS_INVALID_PARAMETER;
151             return eStatus;
152         }
153     }
154     else if (operation == ENC_MBENC)
155     {
156         switch (krnStateIdx)
157         {
158         case CODECHAL_HEVC_MBENC_2xSCALING:
159         case CODECHAL_HEVC_MBENC_32x32MD:
160         case CODECHAL_HEVC_MBENC_16x16SAD:
161         case CODECHAL_HEVC_MBENC_16x16MD:
162         case CODECHAL_HEVC_MBENC_8x8PU:
163         case CODECHAL_HEVC_MBENC_8x8FMODE:
164         case CODECHAL_HEVC_MBENC_32x32INTRACHECK:
165         case CODECHAL_HEVC_MBENC_BENC:
166             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_2xDownSampling_Kernel;
167             currKrnHeader += krnStateIdx;
168             break;
169 
170         case CODECHAL_HEVC_MBENC_BPAK:
171             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_PB_Pak;
172             break;
173 
174         case CODECHAL_HEVC_MBENC_ADV:
175             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_PB_Adv;
176             break;
177 
178         case CODECHAL_HEVC_MBENC_DS_COMBINED:
179             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_DS_Combined;
180             break;
181 
182         case CODECHAL_HEVC_MBENC_PENC:
183             currKrnHeader = &kernelHeaderTable->HEVC_LCUEnc_P_MB;
184             break;
185 
186         case CODECHAL_HEVC_MBENC_ADV_P:
187             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_P_Adv;
188             break;
189 
190         default:
191             CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
192             eStatus = MOS_STATUS_INVALID_PARAMETER;
193             return eStatus;
194         }
195     }
196     else
197     {
198         CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
199         eStatus = MOS_STATUS_INVALID_PARAMETER;
200         return eStatus;
201     }
202 
203     *((PCODECHAL_KERNEL_HEADER)krnHeader) = *currKrnHeader;
204 
205     PCODECHAL_KERNEL_HEADER nextKrnHeader = (currKrnHeader + 1);
206     PCODECHAL_KERNEL_HEADER invalidEntry = (PCODECHAL_KERNEL_HEADER)(((uint8_t*)binary) + sizeof(*kernelHeaderTable));
207     uint32_t nextKrnOffset = *krnSize;
208 
209     if (nextKrnHeader < invalidEntry)
210     {
211         nextKrnOffset = nextKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT;
212     }
213     *krnSize = nextKrnOffset - (currKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
214 
215     return eStatus;
216 }
217 
SetSequenceStructs()218 MOS_STATUS CodechalEncHevcStateG9Kbl::SetSequenceStructs()
219 {
220     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
221 
222     CODECHAL_ENCODE_FUNCTION_ENTER;
223 
224     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncHevcStateG9::SetSequenceStructs());
225 
226     // KBL HEVC only: turn off Recon's MMC to avoid perf drop at 4K resolution TU4/7
227     m_disableReconMMCD = (m_hevcSeqParams->TargetUsage != (uint32_t)TARGETUSAGE_BEST_QUALITY) && m_encode4KSequence;
228 
229     return eStatus;
230 }
231 
CodechalEncHevcStateG9Kbl(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)232 CodechalEncHevcStateG9Kbl::CodechalEncHevcStateG9Kbl(
233     CodechalHwInterface* hwInterface,
234     CodechalDebugInterface* debugInterface,
235     PCODECHAL_STANDARD_INFO standardInfo)
236     :CodechalEncHevcStateG9(hwInterface, debugInterface, standardInfo)
237 {
238     m_kernelBase = (uint8_t *)IGCODECKRN_G9;
239     pfnGetKernelHeaderAndSize = GetKernelHeaderAndSize;
240     m_noMeKernelForPFrame = false;
241 
242     MOS_STATUS eStatus = InitMhw();
243     if (eStatus != MOS_STATUS_SUCCESS)
244     {
245         CODECHAL_ENCODE_ASSERTMESSAGE("HEVC encoder MHW initialization failed.");
246     }
247 }
248 
249