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