1 /*
2 * Copyright (c) 2017, 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_skl.cpp
24 //! \brief    HEVC dual-pipe encoder for GEN9 SKL.
25 //!
26 
27 #include "codechal_encode_hevc_g9_skl.h"
28 #include "igcodeckrn_g9.h"
29 
30 //! HEVC encoder kernel header structure for G9 SKL
31 struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL
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_SKL
60 using PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL = struct CODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL*;
61 
GetKernelHeaderAndSize(void * binary,EncOperation operation,uint32_t krnStateIdx,void * krnHeader,uint32_t * krnSize)62 MOS_STATUS CodechalEncHevcStateG9Skl::GetKernelHeaderAndSize(
63     void                           *binary,
64     EncOperation                   operation,
65     uint32_t                       krnStateIdx,
66     void                           *krnHeader,
67     uint32_t                       *krnSize)
68 {
69     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
70 
71     CODECHAL_ENCODE_FUNCTION_ENTER;
72 
73     CODECHAL_ENCODE_CHK_NULL_RETURN(binary);
74     CODECHAL_ENCODE_CHK_NULL_RETURN(krnHeader);
75     CODECHAL_ENCODE_CHK_NULL_RETURN(krnSize);
76 
77     PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL kernelHeaderTable = (PCODECHAL_ENC_HEVC_KERNEL_HEADER_G9_SKL)binary;
78     PCODECHAL_KERNEL_HEADER currKrnHeader = nullptr;
79 
80     if (operation == ENC_SCALING4X)
81     {
82         currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_DS4HME;
83     }
84     else if (operation == ENC_ME)
85     {
86         // SKL supports P frame. P HME index CODECHAL_ENCODE_ME_IDX_P is 0 and B HME index CODECHAL_ENCODE_ME_IDX_B is 1
87         if (krnStateIdx == 0)
88         {
89             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_P_HME;
90         }
91         else
92         {
93             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_B_HME;
94         }
95     }
96     else if (operation == ENC_BRC)
97     {
98         switch (krnStateIdx)
99         {
100         case CODECHAL_HEVC_BRC_COARSE_INTRA:
101             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_COARSE;
102             break;
103 
104         case CODECHAL_HEVC_BRC_INIT:
105             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Init;
106             break;
107 
108         case CODECHAL_HEVC_BRC_RESET:
109             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Reset;
110             break;
111 
112         case CODECHAL_HEVC_BRC_FRAME_UPDATE:
113             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_Update;
114             break;
115 
116         case CODECHAL_HEVC_BRC_LCU_UPDATE:
117             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_BRC_LCU_Update;
118             break;
119 
120         default:
121             CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported BRC mode requested");
122             eStatus = MOS_STATUS_INVALID_PARAMETER;
123             return eStatus;
124         }
125     }
126     else if (operation == ENC_MBENC)
127     {
128         switch (krnStateIdx)
129         {
130         case CODECHAL_HEVC_MBENC_2xSCALING:
131         case CODECHAL_HEVC_MBENC_32x32MD:
132         case CODECHAL_HEVC_MBENC_16x16SAD:
133         case CODECHAL_HEVC_MBENC_16x16MD:
134         case CODECHAL_HEVC_MBENC_8x8PU:
135         case CODECHAL_HEVC_MBENC_8x8FMODE:
136         case CODECHAL_HEVC_MBENC_32x32INTRACHECK:
137         case CODECHAL_HEVC_MBENC_BENC:
138             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_I_2xDownSampling_Kernel;
139             currKrnHeader += krnStateIdx;
140             break;
141 
142         case CODECHAL_HEVC_MBENC_BPAK:
143             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_PB_Pak;
144             break;
145 
146         case CODECHAL_HEVC_MBENC_ADV:
147             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_PB_Adv;
148             break;
149 
150         case CODECHAL_HEVC_MBENC_DS_COMBINED:
151             // Ignore this kernel on SKL.
152             *krnSize = 0;
153             return eStatus;
154 
155         case CODECHAL_HEVC_MBENC_PENC:
156             currKrnHeader = &kernelHeaderTable->HEVC_LCUEnc_P_MB;
157             break;
158 
159         case CODECHAL_HEVC_MBENC_ADV_P:
160             currKrnHeader = &kernelHeaderTable->Hevc_LCUEnc_P_Adv;
161             break;
162 
163         default:
164             CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
165             eStatus = MOS_STATUS_INVALID_PARAMETER;
166             return eStatus;
167         }
168     }
169     else
170     {
171         CODECHAL_ENCODE_ASSERTMESSAGE("Unsupported ENC mode requested");
172         eStatus = MOS_STATUS_INVALID_PARAMETER;
173         return eStatus;
174     }
175 
176     *((PCODECHAL_KERNEL_HEADER)krnHeader) = *currKrnHeader;
177 
178     PCODECHAL_KERNEL_HEADER nextKrnHeader = (currKrnHeader + 1);
179     PCODECHAL_KERNEL_HEADER invalidEntry = (PCODECHAL_KERNEL_HEADER)(((uint8_t*)binary) + sizeof(*kernelHeaderTable));
180     uint32_t nextKrnOffset = *krnSize;
181 
182     if (nextKrnHeader < invalidEntry)
183     {
184         nextKrnOffset = nextKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT;
185     }
186     *krnSize = nextKrnOffset - (currKrnHeader->KernelStartPointer << MHW_KERNEL_OFFSET_SHIFT);
187 
188     return eStatus;
189 }
190 
UpdateSSDSliceCount()191 void CodechalEncHevcStateG9Skl::UpdateSSDSliceCount()
192 {
193     CodechalEncodeHevcBase::UpdateSSDSliceCount();
194 
195     uint32_t sliceCount;
196     if (m_frameHeight * m_frameWidth >= 3840 * 2160 && m_targetUsage <= 4)
197     {
198         sliceCount = 0;
199     }
200     else
201     {
202         sliceCount = 2;
203     }
204 
205     if (m_osInterface->pfnSetSliceCount)
206     {
207         m_osInterface->pfnSetSliceCount(m_osInterface, &sliceCount);
208     }
209 }
210 
Initialize(CodechalSetting * settings)211 MOS_STATUS CodechalEncHevcStateG9Skl::Initialize(CodechalSetting * settings)
212 {
213     MOS_STATUS eStatus = MOS_STATUS_SUCCESS;
214 
215     CODECHAL_ENCODE_FUNCTION_ENTER;
216 
217     // common initilization
218     CODECHAL_ENCODE_CHK_STATUS_RETURN(CodechalEncHevcStateG9::Initialize(settings));
219 
220     m_cscDsState->EnableMmc();
221 
222     return eStatus;
223 }
224 
CodechalEncHevcStateG9Skl(CodechalHwInterface * hwInterface,CodechalDebugInterface * debugInterface,PCODECHAL_STANDARD_INFO standardInfo)225 CodechalEncHevcStateG9Skl::CodechalEncHevcStateG9Skl(
226     CodechalHwInterface* hwInterface,
227     CodechalDebugInterface* debugInterface,
228     PCODECHAL_STANDARD_INFO standardInfo)
229     :CodechalEncHevcStateG9(hwInterface, debugInterface, standardInfo)
230 {
231     m_kernelBase = (uint8_t *)IGCODECKRN_G9;
232     pfnGetKernelHeaderAndSize = GetKernelHeaderAndSize;
233     m_noMeKernelForPFrame = false;
234 
235     MOS_STATUS eStatus = InitMhw();
236     if (eStatus != MOS_STATUS_SUCCESS)
237     {
238         CODECHAL_ENCODE_ASSERTMESSAGE("HEVC encoder MHW initialization failed.");
239     }
240 }
241 
242