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