1 /*
2 * Copyright (c) 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     media_ddi_encode_fei_hevc.cpp
24 //! \brief    Implements class for DDI media hevc fei encode
25 //!
26 
27 #include "media_libva.h"
28 #include "media_libva_encoder.h"
29 #include "media_libva_util.h"
30 #include "hwinfo_linux.h"
31 #include "codechal_encode_hevc_base.h"
32 #include "media_ddi_encode_base.h"
33 #include "media_ddi_encode_fei_hevc.h"
34 #include "media_ddi_encode_const.h"
35 #include "media_ddi_factory.h"
36 
37 extern template class MediaDdiFactoryNoArg<DdiEncodeBase>;
38 
39 static bool isEncodeHevcFeiRegistered =
40     MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeHevcFei>(ENCODE_ID_HEVCFEI);
41 
~DdiEncodeHevcFei()42 DdiEncodeHevcFei::~DdiEncodeHevcFei()
43 {
44     if (nullptr == m_encodeCtx)
45     {
46         return;
47     }
48     MOS_FreeMemory(m_encodeCtx->pFeiPicParams);
49     m_encodeCtx->pFeiPicParams = nullptr;
50 
51 }
52 
ContextInitialize(CodechalSetting * codecHalSettings)53 VAStatus DdiEncodeHevcFei::ContextInitialize(CodechalSetting * codecHalSettings)
54 {
55     VAStatus status = DdiEncodeHevc::ContextInitialize(codecHalSettings);
56     if (VA_STATUS_SUCCESS != status)
57     {
58         return status;
59     }
60 
61     codecHalSettings->codecFunction = m_encodeCtx->codecFunction;
62 
63     m_encodeCtx->pFeiPicParams = (void *)MOS_AllocAndZeroMemory(CODECHAL_HEVC_MAX_PPS_NUM * sizeof(CodecEncodeHevcFeiPicParams));
64     DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "nullptr m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
65 
66     return VA_STATUS_SUCCESS;
67 }
68 
EncodeInCodecHal(uint32_t numSlices)69 VAStatus DdiEncodeHevcFei::EncodeInCodecHal(uint32_t numSlices)
70 {
71     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
72     DDI_CHK_NULL(m_encodeCtx->pCodecHal, "nullptr m_encodeCtx->pCodecHal", VA_STATUS_ERROR_INVALID_PARAMETER);
73 
74     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
75 
76     EncoderParams encodeParams;
77     MOS_ZeroMemory(&encodeParams, sizeof(encodeParams));
78 
79     CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
80 
81     if(CodecHalIsFeiEncode(m_encodeCtx->codecFunction))
82     {
83         encodeParams.ExecCodecFunction = m_encodeCtx->codecFunction;
84     }
85     else
86     {
87         DDI_ASSERTMESSAGE("DDI:Failed in HEVC FEI Function check!");
88         return VA_STATUS_ERROR_INVALID_PARAMETER;
89     }
90 
91     // Raw Surface
92     MOS_SURFACE rawSurface;
93     MOS_ZeroMemory(&rawSurface, sizeof(rawSurface));
94     rawSurface.dwOffset = 0;
95     if (m_encodeCtx->vaProfile == VAProfileHEVCMain10)
96     {
97         rawSurface.Format = Format_P010;
98     }
99     else  //VAProfileHEVCMain
100     {
101         rawSurface.Format = Format_NV12;
102     }
103 
104     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface.OsResource));
105 
106     // Recon Surface
107     MOS_SURFACE reconSurface;
108     MOS_ZeroMemory(&reconSurface, sizeof(reconSurface));
109     reconSurface.dwOffset = 0;
110     if (m_encodeCtx->vaProfile == VAProfileHEVCMain10)
111     {
112         reconSurface.Format = Format_P010;
113     }
114     else  //VAProfileHEVCMain
115     {
116         reconSurface.Format = Format_NV12;
117     }
118 
119     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface.OsResource));
120 
121     //clear registered recon/ref surface flags
122     DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, true), "ClearRefList failed!");
123 
124     // Bitstream surface
125     MOS_RESOURCE bitstreamSurface;
126     MOS_ZeroMemory(&bitstreamSurface, sizeof(bitstreamSurface));
127     bitstreamSurface        = m_encodeCtx->resBitstreamBuffer;  // in render picture
128     bitstreamSurface.Format = Format_Buffer;
129 
130     encodeParams.psRawSurface        = &rawSurface;
131     encodeParams.psReconSurface      = &reconSurface;
132     encodeParams.presBitstreamBuffer = &bitstreamSurface;
133 
134     MOS_SURFACE mbQpSurface;
135     if(feiPicParams->bPerBlockQP)
136     {
137         // MBQp surface
138         MOS_ZeroMemory(&mbQpSurface, sizeof(mbQpSurface));
139         mbQpSurface.Format     = Format_Buffer_2D;
140         mbQpSurface.dwOffset   = 0;
141         mbQpSurface.OsResource = feiPicParams->resCTBQp;
142 
143         encodeParams.psMbQpDataSurface = &mbQpSurface;
144         encodeParams.bMbQpDataEnabled  = true;
145     }
146 
147     encodeParams.pSeqParams   = m_encodeCtx->pSeqParams;
148     encodeParams.pVuiParams   = m_encodeCtx->pVuiParams;
149     encodeParams.pPicParams   = m_encodeCtx->pPicParams;
150     encodeParams.pSliceParams = m_encodeCtx->pSliceParams;
151     encodeParams.pFeiPicParams = feiPicParams;
152 
153     // Sequence data
154     encodeParams.bNewSeq = m_encodeCtx->bNewSeq;
155 
156     // VUI
157     encodeParams.bNewVuiData = m_encodeCtx->bNewVuiData;
158 
159     // Slice level data
160     encodeParams.dwNumSlices = numSlices;
161 
162     // IQmatrix params
163     encodeParams.bNewQmatrixData = m_encodeCtx->bNewQmatrixData;
164     encodeParams.bPicQuant       = m_encodeCtx->bPicQuant;
165     encodeParams.ppNALUnitParams = m_encodeCtx->ppNALUnitParams;
166     encodeParams.pSeiData        = m_encodeCtx->pSEIFromApp;
167     encodeParams.pSeiParamBuffer = m_encodeCtx->pSEIFromApp->pSEIBuffer;
168     encodeParams.dwSEIDataOffset = 0;
169 
170     CODECHAL_HEVC_IQ_MATRIX_PARAMS hevcIqMatrixParams;
171     encodeParams.pIQMatrixBuffer = &hevcIqMatrixParams;
172 
173     // whether driver need to pack slice header
174     if (m_encodeCtx->bHavePackedSliceHdr)
175     {
176         encodeParams.bAcceleratorHeaderPackingCaps = false;
177     }
178     else
179     {
180         encodeParams.bAcceleratorHeaderPackingCaps = true;
181     }
182 
183     encodeParams.pBSBuffer      = m_encodeCtx->pbsBuffer;
184     encodeParams.pSlcHeaderData = (void *)m_encodeCtx->pSliceHeaderData;
185 
186     MOS_STATUS status = m_encodeCtx->pCodecHal->Execute(&encodeParams);
187     if (MOS_STATUS_SUCCESS != status)
188     {
189         DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
190         return VA_STATUS_ERROR_ENCODING_ERROR;
191     }
192 
193     return VA_STATUS_SUCCESS;
194 
195 }
196 
ResetAtFrameLevel()197 VAStatus DdiEncodeHevcFei::ResetAtFrameLevel()
198 {
199     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
200 
201     // Assume there is only one SPS parameter
202     PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS hevcSeqParams = (PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
203     hevcSeqParams->bResetBRC                         = 0x0;
204 
205     m_encodeCtx->dwNumSlices      = 0x0;
206     m_encodeCtx->indexNALUnit     = 0x0;
207     m_encodeCtx->uiSliceHeaderCnt = 0x0;
208 
209     // reset bsbuffer every frame
210     m_encodeCtx->pbsBuffer->pCurrent    = m_encodeCtx->pbsBuffer->pBase;
211     m_encodeCtx->pbsBuffer->SliceOffset = 0x0;
212     m_encodeCtx->pbsBuffer->BitOffset   = 0x0;
213     m_encodeCtx->pbsBuffer->BitSize     = 0x0;
214 
215     CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
216 
217     m_encodeCtx->codecFunction              = CODECHAL_FUNCTION_FEI_ENC_PAK;
218     feiPicParams->NumMVPredictorsL0       = 0;     // number of MV Predictors L0 provided, max is 4
219     feiPicParams->NumMVPredictorsL1       = 0;     // number of MV Predictors L1 provided, max is 2
220     feiPicParams->SearchPath              = 0;     // search path, default is 0, 0 and 2 mean full search, 1 means diamond search
221     feiPicParams->LenSP                   = 57;    // max number of SUs per reference which is evaluated by the predetermined SUs, range is [1, 63]
222     feiPicParams->MultiPredL0             = 0;     // 000: no neighbor Motion Vectors will be used as predictor for L0, 001: spatial Motion Vectors, 010 temporal Motion Vectors, others: reserved.
223     feiPicParams->MultiPredL1             = 0;     // 000: no neighbor Motion Vectors will be used as predictor for L1, 001: spatial Motion Vectors, 010 temporal Motion Vectors, others: reserved.
224     feiPicParams->SubPelMode              = 3;     // half/quater pixels mode, 00b integer mode search, 01b half mode search, 11b quater mode search
225     feiPicParams->AdaptiveSearch          = true;  // whether adaptive searching is enabled for IME
226     feiPicParams->MVPredictorInput        = 0;     // 000: disable MV Predictor input, 001: enabled per 16x16 block,
227                                                     // 010: enabled per 32x32 block,
228                                                     // 011: enabled per 64x64 block,
229                                                     // 111: block size can vary and is determined by BlockSize in MVP
230                                                     // others: reserved
231     feiPicParams->bPerBlockQP             = false; // if enable per block QP input
232     feiPicParams->bPerCTBInput            = false; // if enable per MB control/special input
233     feiPicParams->bForceLCUSplit          = false; // specifies whether CTB should be forced to split to remove Inter big LCU
234     feiPicParams->bEnableCU64Check        = true;  // specifies whether 64x64 CB should be forced to split
235     feiPicParams->bEnableCU64AmpCheck     = false; // specifies if 64x64 CB AMP should be checked, 0: No CU 64x64 AMP check, 1: check LCU64x64 AMP
236     feiPicParams->bCU64SkipCheckOnly      = false; // specifies if check the 64x64 merge candidate, 0: after skip check, also run merge for TU1, 1: only skip check for 64x64 for TU4
237     feiPicParams->bColocatedCTBDistortion = false; // if enable, extra distortion between current CTB and co-located CTB is provided
238     feiPicParams->RefWidth                = 48;
239     feiPicParams->RefHeight               = 40;
240     feiPicParams->SearchWindow            = 0;
241     feiPicParams->MaxNumIMESearchCenter   = 6;     // specifies number [1~6] of MV predictors for IME searches
242     feiPicParams->NumConcurrentEncFramePartition = 1;    // specifies number [1, 2, 4] of splits that encoder could be run concurrently
243     feiPicParams->dwMaxFrameSize          = 0;     // specifies max frame size in bytes for multi-pass pak, 0 means disabling multi-pass pak
244 
245     feiPicParams->bDistortionEnable       = false;
246     feiPicParams->bCTBCmdCuRecordEnable   = false;
247 
248     // clear the packed header information
249     if (nullptr != m_encodeCtx->ppNALUnitParams)
250     {
251         MOS_ZeroMemory(m_encodeCtx->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * HEVC_MAX_NAL_UNIT_TYPE);
252     }
253 
254     m_encodeCtx->bHavePackedSliceHdr   = false;
255     m_encodeCtx->bLastPackedHdrIsSlice = false;
256     m_encodeCtx->bMBQpEnable           = false;
257 
258     return VA_STATUS_SUCCESS;
259 
260 }
261 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)262 VAStatus DdiEncodeHevcFei::RenderPicture(VADriverContextP ctx, VAContextID context, VABufferID *buffers, int32_t numBuffers)
263 {
264     VAStatus vaStatus = VA_STATUS_SUCCESS;
265 
266     DDI_FUNCTION_ENTER();
267 
268     DDI_CHK_NULL(ctx, "nullptr context", VA_STATUS_ERROR_INVALID_CONTEXT);
269 
270     DDI_MEDIA_CONTEXT *mediaCtx = DdiMedia_GetMediaContext(ctx);
271     DDI_CHK_NULL(mediaCtx, "Null mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
272 
273     DDI_CHK_NULL(m_encodeCtx, "Null m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
274 
275     for (int32_t i = 0; i < numBuffers; i++)
276     {
277         DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
278         DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER);
279         if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType)
280         {
281             DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer));
282             m_encodeCtx->bMbDisableSkipMapEnabled = true;
283             continue;
284         }
285         uint32_t dataSize = buf->iSize;
286         // can use internal function instead of DdiMedia_MapBuffer here?
287         void *data = nullptr;
288         DdiMedia_MapBuffer(ctx, buffers[i], &data);
289 
290         DDI_CHK_NULL(data, "Null data.", VA_STATUS_ERROR_INVALID_BUFFER);
291 
292         switch (buf->uiType)
293         {
294         case VAEncSequenceParameterBufferType:
295             DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
296             m_encodeCtx->bNewSeq = true;
297             break;
298 
299         case VAEncPictureParameterBufferType:
300             DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
301             DDI_CHK_STATUS(
302                     AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo),
303                     VA_STATUS_ERROR_INVALID_BUFFER);
304             break;
305 
306         case VAEncSliceParameterBufferType:
307         {
308             uint32_t numSlices = buf->uiNumElements;
309             DDI_CHK_STATUS(ParseSlcParams(mediaCtx, data, numSlices), VA_STATUS_ERROR_INVALID_BUFFER);
310             break;
311         }
312 
313         case VAEncPackedHeaderParameterBufferType:
314             vaStatus = ParsePackedHeaderParams(data);
315             break;
316 
317         case VAEncPackedHeaderDataBufferType:
318             vaStatus = ParsePackedHeaderData(data);
319             break;
320 
321         case VAEncMiscParameterBufferType:
322             DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
323             break;
324 
325         case VAEncQPBufferType:
326             DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer);
327             m_encodeCtx->bMBQpEnable = true;
328             break;
329 
330         case VAEncFEIMBControlBufferType:
331         case VAEncFEIMVPredictorBufferType:
332         case VAEncFEIMBCodeBufferType:
333         case VAEncFEICTBCmdBufferType:
334         case VAEncFEICURecordBufferType:
335         case VAEncFEIDistortionBufferType:
336             {
337                 // handled in VAEncMiscParameterBufferType/VAEncMiscParameterTypeFEIFrameControlIntel case by vaBufferID
338                 break;
339             }
340 
341         default:
342             DDI_ASSERTMESSAGE("not supported buffer type.");
343             break;
344         }
345         DdiMedia_UnmapBuffer(ctx, buffers[i]);
346     }
347 
348     DDI_FUNCTION_EXIT(vaStatus);
349     return vaStatus;
350 
351 }
352 
ParseMiscParamFeiPic(void * data)353 VAStatus DdiEncodeHevcFei::ParseMiscParamFeiPic(void *data)
354 {
355     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
356     CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
357     DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
358     VAEncMiscParameterFEIFrameControlHEVC *vaEncMiscParamFeiPic = (VAEncMiscParameterFEIFrameControlHEVC *)data;
359 
360     m_encodeCtx->codecFunction     = CODECHAL_FUNCTION_INVALID;
361     if(vaEncMiscParamFeiPic->function & VA_FEI_FUNCTION_ENC_PAK)
362         m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC_PAK;
363     if(vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_ENC)
364         m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC;
365     if(vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_PAK)
366         m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_PAK;
367 
368     feiPicParams->NumMVPredictorsL0       = vaEncMiscParamFeiPic->num_mv_predictors_l0;
369     feiPicParams->NumMVPredictorsL1       = vaEncMiscParamFeiPic->num_mv_predictors_l1;
370     feiPicParams->SearchPath              = vaEncMiscParamFeiPic->search_path;
371     feiPicParams->LenSP                   = vaEncMiscParamFeiPic->len_sp;
372     feiPicParams->MultiPredL0             = vaEncMiscParamFeiPic->multi_pred_l0;
373     feiPicParams->MultiPredL1             = vaEncMiscParamFeiPic->multi_pred_l1;
374     feiPicParams->SubPelMode              = vaEncMiscParamFeiPic->sub_pel_mode;
375     feiPicParams->AdaptiveSearch          = vaEncMiscParamFeiPic->adaptive_search;
376     feiPicParams->MVPredictorInput        = vaEncMiscParamFeiPic->mv_predictor_input;
377     feiPicParams->bPerBlockQP             = vaEncMiscParamFeiPic->per_block_qp;
378     feiPicParams->bPerCTBInput            = vaEncMiscParamFeiPic->per_ctb_input;
379     feiPicParams->bColocatedCTBDistortion = vaEncMiscParamFeiPic->colocated_ctb_distortion;
380     feiPicParams->bForceLCUSplit          = vaEncMiscParamFeiPic->force_lcu_split;
381     feiPicParams->bEnableCU64Check        = vaEncMiscParamFeiPic->enable_cu64_check;
382     feiPicParams->bEnableCU64AmpCheck     = vaEncMiscParamFeiPic->enable_cu64_amp_check;
383     feiPicParams->bCU64SkipCheckOnly      = vaEncMiscParamFeiPic->cu64_skip_check_only;
384     feiPicParams->RefWidth                = vaEncMiscParamFeiPic->ref_width;
385     feiPicParams->RefHeight               = vaEncMiscParamFeiPic->ref_height;
386     feiPicParams->SearchWindow            = vaEncMiscParamFeiPic->search_window;
387     feiPicParams->MaxNumIMESearchCenter   = vaEncMiscParamFeiPic->max_num_ime_search_center;
388     feiPicParams->FastIntraMode           = vaEncMiscParamFeiPic->fast_intra_mode;
389     feiPicParams->NumConcurrentEncFramePartition = vaEncMiscParamFeiPic->num_concurrent_enc_frame_partition;
390     feiPicParams->dwMaxFrameSize          = vaEncMiscParamFeiPic->max_frame_size;
391 
392     DDI_MEDIA_BUFFER *mediaBuffer;
393     VAStatus          status = VA_STATUS_SUCCESS;
394     if(feiPicParams->bPerCTBInput)
395     {
396         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->ctb_ctrl);
397         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
398         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCTBCtrl));
399     }
400     if(feiPicParams->MVPredictorInput)
401     {
402         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mv_predictor);
403         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
404         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMVPredictor));
405     }
406     else if((feiPicParams->NumMVPredictorsL0 !=0) || (feiPicParams->NumMVPredictorsL1 != 0))
407     {
408         DDI_ASSERTMESSAGE("feiPicParams->NumMVPredictorsL0 and NumMVPredictorsL1 should be set to 0 when feiPicParams->MVPredictorInput is false!");
409         status = VA_STATUS_ERROR_INVALID_PARAMETER;
410     }
411     if(feiPicParams->bPerBlockQP)
412     {
413         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->qp);
414         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
415         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCTBQp));
416     }
417 
418     feiPicParams->bCTBCmdCuRecordEnable = false;
419     if(vaEncMiscParamFeiPic->ctb_cmd != VA_INVALID_ID)
420     {
421         feiPicParams->bCTBCmdCuRecordEnable = true;
422         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->ctb_cmd);
423         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
424         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCTBCmd));
425         if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
426         {
427             RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MVDATA);
428             if( VA_STATUS_SUCCESS != AddToEncStatusReportQueue( (void *)(feiPicParams->resCTBCmd.bo), FEI_ENC_BUFFER_TYPE_MVDATA) )
429             {
430                 DDI_ASSERTMESSAGE("feiPicParams->resCTBCmd is invalid for FEI ENC only");
431                 status = VA_STATUS_ERROR_INVALID_PARAMETER;
432             }
433         }
434     }
435     if(vaEncMiscParamFeiPic->cu_record != VA_INVALID_ID)
436     {
437         if(feiPicParams->bCTBCmdCuRecordEnable == false)
438         {
439             DDI_ASSERTMESSAGE("CTB cmd and CU record should be enabled or disabled together!");
440             status = VA_STATUS_ERROR_INVALID_PARAMETER;
441         }
442         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->cu_record);
443         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
444         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resCURecord));
445         if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
446         {
447             RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MBCODE);
448             if( VA_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resCURecord.bo), FEI_ENC_BUFFER_TYPE_MBCODE) )
449             {
450                 DDI_ASSERTMESSAGE("feiPicParams->resCURecord is invalid for FEI ENC only");
451                 status = VA_STATUS_ERROR_INVALID_PARAMETER;
452             }
453         }
454     }
455 
456     if(vaEncMiscParamFeiPic->distortion != VA_INVALID_ID)
457     {
458         feiPicParams->bDistortionEnable = true;
459         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->distortion);
460         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
461         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resDistortion));
462         if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
463         {
464             RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_DISTORTION);
465             if( VA_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resDistortion.bo), FEI_ENC_BUFFER_TYPE_DISTORTION) )
466             {
467                 DDI_ASSERTMESSAGE("feiPicParams->resDistortion is invalid for FEI ENC only");
468                 status = VA_STATUS_ERROR_INVALID_PARAMETER;
469             }
470         }
471     }
472     if(m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
473     {
474         AddToEncStatusReportQueueUpdatePos();
475     }
476 
477     //add for mutlple pass pak
478     feiPicParams->dwMaxFrameSize = vaEncMiscParamFeiPic->max_frame_size;
479     if (feiPicParams->dwMaxFrameSize)
480     {
481         feiPicParams->dwNumPasses = vaEncMiscParamFeiPic->num_passes;
482         if ((feiPicParams->dwNumPasses == 0) || (feiPicParams->dwNumPasses > feiHevcMaxPassesNum))
483         {
484             return VA_STATUS_ERROR_INVALID_PARAMETER;
485         }
486         if (feiPicParams->pDeltaQp != nullptr)
487         {
488             MOS_FreeMemory(feiPicParams->pDeltaQp);
489         }
490         feiPicParams->pDeltaQp = (uint8_t *)MOS_AllocAndZeroMemory(sizeof(uint8_t) * feiPicParams->dwNumPasses);
491         if (!feiPicParams->pDeltaQp)
492         {
493             return VA_STATUS_ERROR_INVALID_PARAMETER;
494         }
495 
496         if (MOS_STATUS_SUCCESS != MOS_SecureMemcpy(feiPicParams->pDeltaQp, feiPicParams->dwNumPasses, vaEncMiscParamFeiPic->delta_qp, feiPicParams->dwNumPasses))
497         {
498             status = VA_STATUS_ERROR_INVALID_PARAMETER;
499         }
500     }
501 
502 finish:
503     return status;
504 }
505 
AddToEncStatusReportQueue(void * encBuf,DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)506 VAStatus DdiEncodeHevcFei::AddToEncStatusReportQueue(
507     void                           *encBuf,
508     DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)
509 {
510     DDI_CHK_NULL(encBuf, "nullptr encBuf", VA_STATUS_ERROR_INVALID_PARAMETER);
511 
512     CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
513     DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
514 
515     if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC)
516     {
517         DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! .");
518         return VA_STATUS_ERROR_INVALID_PARAMETER;
519     }
520     if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX))
521     {
522         DDI_ASSERTMESSAGE("ENC output buffers status checking, gets invalid buffer type index! .");
523         return VA_STATUS_ERROR_INVALID_PARAMETER;
524     }
525 
526     int32_t idx                                                 = m_encodeCtx->statusReportBuf.ulHeadPosition;
527     m_encodeCtx->statusReportBuf.encInfos[idx].pEncBuf[typeIdx] = encBuf;
528     m_encodeCtx->statusReportBuf.encInfos[idx].uiStatus         = 0;
529     m_encodeCtx->statusReportBuf.encInfos[idx].uiBuffers++;
530 
531     return VA_STATUS_SUCCESS;
532 }
533 
AddToEncStatusReportQueueUpdatePos()534 VAStatus DdiEncodeHevcFei::AddToEncStatusReportQueueUpdatePos()
535 {
536     CodecEncodeHevcFeiPicParams *feiPicParams = (CodecEncodeHevcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
537     DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
538 
539     if(m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC)
540     {
541         DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! .");
542         return VA_STATUS_ERROR_INVALID_PARAMETER;
543     }
544 
545     int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition;
546     if((m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers == (feiPicParams->bCTBCmdCuRecordEnable * 2 + feiPicParams->bDistortionEnable)) &&  m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers != 0)
547     {
548         m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
549     }
550 
551 finish:
552     return VA_STATUS_SUCCESS;
553 }
554 
ParseMiscParams(void * ptr)555 VAStatus DdiEncodeHevcFei::ParseMiscParams(void *ptr)
556 {
557     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
558     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
559     DDI_CHK_NULL(m_encodeCtx->pSeqParams, "nullptr m_encodeCtx->pSeqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
560     DDI_CHK_NULL(m_encodeCtx->pPicParams, "nullptr m_encodeCtx->pPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
561 
562     PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS seqParams = (PCODEC_HEVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
563     PCODEC_HEVC_ENCODE_PICTURE_PARAMS  picParams = (PCODEC_HEVC_ENCODE_PICTURE_PARAMS)(m_encodeCtx->pPicParams);
564 
565     VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr;
566     DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER);
567 
568     switch ((int32_t)(miscParamBuf->type))
569     {
570     case VAEncMiscParameterTypeQualityLevel:
571     {
572         VAEncMiscParameterBufferQualityLevel *vaEncMiscParamQualityLevel = (VAEncMiscParameterBufferQualityLevel *)miscParamBuf->data;
573         seqParams->TargetUsage                                           = (uint8_t)vaEncMiscParamQualityLevel->quality_level;
574 
575         // HEVC only supports TU=1, 4, and 7
576         if (1 != seqParams->TargetUsage && 4 != seqParams->TargetUsage && 7 != seqParams->TargetUsage)
577         {
578             DDI_ASSERTMESSAGE("unsupported target usage in HEVC encoder.");
579             return VA_STATUS_ERROR_INVALID_PARAMETER;
580         }
581         break;
582     }
583     case VAEncMiscParameterTypeHRD:
584     {
585         VAEncMiscParameterHRD *vaEncMiscParamHRD = (VAEncMiscParameterHRD *)miscParamBuf->data;
586         seqParams->VBVBufferSizeInBit            = vaEncMiscParamHRD->buffer_size;
587         seqParams->InitVBVBufferFullnessInBit    = vaEncMiscParamHRD->initial_buffer_fullness;
588         seqParams->RateControlMethod             = RATECONTROL_CBR;
589         break;
590     }
591     case VAEncMiscParameterTypeFrameRate:
592     {
593         VAEncMiscParameterFrameRate *vaEncMiscParamFR = (VAEncMiscParameterFrameRate *)miscParamBuf->data;
594         seqParams->FrameRate.Numerator                = vaEncMiscParamFR->framerate & 0xffff;
595         seqParams->FrameRate.Denominator              = (vaEncMiscParamFR->framerate >> 16 ) & 0xffff;
596         if(seqParams->FrameRate.Denominator == 0)
597         {
598             seqParams->FrameRate.Denominator = 1;
599         }
600         break;
601     }
602     case VAEncMiscParameterTypeRateControl:
603     {
604         // Assume only one SPS here, modify when enable multiple SPS support
605         VAEncMiscParameterRateControl *vaEncMiscParamRC = (VAEncMiscParameterRateControl *)miscParamBuf->data;
606 
607         seqParams->TargetBitRate = MOS_ROUNDUP_DIVIDE(vaEncMiscParamRC->bits_per_second, CODECHAL_ENCODE_BRC_KBPS);
608         seqParams->MBBRC         = (vaEncMiscParamRC->rc_flags.bits.mb_rate_control <= mbBrcDisabled) ? vaEncMiscParamRC->rc_flags.bits.mb_rate_control : 0;
609         //enable parallelBRC for Android and Linux
610         seqParams->ParallelBRC = vaEncMiscParamRC->rc_flags.bits.enable_parallel_brc;
611 
612         // Assuming picParams are sent before MiscParams
613         picParams->BRCMinQp = vaEncMiscParamRC->min_qp;
614         picParams->BRCMaxQp = vaEncMiscParamRC->max_qp;
615 
616         if (VA_RC_NONE == m_encodeCtx->uiRCMethod || VA_RC_CQP == m_encodeCtx->uiRCMethod)
617         {
618             seqParams->RateControlMethod = RATECONTROL_CQP;
619             seqParams->MBBRC             = 0;
620         }
621         else if ((VA_RC_CBR | VA_RC_MB) == m_encodeCtx->uiRCMethod || (VA_RC_CBR | VA_RC_MB | VA_RC_PARALLEL) == m_encodeCtx->uiRCMethod)
622         {
623             seqParams->MaxBitRate        = seqParams->TargetBitRate;
624             seqParams->MinBitRate        = seqParams->TargetBitRate;
625             seqParams->RateControlMethod = RATECONTROL_CBR;
626         }
627         else if (VA_RC_ICQ == m_encodeCtx->uiRCMethod || (VA_RC_ICQ | VA_RC_PARALLEL) == m_encodeCtx->uiRCMethod)
628         {
629             seqParams->ICQQualityFactor  = vaEncMiscParamRC->ICQ_quality_factor;
630             seqParams->RateControlMethod = RATECONTROL_ICQ;
631             seqParams->MBBRC             = 1;
632         }
633         else
634         {
635             switch (m_encodeCtx->uiRCMethod)
636             {
637             case (VA_RC_VCM | VA_RC_PARALLEL):
638             case VA_RC_VCM:
639                 seqParams->RateControlMethod = RATECONTROL_VCM;
640                 seqParams->MBBRC             = 0;
641                 break;
642             case (VA_RC_VBR | VA_RC_MB | VA_RC_PARALLEL):
643             case (VA_RC_VBR | VA_RC_MB):
644                 seqParams->RateControlMethod = RATECONTROL_VBR;
645                 break;
646             default:
647                 DDI_ASSERTMESSAGE("invalid RC method.");
648                 return VA_STATUS_ERROR_INVALID_PARAMETER;
649             }
650 
651             seqParams->MaxBitRate    = seqParams->TargetBitRate;
652             seqParams->MinBitRate    = seqParams->TargetBitRate * (2 * vaEncMiscParamRC->target_percentage - 100) / 100;
653             seqParams->TargetBitRate = seqParams->TargetBitRate * vaEncMiscParamRC->target_percentage / 100;
654 
655             if ((m_encodeCtx->uiTargetBitRate != seqParams->TargetBitRate) ||
656                 (m_encodeCtx->uiMaxBitRate != seqParams->MaxBitRate))
657             {
658                 if ((m_encodeCtx->uiTargetBitRate != 0) && (m_encodeCtx->uiMaxBitRate != 0))
659                 {
660                     seqParams->bResetBRC = 0x1;
661                 }
662                 m_encodeCtx->uiTargetBitRate = seqParams->TargetBitRate;
663                 m_encodeCtx->uiMaxBitRate    = seqParams->MaxBitRate;
664             }
665         }
666 
667         break;
668     }
669     case VAEncMiscParameterTypeParallelBRC:
670     {
671         VAEncMiscParameterParallelRateControl *vaEncMiscParameterParallel = (VAEncMiscParameterParallelRateControl *)miscParamBuf->data;
672 
673         seqParams->NumOfBInGop[0] = vaEncMiscParameterParallel->num_b_in_gop[0];
674         seqParams->NumOfBInGop[1] = vaEncMiscParameterParallel->num_b_in_gop[1];
675         seqParams->NumOfBInGop[2] = vaEncMiscParameterParallel->num_b_in_gop[2];
676 
677         break;
678     }
679     case VAEncMiscParameterTypeRIR:
680     {
681         VAEncMiscParameterRIR *vaEncMiscParamRIR = (VAEncMiscParameterRIR *)miscParamBuf->data;
682         picParams->bEnableRollingIntraRefresh    = vaEncMiscParamRIR->rir_flags.value & 0x3;  //only lower two bits are valid
683 
684         // Set for all frames since pic type is not known yet. Disable in slice params if its I or B type.
685         if ((ROLLING_I_COLUMN == picParams->bEnableRollingIntraRefresh) || (ROLLING_I_ROW == picParams->bEnableRollingIntraRefresh))
686         {
687             picParams->IntraInsertionLocation  = (uint16_t)vaEncMiscParamRIR->intra_insertion_location;
688             picParams->IntraInsertionSize      = (uint8_t)vaEncMiscParamRIR->intra_insert_size;
689             picParams->QpDeltaForInsertedIntra = vaEncMiscParamRIR->qp_delta_for_inserted_intra;
690         }
691         else if ((ROLLING_I_ROW | ROLLING_I_COLUMN) == picParams->bEnableRollingIntraRefresh)  // cannot have row and column rolling
692         {
693             picParams->bEnableRollingIntraRefresh = ROLLING_I_DISABLED;
694             return VA_STATUS_ERROR_INVALID_PARAMETER;
695         }
696 
697         break;
698     }
699     case VAEncMiscParameterTypeROI:
700     {
701         VAEncMiscParameterBufferROI *vaEncMiscParamROI = (VAEncMiscParameterBufferROI *)miscParamBuf->data;
702         uint32_t                     maxROIsupported   = CODECHAL_ENCODE_HEVC_MAX_NUM_ROI;
703         uint8_t                      blockSize         = (m_encodeCtx->bVdencActive) ? vdencRoiBlockSize : CODECHAL_MACROBLOCK_WIDTH;
704 
705         if (vaEncMiscParamROI->num_roi)
706         {
707             for (uint32_t i = 0; i < vaEncMiscParamROI->num_roi; ++i)
708             {
709                 picParams->ROI[i].PriorityLevelOrDQp = vaEncMiscParamROI->roi[i].roi_value;
710                 picParams->ROI[i].Top                = vaEncMiscParamROI->roi[i].roi_rectangle.y;
711                 picParams->ROI[i].Left               = vaEncMiscParamROI->roi[i].roi_rectangle.x;
712                 picParams->ROI[i].Bottom             = vaEncMiscParamROI->roi[i].roi_rectangle.y +
713                                            vaEncMiscParamROI->roi[i].roi_rectangle.height - 1;
714                 picParams->ROI[i].Right = vaEncMiscParamROI->roi[i].roi_rectangle.x +
715                                           vaEncMiscParamROI->roi[i].roi_rectangle.width - 1;
716 
717                 if (m_encodeCtx->bVdencActive == false)
718                 {
719                     // align to CTB edge (32 on Gen9) to avoid QP average issue
720                     picParams->ROI[i].Left   = MOS_ALIGN_FLOOR(picParams->ROI[i].Left, 32);
721                     picParams->ROI[i].Right  = MOS_ALIGN_CEIL(picParams->ROI[i].Right, 32);
722                     picParams->ROI[i].Top    = MOS_ALIGN_FLOOR(picParams->ROI[i].Top, 32);
723                     picParams->ROI[i].Bottom = MOS_ALIGN_CEIL(picParams->ROI[i].Bottom, 32);
724                 }
725 
726                 // Convert from pixel units to block size units
727                 picParams->ROI[i].Left /= blockSize;
728                 picParams->ROI[i].Right /= blockSize;
729                 picParams->ROI[i].Top /= blockSize;
730                 picParams->ROI[i].Bottom /= blockSize;
731             }
732             picParams->NumROI = MOS_MIN(vaEncMiscParamROI->num_roi, maxROIsupported);
733         }
734 #ifndef ANDROID
735         // support DeltaQP based ROI by default
736         seqParams->ROIValueInDeltaQP = vaEncMiscParamROI->roi_flags.bits.roi_value_is_qp_delta;
737 #endif
738         break;
739     }
740     case VAEncMiscParameterTypeSkipFrame:
741     {
742         VAEncMiscParameterSkipFrame *vaEncMiscParamSkipFrame = (VAEncMiscParameterSkipFrame *)miscParamBuf->data;
743         // populate skipped frame params from DDI
744         if (FRAME_SKIP_NORMAL != vaEncMiscParamSkipFrame->skip_frame_flag)
745         {
746             DDI_ASSERTMESSAGE("unsupported misc parameter type.");
747             return VA_STATUS_ERROR_INVALID_PARAMETER;
748         }
749         picParams->SkipFrameFlag  = vaEncMiscParamSkipFrame->skip_frame_flag;
750         picParams->NumSkipFrames  = vaEncMiscParamSkipFrame->num_skip_frames;
751         picParams->SizeSkipFrames = vaEncMiscParamSkipFrame->size_skip_frames;
752         break;
753     }
754     case VAEncMiscParameterTypeMaxSliceSize:
755     {
756         VAEncMiscParameterMaxSliceSize *vaEncMiscParamMaxSliceSize = (VAEncMiscParameterMaxSliceSize *)miscParamBuf->data;
757         m_encodeCtx->EnableSliceLevelRateCtrl                      = true;
758         seqParams->SliceSizeControl                                = true;
759         picParams->MaxSliceSizeInBytes                             = vaEncMiscParamMaxSliceSize->max_slice_size;
760         break;
761     }
762     case VAEncMiscParameterTypeEncQuality:
763     {
764         VAEncMiscParameterEncQuality *vaEncMiscParamEncQuality        = (VAEncMiscParameterEncQuality *)miscParamBuf->data;
765         picParams->bUseRawPicForRef                                = vaEncMiscParamEncQuality->useRawPicForRef;
766         break;
767     }
768     case VAEncMiscParameterTypeFEIFrameControl:
769     {
770         if (VA_STATUS_SUCCESS != ParseMiscParamFeiPic((void *)miscParamBuf->data))
771         {
772             DDI_ASSERTMESSAGE("parse misc FEI picture parameters error.");
773             return VA_STATUS_ERROR_INVALID_PARAMETER;
774         }
775         break;
776     }
777     default:
778         DDI_ASSERTMESSAGE("unsupported misc parameter type.");
779         return VA_STATUS_ERROR_INVALID_PARAMETER;
780     }
781 
782     return VA_STATUS_SUCCESS;
783 }
784 
785