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     media_ddi_encode_fei_avc.cpp
24 //! \brief    Implements class for DDI media avc 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 "media_ddi_encode_base.h"
32 #include "media_ddi_encode_fei_avc.h"
33 #include "media_ddi_encode_const.h"
34 #include "media_ddi_factory.h"
35 static const uint8_t feiMaxPassesNum = 4;
36 
37 extern template class MediaDdiFactoryNoArg<DdiEncodeBase>;
38 
39 static bool isEncodeAvcFeiRegistered =
40     MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeAvcFei>(ENCODE_ID_AVCFEI);
41 
~DdiEncodeAvcFei()42 DdiEncodeAvcFei::~DdiEncodeAvcFei()
43 {
44     if (nullptr == m_encodeCtx)
45     {
46         return;
47     }
48     MOS_FreeMemory(m_encodeCtx->pFeiPicParams);
49     m_encodeCtx->pFeiPicParams = nullptr;
50 
51     MOS_FreeMemory(m_encodeCtx->pPreEncParams);
52     m_encodeCtx->pPreEncParams = nullptr;
53 
54     MOS_FreeMemory(iqMatrixParams);
55     iqMatrixParams = nullptr;
56 
57     MOS_FreeMemory(iqWeightScaleLists);
58     iqWeightScaleLists = nullptr;
59 
60 }
61 
ContextInitialize(CodechalSetting * codecHalSettings)62 VAStatus DdiEncodeAvcFei::ContextInitialize(CodechalSetting * codecHalSettings)
63 {
64     VAStatus status = DdiEncodeAvc::ContextInitialize(codecHalSettings);
65     if (VA_STATUS_SUCCESS != status)
66     {
67         return status;
68     }
69 
70     codecHalSettings->codecFunction = m_encodeCtx->codecFunction;
71 
72     m_encodeCtx->pFeiPicParams = (void *)MOS_AllocAndZeroMemory(CODEC_AVC_MAX_PPS_NUM * sizeof(CodecEncodeAvcFeiPicParams));
73     DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "nullptr m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
74 
75     m_encodeCtx->pPreEncParams = (void *)MOS_AllocAndZeroMemory(CODEC_AVC_MAX_PPS_NUM * sizeof(FeiPreEncParams));
76     DDI_CHK_NULL(m_encodeCtx->pPreEncParams, "nullptr m_encodeCtx->pPreEncParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
77 
78     iqMatrixParams = (PCODEC_AVC_IQ_MATRIX_PARAMS)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_IQ_MATRIX_PARAMS));
79     DDI_CHK_NULL(iqMatrixParams, "nullptr iqMatrixParams", VA_STATUS_ERROR_ALLOCATION_FAILED);
80 
81     iqWeightScaleLists = (PCODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS)MOS_AllocAndZeroMemory(sizeof(CODEC_AVC_ENCODE_IQ_WEIGTHSCALE_LISTS));
82     DDI_CHK_NULL(iqWeightScaleLists, "nullptr iqWeightScaleLists", VA_STATUS_ERROR_ALLOCATION_FAILED);
83 
84     return VA_STATUS_SUCCESS;
85 }
86 
EncodeInCodecHal(uint32_t numSlices)87 VAStatus DdiEncodeAvcFei::EncodeInCodecHal(uint32_t numSlices)
88 {
89     uint8_t   ppsIdx, spsIdx;
90     PCODEC_AVC_ENCODE_PIC_PARAMS      picParams;
91 
92     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
93     DDI_CHK_NULL(m_encodeCtx->pCodecHal, "nullptr m_encodeCtx->pCodecHal", VA_STATUS_ERROR_INVALID_CONTEXT);
94     DDI_CHK_NULL(m_encodeCtx->pMediaCtx, "nullptr m_encodeCtx->pMediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
95     CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
96     FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
97 
98     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl     = &(m_encodeCtx->RTtbl);
99 
100     MOS_STATUS status;
101 
102     EncoderParams *encodeParams = &m_encodeCtx->EncodeParams;
103     MOS_ZeroMemory(encodeParams, sizeof(EncoderParams));
104 
105     if ((feiPicParams != nullptr) && CodecHalIsFeiEncode(m_encodeCtx->codecFunction))
106     {
107         encodeParams->ExecCodecFunction = m_encodeCtx->codecFunction;
108     }
109     else if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
110     {
111         encodeParams->ExecCodecFunction = m_encodeCtx->codecFunction;
112     }
113     else
114     {
115         encodeParams->ExecCodecFunction = CODECHAL_FUNCTION_ENC_PAK;
116     }
117 
118     // Raw Surface
119     PMOS_SURFACE rawSurface = &encodeParams->rawSurface;
120     rawSurface->Format   = Format_NV12;
121     rawSurface->dwOffset = 0;
122 
123     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface->OsResource));
124 
125     if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
126     {
127         if (rtTbl->pRT[preEncParams->CurrOriginalPicture.FrameIdx] != rtTbl->pCurrentRT)
128         {
129             DDI_ASSERTMESSAGE("PREENC CurrOriginalPicture.FrameIdx != pCurrentRT");
130         }
131         rawSurface->dwWidth                  = rawSurface->OsResource.iWidth;
132         rawSurface->dwHeight                 = rawSurface->OsResource.iHeight;
133         rawSurface->dwPitch                  = rawSurface->OsResource.iPitch;
134         rawSurface->TileType                 = rawSurface->OsResource.TileType;
135         rawSurface->TileModeGMM              = rawSurface->OsResource.TileModeGMM;
136         rawSurface->bGMMTileEnabled          = rawSurface->OsResource.bGMMTileEnabled;
137         preEncParams->psCurrOriginalSurface  = rawSurface;
138         encodeParams->pPreEncParams          = m_encodeCtx->pPreEncParams;
139         DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, false), "ClearRefList failed!");
140     }
141     else
142     {
143         // Recon Surface
144         PMOS_SURFACE reconSurface = &encodeParams->reconSurface;
145         reconSurface->Format   = Format_NV12;
146         reconSurface->dwOffset = 0;
147 
148         DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface->OsResource));
149 
150         // Bitstream surface
151         PMOS_RESOURCE bitstreamSurface = &encodeParams->resBitstreamBuffer;
152         *bitstreamSurface        = m_encodeCtx->resBitstreamBuffer;  // in render picture
153         bitstreamSurface->Format = Format_Buffer;
154 
155         encodeParams->psRawSurface = &encodeParams->rawSurface;
156         encodeParams->psReconSurface = &encodeParams->reconSurface;
157         encodeParams->presBitstreamBuffer = &encodeParams->resBitstreamBuffer;
158 
159         PMOS_SURFACE mbQpSurface = &encodeParams->mbQpSurface;
160         if (m_encodeCtx->bMBQpEnable)
161         {
162             mbQpSurface->Format             = Format_Buffer_2D;
163             mbQpSurface->dwOffset           = 0;
164             mbQpSurface->OsResource         = m_encodeCtx->resMBQpBuffer;
165             encodeParams->psMbQpDataSurface = &encodeParams->mbQpSurface;
166             encodeParams->bMbQpDataEnabled  = true;
167         }
168 
169         PMOS_SURFACE disableSkipMapSurface = &encodeParams->disableSkipMapSurface;
170         encodeParams->bMbDisableSkipMapEnabled = m_encodeCtx->bMbDisableSkipMapEnabled;
171         if (encodeParams->bMbDisableSkipMapEnabled)
172         {
173             disableSkipMapSurface->Format           = Format_Buffer;
174             disableSkipMapSurface->dwOffset         = 0;
175             disableSkipMapSurface->OsResource       = m_encodeCtx->resPerMBSkipMapBuffer;
176             encodeParams->psMbDisableSkipMapSurface = &encodeParams->disableSkipMapSurface;
177         }
178 
179         // correct some params
180         if (CODECHAL_ENCODE_MODE_AVC == m_encodeCtx->wModeType)
181         {
182             PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams;
183             CODECHAL_ENCODE_AVC_VUI_PARAMS    *vuiParam;
184 
185             vuiParam  = (CODECHAL_ENCODE_AVC_VUI_PARAMS *)m_encodeCtx->pVuiParams;
186             seqParams = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
187 
188             if (VA_RC_CQP == m_encodeCtx->uiRCMethod)
189             {
190                 vuiParam->bit_rate_value_minus1[0]    = 0;
191                 vuiParam->cpb_size_value_minus1[0]    = 0;
192                 seqParams->TargetBitRate              = 0;
193                 seqParams->MaxBitRate                 = 0;
194                 seqParams->MinBitRate                 = 0;
195                 seqParams->InitVBVBufferFullnessInBit = 0;
196                 seqParams->VBVBufferSizeInBit         = 0;
197             }
198 
199             encodeParams->uiSlcStructCaps = CODECHAL_SLICE_STRUCT_ARBITRARYMBSLICE;
200         }
201 
202         ppsIdx                           = ((PCODEC_AVC_ENCODE_SLICE_PARAMS)(m_encodeCtx->pSliceParams))->pic_parameter_set_id;
203         picParams                        = (PCODEC_AVC_ENCODE_PIC_PARAMS)m_encodeCtx->pPicParams + ppsIdx;
204         spsIdx                           = picParams->seq_parameter_set_id;
205         encodeParams->pSeqParams         = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)m_encodeCtx->pSeqParams + spsIdx;
206         encodeParams->pPicParams         = picParams;
207         encodeParams->pVuiParams         = m_encodeCtx->pVuiParams;
208         encodeParams->pSliceParams       = m_encodeCtx->pSliceParams;
209         encodeParams->pAVCQCParams       = m_qcParams;
210         encodeParams->pAVCRoundingParams = m_roundingParams;
211 
212         // Sequence data
213         encodeParams->bNewSeq = m_encodeCtx->bNewSeq;
214         // VUI
215         encodeParams->bNewVuiData = m_encodeCtx->bNewVuiData;
216 
217         // Slice level data
218         encodeParams->dwNumSlices = numSlices;
219 
220         // IQmatrix params
221         encodeParams->bNewQmatrixData = m_encodeCtx->bNewQmatrixData;
222         encodeParams->bPicQuant       = m_encodeCtx->bPicQuant;
223         encodeParams->ppNALUnitParams = m_encodeCtx->ppNALUnitParams;
224         encodeParams->pSeiData        = m_encodeCtx->pSEIFromApp;
225         encodeParams->pSeiParamBuffer = m_encodeCtx->pSEIFromApp->pSEIBuffer;
226         encodeParams->dwSEIDataOffset = 0;
227 
228         status = MOS_SecureMemcpy(&iqMatrixParams->ScalingList4x4,
229             6 * 16 * sizeof(uint8_t),
230             &m_scalingLists4x4,
231             6 * 16 * sizeof(uint8_t));
232         if (MOS_STATUS_SUCCESS != status)
233         {
234             DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 4x4!");
235             return VA_STATUS_ERROR_INVALID_PARAMETER;
236         }
237 
238         status = MOS_SecureMemcpy(&iqMatrixParams->ScalingList8x8,
239             2 * 64 * sizeof(uint8_t),
240             &m_scalingLists8x8,
241             2 * 64 * sizeof(uint8_t));
242         if (MOS_STATUS_SUCCESS != status)
243         {
244             DDI_ASSERTMESSAGE("DDI:Failed to copy scaling list 8x8!");
245             return VA_STATUS_ERROR_INVALID_PARAMETER;
246         }
247 
248         encodeParams->pIQMatrixBuffer = iqMatrixParams;
249 
250         status = MOS_SecureMemcpy(&iqWeightScaleLists->WeightScale4x4,
251             (CODEC_AVC_WEIGHT_SCALE_4x4 * sizeof(uint32_t)),
252             &m_weightScale4x4,
253             (CODEC_AVC_WEIGHT_SCALE_4x4 * sizeof(uint32_t)));
254         if (MOS_STATUS_SUCCESS != status)
255         {
256             DDI_ASSERTMESSAGE("DDI:Failed to copy weight scale list 4x4!");
257             return VA_STATUS_ERROR_INVALID_PARAMETER;
258         }
259 
260         status = MOS_SecureMemcpy(&iqWeightScaleLists->WeightScale8x8,
261             (CODEC_AVC_WEIGHT_SCALE_8x8 * sizeof(uint32_t)),
262             &m_weightScale8x8,
263             (CODEC_AVC_WEIGHT_SCALE_8x8 * sizeof(uint32_t)));
264         if (MOS_STATUS_SUCCESS != status)
265         {
266             DDI_ASSERTMESSAGE("DDI:Failed to copy weight scale list 8x8!");
267             return VA_STATUS_ERROR_INVALID_PARAMETER;
268         }
269 
270         encodeParams->pIQWeightScaleLists = iqWeightScaleLists;
271 
272         // whether driver need to pack slice header
273         if (true == m_encodeCtx->bHavePackedSliceHdr)
274         {
275             encodeParams->bAcceleratorHeaderPackingCaps = false;
276         }
277         else
278         {
279             encodeParams->bAcceleratorHeaderPackingCaps = true;
280         }
281 
282         encodeParams->pBSBuffer      = m_encodeCtx->pbsBuffer;
283         encodeParams->pSlcHeaderData = (void *)m_encodeCtx->pSliceHeaderData;
284         encodeParams->pFeiPicParams  = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
285         //clear registered recon/ref surface flags
286         DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, true), "ClearRefList failed!");
287     }
288 
289     CodechalEncoderState *encoder = dynamic_cast<CodechalEncoderState *>(m_encodeCtx->pCodecHal);
290     DDI_CHK_NULL(encoder, "nullptr Codechal encode", VA_STATUS_ERROR_INVALID_PARAMETER);
291 
292     if (!encoder->m_mfeEnabled)
293     {
294         status = m_encodeCtx->pCodecHal->Execute(encodeParams);
295         if (MOS_STATUS_SUCCESS != status)
296         {
297             DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
298             return VA_STATUS_ERROR_ENCODING_ERROR;
299         }
300     }
301 
302     return VA_STATUS_SUCCESS;
303 }
304 
ResetAtFrameLevel()305 VAStatus DdiEncodeAvcFei::ResetAtFrameLevel()
306 {
307     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
308     DDI_CHK_NULL(m_encodeCtx->pFeiPicParams, "nullptr m_encodeCtx->pFeiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
309     DDI_CHK_NULL(m_encodeCtx->pPreEncParams, "nullptr m_encodeCtx->pPreEncParams", VA_STATUS_ERROR_INVALID_PARAMETER);
310 
311     // Assume there is only one SPS parameter
312     PCODEC_AVC_ENCODE_SEQUENCE_PARAMS seqParams      = (PCODEC_AVC_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
313     seqParams->bInitBRC                              = 0x0;
314     seqParams->bResetBRC                             = 0x0;
315     CodecEncodeAvcFeiPicParams         *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
316     FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
317 
318     m_encodeCtx->dwNumSlices      = 0x0;
319     m_encodeCtx->indexNALUnit     = 0x0;
320     m_encodeCtx->uiSliceHeaderCnt = 0x0;
321 
322     // reset bsbuffer every frame
323     m_encodeCtx->pbsBuffer->pCurrent    = m_encodeCtx->pbsBuffer->pBase;
324     m_encodeCtx->pbsBuffer->SliceOffset = 0x0;
325     m_encodeCtx->pbsBuffer->BitOffset   = 0x0;
326     m_encodeCtx->pbsBuffer->BitSize     = 0x0;
327 
328     // clear the packed header information
329     if (nullptr != m_encodeCtx->ppNALUnitParams)
330     {
331         MOS_ZeroMemory(m_encodeCtx->ppNALUnitParams[0], sizeof(CODECHAL_NAL_UNIT_PARAMS) * CODECHAL_ENCODE_AVC_MAX_NAL_TYPE);
332     }
333 
334     m_encodeCtx->bHavePackedSliceHdr      = false;
335     m_encodeCtx->bLastPackedHdrIsSlice    = false;
336     m_encodeCtx->bMbDisableSkipMapEnabled = false;
337     m_encodeCtx->bMBQpEnable              = false;
338 
339     if (nullptr != m_roundingParams)
340     {
341         MOS_ZeroMemory(m_roundingParams, sizeof(CODECHAL_ENCODE_AVC_ROUNDING_PARAMS));
342     }
343 
344     if (CodecHalIsFeiEncode(m_encodeCtx->codecFunction) && m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_PRE_ENC)
345     {
346         m_encodeCtx->codecFunction             = CODECHAL_FUNCTION_FEI_ENC_PAK;
347         feiPicParams->NumMVPredictorsL0      = 0;      // number of MV Predictors L0 provided, max is 4
348         feiPicParams->NumMVPredictorsL1      = 0;      // number of MV Predictors L1 provided, max is 2
349         feiPicParams->SearchPath             = 0;      // search path, default is 0, 0 and 2 mean full search, 1 means diamond search
350         feiPicParams->LenSP                  = 57;     // max number of SUs per reference which is evaluated by the predetermined SUs, range is [1, 63]
351         feiPicParams->SubMBPartMask          = 0x77;   // the bit-mask for disabling sub-partition, bit 0 16x16, bit 1 16x8, bit 2 8x16 ... default value is 1110111b
352         feiPicParams->IntraPartMask          = 0;      // luma intra partition mask bits, bit 0 16x16, bit 1 8x8, bit 2 4x4
353         feiPicParams->MultiPredL0            = false;  // true neighbor MV will be used as predictori for L0, false will not.
354         feiPicParams->MultiPredL1            = false;  // true neighbor MV will be used as predictori for L0, false will not.
355         feiPicParams->SubPelMode             = 3;      // half/quater pixels mode, 00b integer mode search, 01b half mode search, 11b quater mode search
356         feiPicParams->InterSAD               = 2;
357         feiPicParams->IntraSAD               = 2;
358         feiPicParams->DistortionType         = 0;      // output distortion type, 0 raw distortion without cost, 1 distortion with cost
359         feiPicParams->RepartitionCheckEnable = false;  // true, enables the additional calls on Fraction & Bidirectional Refinement
360         feiPicParams->AdaptiveSearch         = true;   // whether adaptive searching is enabled for IME
361         feiPicParams->MVPredictorEnable      = false;  // if enable MV Predictor input
362         feiPicParams->bMBQp                  = false;  // if enable MB per QP input
363         feiPicParams->bPerMBInput            = false;  // if enable per MB control/special input
364         feiPicParams->bMBSizeCtrl            = false;  // if enable MB size control when enabled per MB special input
365         feiPicParams->RefWidth               = 48;
366         feiPicParams->RefHeight              = 40;
367         feiPicParams->SearchWindow           = 0;
368 
369         feiPicParams->DistortionEnable = false;
370         feiPicParams->MbCodeMvEnable   = false;
371     }
372 
373     if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_PRE_ENC)
374     {
375         preEncParams->dwNumPastReferences   = 1;  // Number of past reference frame
376         preEncParams->dwNumFutureReferences = 0;  // Number of future reference frame
377         MOS_ZeroMemory(&(preEncParams->CurrOriginalPicture), sizeof(CODEC_PICTURE));
378         MOS_ZeroMemory(&(preEncParams->PastRefPicture), sizeof(CODEC_PICTURE));
379         MOS_ZeroMemory(&(preEncParams->FutureRefPicture), sizeof(CODEC_PICTURE));
380 
381         preEncParams->dwFrameQp         = 25;    // Frame level QP
382         preEncParams->dwLenSP           = 57;    // max number of SUs per reference which is evaluated by the predetermined SUs, range is [1, 63]
383         preEncParams->dwSearchPath      = 0;     // search path, default is 0, 0 and 2 mean full search, 1 means diamond search
384         preEncParams->dwSubMBPartMask   = 0x77;  // the bit-mask for disabling sub-partition, bit 0 16x16, bit 1 16x8, bit 2 8x16 ... default value is 1110111b
385         preEncParams->dwIntraPartMask   = 0;
386         preEncParams->dwSubPelMode      = 3;  // half/quater pixels mode, 00b integer mode search, 01b half mode search, 11b quater mode search
387         preEncParams->dwInterSAD        = 2;
388         preEncParams->dwIntraSAD        = 2;
389         preEncParams->bAdaptiveSearch   = 1;      // whether adaptive searching is enabled for IME
390         preEncParams->dwMVPredictorCtrl = 0;      // MV predictor control, 0, disable, 1, enabled for past reference, 2, enabled for future reference, 3 enabled for both
391         preEncParams->bMBQp             = false;  // if enable MB per QP input
392         preEncParams->bFTEnable         = false;  // if use provided QP (frame level QP and per MB QP) and obtained MV to judge the number of non zero coefficients
393         preEncParams->dwRefWidth        = 48;
394         preEncParams->dwRefHeight       = 40;
395         preEncParams->dwSearchWindow    = 0;             // defines predefined search windows, 0, disable
396                                                          // 1, Tiny 4 SUs 24x24 windows
397                                                          // 2, small 9 SUs 28x28 windows
398                                                          // 3, diamond 16 SUs 48x40 windows
399                                                          // 4, large diamon 32SUs 48x40 windows
400                                                          // 5, exhaustive 48SUs 48x40 windows
401         preEncParams->bDisableMVOutput         = false;  // if disable MV output buffer
402         preEncParams->bDisableStatisticsOutput = false;  // if disable Statisticts output buffer
403         preEncParams->bEnable8x8Statistics     = false;  // if enable, generate block8x8 average and variance output
404     }
405 
406     return VA_STATUS_SUCCESS;
407 }
408 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)409 VAStatus DdiEncodeAvcFei::RenderPicture(
410     VADriverContextP ctx,
411     VAContextID      context,
412     VABufferID       *buffers,
413     int32_t          numBuffers)
414 {
415     DDI_FUNCTION_ENTER();
416 
417     DDI_CHK_NULL(ctx, "nullptr context in vpgEncodeRenderPicture!", VA_STATUS_ERROR_INVALID_CONTEXT);
418     PDDI_MEDIA_CONTEXT mediaCtx = DdiMedia_GetMediaContext(ctx);
419     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
420 
421     // assume the VAContextID is encoder ID
422     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
423 
424     uint32_t numSlices = 0;
425     VAStatus vaStatus  = VA_STATUS_SUCCESS;
426 
427     DDI_MEDIA_BUFFER *buf;
428     void             *data;
429     uint32_t         dataSize;
430     for (int32_t i = 0; i < numBuffers; i++)
431     {
432         buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
433         DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER);
434         if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType)
435         {
436             DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer));
437             m_encodeCtx->bMbDisableSkipMapEnabled = true;
438             continue;
439         }
440         dataSize = buf->iSize;
441         // can use internal function instead of DdiMedia_MapBuffer here?
442         DdiMedia_MapBuffer(ctx, buffers[i], &data);
443 
444         DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_BUFFER);
445 
446         switch (buf->uiType)
447         {
448         case VAIQMatrixBufferType:
449         case VAQMatrixBufferType:
450             DDI_CHK_STATUS(Qmatrix(data), VA_STATUS_ERROR_INVALID_BUFFER);
451             break;
452 
453         case VAEncSequenceParameterBufferType:
454             DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
455             m_encodeCtx->bNewSeq = true;
456             break;
457 
458         case VAEncPictureParameterBufferType:
459             DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
460 
461             // it should use pFeiPicParams->function, but it may be still not set here yet
462             if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
463                 break;
464 
465             DDI_CHK_STATUS(
466                 AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo),
467                 VA_STATUS_ERROR_INVALID_BUFFER);
468             break;
469 
470         case VAEncSliceParameterBufferType:
471             numSlices = buf->uiNumElements;
472             DDI_CHK_STATUS(ParseSlcParams(mediaCtx, data, numSlices), VA_STATUS_ERROR_INVALID_BUFFER);
473             break;
474 
475         case VAEncPackedHeaderParameterBufferType:
476             DDI_CHK_STATUS(ParsePackedHeaderParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
477             break;
478 
479         case VAEncPackedHeaderDataBufferType:
480             vaStatus = ParsePackedHeaderData(data);
481             break;
482 
483         case VAEncMiscParameterBufferType:
484             DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
485             break;
486 
487         case VAEncQPBufferType:
488             DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer);
489             m_encodeCtx->bMBQpEnable = true;
490             break;
491 
492         case VAStatsStatisticsParameterBufferType:
493             DDI_CHK_STATUS(ParseStatsParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
494             break;
495 
496         case VAEncFEIMBControlBufferType:
497         case VAEncFEIMVPredictorBufferType:
498         case VAEncFEIMVBufferType:
499         case VAEncFEIMBCodeBufferType:
500         case VAEncFEIDistortionBufferType:
501         case VAStatsMVPredictorBufferType:
502         case VAStatsStatisticsBufferType:
503         case VAStatsStatisticsBottomFieldBufferType:
504         case VAStatsMVBufferType:
505         {
506             // handled in VAEncMiscParameterBufferType/VAEncMiscParameterTypeFEIFrameControlIntel case by vaBufferID
507             break;
508         }
509         default:
510             DDI_ASSERTMESSAGE("not supported buffer type in vpgEncodeRenderPicture.");
511             // vaStatus = VA_STATUS_ERROR_UNSUPPORTED_BUFFERTYPE;
512             break;
513         }
514         DdiMedia_UnmapBuffer(ctx, buffers[i]);
515     }
516 
517     DDI_FUNCTION_EXIT(vaStatus);
518     return vaStatus;
519 }
520 
ParseMiscParamFeiPic(void * data)521 VAStatus DdiEncodeAvcFei::ParseMiscParamFeiPic(void *data)
522 {
523     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
524     CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
525     DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
526     VAEncMiscParameterFEIFrameControlH264 *vaEncMiscParamFeiPic = (VAEncMiscParameterFEIFrameControlH264*)data;
527 
528     m_encodeCtx->codecFunction     = CODECHAL_FUNCTION_INVALID;
529     if (vaEncMiscParamFeiPic->function & VA_FEI_FUNCTION_ENC_PAK)
530         m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC_PAK;
531     if (vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_ENC)
532         m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_ENC;
533     if (vaEncMiscParamFeiPic->function == VA_FEI_FUNCTION_PAK)
534         m_encodeCtx->codecFunction = CODECHAL_FUNCTION_FEI_PAK;
535 
536     feiPicParams->NumMVPredictorsL0      = vaEncMiscParamFeiPic->num_mv_predictors_l0;
537     feiPicParams->NumMVPredictorsL1      = vaEncMiscParamFeiPic->num_mv_predictors_l1;
538     feiPicParams->SearchPath             = vaEncMiscParamFeiPic->search_path;
539     feiPicParams->LenSP                  = vaEncMiscParamFeiPic->len_sp;
540     feiPicParams->SubMBPartMask          = vaEncMiscParamFeiPic->sub_mb_part_mask;
541     feiPicParams->IntraPartMask          = vaEncMiscParamFeiPic->intra_part_mask;
542     feiPicParams->MultiPredL0            = vaEncMiscParamFeiPic->multi_pred_l0;
543     feiPicParams->MultiPredL1            = vaEncMiscParamFeiPic->multi_pred_l1;
544     feiPicParams->SubPelMode             = vaEncMiscParamFeiPic->sub_pel_mode;
545     feiPicParams->InterSAD               = vaEncMiscParamFeiPic->inter_sad;
546     feiPicParams->IntraSAD               = vaEncMiscParamFeiPic->intra_sad;
547     feiPicParams->DistortionType         = vaEncMiscParamFeiPic->distortion_type;
548     feiPicParams->RepartitionCheckEnable = vaEncMiscParamFeiPic->repartition_check_enable;
549     feiPicParams->AdaptiveSearch         = vaEncMiscParamFeiPic->adaptive_search;
550     feiPicParams->MVPredictorEnable      = vaEncMiscParamFeiPic->mv_predictor_enable;
551     feiPicParams->bMBQp                  = vaEncMiscParamFeiPic->mb_qp;
552     feiPicParams->bPerMBInput            = vaEncMiscParamFeiPic->mb_input;
553     feiPicParams->bMBSizeCtrl            = vaEncMiscParamFeiPic->mb_size_ctrl;
554     feiPicParams->RefWidth               = vaEncMiscParamFeiPic->ref_width;
555     feiPicParams->RefHeight              = vaEncMiscParamFeiPic->ref_height;
556     feiPicParams->SearchWindow           = vaEncMiscParamFeiPic->search_window;
557 
558     DDI_MEDIA_BUFFER *mediaBuffer;
559     VAStatus          status = VA_STATUS_SUCCESS;
560     if (feiPicParams->bPerMBInput)
561     {
562         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mb_ctrl);
563         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
564         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMBCtrl));
565     }
566     if (feiPicParams->MVPredictorEnable == 1)
567     {
568         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mv_predictor);
569         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
570         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMVPredictor));
571     }
572     else if ((feiPicParams->NumMVPredictorsL0 != 0) || (feiPicParams->NumMVPredictorsL1 != 0))
573     {
574         DDI_ASSERTMESSAGE("feiPicParams->NumMVPredictorsL0 and NumMVPredictorsL1 should be set to 0 when feiPicParams->MVPredictorEnable is false!");
575         status = VA_STATUS_ERROR_INVALID_PARAMETER;
576     }
577     if (feiPicParams->bMBQp)
578     {
579         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->qp);
580         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
581         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMBQp));
582     }
583 
584     feiPicParams->MbCodeMvEnable = false;
585     if (vaEncMiscParamFeiPic->mv_data != VA_INVALID_ID)
586     {
587         feiPicParams->MbCodeMvEnable = true;
588         mediaBuffer                  = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mv_data);
589         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
590         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMVData));
591         if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
592         {
593             RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MVDATA);
594             if (VA_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resMVData.bo), FEI_ENC_BUFFER_TYPE_MVDATA))
595             {
596                 DDI_ASSERTMESSAGE("feiPicParams->resMVData is invalid for FEI ENC only");
597                 status = VA_STATUS_ERROR_INVALID_PARAMETER;
598             }
599         }
600     }
601     if (vaEncMiscParamFeiPic->mb_code_data != VA_INVALID_ID)
602     {
603         if (feiPicParams->MbCodeMvEnable == false)
604         {
605             DDI_ASSERTMESSAGE("MV data and MB Code should be enabled or disabled together!");
606             status = MOS_STATUS_INVALID_PARAMETER;
607         }
608         mediaBuffer = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->mb_code_data);
609         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
610         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resMBCode));
611         if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
612         {
613             RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_MBCODE);
614             if (MOS_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resMBCode.bo), FEI_ENC_BUFFER_TYPE_MBCODE))
615             {
616                 DDI_ASSERTMESSAGE("feiPicParams->resMBCode is invalid for FEI ENC only");
617                 status = VA_STATUS_ERROR_INVALID_PARAMETER;
618             }
619         }
620     }
621     if (vaEncMiscParamFeiPic->distortion != VA_INVALID_ID)
622     {
623         feiPicParams->DistortionEnable = true;
624         mediaBuffer                    = DdiMedia_GetBufferFromVABufferID(m_encodeCtx->pMediaCtx, vaEncMiscParamFeiPic->distortion);
625         DDI_CHK_NULL(mediaBuffer, "nullptr mediaBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
626         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(feiPicParams->resDistortion));
627         if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
628         {
629             RemoveFromEncStatusReportQueue(mediaBuffer, FEI_ENC_BUFFER_TYPE_DISTORTION);
630             if (MOS_STATUS_SUCCESS != AddToEncStatusReportQueue((void *)(feiPicParams->resDistortion.bo), FEI_ENC_BUFFER_TYPE_DISTORTION))
631             {
632                 DDI_ASSERTMESSAGE("feiPicParams->resDistortion is invalid for FEI ENC only");
633                 status = VA_STATUS_ERROR_INVALID_PARAMETER;
634             }
635         }
636     }
637     if (m_encodeCtx->codecFunction == CODECHAL_FUNCTION_FEI_ENC)
638     {
639         AddToEncStatusReportQueueUpdatePos();
640     }
641 
642     //add for mutlple pass pak
643     feiPicParams->dwMaxFrameSize = vaEncMiscParamFeiPic->max_frame_size;
644     if (feiPicParams->dwMaxFrameSize)
645     {
646         feiPicParams->dwNumPasses = vaEncMiscParamFeiPic->num_passes;
647         if ((feiPicParams->dwNumPasses == 0) || (feiPicParams->dwNumPasses > feiMaxPassesNum))
648         {
649             return VA_STATUS_ERROR_INVALID_PARAMETER;
650         }
651         if (feiPicParams->pDeltaQp != nullptr)
652         {
653             MOS_FreeMemory(feiPicParams->pDeltaQp);
654         }
655         feiPicParams->pDeltaQp = (uint8_t *)MOS_AllocAndZeroMemory(sizeof(uint8_t) * feiPicParams->dwNumPasses);
656         if (!feiPicParams->pDeltaQp)
657         {
658             return VA_STATUS_ERROR_INVALID_PARAMETER;
659         }
660 
661         if (MOS_STATUS_SUCCESS != MOS_SecureMemcpy(feiPicParams->pDeltaQp, feiPicParams->dwNumPasses, vaEncMiscParamFeiPic->delta_qp, feiPicParams->dwNumPasses))
662         {
663             status = VA_STATUS_ERROR_INVALID_PARAMETER;
664         }
665     }
666 
667     return status;
668 }
669 
AddToEncStatusReportQueue(void * encBuf,DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)670 VAStatus DdiEncodeAvcFei::AddToEncStatusReportQueue(
671     void                           *encBuf,
672     DDI_ENCODE_FEI_ENC_BUFFER_TYPE typeIdx)
673 {
674     DDI_CHK_NULL(encBuf, "nullptr encBuf", VA_STATUS_ERROR_INVALID_PARAMETER);
675 
676     CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
677     DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
678 
679     if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC)
680     {
681         DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! .");
682         return VA_STATUS_ERROR_INVALID_PARAMETER;
683     }
684     if ((typeIdx < 0) || (typeIdx >= FEI_ENC_BUFFER_TYPE_MAX))
685     {
686         DDI_ASSERTMESSAGE("ENC output buffers status checking, gets invalid buffer type index! .");
687         return VA_STATUS_ERROR_INVALID_PARAMETER;
688     }
689 
690     int32_t idx                                                 = m_encodeCtx->statusReportBuf.ulHeadPosition;
691     m_encodeCtx->statusReportBuf.encInfos[idx].pEncBuf[typeIdx] = encBuf;
692     m_encodeCtx->statusReportBuf.encInfos[idx].uiStatus         = 0;
693     m_encodeCtx->statusReportBuf.encInfos[idx].uiBuffers++;
694 
695     return VA_STATUS_SUCCESS;
696 }
697 
AddToEncStatusReportQueueUpdatePos()698 VAStatus DdiEncodeAvcFei::AddToEncStatusReportQueueUpdatePos()
699 {
700     CodecEncodeAvcFeiPicParams *feiPicParams = (CodecEncodeAvcFeiPicParams *)(m_encodeCtx->pFeiPicParams);
701     DDI_CHK_NULL(feiPicParams, "nullptr feiPicParams", VA_STATUS_ERROR_INVALID_PARAMETER);
702 
703     if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_ENC)
704     {
705         DDI_ASSERTMESSAGE("ENC output buffers status checking is not allowed for non-FEI_ENC case! .");
706         return VA_STATUS_ERROR_INVALID_PARAMETER;
707     }
708 
709     int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition;
710     if ((m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers == (feiPicParams->MbCodeMvEnable * 2 + feiPicParams->DistortionEnable)) &&
711         m_encodeCtx->statusReportBuf.encInfos[i].uiBuffers != 0)
712     {
713         m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
714     }
715 
716     return VA_STATUS_SUCCESS;
717 }
718 
AddToPreEncStatusReportQueue(void * preEncBuf,DDI_ENCODE_PRE_ENC_BUFFER_TYPE typeIdx)719 VAStatus DdiEncodeAvcFei::AddToPreEncStatusReportQueue(
720     void                           *preEncBuf,
721     DDI_ENCODE_PRE_ENC_BUFFER_TYPE typeIdx)
722 {
723     DDI_CHK_NULL(preEncBuf, "nullptr preEncBuf", VA_STATUS_ERROR_INVALID_PARAMETER);
724 
725     if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_PRE_ENC)
726     {
727         DDI_ASSERTMESSAGE("PRE ENC output buffers status checking is not allowed for non-PRE_ENC case! .");
728         return VA_STATUS_ERROR_INVALID_PARAMETER;
729     }
730     if ((typeIdx < 0) || (typeIdx >= PRE_ENC_BUFFER_TYPE_MAX))
731     {
732         DDI_ASSERTMESSAGE("PRE ENC output buffers status checking, gets invalid buffer type index! .");
733         return VA_STATUS_ERROR_INVALID_PARAMETER;
734     }
735 
736     int32_t i                                                       = m_encodeCtx->statusReportBuf.ulHeadPosition;
737     m_encodeCtx->statusReportBuf.preencInfos[i].pPreEncBuf[typeIdx] = preEncBuf;
738     m_encodeCtx->statusReportBuf.preencInfos[i].uiStatus            = 0;
739     m_encodeCtx->statusReportBuf.preencInfos[i].uiBuffers++;
740 
741     return VA_STATUS_SUCCESS;
742 }
743 
AddToPreEncStatusReportQueueUpdatePos()744 VAStatus DdiEncodeAvcFei::AddToPreEncStatusReportQueueUpdatePos()
745 {
746     FeiPreEncParams *preEncParams = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
747     DDI_CHK_NULL(preEncParams, "nullptr preEncParams", VA_STATUS_ERROR_INVALID_PARAMETER);
748 
749     if (m_encodeCtx->codecFunction != CODECHAL_FUNCTION_FEI_PRE_ENC)
750     {
751         DDI_ASSERTMESSAGE("PRE ENC output buffers status checking is not allowed for non-PRE_ENC case! .");
752         return VA_STATUS_ERROR_INVALID_PARAMETER;
753     }
754 
755     uint32_t numBuffers = (!preEncParams->bInterlaced) ? (2 - preEncParams->bDisableMVOutput - preEncParams->bDisableStatisticsOutput)
756                                                        : (3 - preEncParams->bDisableMVOutput - 2 * preEncParams->bDisableStatisticsOutput);
757     int32_t i = m_encodeCtx->statusReportBuf.ulHeadPosition;
758     if ((m_encodeCtx->statusReportBuf.preencInfos[i].uiBuffers == numBuffers) &&
759         m_encodeCtx->statusReportBuf.preencInfos[i].uiBuffers != 0)
760     {
761         m_encodeCtx->statusReportBuf.ulHeadPosition = (m_encodeCtx->statusReportBuf.ulHeadPosition + 1) % DDI_ENCODE_MAX_STATUS_REPORT_BUFFER;
762     }
763 
764     return VA_STATUS_SUCCESS;
765 }
766 
ParseMiscParams(void * ptr)767 VAStatus DdiEncodeAvcFei::ParseMiscParams(void *ptr)
768 {
769     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
770     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
771 
772     VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr;
773     DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER);
774 
775     VAStatus status = MOS_STATUS_SUCCESS;
776     switch ((int32_t)(miscParamBuf->type))
777     {
778     case VAEncMiscParameterTypeHRD:
779         status = ParseMiscParamHRD((void *)miscParamBuf->data);
780         break;
781 
782     case VAEncMiscParameterTypeFrameRate:
783         status = ParseMiscParamFR((void *)miscParamBuf->data);
784         break;
785 
786     case VAEncMiscParameterTypeRateControl:
787         status = ParseMiscParamRC((void *)miscParamBuf->data);
788         break;
789 
790     case VAEncMiscParameterTypeEncQuality:
791         status = ParseMiscParamEncQuality((void *)miscParamBuf->data);
792         break;
793 
794     case VAEncMiscParameterTypeQuantization:
795         status = ParseMiscParamQuantization((void *)miscParamBuf->data);
796         break;
797 
798     case VAEncMiscParameterTypeRIR:
799         status = ParseMiscParameterRIR((void *)miscParamBuf->data);
800         break;
801 
802     case VAEncMiscParameterTypeSkipFrame:
803         status = ParseMiscParamSkipFrame((void *)miscParamBuf->data);
804         break;
805 
806     case VAEncMiscParameterTypeMaxFrameSize:
807         status = ParseMiscParamMaxFrameSize((void *)miscParamBuf->data);
808         break;
809 
810     case VAEncMiscParameterTypeQualityLevel:
811         status = ParseMiscParamQualityLevel((void *)miscParamBuf->data);
812         break;
813 
814     case VAEncMiscParameterTypeMaxSliceSize:
815         status = ParseMiscParamMaxSliceSize((void *)miscParamBuf->data);
816         break;
817 
818     case VAEncMiscParameterTypeROI:
819         status = ParseMiscParamROI((void *)miscParamBuf->data);
820         break;
821 
822     case VAEncMiscParameterTypeFEIFrameControl:
823         status = ParseMiscParamFeiPic((void *)miscParamBuf->data);
824         break;
825 
826     case VAEncMiscParameterTypeDirtyRect:
827         status = ParseMiscParamDirtyROI((void *)miscParamBuf->data);
828         break;
829 
830     case VAEncMiscParameterTypeCustomRoundingControl:
831         status = ParseMiscParamRounding((void *)miscParamBuf->data);
832         break;
833 
834     case VAEncMiscParameterTypeSubMbPartPel:
835         status = ParseMiscParamSubMbPartPel((void *)miscParamBuf->data);
836         break;
837 
838     default:
839         DDI_ASSERTMESSAGE("unsupported misc parameter type.");
840         status = VA_STATUS_ERROR_INVALID_PARAMETER;
841         break;
842     }
843 
844     return status;
845 }
846 
ParseStatsParams(PDDI_MEDIA_CONTEXT mediaCtx,void * ptr)847 VAStatus DdiEncodeAvcFei::ParseStatsParams(PDDI_MEDIA_CONTEXT mediaCtx, void *ptr)
848 {
849     if ((nullptr == ptr) || (nullptr == m_encodeCtx))
850     {
851         DDI_ASSERTMESSAGE("invalidate input parameters");
852         return VA_STATUS_ERROR_INVALID_PARAMETER;
853     }
854 
855     VAStatsStatisticsParameterH264 *statsParams  = (VAStatsStatisticsParameterH264 *)ptr;
856     FeiPreEncParams *preEncParams  = (FeiPreEncParams*)(m_encodeCtx->pPreEncParams);
857     DDI_CODEC_RENDER_TARGET_TABLE        *rtTbl        = &(m_encodeCtx->RTtbl);
858 
859     preEncParams->dwNumPastReferences      = statsParams->stats_params.num_past_references;
860     preEncParams->dwNumFutureReferences    = statsParams->stats_params.num_future_references;
861     preEncParams->dwFrameQp                = statsParams->frame_qp;
862     preEncParams->dwLenSP                  = statsParams->len_sp;
863     preEncParams->dwSearchPath             = statsParams->search_path;
864     preEncParams->dwSubMBPartMask          = statsParams->sub_mb_part_mask;
865     preEncParams->dwIntraPartMask          = statsParams->intra_part_mask;
866     preEncParams->dwSubPelMode             = statsParams->sub_pel_mode;
867     preEncParams->dwInterSAD               = statsParams->inter_sad;
868     preEncParams->dwIntraSAD               = statsParams->intra_sad;
869     preEncParams->bAdaptiveSearch          = statsParams->adaptive_search;
870     preEncParams->dwMVPredictorCtrl        = statsParams->mv_predictor_ctrl;
871     preEncParams->bMBQp                    = statsParams->mb_qp;
872     preEncParams->bFTEnable                = statsParams->ft_enable;
873     preEncParams->dwRefWidth               = statsParams->ref_width;
874     preEncParams->dwRefHeight              = statsParams->ref_height;
875     preEncParams->dwSearchWindow           = statsParams->search_window;
876     preEncParams->bDisableMVOutput         = statsParams->disable_mv_output;
877     preEncParams->bDisableStatisticsOutput = statsParams->disable_statistics_output;
878     preEncParams->bEnable8x8Statistics     = statsParams->enable_8x8_statistics;
879     preEncParams->bInputUpdated            = false;
880     preEncParams->bCurPicUpdated           = false;
881     preEncParams->bPastRefUpdated          = false;
882     preEncParams->bFutureRefUpdated        = false;
883     preEncParams->bPastRefStatsNeeded      = false;
884     preEncParams->bFutureRefStatsNeeded    = false;
885 
886     if (statsParams->stats_params.input.picture_id == VA_INVALID_ID)
887     {
888         DDI_ASSERTMESSAGE("invalidate input parameters, current picture id is invalidate");
889         return VA_STATUS_ERROR_INVALID_PARAMETER;
890     }
891 
892     if ((statsParams->stats_params.input.flags & VA_PICTURE_STATS_CONTENT_UPDATED) != 0)
893     {
894         preEncParams->bCurPicUpdated = true;
895     }
896 
897     CODEC_PICTURE_FLAG picFlags = ((statsParams->stats_params.input.flags & 0xF) == VA_PICTURE_STATS_PROGRESSIVE) ? PICTURE_FRAME : (((statsParams->stats_params.input.flags & 0xF) == VA_PICTURE_STATS_TOP_FIELD) ? PICTURE_TOP_FIELD : (((statsParams->stats_params.input.flags & 0xF) == VA_PICTURE_STATS_BOTTOM_FIELD) ? PICTURE_BOTTOM_FIELD : PICTURE_INVALID));
898     preEncParams->bInterlaced   = (picFlags == PICTURE_TOP_FIELD || picFlags == PICTURE_BOTTOM_FIELD);
899 
900     DDI_MEDIA_SURFACE *currentSurface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, statsParams->stats_params.input.picture_id);
901     if (nullptr == currentSurface)
902     {
903         DDI_ASSERTMESSAGE("invalidate current ref surface");
904         return VA_STATUS_ERROR_INVALID_PARAMETER;
905     }
906 
907     DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, currentSurface), "RegisterRTSurfaces failed!");
908     preEncParams->CurrOriginalPicture.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, currentSurface);
909     preEncParams->CurrOriginalPicture.PicFlags = picFlags;
910     DDI_MEDIA_BUFFER *mediaBuffer;
911     if ((preEncParams->dwNumPastReferences == 1) && (statsParams->stats_params.past_references[0].picture_id != VA_INVALID_ID))
912     {
913         if ((statsParams->stats_params.past_references->flags & VA_PICTURE_STATS_CONTENT_UPDATED) != 0)
914         {
915             preEncParams->bPastRefUpdated = true;
916         }
917         DDI_MEDIA_SURFACE *pastRefSurface = (DDI_MEDIA_SURFACE *)DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, statsParams->stats_params.past_references->picture_id);
918         if (nullptr == pastRefSurface)
919         {
920             DDI_ASSERTMESSAGE("invalidate Future ref surface");
921             return VA_STATUS_ERROR_INVALID_PARAMETER;
922         }
923         DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, pastRefSurface), "RegisterRTSurfaces failed!");
924         preEncParams->PastRefPicture.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, pastRefSurface);
925         picFlags                              = ((statsParams->stats_params.past_references->flags & 0xF) == VA_PICTURE_STATS_PROGRESSIVE) ? PICTURE_FRAME : (((statsParams->stats_params.past_references->flags & 0xF) == VA_PICTURE_STATS_TOP_FIELD) ? PICTURE_TOP_FIELD : (((statsParams->stats_params.past_references->flags & 0xF) == VA_PICTURE_STATS_BOTTOM_FIELD) ? PICTURE_BOTTOM_FIELD : PICTURE_INVALID));
926         preEncParams->PastRefPicture.PicFlags = picFlags;
927 
928         DdiMedia_MediaSurfaceToMosResource(pastRefSurface, &(preEncParams->sPastRefSurface.OsResource));
929         preEncParams->sPastRefSurface.dwWidth  = preEncParams->sPastRefSurface.OsResource.iWidth;
930         preEncParams->sPastRefSurface.dwHeight = preEncParams->sPastRefSurface.OsResource.iHeight;
931         preEncParams->sPastRefSurface.dwPitch  = preEncParams->sPastRefSurface.OsResource.iPitch;
932         preEncParams->sPastRefSurface.TileType = preEncParams->sPastRefSurface.OsResource.TileType;
933         preEncParams->sPastRefSurface.TileModeGMM = preEncParams->sPastRefSurface.OsResource.TileModeGMM;
934         preEncParams->sPastRefSurface.bGMMTileEnabled = preEncParams->sPastRefSurface.OsResource.bGMMTileEnabled;
935         preEncParams->bPastRefStatsNeeded      = false;
936 
937         if (statsParams->stats_params.past_ref_stat_buf)
938         {
939             if (!preEncParams->bDisableStatisticsOutput)
940             {
941                 mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.past_ref_stat_buf));
942                 if (nullptr == mediaBuffer)
943                 {
944                     DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Past ref");
945                     return VA_STATUS_ERROR_INVALID_PARAMETER;
946                 }
947                 DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sPastRefStatsBuffer));
948                 if (picFlags == PICTURE_TOP_FIELD || picFlags == PICTURE_BOTTOM_FIELD)
949                 {
950                     mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.past_ref_stat_buf + 1));
951                     if (nullptr == mediaBuffer)
952                     {
953                         DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Past bottom field ref");
954                         return VA_STATUS_ERROR_INVALID_PARAMETER;
955                     }
956                     DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sPastRefStatsBotFieldBuffer));
957                 }
958                 preEncParams->bPastRefStatsNeeded = true;
959             }
960             else
961                 preEncParams->bPastRefStatsNeeded = false;
962         }
963     }
964     else
965     {
966         preEncParams->PastRefPicture.FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
967         preEncParams->PastRefPicture.PicFlags = PICTURE_INVALID;
968     }
969 
970     if ((preEncParams->dwNumFutureReferences == 1) && (statsParams->stats_params.future_references[0].picture_id != VA_INVALID_ID))
971     {
972         if ((statsParams->stats_params.future_references->flags & VA_PICTURE_STATS_CONTENT_UPDATED) != 0)
973         {
974             preEncParams->bFutureRefUpdated = true;
975         }
976         DDI_MEDIA_SURFACE *futureRefSurface = (DDI_MEDIA_SURFACE *)DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, statsParams->stats_params.future_references->picture_id);
977         if (nullptr == futureRefSurface)
978         {
979             DDI_ASSERTMESSAGE("invalidate Future ref surface");
980             return VA_STATUS_ERROR_INVALID_PARAMETER;
981         }
982         DDI_CHK_RET(RegisterRTSurfaces(&m_encodeCtx->RTtbl, futureRefSurface), "RegisterRTSurfaces failed!");
983         preEncParams->FutureRefPicture.FrameIdx = (uint8_t)GetRenderTargetID(rtTbl, futureRefSurface);
984         picFlags                                = ((statsParams->stats_params.future_references->flags & 0xF) == VA_PICTURE_STATS_PROGRESSIVE) ? PICTURE_FRAME : (((statsParams->stats_params.future_references->flags & 0xF) == VA_PICTURE_STATS_TOP_FIELD) ? PICTURE_TOP_FIELD : (((statsParams->stats_params.future_references->flags & 0xF) == VA_PICTURE_STATS_BOTTOM_FIELD) ? PICTURE_BOTTOM_FIELD : PICTURE_INVALID));
985         preEncParams->FutureRefPicture.PicFlags = picFlags;
986 
987         DdiMedia_MediaSurfaceToMosResource(futureRefSurface, &(preEncParams->sFutureRefSurface.OsResource));
988         preEncParams->sFutureRefSurface.dwWidth  = preEncParams->sFutureRefSurface.OsResource.iWidth;
989         preEncParams->sFutureRefSurface.dwHeight = preEncParams->sFutureRefSurface.OsResource.iHeight;
990         preEncParams->sFutureRefSurface.dwPitch  = preEncParams->sFutureRefSurface.OsResource.iPitch;
991         preEncParams->sFutureRefSurface.TileType = preEncParams->sFutureRefSurface.OsResource.TileType;
992         preEncParams->bFutureRefStatsNeeded      = false;
993         if (!preEncParams->bDisableStatisticsOutput)
994         {
995             if (statsParams->stats_params.future_ref_stat_buf)
996             {
997                 mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.future_ref_stat_buf));
998                 if (nullptr == mediaBuffer)
999                 {
1000                     DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Future ref");
1001                     return VA_STATUS_ERROR_INVALID_PARAMETER;
1002                 }
1003                 DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sFutureRefStatsBuffer));
1004                 if (picFlags == PICTURE_TOP_FIELD || picFlags == PICTURE_BOTTOM_FIELD)
1005                 {
1006                     mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, *(statsParams->stats_params.future_ref_stat_buf + 1));
1007                     if (nullptr == mediaBuffer)
1008                     {
1009                         DDI_ASSERTMESSAGE("invalidate statistics output media buffer for Future ref");
1010                         return VA_STATUS_ERROR_INVALID_PARAMETER;
1011                     }
1012                     DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->sFutureRefStatsBotFieldBuffer));
1013                 }
1014                 preEncParams->bFutureRefStatsNeeded = true;
1015             }
1016             else
1017                 preEncParams->bFutureRefStatsNeeded = false;
1018         }
1019     }
1020     else
1021     {
1022         preEncParams->FutureRefPicture.FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
1023         preEncParams->FutureRefPicture.PicFlags = PICTURE_INVALID;
1024     }
1025 
1026     if (preEncParams->dwMVPredictorCtrl)
1027     {
1028         mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.mv_predictor);
1029         if (nullptr == mediaBuffer)
1030         {
1031             DDI_ASSERTMESSAGE("invalidate mv_predictor media buffer");
1032             return VA_STATUS_ERROR_INVALID_PARAMETER;
1033         }
1034         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resMvPredBuffer));
1035     }
1036     if (preEncParams->bMBQp)
1037     {
1038         mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.qp);
1039         if (nullptr == mediaBuffer)
1040         {
1041             DDI_ASSERTMESSAGE("invalidate qp media buffer");
1042             return VA_STATUS_ERROR_INVALID_PARAMETER;
1043         }
1044         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resMbQpBuffer));
1045     }
1046 
1047     uint32_t i = 0;
1048     if (!preEncParams->bDisableMVOutput)
1049     {
1050         mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.outputs[i++]);
1051         if (nullptr == mediaBuffer)
1052         {
1053             DDI_ASSERTMESSAGE("invalidate mv output media buffer");
1054             return VA_STATUS_ERROR_INVALID_PARAMETER;
1055         }
1056         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resMvBuffer));
1057         RemoveFromPreEncStatusReportQueue(mediaBuffer, PRE_ENC_BUFFER_TYPE_MVDATA);
1058         if (VA_STATUS_SUCCESS != AddToPreEncStatusReportQueue((void *)(preEncParams->resMvBuffer.bo), PRE_ENC_BUFFER_TYPE_MVDATA))
1059         {
1060             DDI_ASSERTMESSAGE("preEncParams->resMvBuffer is invalid for PREENC only");
1061             return VA_STATUS_ERROR_INVALID_PARAMETER;
1062         }
1063     }
1064 
1065     if (!preEncParams->bDisableStatisticsOutput)
1066     {
1067         mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.outputs[i++]);
1068         if (nullptr == mediaBuffer)
1069         {
1070             DDI_ASSERTMESSAGE("invalidate statistics output media buffer");
1071             return VA_STATUS_ERROR_INVALID_PARAMETER;
1072         }
1073         DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resStatsBuffer));
1074         RemoveFromPreEncStatusReportQueue(mediaBuffer, PRE_ENC_BUFFER_TYPE_STATS);
1075         if (VA_STATUS_SUCCESS != AddToPreEncStatusReportQueue((void *)(preEncParams->resStatsBuffer.bo), PRE_ENC_BUFFER_TYPE_STATS))
1076         {
1077             DDI_ASSERTMESSAGE("preEncParams->resStatsBuffer is invalid for PREENC only");
1078             return VA_STATUS_ERROR_INVALID_PARAMETER;
1079         }
1080 
1081         if (preEncParams->bInterlaced)
1082         {
1083             mediaBuffer = DdiMedia_GetBufferFromVABufferID(mediaCtx, statsParams->stats_params.outputs[i++]);
1084             if (nullptr == mediaBuffer)
1085             {
1086                 DDI_ASSERTMESSAGE("invalidate statistics output media bottom field buffer, must provide bottom field statistics buffer for both top and bottom field PreENC");
1087                 return VA_STATUS_ERROR_INVALID_PARAMETER;
1088             }
1089             DdiMedia_MediaBufferToMosResource(mediaBuffer, &(preEncParams->resStatsBotFieldBuffer));
1090             RemoveFromPreEncStatusReportQueue(mediaBuffer, PRE_ENC_BUFFER_TYPE_STATS_BOT);
1091             if (VA_STATUS_SUCCESS != AddToPreEncStatusReportQueue((void *)(preEncParams->resStatsBotFieldBuffer.bo), PRE_ENC_BUFFER_TYPE_STATS_BOT))
1092             {
1093                 DDI_ASSERTMESSAGE("preEncParams->resStatsBotFieldBuffer is invalid for PREENC only");
1094                 return VA_STATUS_ERROR_INVALID_PARAMETER;
1095             }
1096         }
1097     }
1098 
1099     AddToPreEncStatusReportQueueUpdatePos();
1100 
1101     return VA_STATUS_SUCCESS;
1102 }
1103