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