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