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