xref: /aosp_15_r20/external/intel-media-driver/media_driver/linux/common/codec/ddi/media_ddi_encode_vp9.cpp (revision ba62d9d3abf0e404f2022b4cd7a85e107f48596f)
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_vp9.cpp
24 //! \brief    Defines class for DDI media vp9 encode.
25 //!
26 
27 #include "media_libva.h"
28 #include "media_libva_encoder.h"
29 #include "media_ddi_encode_vp9.h"
30 #include "media_libva_util.h"
31 #include "codec_def_encode_vp9.h"
32 #include "media_ddi_encode_const.h"
33 #include "media_ddi_factory.h"
34 #include "media_libvpx_vp9.h"
35 
36 extern template class MediaDdiFactoryNoArg<DdiEncodeBase>;
37 static bool isEncodeVp9Registered =
38     MediaDdiFactoryNoArg<DdiEncodeBase>::RegisterCodec<DdiEncodeVp9>(ENCODE_ID_VP9);
39 
~DdiEncodeVp9()40 DdiEncodeVp9::~DdiEncodeVp9()
41 {
42     if (m_encodeCtx == nullptr)
43     {
44         return;
45     }
46 
47     MOS_FreeMemory(m_encodeCtx->pSeqParams);
48     m_encodeCtx->pSeqParams = nullptr;
49 
50     MOS_FreeMemory(m_encodeCtx->pPicParams);
51     m_encodeCtx->pPicParams = nullptr;
52 
53     MOS_FreeMemory(m_encodeCtx->pQmatrixParams);
54     m_encodeCtx->pQmatrixParams = nullptr;
55 
56     MOS_FreeMemory(m_encodeCtx->pEncodeStatusReport);
57     m_encodeCtx->pEncodeStatusReport = nullptr;
58 
59     if (m_encodeCtx->pbsBuffer)
60     {
61         MOS_FreeMemory(m_encodeCtx->pbsBuffer->pBase);
62         m_encodeCtx->pbsBuffer->pBase = nullptr;
63     }
64     MOS_FreeMemory(m_encodeCtx->pbsBuffer);
65     m_encodeCtx->pbsBuffer = nullptr;
66 
67     if (m_encodeCtx->ppNALUnitParams && m_encodeCtx->ppNALUnitParams[0])
68     {
69         /* ppNALUnitParams[0] indicates the start address of NALUnitParams */
70         MOS_FreeMemory(m_encodeCtx->ppNALUnitParams[0]);
71         m_encodeCtx->ppNALUnitParams[0] = nullptr;
72     }
73 
74     MOS_FreeMemory(m_encodeCtx->ppNALUnitParams);
75     m_encodeCtx->ppNALUnitParams = nullptr;
76 
77     MOS_FreeMemory(m_segParams);
78     m_segParams = nullptr;
79 
80     MOS_FreeMemory(m_codedBufStatus);
81     m_codedBufStatus = nullptr;
82 }
83 
EncodeInCodecHal(uint32_t numSlices)84 VAStatus DdiEncodeVp9::EncodeInCodecHal(uint32_t numSlices)
85 {
86     DDI_UNUSED(numSlices);
87 
88     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
89     DDI_CHK_NULL(m_encodeCtx->pCodecHal, "nullptr m_encodeCtx->pCodecHal", VA_STATUS_ERROR_INVALID_CONTEXT);
90 
91     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
92 
93     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *seqParams = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
94     CODEC_VP9_ENCODE_PIC_PARAMS *vp9PicParam = (PCODEC_VP9_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams);
95 
96     EncoderParams encodeParams;
97     MOS_ZeroMemory(&encodeParams, sizeof(EncoderParams));
98     encodeParams.ExecCodecFunction = m_encodeCtx->codecFunction;
99 
100     /* check whether the target bit rate is initialized for BRC */
101     if ((VA_RC_CBR == m_encodeCtx->uiRCMethod) ||
102         (VA_RC_VBR == m_encodeCtx->uiRCMethod))
103     {
104         if (seqParams->TargetBitRate[0] == 0)
105         {
106             DDI_ASSERTMESSAGE("DDI: No RateControl param for BRC\n!");
107             return VA_STATUS_ERROR_INVALID_PARAMETER;
108         }
109     }
110 
111     // Raw Surface
112     MOS_SURFACE rawSurface;
113     MOS_ZeroMemory(&rawSurface, sizeof(MOS_SURFACE));
114 
115     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentRT, &(rawSurface.OsResource));
116 
117     switch (rawSurface.OsResource.Format)
118     {
119     case Format_NV12:
120         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV420;
121         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_8;
122         break;
123     case Format_YUY2:
124         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV422;
125         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_8;
126         break;
127     case Format_UYVY:
128         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV422;
129         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_8;
130         break;
131     case Format_AYUV:
132     case Format_A8R8G8B8:
133     case Format_A8B8G8R8:
134         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV444;
135         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_8;
136         break;
137     case Format_P010:
138         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV420;
139         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_10;
140         break;
141     case Format_Y210:
142         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV422;
143         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_10;
144         break;
145     case Format_Y410:
146     case Format_R10G10B10A2:
147     case Format_B10G10R10A2:
148         seqParams->SeqFlags.fields.SourceFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV444;
149         seqParams->SeqFlags.fields.SourceBitDepth = VP9_ENCODED_BIT_DEPTH_10;
150         break;
151     // P016 and Y416 aren't supported yet so return error for these formats
152     case Format_P016:
153     case Format_Y416:
154     default:
155         DDI_ASSERTMESSAGE("DDI:Incorrect Format for input surface\n!");
156         return VA_STATUS_ERROR_INVALID_PARAMETER;
157         break;
158     }
159 
160     rawSurface.Format = rawSurface.OsResource.Format;
161 
162     // Recon Surface
163     MOS_SURFACE reconSurface;
164     MOS_ZeroMemory(&reconSurface, sizeof(MOS_SURFACE));
165     reconSurface.dwOffset = 0;
166 
167     DdiMedia_MediaSurfaceToMosResource(rtTbl->pCurrentReconTarget, &(reconSurface.OsResource));
168 
169     switch (m_encodeCtx->vaProfile)
170     {
171     case VAProfileVP9Profile1:
172         reconSurface.Format                        = Format_AYUV;
173         seqParams->SeqFlags.fields.EncodedFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV444;
174         seqParams->SeqFlags.fields.EncodedBitDepth = VP9_ENCODED_BIT_DEPTH_8;
175         break;
176     case VAProfileVP9Profile2:
177         reconSurface.Format                        = Format_P010;
178         seqParams->SeqFlags.fields.EncodedFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV420;
179         seqParams->SeqFlags.fields.EncodedBitDepth = VP9_ENCODED_BIT_DEPTH_10;
180         break;
181     case VAProfileVP9Profile3:
182         reconSurface.Format                        = Format_Y410;
183         seqParams->SeqFlags.fields.EncodedFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV444;
184         seqParams->SeqFlags.fields.EncodedBitDepth = VP9_ENCODED_BIT_DEPTH_10;
185         break;
186     case VAProfileVP9Profile0:
187     default:
188         reconSurface.Format                        = Format_NV12;
189         seqParams->SeqFlags.fields.EncodedFormat   = VP9_ENCODED_CHROMA_FORMAT_YUV420;
190         seqParams->SeqFlags.fields.EncodedBitDepth = VP9_ENCODED_BIT_DEPTH_8;
191         break;
192     }
193 
194     // Bitstream surface
195     MOS_RESOURCE bitstreamSurface;
196     MOS_ZeroMemory(&bitstreamSurface, sizeof(MOS_RESOURCE));
197     bitstreamSurface        = m_encodeCtx->resBitstreamBuffer;  // in render picture
198     bitstreamSurface.Format = Format_Buffer;
199 
200     //clear registered recon/ref surface flags
201     DDI_CHK_RET(ClearRefList(&m_encodeCtx->RTtbl, true), "ClearRefList failed!");
202 
203     encodeParams.psRawSurface               = &rawSurface;
204     encodeParams.psReconSurface             = &reconSurface;
205     encodeParams.presBitstreamBuffer        = &bitstreamSurface;
206     encodeParams.presMbCodeSurface          = &m_encodeCtx->resMbCodeBuffer;
207 
208     // Segmentation map buffer
209     encodeParams.psMbSegmentMapSurface = &m_encodeCtx->segMapBuffer;
210     encodeParams.bSegmentMapProvided   = !Mos_ResourceIsNull(&m_encodeCtx->segMapBuffer.OsResource);
211 
212     if (VA_RC_CQP == m_encodeCtx->uiRCMethod)
213     {
214         seqParams->RateControlMethod          = RATECONTROL_CQP;
215         seqParams->TargetBitRate[0]           = 0;
216         seqParams->MaxBitRate                 = 0;
217         seqParams->MinBitRate                 = 0;
218         seqParams->InitVBVBufferFullnessInBit = 0;
219         seqParams->VBVBufferSizeInBit         = 0;
220     }
221     else if (VA_RC_CBR == m_encodeCtx->uiRCMethod)
222     {
223         seqParams->RateControlMethod = RATECONTROL_CBR;
224         seqParams->MaxBitRate        = MOS_MAX(seqParams->MaxBitRate, seqParams->TargetBitRate[0]);
225         seqParams->MinBitRate        = MOS_MIN(seqParams->MinBitRate, seqParams->TargetBitRate[0]);
226     }
227     else if (VA_RC_VBR == m_encodeCtx->uiRCMethod)
228     {
229         seqParams->RateControlMethod = RATECONTROL_VBR;
230     }
231     else if(VA_RC_ICQ == m_encodeCtx->uiRCMethod)
232     {
233         seqParams->RateControlMethod = RATECONTROL_CQL;
234     }
235 
236     if (m_encodeCtx->bNewSeq)
237         seqParams->TargetUsage = vp9TargetUsage;
238 
239     /* If the segmentation is not enabled, the SegData will be reset */
240     if (vp9PicParam->PicFlags.fields.segmentation_enabled == 0)
241     {
242         DDI_CHK_NULL(m_segParams, "nullptr m_segParams", VA_STATUS_ERROR_INVALID_PARAMETER);
243         for (int i = 0; i < 8; i++)
244         {
245             MOS_ZeroMemory(&(m_segParams->SegData[i]), sizeof(CODEC_VP9_ENCODE_SEG_PARAMS));
246         }
247     }
248     else if (!isSegParamsChanged &&
249             vp9PicParam->PicFlags.fields.frame_type != CODEC_VP9_KEY_FRAME &&
250             vp9PicParam->PicFlags.fields.error_resilient_mode == 0)
251     {
252         /* segmentation is enabled, but segment parameters are not changed */
253         vp9PicParam->PicFlags.fields.seg_update_data = 0;
254     }
255 
256     encodeParams.pSeqParams      = m_encodeCtx->pSeqParams;
257     encodeParams.pPicParams      = m_encodeCtx->pPicParams;
258     encodeParams.pSliceParams    = m_encodeCtx->pSliceParams;
259     encodeParams.ppNALUnitParams = m_encodeCtx->ppNALUnitParams;
260     encodeParams.pSegmentParams  = m_segParams;
261 
262     if(seqParams->NumTemporalLayersMinus1 > 7)
263     {
264         return VA_STATUS_ERROR_INVALID_PARAMETER;
265     }
266     for (uint32_t i = 0; i < (seqParams->NumTemporalLayersMinus1+1); i++)
267     {
268         if (savedFrameRate[i] == 0)
269         {
270             /* use the default framerate if FrameRate is not passed */
271             seqParams->FrameRate[i].uiNumerator   = 30;
272             seqParams->FrameRate[i].uiDenominator = 1;
273         }
274     }
275 
276     if (!headerInsertFlag)
277     {
278         vp9_header_bitoffset picBitOffset;
279         uint32_t headerLen = 0;
280         uint32_t codecProfile = VP9_PROFILE_0;
281 
282         if ((m_encodeCtx->vaProfile >= VAProfileVP9Profile0) &&
283             (m_encodeCtx->vaProfile <= VAProfileVP9Profile3))
284         {
285             codecProfile = m_encodeCtx->vaProfile - VAProfileVP9Profile0;
286         }
287 
288         Vp9WriteUncompressHeader(m_encodeCtx,
289                                    codecProfile,
290                                    m_encodeCtx->pbsBuffer->pBase,
291                                    &headerLen,
292                                    &picBitOffset);
293 
294         vp9PicParam->BitOffsetForFirstPartitionSize = picBitOffset.bit_offset_first_partition_size;
295         vp9PicParam->BitOffsetForQIndex             = picBitOffset.bit_offset_qindex;
296         vp9PicParam->BitOffsetForLFLevel            = picBitOffset.bit_offset_lf_level;
297         vp9PicParam->BitOffsetForLFRefDelta         = picBitOffset.bit_offset_ref_lf_delta;
298         vp9PicParam->BitOffsetForLFModeDelta        = picBitOffset.bit_offset_mode_lf_delta;
299         vp9PicParam->BitOffsetForSegmentation       = picBitOffset.bit_offset_segmentation;
300         vp9PicParam->BitSizeForSegmentation         = picBitOffset.bit_size_segmentation;
301 
302         m_encodeCtx->ppNALUnitParams[0]->uiNalUnitType             = 0x22;
303         m_encodeCtx->ppNALUnitParams[0]->bInsertEmulationBytes     = false;
304         m_encodeCtx->ppNALUnitParams[0]->uiSkipEmulationCheckCount = 0;
305         m_encodeCtx->ppNALUnitParams[0]->uiSize                    = headerLen;
306         m_encodeCtx->ppNALUnitParams[0]->uiOffset                  = 0;
307     }
308 
309     encodeParams.bNewSeq = m_encodeCtx->bNewSeq;
310     if (seqParams->SeqFlags.fields.bResetBRC)
311     {
312         /* When the BRC needs to be reset, it indicates that the new Seq is issued. */
313         encodeParams.bNewSeq = true;
314     }
315 
316     encodeParams.bNewQmatrixData = m_encodeCtx->bNewQmatrixData;
317     encodeParams.bPicQuant       = m_encodeCtx->bPicQuant;
318 
319     encodeParams.pBSBuffer = m_encodeCtx->pbsBuffer;
320 
321     MOS_STATUS status = m_encodeCtx->pCodecHal->Execute(&encodeParams);
322     if (MOS_STATUS_SUCCESS != status)
323     {
324         DDI_ASSERTMESSAGE("DDI:Failed in Codechal!");
325         return VA_STATUS_ERROR_ENCODING_ERROR;
326     }
327 
328     return VA_STATUS_SUCCESS;
329 }
330 
ContextInitialize(CodechalSetting * codecHalSettings)331 VAStatus DdiEncodeVp9::ContextInitialize(CodechalSetting *codecHalSettings)
332 {
333     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx.", VA_STATUS_ERROR_INVALID_CONTEXT);
334     DDI_CHK_NULL(m_encodeCtx->pCpDdiInterface, "nullptr m_encodeCtx->pCpDdiInterface.", VA_STATUS_ERROR_INVALID_CONTEXT);
335     DDI_CHK_NULL(codecHalSettings, "nullptr codecHalSettings.", VA_STATUS_ERROR_INVALID_CONTEXT);
336 
337     codecHalSettings->codecFunction = m_encodeCtx->codecFunction;
338     codecHalSettings->width       = m_encodeCtx->dworiFrameWidth;
339     codecHalSettings->height      = m_encodeCtx->dworiFrameHeight;
340     codecHalSettings->mode          = m_encodeCtx->wModeType;
341     codecHalSettings->standard      = CODECHAL_VP9;
342     codecHalSettings->chromaFormat  = (m_chromaFormat == yuv444) ?
343         VP9_ENCODED_CHROMA_FORMAT_YUV444 : VP9_ENCODED_CHROMA_FORMAT_YUV420;
344     codecHalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_8_BITS;
345     if (m_is10Bit)
346     {
347         codecHalSettings->lumaChromaDepth = CODECHAL_LUMA_CHROMA_DEPTH_10_BITS;
348     }
349 
350     VAStatus vaStatus = VA_STATUS_SUCCESS;
351 
352     m_encodeCtx->pSeqParams = (void *)MOS_AllocAndZeroMemory(sizeof(CODEC_VP9_ENCODE_SEQUENCE_PARAMS));
353     DDI_CHK_NULL(m_encodeCtx->pSeqParams, "nullptr m_encodeCtx->pSeqParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
354 
355     m_encodeCtx->pPicParams = (void *)MOS_AllocAndZeroMemory(sizeof(CODEC_VP9_ENCODE_PIC_PARAMS));
356     DDI_CHK_NULL(m_encodeCtx->pPicParams, "nullptr m_encodeCtx->pPicParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
357 
358     // Allocate Encode Status Report
359     m_encodeCtx->pEncodeStatusReport = (void *)MOS_AllocAndZeroMemory(CODECHAL_ENCODE_STATUS_NUM * sizeof(EncodeStatusReport));
360     DDI_CHK_NULL(m_encodeCtx->pEncodeStatusReport, "nullptr m_encodeCtx->pEncodeStatusReport.", VA_STATUS_ERROR_ALLOCATION_FAILED);
361 
362     // Create the bit stream buffer to hold the packed headers from application
363     m_encodeCtx->pbsBuffer = (PBSBuffer)MOS_AllocAndZeroMemory(sizeof(BSBuffer));
364     DDI_CHK_NULL(m_encodeCtx->pbsBuffer, "nullptr m_encodeCtx->pbsBuffer.", VA_STATUS_ERROR_ALLOCATION_FAILED);
365 
366     /* It is enough to allocate 4096 bytes for VP9 packed header */
367     m_encodeCtx->pbsBuffer->BufferSize = 4096;
368     m_encodeCtx->pbsBuffer->pBase      = (uint8_t *)MOS_AllocAndZeroMemory(m_encodeCtx->pbsBuffer->BufferSize);
369     DDI_CHK_NULL(m_encodeCtx->pbsBuffer->pBase, "nullptr m_encodeCtx->pbsBuffer->pBase.", VA_STATUS_ERROR_ALLOCATION_FAILED);
370 
371     const int32_t packedNum = 2;
372     /* VP9 has only one Packed header.  */
373     m_encodeCtx->ppNALUnitParams = (PCODECHAL_NAL_UNIT_PARAMS *)MOS_AllocAndZeroMemory(sizeof(PCODECHAL_NAL_UNIT_PARAMS) * packedNum);
374     DDI_CHK_NULL(m_encodeCtx->ppNALUnitParams, "nullptr m_encodeCtx->ppNALUnitParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
375 
376     CODECHAL_NAL_UNIT_PARAMS *nalUnitParams = (CODECHAL_NAL_UNIT_PARAMS *)MOS_AllocAndZeroMemory(sizeof(CODECHAL_NAL_UNIT_PARAMS) * packedNum);
377     DDI_CHK_NULL(nalUnitParams, "nullptr nalUnitParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
378 
379     for (int32_t i = 0; i < packedNum; i++)
380     {
381         m_encodeCtx->ppNALUnitParams[i] = &(nalUnitParams[i]);
382     }
383 
384     // Allocate segment params
385     m_segParams = (CODEC_VP9_ENCODE_SEGMENT_PARAMS *)MOS_AllocAndZeroMemory(sizeof(CODEC_VP9_ENCODE_SEGMENT_PARAMS) * 8);
386     DDI_CHK_NULL(m_segParams, "nullptr m_segParams.", VA_STATUS_ERROR_ALLOCATION_FAILED);
387     m_encodeCtx->pVpxSegParams = (void*)m_segParams;
388 
389     // Allocate coded buffer status
390     m_codedBufStatus = (VACodedBufferVP9Status *)MOS_AllocAndZeroMemory(DDI_ENCODE_MAX_STATUS_REPORT_BUFFER * sizeof(VACodedBufferVP9Status));
391     DDI_CHK_NULL(m_codedBufStatus, "nullptr m_codedBufStatus.", VA_STATUS_ERROR_ALLOCATION_FAILED);
392 
393     /* RT is used as the default target usage */
394     vp9TargetUsage = TARGETUSAGE_RT_SPEED;
395 
396     return vaStatus;
397 }
398 
RenderPicture(VADriverContextP ctx,VAContextID context,VABufferID * buffers,int32_t numBuffers)399 VAStatus DdiEncodeVp9::RenderPicture(
400     VADriverContextP ctx,
401     VAContextID      context,
402     VABufferID       *buffers,
403     int32_t          numBuffers)
404 {
405     VAStatus vaStatus = VA_STATUS_SUCCESS;
406 
407     DDI_FUNCTION_ENTER();
408 
409     DDI_CHK_NULL(ctx, "nullptr context", VA_STATUS_ERROR_INVALID_CONTEXT);
410 
411     DDI_MEDIA_CONTEXT *mediaCtx = DdiMedia_GetMediaContext(ctx);
412     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
413 
414     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_CONTEXT);
415 
416     for (int32_t i = 0; i < numBuffers; i++)
417     {
418         DDI_MEDIA_BUFFER *buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, buffers[i]);
419         DDI_CHK_NULL(buf, "Invalid buffer.", VA_STATUS_ERROR_INVALID_BUFFER);
420         if (buf->uiType == VAEncMacroblockDisableSkipMapBufferType)
421         {
422             DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resPerMBSkipMapBuffer));
423             m_encodeCtx->bMbDisableSkipMapEnabled = true;
424             continue;
425         }
426         uint32_t dataSize = buf->iSize;
427         // can use internal function instead of DdiMedia_MapBuffer here?
428         void *data = nullptr;
429         DdiMedia_MapBuffer(ctx, buffers[i], &data);
430         DDI_CHK_NULL(data, "nullptr data.", VA_STATUS_ERROR_INVALID_BUFFER);
431 
432         switch (buf->uiType)
433         {
434         case VAIQMatrixBufferType:
435         case VAQMatrixBufferType:
436             DDI_CHK_STATUS(Qmatrix(data), VA_STATUS_ERROR_INVALID_BUFFER);
437             break;
438 
439         case VAEncSequenceParameterBufferType:
440             DDI_CHK_STATUS(ParseSeqParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
441             m_encodeCtx->bNewSeq = true;
442             break;
443 
444         case VAEncPictureParameterBufferType:
445             DDI_CHK_STATUS(ParsePicParams(mediaCtx, data), VA_STATUS_ERROR_INVALID_BUFFER);
446 
447             DDI_CHK_STATUS(
448                     AddToStatusReportQueue((void *)m_encodeCtx->resBitstreamBuffer.bo),
449                     VA_STATUS_ERROR_INVALID_BUFFER);
450             break;
451 
452         case VAEncPackedHeaderParameterBufferType:
453             DDI_CHK_STATUS(ParsePackedHeaderParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
454             break;
455 
456         case VAEncPackedHeaderDataBufferType:
457             DDI_CHK_STATUS(ParsePackedHeaderData(data), VA_STATUS_ERROR_INVALID_BUFFER);
458             break;
459 
460         case VAEncMiscParameterBufferType:
461             DDI_CHK_STATUS(ParseMiscParams(data), VA_STATUS_ERROR_INVALID_BUFFER);
462             break;
463 
464         case VAEncMacroblockMapBufferType:
465             DDI_CHK_STATUS(ParseSegMapParams(buf), VA_STATUS_ERROR_INVALID_BUFFER);
466             break;
467 
468         case VAEncQPBufferType:
469             DdiMedia_MediaBufferToMosResource(buf, &m_encodeCtx->resMBQpBuffer);
470             m_encodeCtx->bMBQpEnable = true;
471             break;
472 
473         default:
474             DDI_ASSERTMESSAGE("not supported buffer type.");
475             break;
476         }
477         DdiMedia_UnmapBuffer(ctx, buffers[i]);
478     }
479 
480     DDI_FUNCTION_EXIT(vaStatus);
481     return vaStatus;
482 }
483 
484 // Reset the paramters before each frame
ResetAtFrameLevel()485 VAStatus DdiEncodeVp9::ResetAtFrameLevel()
486 {
487     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
488 
489     lastPackedHeaderType = 0;
490     headerInsertFlag     = 0;
491 
492     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *vp9SeqParam = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
493 
494     if (vp9SeqParam)
495     {
496         vp9SeqParam->SeqFlags.fields.bResetBRC = 0;
497         vp9SeqParam->MaxBitRate = 0;
498         vp9SeqParam->MinBitRate = 0xffffffff;
499     }
500 
501     m_encodeCtx->bMBQpEnable = false;
502 
503     MOS_ZeroMemory(&(m_encodeCtx->segMapBuffer), sizeof(MOS_SURFACE));
504 
505     return VA_STATUS_SUCCESS;
506 }
507 
ParseSeqParams(void * ptr)508 VAStatus DdiEncodeVp9::ParseSeqParams(void *ptr)
509 {
510     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
511     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
512 
513     VAEncSequenceParameterBufferVP9 *seqParams = (VAEncSequenceParameterBufferVP9 *)ptr;
514 
515     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *vp9SeqParams = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
516     DDI_CHK_NULL(vp9SeqParams, "nullptr vp9SeqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
517 
518     vp9SeqParams->wMaxFrameWidth   = seqParams->max_frame_width;
519     vp9SeqParams->wMaxFrameHeight  = seqParams->max_frame_height;
520     vp9SeqParams->GopPicSize       = seqParams->intra_period;
521 
522     /* the bits_per_second is only used when the target bit_rate is not initialized */
523     if (vp9SeqParams->TargetBitRate[0] == 0)
524     {
525         vp9SeqParams->TargetBitRate[0] = MOS_ROUNDUP_DIVIDE(seqParams->bits_per_second, CODECHAL_ENCODE_BRC_KBPS);
526     }
527 
528     if (vp9SeqParams->GopPicSize != savedGopSize)
529     {
530         savedGopSize = vp9SeqParams->GopPicSize;
531         vp9SeqParams->SeqFlags.fields.bResetBRC = 1;
532     }
533 
534     return VA_STATUS_SUCCESS;
535 }
536 
ParsePicParams(DDI_MEDIA_CONTEXT * mediaCtx,void * ptr)537 VAStatus DdiEncodeVp9::ParsePicParams(DDI_MEDIA_CONTEXT *mediaCtx, void *ptr)
538 {
539     DDI_CHK_NULL(mediaCtx, "nullptr mediaCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
540     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
541     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
542 
543     VAEncPictureParameterBufferVP9 *picParam = (VAEncPictureParameterBufferVP9 *)ptr;
544 
545     if ((picParam->frame_width_src == 0) && (picParam->frame_width_dst == 0))
546     {
547         DDI_ASSERTMESSAGE("DDI: frame width in VP9 PicParam is zero\n.");
548         return VA_STATUS_ERROR_INVALID_PARAMETER;
549     }
550     if ((picParam->frame_height_src == 0) && (picParam->frame_height_dst == 0))
551     {
552         DDI_ASSERTMESSAGE("DDI: frame height in VP9 PicParam is zero\n.");
553         return VA_STATUS_ERROR_INVALID_PARAMETER;
554     }
555 
556     CODEC_VP9_ENCODE_PIC_PARAMS *vp9PicParam = (PCODEC_VP9_ENCODE_PIC_PARAMS)(m_encodeCtx->pPicParams);
557 
558     DDI_CHK_NULL(vp9PicParam, "nullptr vp9PicParam", VA_STATUS_ERROR_INVALID_PARAMETER);
559 
560     MOS_ZeroMemory(vp9PicParam, sizeof(CODEC_VP9_ENCODE_PIC_PARAMS));
561 
562     vp9PicParam->PicFlags.fields.frame_type                   = picParam->pic_flags.bits.frame_type;
563     vp9PicParam->PicFlags.fields.show_frame                   = picParam->pic_flags.bits.show_frame;
564     vp9PicParam->PicFlags.fields.error_resilient_mode         = picParam->pic_flags.bits.error_resilient_mode;
565     vp9PicParam->PicFlags.fields.intra_only                   = picParam->pic_flags.bits.intra_only;
566     vp9PicParam->PicFlags.fields.allow_high_precision_mv      = picParam->pic_flags.bits.allow_high_precision_mv;
567     vp9PicParam->PicFlags.fields.mcomp_filter_type            = picParam->pic_flags.bits.mcomp_filter_type;
568     vp9PicParam->PicFlags.fields.frame_parallel_decoding_mode = picParam->pic_flags.bits.frame_parallel_decoding_mode;
569     vp9PicParam->PicFlags.fields.reset_frame_context          = picParam->pic_flags.bits.reset_frame_context;
570     vp9PicParam->PicFlags.fields.refresh_frame_context        = picParam->pic_flags.bits.refresh_frame_context;
571     vp9PicParam->PicFlags.fields.frame_context_idx            = picParam->pic_flags.bits.frame_context_idx;
572     vp9PicParam->PicFlags.fields.segmentation_enabled         = picParam->pic_flags.bits.segmentation_enabled;
573     vp9PicParam->PicFlags.fields.segmentation_temporal_update = picParam->pic_flags.bits.segmentation_temporal_update;
574     vp9PicParam->PicFlags.fields.segmentation_update_map      = picParam->pic_flags.bits.segmentation_update_map;
575     vp9PicParam->PicFlags.fields.LosslessFlag                 = picParam->pic_flags.bits.lossless_mode;
576     vp9PicParam->PicFlags.fields.comp_prediction_mode         = picParam->pic_flags.bits.comp_prediction_mode;
577     vp9PicParam->PicFlags.fields.super_frame                  = picParam->pic_flags.bits.super_frame_flag;
578     vp9PicParam->PicFlags.fields.seg_update_data              = picParam->pic_flags.bits.segmentation_enabled;
579 #if VA_CHECK_VERSION(1, 23, 0)
580     vp9PicParam->PicFlags.fields.seg_id_block_size            = picParam->seg_id_block_size;
581 #endif
582 
583     vp9PicParam->SrcFrameWidthMinus1          = picParam->frame_width_src - 1;
584     vp9PicParam->SrcFrameHeightMinus1         = picParam->frame_height_src - 1;
585 
586     vp9PicParam->DstFrameWidthMinus1          = picParam->frame_width_dst - 1;
587     vp9PicParam->DstFrameHeightMinus1         = picParam->frame_height_dst - 1;
588 
589     /* width_src and width_dst won't be zero at the same time
590      * If only one of them is zero, assume that there is no dynamica scaling.
591      * In such case it is dervied.
592      */
593     if ((picParam->frame_width_src == 0) || (picParam->frame_width_dst == 0))
594     {
595         if (picParam->frame_width_src == 0)
596         {
597             vp9PicParam->SrcFrameWidthMinus1 = picParam->frame_width_dst - 1;
598         }
599         else
600         {
601             vp9PicParam->DstFrameWidthMinus1 = picParam->frame_width_src - 1;
602         }
603     }
604 
605     /* Handle the zero height by using the mechanism similar to width */
606     if ((picParam->frame_height_src == 0) || (picParam->frame_height_dst == 0))
607     {
608         if (picParam->frame_height_src == 0)
609         {
610             vp9PicParam->SrcFrameHeightMinus1 = picParam->frame_height_dst - 1;
611         }
612         else
613         {
614             vp9PicParam->DstFrameHeightMinus1 = picParam->frame_height_src - 1;
615         }
616     }
617 
618     vp9PicParam->filter_level                 = picParam->filter_level;
619     vp9PicParam->sharpness_level              = picParam->sharpness_level;
620 
621     vp9PicParam->LumaACQIndex                 = picParam->luma_ac_qindex;
622     vp9PicParam->LumaDCQIndexDelta            = picParam->luma_dc_qindex_delta;
623     vp9PicParam->ChromaACQIndexDelta          = picParam->chroma_ac_qindex_delta;
624     vp9PicParam->ChromaDCQIndexDelta          = picParam->chroma_dc_qindex_delta;
625 
626     vp9PicParam->RefFlags.fields.LastRefIdx        = picParam->ref_flags.bits.ref_last_idx;
627     vp9PicParam->RefFlags.fields.GoldenRefIdx      = picParam->ref_flags.bits.ref_gf_idx;
628     vp9PicParam->RefFlags.fields.AltRefIdx         = picParam->ref_flags.bits.ref_arf_idx;
629     vp9PicParam->RefFlags.fields.LastRefSignBias   = picParam->ref_flags.bits.ref_last_sign_bias;
630     vp9PicParam->RefFlags.fields.GoldenRefSignBias = picParam->ref_flags.bits.ref_gf_sign_bias;
631     vp9PicParam->RefFlags.fields.AltRefSignBias    = picParam->ref_flags.bits.ref_arf_sign_bias;
632 
633     vp9PicParam->RefFlags.fields.ref_frame_ctrl_l0   = picParam->ref_flags.bits.ref_frame_ctrl_l0;
634     vp9PicParam->RefFlags.fields.ref_frame_ctrl_l1   = picParam->ref_flags.bits.ref_frame_ctrl_l1;
635     vp9PicParam->RefFlags.fields.refresh_frame_flags = picParam->refresh_frame_flags;
636     vp9PicParam->temporal_id                         = picParam->ref_flags.bits.temporal_id;
637 
638     for (int32_t i = 0; i < 4; i++)
639     {
640         vp9PicParam->LFRefDelta[i] = picParam->ref_lf_delta[i];
641     }
642 
643     vp9PicParam->LFModeDelta[0] = picParam->mode_lf_delta[0];
644     vp9PicParam->LFModeDelta[1] = picParam->mode_lf_delta[1];
645 
646     vp9PicParam->sharpness_level = picParam->sharpness_level;
647 
648     vp9PicParam->BitOffsetForFirstPartitionSize = picParam->bit_offset_first_partition_size;
649     vp9PicParam->BitOffsetForQIndex             = picParam->bit_offset_qindex;
650     vp9PicParam->BitOffsetForLFLevel            = picParam->bit_offset_lf_level;
651     vp9PicParam->BitOffsetForLFRefDelta         = picParam->bit_offset_ref_lf_delta;
652     vp9PicParam->BitOffsetForLFModeDelta        = picParam->bit_offset_mode_lf_delta;
653     vp9PicParam->BitOffsetForSegmentation       = picParam->bit_offset_segmentation;
654     vp9PicParam->BitSizeForSegmentation         = picParam->bit_size_segmentation;
655 
656     vp9PicParam->log2_tile_rows = picParam->log2_tile_rows;
657     vp9PicParam->log2_tile_columns = picParam->log2_tile_columns;
658 
659     vp9PicParam->SkipFrameFlag  = picParam->skip_frame_flag;
660     vp9PicParam->NumSkipFrames  = picParam->number_skip_frames;
661     vp9PicParam->SizeSkipFrames = picParam->skip_frames_size;
662 
663     DDI_CODEC_RENDER_TARGET_TABLE *rtTbl = &(m_encodeCtx->RTtbl);
664 
665     auto recon = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->reconstructed_frame);
666     if(m_encodeCtx->vaProfile == VAProfileVP9Profile1
667        ||m_encodeCtx->vaProfile == VAProfileVP9Profile2
668        ||m_encodeCtx->vaProfile == VAProfileVP9Profile3)
669     {
670         recon = DdiMedia_ReplaceSurfaceWithVariant(recon, m_encodeCtx->vaEntrypoint);
671     }
672     DDI_CHK_RET(RegisterRTSurfaces(rtTbl, recon),"RegisterRTSurfaces failed!");
673 
674     SetupCodecPicture(mediaCtx, rtTbl, &vp9PicParam->CurrReconstructedPic,
675                                              picParam->reconstructed_frame, false);
676     rtTbl->pCurrentReconTarget = recon;
677     DDI_CHK_NULL(rtTbl->pCurrentReconTarget, "NULL rtTbl->pCurrentReconTarget", VA_STATUS_ERROR_INVALID_PARAMETER);
678 
679     // curr orig pic
680     vp9PicParam->CurrOriginalPic.FrameIdx = GetRenderTargetID(rtTbl, rtTbl->pCurrentReconTarget);
681     vp9PicParam->CurrOriginalPic.PicFlags = vp9PicParam->CurrReconstructedPic.PicFlags;
682 
683     for (int32_t i = 0; i < 8; i++)
684     {
685         if (picParam->reference_frames[i] != VA_INVALID_SURFACE)
686         {
687             UpdateRegisteredRTSurfaceFlag(rtTbl, DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, picParam->reference_frames[i]));
688         }
689         SetupCodecPicture(
690             mediaCtx,
691             rtTbl,
692             &vp9PicParam->RefFrameList[i],
693             picParam->reference_frames[i],
694             true);
695     }
696 
697     DDI_MEDIA_BUFFER *buf = nullptr;
698 
699     buf = DdiMedia_GetBufferFromVABufferID(mediaCtx, picParam->coded_buf);
700     DDI_CHK_NULL(buf, "nullptr buf", VA_STATUS_ERROR_INVALID_PARAMETER);
701     RemoveFromStatusReportQueue(buf);
702     DdiMedia_MediaBufferToMosResource(buf, &(m_encodeCtx->resBitstreamBuffer));
703 
704     return VA_STATUS_SUCCESS;
705 }
706 
ParsePackedHeaderParams(void * ptr)707 VAStatus DdiEncodeVp9::ParsePackedHeaderParams(void *ptr)
708 {
709     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
710     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
711 
712     m_encodeCtx->bLastPackedHdrIsSlice = false;
713 
714     VAEncPackedHeaderParameterBuffer *packedHeaderParamBuf = (VAEncPackedHeaderParameterBuffer *)ptr;
715 
716     if (packedHeaderParamBuf->type != VAEncPackedHeaderRawData)
717     {
718         DDI_ASSERTMESSAGE("DDI: incorrect packed header type %d\n.", packedHeaderParamBuf->type);
719         return VA_STATUS_ERROR_INVALID_PARAMETER;
720     }
721 
722     // VP9 will always only have 1 NAL type (PPS)
723     m_encodeCtx->ppNALUnitParams[0]->uiNalUnitType             = 0x22;
724     m_encodeCtx->ppNALUnitParams[0]->bInsertEmulationBytes     = false;
725     m_encodeCtx->ppNALUnitParams[0]->uiSkipEmulationCheckCount = 0;
726     m_encodeCtx->ppNALUnitParams[0]->uiSize                    = (packedHeaderParamBuf->bit_length + 7) / 8;
727     m_encodeCtx->ppNALUnitParams[0]->uiOffset                  = 0;
728 
729     lastPackedHeaderType = VAEncPackedHeaderRawData;
730 
731     return VA_STATUS_SUCCESS;
732 }
733 
ParsePackedHeaderData(void * ptr)734 VAStatus DdiEncodeVp9::ParsePackedHeaderData(void *ptr)
735 {
736     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
737     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
738 
739     BSBuffer *bsBuffer = m_encodeCtx->pbsBuffer;
740     DDI_CHK_NULL(bsBuffer, "nullptr bsBuffer", VA_STATUS_ERROR_INVALID_PARAMETER);
741 
742     if (lastPackedHeaderType != VAEncPackedHeaderRawData)
743     {
744         DDI_ASSERTMESSAGE("DDI: the packed header param/data is not passed in pair \n.");
745         return VA_STATUS_ERROR_INVALID_PARAMETER;
746     }
747 
748     /* Only one header data is enough */
749     if (headerInsertFlag)
750     {
751         return VA_STATUS_SUCCESS;
752     }
753 
754     // Since VP9 only has 1 NAL type it's safe to reset each time unconditionally
755     bsBuffer->pCurrent    = bsBuffer->pBase;
756     bsBuffer->SliceOffset = 0;
757     bsBuffer->BitOffset   = 0;
758     bsBuffer->BitSize     = 0;
759 
760     // copy pps header data
761     uint32_t hdrDataSize = m_encodeCtx->ppNALUnitParams[0]->uiSize;
762     DDI_CHK_RET(
763         MOS_SecureMemcpy(
764             bsBuffer->pCurrent,
765             bsBuffer->BufferSize,
766             (uint8_t *)ptr,
767             hdrDataSize),
768         "DDI:packed header size is too large to be supported!");
769 
770     m_encodeCtx->ppNALUnitParams[0]->uiOffset = bsBuffer->pCurrent - bsBuffer->pBase;
771 
772     bsBuffer->pCurrent += hdrDataSize;
773     bsBuffer->SliceOffset += hdrDataSize;
774     bsBuffer->BitSize += hdrDataSize * 8;
775     headerInsertFlag   = true;
776 
777     return VA_STATUS_SUCCESS;
778 }
779 
780 /*
781  * For VP9 this buffer is used to contain segment params
782  */
Qmatrix(void * ptr)783 VAStatus DdiEncodeVp9::Qmatrix(void *ptr)
784 {
785     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
786     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
787     DDI_CHK_NULL(m_segParams, "nullptr m_segParams", VA_STATUS_ERROR_INVALID_PARAMETER);
788 
789     VAEncMiscParameterTypeVP9PerSegmantParam *segParams = (VAEncMiscParameterTypeVP9PerSegmantParam *)ptr;
790     isSegParamsChanged = false;
791 
792     for (int32_t i = 0; i < 8; ++i)
793     {
794         if (   m_segParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled != segParams->seg_data[i].seg_flags.bits.segment_reference_enabled
795             || m_segParams->SegData[i].SegmentFlags.fields.SegmentReference != segParams->seg_data[i].seg_flags.bits.segment_reference
796             || m_segParams->SegData[i].SegmentFlags.fields.SegmentSkipped != segParams->seg_data[i].seg_flags.bits.segment_reference_skipped
797             || m_segParams->SegData[i].SegmentQIndexDelta != MOS_CLAMP_MIN_MAX(segParams->seg_data[i].segment_qindex_delta, -255, 255)
798             || m_segParams->SegData[i].SegmentLFLevelDelta != MOS_CLAMP_MIN_MAX(segParams->seg_data[i].segment_lf_level_delta, -63, 63))
799             isSegParamsChanged = true;
800 
801         m_segParams->SegData[i].SegmentFlags.fields.SegmentReferenceEnabled =
802             segParams->seg_data[i].seg_flags.bits.segment_reference_enabled;
803         m_segParams->SegData[i].SegmentFlags.fields.SegmentReference =
804             segParams->seg_data[i].seg_flags.bits.segment_reference;
805         m_segParams->SegData[i].SegmentFlags.fields.SegmentSkipped =
806             segParams->seg_data[i].seg_flags.bits.segment_reference_skipped;
807 
808         m_segParams->SegData[i].SegmentQIndexDelta  =
809             MOS_CLAMP_MIN_MAX(segParams->seg_data[i].segment_qindex_delta, -255, 255);
810 
811         m_segParams->SegData[i].SegmentLFLevelDelta =
812             MOS_CLAMP_MIN_MAX(segParams->seg_data[i].segment_lf_level_delta, -63, 63);
813     }
814 
815     return VA_STATUS_SUCCESS;
816 }
817 
ParseMiscParamVBV(void * data)818 VAStatus DdiEncodeVp9::ParseMiscParamVBV(void *data)
819 {
820     VAEncMiscParameterHRD *vaEncMiscParamHRD = (VAEncMiscParameterHRD *)data;
821 
822     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *seqParams = (CODEC_VP9_ENCODE_SEQUENCE_PARAMS *)m_encodeCtx->pSeqParams;
823 
824     if ((seqParams == nullptr) || (vaEncMiscParamHRD == nullptr))
825     {
826         return VA_STATUS_ERROR_INVALID_PARAMETER;
827     }
828 
829     seqParams->VBVBufferSizeInBit         = vaEncMiscParamHRD->buffer_size;
830     seqParams->InitVBVBufferFullnessInBit = vaEncMiscParamHRD->initial_buffer_fullness;
831 
832     seqParams->UpperVBVBufferLevelThresholdInBit = 800000;
833     seqParams->LowerVBVBufferLevelThresholdInBit = 320000;
834 
835     if ((savedHrdSize != seqParams->VBVBufferSizeInBit) ||
836         (savedHrdBufFullness != seqParams->InitVBVBufferFullnessInBit))
837     {
838         savedHrdSize        = seqParams->VBVBufferSizeInBit;
839         savedHrdBufFullness = seqParams->InitVBVBufferFullnessInBit;
840         seqParams->SeqFlags.fields.bResetBRC = 0x1;
841     }
842 
843     return VA_STATUS_SUCCESS;
844 }
845 
846 // Parse the frame rate paramters from app
ParseMiscParamFR(void * data)847 VAStatus DdiEncodeVp9::ParseMiscParamFR(void *data)
848 {
849     VAEncMiscParameterFrameRate *vaFrameRate = (VAEncMiscParameterFrameRate *)data;
850     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *seqParams = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
851 
852     /* This is the optional */
853     if ((vaFrameRate == nullptr) || (seqParams == nullptr) ||
854         (vaFrameRate->framerate_flags.bits.temporal_id > seqParams->NumTemporalLayersMinus1))
855     {
856         return VA_STATUS_ERROR_INVALID_PARAMETER;
857     }
858 
859     uint32_t temporalId = vaFrameRate->framerate_flags.bits.temporal_id;
860 
861     if (vaFrameRate->framerate != savedFrameRate[temporalId])
862     {
863           savedFrameRate[temporalId] = vaFrameRate->framerate;
864           seqParams->SeqFlags.fields.bResetBRC |= 0x1;
865 
866           uint32_t frameRate = vaFrameRate->framerate;
867           seqParams->FrameRate[temporalId].uiNumerator   = frameRate & (0xFFFF);
868           seqParams->FrameRate[temporalId].uiDenominator = (frameRate >> 16) & (0xFFFF);
869           if (seqParams->FrameRate[temporalId].uiDenominator == 0)
870           {
871               seqParams->FrameRate[temporalId].uiDenominator = 1;
872           }
873     }
874 
875     return VA_STATUS_SUCCESS;
876 }
877 
878 // Parse rate control related information from app
ParseMiscParamRC(void * data)879 VAStatus DdiEncodeVp9::ParseMiscParamRC(void *data)
880 {
881     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *seqParams = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
882     DDI_CHK_NULL(seqParams, "nullptr vp9SeqParams", VA_STATUS_ERROR_INVALID_PARAMETER);
883 
884     VAEncMiscParameterRateControl *vaEncMiscParamRC = (VAEncMiscParameterRateControl *)data;
885     DDI_CHK_NULL(data, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
886 
887     uint32_t temporalId = vaEncMiscParamRC->rc_flags.bits.temporal_id;
888     DDI_CHK_LESS(temporalId, (seqParams->NumTemporalLayersMinus1+1),
889         "invalid temporal id", VA_STATUS_ERROR_INVALID_PARAMETER);
890 
891     uint32_t bitRate                     = MOS_ROUNDUP_DIVIDE(vaEncMiscParamRC->bits_per_second, CODECHAL_ENCODE_BRC_KBPS);
892     seqParams->MaxBitRate                = MOS_MAX(seqParams->MaxBitRate, bitRate);
893     seqParams->SeqFlags.fields.bResetBRC = vaEncMiscParamRC->rc_flags.bits.reset;  // adding reset here. will apply both CBR and VBR
894 
895     if (VA_RC_CBR == m_encodeCtx->uiRCMethod)
896     {
897         seqParams->TargetBitRate[temporalId] = bitRate;
898         seqParams->MinBitRate                = MOS_MIN(seqParams->MinBitRate, bitRate);
899         seqParams->RateControlMethod         = RATECONTROL_CBR;
900         if (savedTargetBit[temporalId] != bitRate)
901         {
902             savedTargetBit[temporalId] = bitRate;
903             seqParams->SeqFlags.fields.bResetBRC |= 0x1;
904         }
905     }
906     else if (VA_RC_VBR == m_encodeCtx->uiRCMethod || VA_RC_ICQ == m_encodeCtx->uiRCMethod)
907     {
908         seqParams->TargetBitRate[temporalId] = bitRate * vaEncMiscParamRC->target_percentage / 100;  // VBR target bits
909         uint32_t minBitRate = bitRate * abs((int32_t)(2 * vaEncMiscParamRC->target_percentage) - 100) / 100;
910         seqParams->MinBitRate = MOS_MIN(seqParams->TargetBitRate[temporalId], minBitRate);
911         seqParams->RateControlMethod = RATECONTROL_VBR;
912 
913         if ((savedTargetBit[temporalId] != seqParams->TargetBitRate[temporalId]) ||
914             (savedMaxBitRate[temporalId] != bitRate))
915         {
916             savedTargetBit[temporalId]           = seqParams->TargetBitRate[temporalId];
917             seqParams->SeqFlags.fields.bResetBRC |= 0x1;
918             savedMaxBitRate[temporalId]          = bitRate;
919         }
920     }
921 
922     if (VA_RC_ICQ == m_encodeCtx->uiRCMethod)
923     {
924         seqParams->ICQQualityFactor  = vaEncMiscParamRC->ICQ_quality_factor;
925         seqParams->RateControlMethod = RATECONTROL_CQL;
926     }
927 
928     /* the reset flag in RC will be considered. */
929     seqParams->SeqFlags.fields.bResetBRC |= vaEncMiscParamRC->rc_flags.bits.reset;  // adding reset here. will apply both CBR and VBR
930 
931     /* Enabling Dynamic Scaling */
932     seqParams->SeqFlags.fields.EnableDynamicScaling = vaEncMiscParamRC->rc_flags.bits.enable_dynamic_scaling;
933 
934     return VA_STATUS_SUCCESS;
935 }
936 
ParseMiscParamEncQuality(void * data)937 VAStatus DdiEncodeVp9::ParseMiscParamEncQuality(void *data)
938 {
939     DDI_UNUSED(m_encodeCtx);
940     DDI_UNUSED(data);
941 
942     /* Ignore it */
943     return VA_STATUS_SUCCESS;
944 }
945 
ParseMiscParamQualityLevel(void * data)946 VAStatus DdiEncodeVp9::ParseMiscParamQualityLevel(void *data)
947 {
948     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
949 
950     VAEncMiscParameterBufferQualityLevel *vaEncMiscParamQualityLevel = (VAEncMiscParameterBufferQualityLevel *)data;
951 
952     /* it will be mapped to 1, 4, 7.
953      * 1-2 mapped to the 1
954      * 6-7 mapped  the 7.
955      * 0-3-4-5 mapped to 4.
956      */
957 
958     if (vaEncMiscParamQualityLevel->quality_level == 0)
959     {
960         vp9TargetUsage = TARGETUSAGE_RT_SPEED;
961     }
962     else if (vaEncMiscParamQualityLevel->quality_level >= TARGETUSAGE_HI_SPEED)
963     {
964         vp9TargetUsage = TARGETUSAGE_BEST_SPEED;
965     }
966     else if (vaEncMiscParamQualityLevel->quality_level <= TARGETUSAGE_HI_QUALITY)
967     {
968 #ifdef _FULL_OPEN_SOURCE
969         vp9TargetUsage = TARGETUSAGE_RT_SPEED;
970 #else
971         vp9TargetUsage = TARGETUSAGE_BEST_QUALITY;
972 #endif
973     }
974     else
975     {
976         vp9TargetUsage = TARGETUSAGE_RT_SPEED;
977     }
978 
979     return VA_STATUS_SUCCESS;
980 }
981 
ParseMiscParameterTemporalLayerParams(void * data)982 VAStatus DdiEncodeVp9::ParseMiscParameterTemporalLayerParams(void *data)
983 {
984     DDI_CHK_NULL(data, "nullptr data", VA_STATUS_ERROR_INVALID_PARAMETER);
985 
986     CODEC_VP9_ENCODE_SEQUENCE_PARAMS *seqParams = (PCODEC_VP9_ENCODE_SEQUENCE_PARAMS)(m_encodeCtx->pSeqParams);
987 
988     VAEncMiscParameterTemporalLayerStructure *vaEncTempLayerStruct = (VAEncMiscParameterTemporalLayerStructure *)data;
989     DDI_CHK_LESS(vaEncTempLayerStruct->number_of_layers, (CODECHAL_ENCODE_VP9_MAX_NUM_TEMPORAL_LAYERS+1),
990         "invalid number of temporal layers", VA_STATUS_ERROR_INVALID_PARAMETER);
991 
992     if (vaEncTempLayerStruct->number_of_layers > 0)
993     {
994         seqParams->NumTemporalLayersMinus1 = vaEncTempLayerStruct->number_of_layers - 1;
995     }
996     else
997     {
998         seqParams->NumTemporalLayersMinus1 = 0;
999     }
1000 
1001     return VA_STATUS_SUCCESS;
1002 }
1003 
ParseSegMapParams(DDI_MEDIA_BUFFER * buf)1004 VAStatus DdiEncodeVp9::ParseSegMapParams(DDI_MEDIA_BUFFER *buf)
1005 {
1006     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1007 
1008     m_encodeCtx->segMapBuffer.Format   = Format_Buffer_2D;
1009     m_encodeCtx->segMapBuffer.dwOffset = 0;
1010     DdiMedia_MediaBufferToMosResource(buf, &((m_encodeCtx->segMapBuffer).OsResource));
1011     return VA_STATUS_SUCCESS;
1012 }
1013 
ParseMiscParams(void * ptr)1014 VAStatus DdiEncodeVp9::ParseMiscParams(void *ptr)
1015 {
1016     DDI_CHK_NULL(m_encodeCtx, "nullptr m_encodeCtx", VA_STATUS_ERROR_INVALID_PARAMETER);
1017     DDI_CHK_NULL(ptr, "nullptr ptr", VA_STATUS_ERROR_INVALID_PARAMETER);
1018 
1019     VAEncMiscParameterBuffer *miscParamBuf = (VAEncMiscParameterBuffer *)ptr;
1020     DDI_CHK_NULL(miscParamBuf->data, "nullptr miscParamBuf->data", VA_STATUS_ERROR_INVALID_PARAMETER);
1021 
1022     VAStatus vaStatus = VA_STATUS_SUCCESS;
1023     switch ((int32_t)(miscParamBuf->type))
1024     {
1025     case VAEncMiscParameterTypeHRD:
1026     {
1027         vaStatus = ParseMiscParamVBV((void *)miscParamBuf->data);
1028         break;
1029     }
1030     case VAEncMiscParameterTypeFrameRate:
1031     {
1032         vaStatus = ParseMiscParamFR((void *)miscParamBuf->data);
1033         break;
1034     }
1035     case VAEncMiscParameterTypeRateControl:
1036     {
1037         vaStatus = ParseMiscParamRC((void *)miscParamBuf->data);
1038         break;
1039     }
1040     case VAEncMiscParameterTypeEncQuality:
1041     {
1042         vaStatus = ParseMiscParamEncQuality((void *)miscParamBuf->data);
1043         break;
1044     }
1045     case VAEncMiscParameterTypeTemporalLayerStructure:
1046     {
1047         vaStatus = ParseMiscParameterTemporalLayerParams((void *)miscParamBuf->data);
1048         break;
1049     }
1050     case VAEncMiscParameterTypeQualityLevel:
1051     {
1052         vaStatus = ParseMiscParamQualityLevel((void *)miscParamBuf->data);
1053         break;
1054     }
1055     default:
1056     {
1057         DDI_ASSERTMESSAGE("DDI: unsupported misc parameter type.");
1058         return VA_STATUS_ERROR_INVALID_PARAMETER;
1059     }
1060     }
1061 
1062     return vaStatus;
1063 }
1064 
ReportExtraStatus(EncodeStatusReport * encodeStatusReport,VACodedBufferSegment * codedBufferSegment)1065 VAStatus DdiEncodeVp9::ReportExtraStatus(
1066     EncodeStatusReport   *encodeStatusReport,
1067     VACodedBufferSegment *codedBufferSegment)
1068 {
1069     DDI_FUNCTION_ENTER();
1070 
1071     DDI_CHK_NULL(encodeStatusReport, "nullptr encodeStatusReport", VA_STATUS_ERROR_INVALID_PARAMETER);
1072     DDI_CHK_NULL(codedBufferSegment, "nullptr codedBufferSegment", VA_STATUS_ERROR_INVALID_PARAMETER);
1073 
1074     VAStatus vaStatus = VA_STATUS_SUCCESS;
1075 
1076     // The coded buffer status are one-to-one correspondence with report buffers, even though the index is updated.
1077     VACodedBufferVP9Status *codedBufStatus = &(m_codedBufStatus[m_encodeCtx->statusReportBuf.ulUpdatePosition]);
1078     codedBufStatus->loop_filter_level = encodeStatusReport->loopFilterLevel;
1079     codedBufStatus->long_term_indication = encodeStatusReport->LongTermIndication;
1080     codedBufStatus->next_frame_width = encodeStatusReport->NextFrameWidthMinus1 + 1;
1081     codedBufStatus->next_frame_height = encodeStatusReport->NextFrameHeightMinus1 + 1;
1082 
1083     /*
1084      * Ignore the private status buffer temporarily. According to the comment for VACodedBufferVP9Status in VA-API,
1085      * driver must set codedBufferSegment->status to be VA_CODED_BUF_STATUS_CODEC_SPECIFIC, however
1086      * VA_CODED_BUF_STATUS_CODEC_SPECIFIC is not defined in VA-API
1087      */
1088     // codedBufferSegment->next = codedBufStatus;
1089 
1090     return vaStatus;
1091 }
1092 
SetupCodecPicture(DDI_MEDIA_CONTEXT * mediaCtx,DDI_CODEC_RENDER_TARGET_TABLE * rtTbl,CODEC_PICTURE * codecHalPic,VASurfaceID surfaceID,bool picReference)1093 void DdiEncodeVp9::SetupCodecPicture(
1094     DDI_MEDIA_CONTEXT                     *mediaCtx,
1095     DDI_CODEC_RENDER_TARGET_TABLE         *rtTbl,
1096     CODEC_PICTURE                         *codecHalPic,
1097     VASurfaceID                           surfaceID,
1098     bool                                  picReference)
1099 {
1100     if(VA_INVALID_SURFACE != surfaceID)
1101     {
1102         DDI_MEDIA_SURFACE *surface = DdiMedia_GetSurfaceFromVASurfaceID(mediaCtx, surfaceID);
1103         codecHalPic->FrameIdx = GetRenderTargetID(rtTbl, surface);
1104     }
1105     else
1106     {
1107         codecHalPic->FrameIdx = (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX;
1108     }
1109 
1110     if (picReference)
1111     {
1112         if (codecHalPic->FrameIdx == (uint8_t)DDI_CODEC_INVALID_FRAME_INDEX)
1113         {
1114             codecHalPic->PicFlags = PICTURE_INVALID;
1115         }
1116         else
1117         {
1118             codecHalPic->PicFlags = PICTURE_SHORT_TERM_REFERENCE;
1119         }
1120     }
1121     else
1122     {
1123         codecHalPic->PicFlags = PICTURE_FRAME;
1124     }
1125 }
1126 
getSequenceParameterBufferSize()1127 uint32_t DdiEncodeVp9::getSequenceParameterBufferSize()
1128 {
1129         return sizeof(VAEncSequenceParameterBufferVP9);
1130 }
1131 
getPictureParameterBufferSize()1132 uint32_t DdiEncodeVp9::getPictureParameterBufferSize()
1133 {
1134         return sizeof(VAEncPictureParameterBufferVP9);
1135 }
1136 
getQMatrixBufferSize()1137 uint32_t DdiEncodeVp9::getQMatrixBufferSize()
1138 {
1139         return sizeof(VAEncSegParamVP9);
1140 }
1141