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